From 9b7d9cf7c19798aa2bd26baebde4e416b27ad7c4 Mon Sep 17 00:00:00 2001 From: Jissin Sam Mathew Date: Tue, 19 May 2026 18:47:12 +0530 Subject: [PATCH 01/11] Implement Assign Job to Technician functionality MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SER001: Assign job to technician 1. Added ServiceManagementService logic to retrieve service bookings and create job cards for assigned technicians. 2. Added UserManagementService support to retrieve technicians by user type and fetch technician details by ID. 3. Connected Controller methods with ServiceManagementService and UserManagementService for service booking retrieval, technician listing, and job card creation. 4. Updated JobCard model to use util::ServiceJobStatus consistently and simplified constructor initialization for assigned and completion timestamps. 5. Added PENDING status in ServiceJobStatus enum for identifying unassigned service bookings. 6. Implemented AdminMenu job assignment flow to list pending service bookings, display available technicians, allow technician selection, and assign jobs for services in the booking. 7. Added notification trigger during job card creation for assigned technicians. Job assignment functionality validation Precondition: 1. System is running. 2. Pending service bookings are available in the system. 3. Technician users are available in the system. 4. Admin user is logged in and admin menu is active. Steps: 1. Launch the application and log in as an admin. 2. Select the Assign Job option from the admin menu. 3. View the list of available pending service bookings. - Verify that pending bookings are displayed. 4. Select a valid service booking. 5. View the list of available technicians. - Verify that technicians are listed for selection. 6. Select a technician to assign the job. - Verify that job cards are created for services in the booking. - Verify that assigned jobs are visible in the technician’s menu. - Verify that a confirmation message is shown. - Verify that a confirmation notification is sent to the assigned technician. Sreeja Reghukumar, please review --- .../controllers/Controller.cpp | 17 ++- .../controllers/Controller.h | 5 + .../models/JobCard.cpp | 14 +- .../models/JobCard.h | 13 +- .../models/ServiceBooking.cpp | 6 +- .../models/ServiceBooking.h | 8 +- .../services/ServiceManagementService.cpp | 69 +++++++++ .../services/ServiceManagementService.h | 1 + .../services/UserManagementService.cpp | 30 ++++ .../utilities/Enums.h | 3 + .../views/AdminMenu.cpp | 143 ++++++++++++++++++ 11 files changed, 284 insertions(+), 25 deletions(-) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp index d536e8a..7faa752 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp @@ -68,7 +68,13 @@ void Controller::removeInventoryItem(const std::string& inventoryItemID) util::Map Controller::getServiceBookings() { - return util::Map(); + auto serviceBookings = m_serviceManagementService.getServiceBookings(); + util::Map readOnlyServiceBookings; + for (int iterator = 0; iterator < serviceBookings.getSize(); iterator++) + { + readOnlyServiceBookings.insert(serviceBookings.getKeyAt(iterator), serviceBookings.getValueAt(iterator)); + } + return readOnlyServiceBookings; } util::Map Controller::getServiceBookingsByUser(const std::string userID) @@ -83,11 +89,18 @@ util::Map Controller::getUsers() util::Map Controller::getUsers(util::UserType userType) { - return util::Map(); + auto userMap = m_userManagementService.getUsers(userType); + util::Map readOnlyUserMap; + for (int iterator = 0; iterator < userMap.getSize(); iterator++) + { + readOnlyUserMap.insert(userMap.getKeyAt(iterator), userMap.getValueAt(iterator)); + } + return readOnlyUserMap; } void Controller::createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID) { + m_serviceManagementService.createJobCard(bookingID, technicianID, serviceID); } void Controller::createService(const std::string& name, const util::Vector& inventoryItemIDs, double laborCost) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h index 3aabb58..b22a9b6 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h @@ -2,6 +2,8 @@ #include "Map.h" #include #include "Enums.h" +#include "ServiceManagementService.h" +#include "UserManagementService.h" class Service; class ComboPackage; @@ -14,6 +16,9 @@ class Notification; class Controller { +private: + ServiceManagementService m_serviceManagementService; + UserManagementService m_userManagementService; public: bool login(const std::string& username, const std::string& password); void logout(); diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp index 04e9195..0229352 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp @@ -7,7 +7,7 @@ JobCard::JobCard() m_booking(nullptr), m_service(nullptr), m_technician(nullptr), - m_status(ServiceJobStatus()) {} + m_status(util::ServiceJobStatus()) {} JobCard::JobCard(const std::string& bookingId, ServiceBooking* booking, @@ -15,9 +15,7 @@ JobCard::JobCard(const std::string& bookingId, const std::string& serviceId, const std::string& technicianId, User* technician, - const util::Timestamp& assignedDate, - ServiceJobStatus status, - const util::Timestamp& completionDate + util::ServiceJobStatus status ) : m_id("JC" + std::to_string(++m_uid)), m_bookingId(bookingId), @@ -26,9 +24,9 @@ JobCard::JobCard(const std::string& bookingId, m_serviceId(serviceId), m_technicianId(technicianId), m_technician(technician), - m_assignedDate(assignedDate), + m_assignedDate(util::Timestamp()), m_status(status), - m_completionDate(completionDate) {} + m_completionDate(util::Timestamp()) {} const std::string& JobCard::getId() const { @@ -70,7 +68,7 @@ const util::Timestamp& JobCard::getAssignedDate() const return m_assignedDate; } -ServiceJobStatus JobCard::getStatus() const +util::ServiceJobStatus JobCard::getStatus() const { return m_status; } @@ -120,7 +118,7 @@ void JobCard::setAssignedDate(const util::Timestamp& assignedDate) m_assignedDate = assignedDate; } -void JobCard::setStatus(ServiceJobStatus status) +void JobCard::setStatus(util::ServiceJobStatus status) { m_status = status; } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h index 15a8a5d..c501e93 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h @@ -1,13 +1,12 @@ #pragma once #include #include "Timestamp.h" +#include "Enums.h" class ServiceBooking; class Service; class User; -enum class ServiceJobStatus : int; - class JobCard { private: @@ -20,7 +19,7 @@ private: std::string m_technicianId; User* m_technician; util::Timestamp m_assignedDate; - ServiceJobStatus m_status; + util::ServiceJobStatus m_status; util::Timestamp m_completionDate; public: @@ -31,9 +30,7 @@ public: const std::string& serviceId, const std::string& technicianId, User* technician, - const util::Timestamp& assignedDate, - ServiceJobStatus status, - const util::Timestamp& completionDate + util::ServiceJobStatus status ); const std::string& getId() const; const std::string& getBookingId() const; @@ -43,7 +40,7 @@ public: const std::string& getTechnicianId() const; User* getTechnician() const; const util::Timestamp& getAssignedDate() const; - ServiceJobStatus getStatus() const; + util::ServiceJobStatus getStatus() const; const util::Timestamp& getCompletionDate() const; void setId(const std::string& id); void setBookingId(const std::string& bookingId); @@ -53,6 +50,6 @@ public: void setTechnicianId(const std::string& technicianId); void setTechnician(User* technician); void setAssignedDate(const util::Timestamp& assignedDate); - void setStatus(ServiceJobStatus status); + void setStatus(util::ServiceJobStatus status); void setCompletionDate(const util::Timestamp& completionDate); }; \ 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 1fdfaf0..aeb7f4d 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp @@ -18,7 +18,7 @@ ServiceBooking::ServiceBooking( const std::string& vehicleBrand, const std::string& vehicleModel, const std::string& assignedTechnicianId, - const std::string& assignedTechnician, + const User* assignedTechnician, double discountPercentage ) : m_id("SRV" + std::to_string(++m_uid)), @@ -80,7 +80,7 @@ const std::string& ServiceBooking::getAssignedTechnicianId() const return m_assignedTechnicianId; } -const std::string& ServiceBooking::getAssignedTechnician() const +const User* ServiceBooking::getAssignedTechnician() const { return m_assignedTechnician; } @@ -135,7 +135,7 @@ void ServiceBooking::setAssignedTechnicianId(const std::string& assignedTechnici m_assignedTechnicianId = assignedTechnicianId; } -void ServiceBooking::setAssignedTechnician(const std::string& assignedTechnician) +void ServiceBooking::setAssignedTechnician(const User* assignedTechnician) { m_assignedTechnician = assignedTechnician; } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h index 5ecc1b0..8996d36 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h @@ -19,7 +19,7 @@ private: std::string m_vehicleBrand; std::string m_vehicleModel; std::string m_assignedTechnicianId; - std::string m_assignedTechnician; + const User* m_assignedTechnician; double m_discountPercentage; public: ServiceBooking(); @@ -34,7 +34,7 @@ public: const std::string& vehicleBrand, const std::string& vehicleModel, const std::string& assignedTechnicianId, - const std::string& assignedTechnician, + const User* assignedTechnician, double discountPercentage ); const std::string& getId() const; @@ -46,7 +46,7 @@ public: const std::string& getVehicleBrand() const; const std::string& getVehicleModel() const; const std::string& getAssignedTechnicianId() const; - const std::string& getAssignedTechnician() const; + const User* getAssignedTechnician() const; double getDiscountPercentage() const; void setId(const std::string& id); void setStatus(const util::ServiceJobStatus& status); @@ -57,6 +57,6 @@ public: void setVehicleBrand(const std::string& vehicleBrand); void setVehicleModel(const std::string& vehicleModel); void setAssignedTechnicianId(const std::string& assignedTechnicianId); - void setAssignedTechnician(const std::string& assignedTechnician); + void setAssignedTechnician(const User* assignedTechnician); void setDiscountPercentage(double discountPercentage); }; \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp index 156c12b..0bc77b9 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp @@ -1 +1,70 @@ #include "ServiceManagementService.h" +#include "UserManagementService.h" +#include "ServiceBooking.h" +#include "Factory.h" +#include "JobCard.h" +#include "Timestamp.h" +#include "Service.h" +#include "InventoryItem.h" + +util::Map ServiceManagementService::getServiceBookings() +{ + return m_dataStore.getServiceBookings(); +} + +ServiceBooking* ServiceManagementService::getServiceBooking(const std::string& serviceID) +{ + auto currentServiceBookings = getServiceBookings(); + for (int iterator = 0; iterator < currentServiceBookings.getSize(); iterator++) + { + if (currentServiceBookings.getValueAt(iterator)->getId() == serviceID) + { + return currentServiceBookings.getValueAt(iterator); + } + } + return nullptr; +} + +void ServiceManagementService::createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID) +{ + UserManagementService m_userManagementService; + ServiceBooking* currentBooking = getServiceBooking(bookingID); + auto& currentJobCards = m_dataStore.getJobCards(); + if (currentBooking == nullptr) + { + throw std::runtime_error("Service Booking not available"); + } + auto& currentServices = currentBooking->getServices(); + if (currentServices.find(serviceID) == -1) + { + throw std::runtime_error("Invalid service Id"); + } + Service* currentService = currentServices.getValueAt(currentServices.find(serviceID)); + User* selectedTechnician = m_userManagementService.getUser(technicianID); + if (selectedTechnician == nullptr) + { + throw std::runtime_error("Technician not available"); + } + auto& inventoryItems = currentService->getRequiredInventoryItems(); + for (int iterator = 0; iterator < inventoryItems.getSize(); iterator++) + { + InventoryItem* currentInventoryItem = inventoryItems.getValueAt(iterator); + if (currentInventoryItem->getQuantity() == 0) + { + std::string errorMessage = "Failed to create job card, " + currentInventoryItem->getPartName() + " is out of stock."; + throw std::runtime_error(errorMessage); + } + else + { + int currentStockQuantity = currentInventoryItem->getQuantity(); + currentInventoryItem->setQuantity(currentStockQuantity - 1); + } + } + currentBooking->setAssignedTechnician(selectedTechnician); + currentBooking->setAssignedTechnicianId(selectedTechnician->getId()); + std::string title = "Job card created"; + std::string message = "Job card created for the service and you are assigned for that."; + JobCard* jobCard = Factory::getObject(bookingID, currentBooking, currentService, serviceID, technicianID, selectedTechnician, util::ServiceJobStatus::STARTED); + currentJobCards.insert(jobCard->getId(), jobCard); + sendNotification(selectedTechnician,title, message); +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h index 85e05ed..ab5723e 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h @@ -22,6 +22,7 @@ public: void purchaseComboPackage(const std::string& comboPackageID, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel); util::Map getServiceBookings(); util::Map getServiceBookings(const std::string& customerID); + ServiceBooking* getServiceBooking(const std::string& serviceID); void createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID); void createService(const std::string& name, const util::Vector& inventoryItemIDs, double laborCost); void removeService(const std::string& serviceID); diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp index 2a5bd9e..4f8adb2 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp @@ -1 +1,31 @@ #include "UserManagementService.h" +#include "User.h" + +util::Map UserManagementService::getUsers(util::UserType type) +{ + util::Map& currentUsers = m_dataStore.getUsers(); + util::Map filteredUsersMap; + for (int iterator = 0; iterator < currentUsers.getSize(); iterator++) + { + User* currentUser = currentUsers.getValueAt(iterator); + if (currentUser->getUserType() == type) + { + filteredUsersMap.insert(currentUser->getId(), currentUser); + } + } + return filteredUsersMap; +} + +User* UserManagementService::getUser(const std::string& userID) +{ + util::Map& currentUsers = m_dataStore.getUsers(); + for (int iterator = 0; iterator < currentUsers.getSize(); iterator++) + { + User* currentUser = currentUsers.getValueAt(iterator); + if (currentUser->getId() == userID) + { + return currentUser; + } + } + return nullptr; +} diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h index 24bbdcd..5353467 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h @@ -24,6 +24,7 @@ namespace util enum class ServiceJobStatus { + PENDING, STARTED, COMPLETED }; @@ -125,6 +126,8 @@ namespace util return "STARTED"; case ServiceJobStatus::COMPLETED: return "COMPLETED"; + case ServiceJobStatus::PENDING: + return "STARTED"; } throw std::invalid_argument("Invalid ServiceJobStatus"); } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp index 0432f3c..e0319ff 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp @@ -1,6 +1,10 @@ +#include #include "AdminMenu.h" #include "InputHelper.h" #include "OutputHelper.h" +#include "ServiceBooking.h" +#include "Enums.h" +#include "Service.h" void AdminMenu::showMenu() { @@ -56,8 +60,147 @@ void AdminMenu::checkStockAvailability() { } +static bool listServiceBookings(util::Map& currentBookings, int& bookingsSize, util::Map& serviceBookingsMap) +{ + int currentIndex = 1; + bool hasPendingService = false; + std::cout << std::left + << std::setw(10) << "Index" + << std::setw(10) << "ID" + << std::setw(12) << "Status" + << std::setw(12) << "CustID" + << std::setw(20) << "Customer" + << std::setw(15) << "VehicleNo" + << std::setw(15) << "Brand" + << std::setw(15) << "Model" + << std::setw(20) << "Technician" + << std::setw(15) << "TechID" + << std::endl; + for (int iterator = 0; iterator < bookingsSize; iterator++) + { + const ServiceBooking* currentBooking = currentBookings.getValueAt(iterator); + if (currentBooking && currentBooking->getStatus() == util::ServiceJobStatus::PENDING) + { + hasPendingService = true; + std::cout << std::left + << std::setw(10) << currentIndex + << std::setw(10) << currentBooking->getId() + << std::setw(12) << util::getServiceJobStatusString(currentBooking->getStatus()) + << std::setw(12) << currentBooking->getCustomerId() + << std::setw(20) << currentBooking->getCustomer()->getName() + << std::setw(15) << currentBooking->getVehicleNumber() + << std::setw(15) << currentBooking->getVehicleBrand() + << std::setw(15) << currentBooking->getVehicleModel() + << std::setw(20) << (currentBooking->getAssignedTechnician() == nullptr ? "Null" : currentBooking->getAssignedTechnician()->getName()) + << std::setw(15) << (currentBooking->getAssignedTechnicianId().empty() ? "Null" : currentBooking->getAssignedTechnicianId()) + << std::endl; + serviceBookingsMap.insert(currentIndex++, currentBooking); + } + } + if (!hasPendingService) + { + std::cout << "No pending service available." << std::endl; + return false; + } + return true; +} + +static const ServiceBooking* selectPendingServiceBookings(util::Map& serviceBookingsMap) +{ + int userInputIndex; + std::cout << "Enter a valid service index: "; + util::read(userInputIndex); + if (serviceBookingsMap.find(userInputIndex) != -1) + { + return serviceBookingsMap.getValueAt(userInputIndex); + } + else + { + std::cout << "Enter a valid index."; + return nullptr; + } +} + +static void listAvailableTechnicians( util::Map currentAvailableTechnicians, int numberOfTechnicians, util::Map& currentAvailableTechniciansMap) +{ + bool hasTechnicians = false; + int currentIndex = 1; + std::cout << std::left + << std::setw(6) << "Index" + << std::setw(15) << "Technician ID" + << std::setw(20) << "Name" + << std::endl; + for (int iterator = 0; iterator < numberOfTechnicians; iterator++) + { + const User* currentTechnician = currentAvailableTechnicians.getValueAt(iterator); + if (currentTechnician->getState() == util::State::INACTIVE) + { + continue; + } + hasTechnicians = true; + std::cout << std::left + << std::setw(6) << currentIndex + << std::setw(15) << currentTechnician->getId() + << std::setw(20) << currentTechnician->getName() + << std::endl; + currentAvailableTechniciansMap.insert(currentIndex++, currentTechnician); + } + if (!hasTechnicians) + { + std::cout << "No technicians currently available."; + } +} + +static const User* selectTechnician(util::Map& currentAvailableTechniciansMap) +{ + int userInputIndex; + util::read(userInputIndex); + if (currentAvailableTechniciansMap.find(userInputIndex) != -1) + { + return currentAvailableTechniciansMap.getValueAt(userInputIndex); + } + else + { + std::cout << "Enter a valid index."; + return nullptr; + } +} + void AdminMenu::assignJob() { + util::clear(); + std::string selectedService; + bool hasPendingService = false; + auto currentBookings = m_controller.getServiceBookings(); + auto availableTechnicians = m_controller.getUsers(util::UserType::TECHNICIAN); + int bookingsSize = currentBookings.getSize(); + util::Map serviceBookingsMap; + util::Map currentAvailableTechniciansMap; + if (listServiceBookings(currentBookings, bookingsSize, serviceBookingsMap)) + { + const ServiceBooking* selectedService = selectPendingServiceBookings(serviceBookingsMap); + if (selectedService) + { + if (availableTechnicians.getSize() != 0) + { + listAvailableTechnicians(availableTechnicians, availableTechnicians.getSize(), currentAvailableTechniciansMap); + const User* selectedTechnician = selectTechnician(currentAvailableTechniciansMap); + if (selectedTechnician) + { + auto& servicesInBooking = selectedService->getServices(); + for (int iterator = 0; iterator < servicesInBooking.getSize(); iterator++) + { + m_controller.createJobCard(selectedService->getId(), selectedTechnician->getId(), servicesInBooking.getValueAt(iterator)->getId()); + } + } + } + else + { + std::cout << "No technicians are currently available."; + } + } + } + } void AdminMenu::createService() From e7f1b51d05e04b8e6d9b9e53502b2994653ac1a3 Mon Sep 17 00:00:00 2001 From: Jissin Mathew Date: Tue, 19 May 2026 20:29:19 +0530 Subject: [PATCH 02/11] Implement Create Service for admin SER002: Create Service 1. Added integration between Controller and ServiceManagementService to support service creation. 2. Implemented ServiceManagementService::createService with validation for duplicate service IDs and insertion into datastore. 3. Enhanced AdminMenu with selectInventoryItems helper to display inventory in tabular format, allow selection, and handle exit condition. 4. Updated AdminMenu::createService to prompt for service name, allow inventory selection, capture labour cost, and create service via Controller. Acceptance Criteria: 1. Admin enters new service name. 2. Admin selects required parts for the services. 3. Service created and visible to customers. Precondition: 1. Admin is logged into the system. 2. Inventory contains at least one active item. 3. Datastore is available for storing services. Steps: 1. Navigate to Admin menu and choose "Create Service". - Verify that the system prompts for service name. 2. Select inventory items from the tabular list. - Verify that inactive items are skipped and active items can be added. 3. Enter labour cost and confirm creation. - Verify that the service is created successfully and stored in datastore. 4. Check customer view. - Verify that the newly created service is visible to customers. Sreeja Reghukumar, please review --- .../controllers/Controller.cpp | 3 +- .../controllers/Controller.h | 4 + .../services/ServiceManagementService.cpp | 17 ++++ .../views/AdminMenu.cpp | 79 +++++++++++++++++++ 4 files changed, 102 insertions(+), 1 deletion(-) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp index d536e8a..15de314 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp @@ -1,4 +1,5 @@ #include "Controller.h" +#include "InventoryItem.h" bool Controller::login(const std::string& username, const std::string& password) { @@ -50,7 +51,6 @@ void Controller::purchaseComboPackage(const std::string& comboPackageID, const s util::Map Controller::getInventoryItems() { - return util::Map(); } const InventoryItem* Controller::getInventoryItem(const std::string& inventoryItemID) @@ -92,6 +92,7 @@ void Controller::createJobCard(const std::string& bookingID, const std::string& void Controller::createService(const std::string& name, const util::Vector& inventoryItemIDs, double laborCost) { + m_serviceManagementService.createService(name, inventoryItemIDs, laborCost); } void Controller::removeService(const std::string& serviceID) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h index 3aabb58..050d65b 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h @@ -2,6 +2,8 @@ #include "Map.h" #include #include "Enums.h" +#include "InventoryManagementService.h" +#include "ServiceManagementService.h" class Service; class ComboPackage; @@ -14,6 +16,8 @@ class Notification; class Controller { +private: + ServiceManagementService m_serviceManagementService; public: bool login(const std::string& username, const std::string& password); void logout(); diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp index 156c12b..a29c200 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp @@ -1 +1,18 @@ #include "ServiceManagementService.h" +#include "Factory.h" +#include "Service.h" + +void ServiceManagementService::createService(const std::string& name, const util::Vector& inventoryItemIDs, double laborCost) +{ + Service* newService = Factory::getObject(name, inventoryItemIDs, laborCost); + if (newService == nullptr) + { + throw std::runtime_error("Unable to create new service."); + } + util::Map& currentServices = m_dataStore.getServices(); + if (currentServices.find(newService->getId()) != -1) + { + throw std::runtime_error("Service with this ID Already exists."); + } + currentServices.insert(newService->getId(), newService); +} \ 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 0432f3c..eb0dc01 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp @@ -1,6 +1,8 @@ +#include #include "AdminMenu.h" #include "InputHelper.h" #include "OutputHelper.h" +#include "InventoryItem.h" void AdminMenu::showMenu() { @@ -60,8 +62,85 @@ void AdminMenu::assignJob() { } +static void selectInventoryItems(util::Map& currentInventoryItems, util::Vector& selectedInventoryItems) +{ + bool doRun = true, hasInventoryItems = false; + util::Map currentInventoryMap; + int currentIndex = 1; + int choice; + if (currentInventoryItems.getSize() == 0) + { + std::cout << "Inventory empty."; + } + while (doRun) + { + bool hasInventoryItems = false; + int currentIndex = 1; + currentInventoryMap.clear(); + std::cout << std::left + << std::setw(6) << "Index" + << std::setw(12) << "Item ID" + << std::setw(20) << "Part Name" + << std::setw(10) << "Price" + << std::setw(10) << "Quantity" + << std::endl; + for (int iterator = 0; iterator < currentInventoryItems.getSize(); iterator++) + { + const InventoryItem* currentInventoryItem = currentInventoryItems.getValueAt(iterator); + if (currentInventoryItem->getState() == util::State::INACTIVE) + { + continue; + } + std::cout << std::left + << std::setw(6) << currentIndex + << std::setw(12) << currentInventoryItem->getId() + << std::setw(20) << currentInventoryItem->getPartName() + << std::setw(10) << currentInventoryItem->getPrice() + << std::setw(10) << currentInventoryItem->getQuantity() + << std::endl; + + hasInventoryItems = true; + currentInventoryMap.insert(currentIndex++, currentInventoryItem); + } + if (!hasInventoryItems) + { + std::cout << "No items present in the inventory." << std::endl; + doRun = false; + break; + } + std::cout << "Select the item (Index) or enter -1 to exit: "; + util::read(choice); + + if (choice == -1) + { + doRun = false; + } + else if (currentInventoryMap.find(choice) != -1) + { + selectedInventoryItems.push_back(currentInventoryMap.getValueAt(choice)->getId()); + std::cout << "Item added successfully." << std::endl; + } + else + { + std::cout << "Enter a valid integer." << std::endl; + } + } +} + void AdminMenu::createService() { + util::clear(); + std::string serviceName; + double labourCost; + std::cout << "Enter the service name: "; + util::read(serviceName); + util::Map currentInventoryItems = m_controller.getInventoryItems(); + util::Vector selectedInventoryItems; + selectInventoryItems(currentInventoryItems,selectedInventoryItems); + std::cout << "Enter the labour cost: "; + util::read(labourCost); + m_controller.createService(serviceName, selectedInventoryItems, labourCost); + std::cout << "Service created sucessfully.\n"; } void AdminMenu::removeService() From 70e1ef66d47c9f36057e004f190846f5f1a56caf Mon Sep 17 00:00:00 2001 From: Jissin Mathew Date: Tue, 19 May 2026 21:36:14 +0530 Subject: [PATCH 03/11] Implement Remove Service for admin SER003: Remove Service 1. Added integration between Controller and ServiceManagementService to support service removal. 2. Implemented ServiceManagementService::removeService with validation for service existence and marking as INACTIVE. 3. Enhanced Controller::getServices to return a read-only map of services for safe UI access. 4. Added AdminMenu::selectServicesToRemove helper to list active services in tabular format and capture user choice. 5. Updated AdminMenu::removeService to prompt for service selection, delegate removal to Controller, and display success/failure messages. Acceptance Criteria: 1. Admin selects service ID. 2. System confirms deletion. 3. Service removed from customer menu. Precondition: 1. Admin is logged into the system. 2. At least one active service exists in the datastore. 3. Customer menu displays available services. Steps: 1. Navigate to Admin menu and choose "Remove Service". - Verify that the system lists active services in tabular format. 2. Select a service ID from the list. - Verify that the system confirms deletion. 3. Check customer menu. - Verify that the removed service no longer appears. Sreeja Reghukumar, please review --- .../controllers/Controller.cpp | 10 +++- .../controllers/Controller.h | 3 + .../services/ServiceManagementService.cpp | 20 +++++++ .../views/AdminMenu.cpp | 60 +++++++++++++++++++ 4 files changed, 92 insertions(+), 1 deletion(-) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp index d536e8a..eafd451 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp @@ -1,4 +1,5 @@ #include "Controller.h" +#include "Service.h" bool Controller::login(const std::string& username, const std::string& password) { @@ -32,7 +33,13 @@ void Controller::updateUserDetails(const std::string& email, const std::string& util::Map Controller::getServices() { - return util::Map(); + util::Map currentServices = m_serviceManagementService.getServices(); + util::Map readOnlyServices; + for (int iterator = 0; iterator < currentServices.getSize(); iterator++) + { + readOnlyServices.insert(currentServices.getValueAt(iterator)->getId(), currentServices.getValueAt(iterator)); + } + return readOnlyServices; } util::Map Controller::getComboPackages() @@ -96,6 +103,7 @@ void Controller::createService(const std::string& name, const util::Vector Controller::getJobCardsByUser() diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h index 3aabb58..8512598 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h @@ -2,6 +2,7 @@ #include "Map.h" #include #include "Enums.h" +#include "ServiceManagementService.h" class Service; class ComboPackage; @@ -14,6 +15,8 @@ class Notification; class Controller { +private: + ServiceManagementService m_serviceManagementService; public: bool login(const std::string& username, const std::string& password); void logout(); diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp index 156c12b..084d81b 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp @@ -1 +1,21 @@ #include "ServiceManagementService.h" +#include "Service.h" +#include "Enums.h" + +util::Map ServiceManagementService::getServices() +{ + return m_dataStore.getServices(); +} + +void ServiceManagementService::removeService(const std::string& serviceID) +{ + util::Map currentServices = getServices(); + if (currentServices.find(serviceID) != -1) + { + currentServices.getValueAt(currentServices.find(serviceID))->setState(util::State::INACTIVE); + } + else + { + throw std::runtime_error("Service not found."); + } +} \ 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 0432f3c..5567e49 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp @@ -1,4 +1,6 @@ +#include #include "AdminMenu.h" +#include "Service.h" #include "InputHelper.h" #include "OutputHelper.h" @@ -64,8 +66,66 @@ void AdminMenu::createService() { } +static std::string selectServicesToRemove(util::Map currentServices) +{ + util::Map currentServicesMap; + bool hasServices = false; + int currentIndex = 1, choice; + std::cout << std::left + << std::setw(6) << "Index" + << std::setw(12) << "Service ID" + << std::setw(20) << "Name" + << std::setw(10) << "Labor Cost" + << std::endl; + for (int iterator = 0; iterator < currentServices.getSize(); iterator++) + { + const Service* currentService = currentServices.getValueAt(iterator); + if (currentService->getState() == util::State::INACTIVE) + { + continue; + } + std::cout << std::left + << std::setw(6) << currentIndex + << std::setw(12) << currentService->getId() + << std::setw(20) << currentService->getName() + << std::setw(10) << currentService->getLaborCost() + << std::endl; + hasServices = true; + currentServicesMap.insert(currentIndex++, currentService); + } + if (!hasServices) + { + std::cout << "No services currently available." << std::endl; + return ""; + } + std::cout << "Enter your choice: "; + util::read(choice); + if (currentServicesMap.find(choice) != -1) + { + return currentServicesMap.getValueAt(currentServicesMap.find(choice))->getId(); + } + else + { + std::cout << "Invalid choice." << std::endl; + return ""; + } +} + void AdminMenu::removeService() { + util::clear(); + std::string selectedServiceID; + util::Map currentServices = m_controller.getServices(); + selectedServiceID = selectServicesToRemove(currentServices); + if (selectedServiceID != "") + { + m_controller.removeService(selectedServiceID); + std::cout << "Service removed sucessfully."; + } + else + { + std::cout << "Failed to remove service."; + } } void AdminMenu::addTechnician() From fc7bb2569b9bdaa84473d4a1cb1e8e68c802f989 Mon Sep 17 00:00:00 2001 From: Jissin Mathew Date: Tue, 19 May 2026 22:54:55 +0530 Subject: [PATCH 04/11] Implement View Service History SER004: View Service History 1. Added integration between Controller and ServiceManagementService to fetch service bookings by customer ID. 2. Enhanced ServiceBooking model to store technician as a User* instead of a string for richer details. 3. Implemented Controller::getServiceBookingsByUser to return a read-only map of bookings for safe access. 4. Updated CustomerMenu::viewServiceHistory to display bookings in tabular format with aligned columns. 5. Added condition check to show technician name if assigned, otherwise display "Not Assigned". 6. Included booking status and discount percentage in the service history output. Acceptance Criteria: 1. System should fetch real-time status. 2. Status should update automatically when technician changes it. 3. Customer should be able to view history. Precondition: 1. Customer is logged into the console application. 2. At least one active service booking exists for the customer. 3. Technician has permission to update booking status. Steps: 1. Navigate to Customer menu and choose "View Service History". - Verify that the console displays current booking status along with technician assignment. 2. Technician updates the status of a booking. - Verify that the console view reflects the updated status automatically. 3. Customer views service history again. - Verify that the history shows the latest status changes. Sreeja Reghukumar, please review --- .../controllers/Controller.cpp | 9 +++- .../controllers/Controller.h | 3 ++ .../models/ServiceBooking.cpp | 6 +-- .../models/ServiceBooking.h | 8 ++-- .../services/ServiceManagementService.cpp | 24 +++++++++++ .../views/CustomerMenu.cpp | 42 +++++++++++++++++++ 6 files changed, 84 insertions(+), 8 deletions(-) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp index d536e8a..e711591 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp @@ -1,4 +1,5 @@ #include "Controller.h" +#include "ServiceBooking.h" bool Controller::login(const std::string& username, const std::string& password) { @@ -73,7 +74,13 @@ util::Map Controller::getServiceBookings() util::Map Controller::getServiceBookingsByUser(const std::string userID) { - return util::Map(); + util::Map readOnlyServiceBookingsByUserMap; + util::Map currentServiceBookingsByUser = m_serviceManagementService.getServiceBookings(userID); + for (int iterator = 0; iterator < currentServiceBookingsByUser.getSize(); iterator++) + { + readOnlyServiceBookingsByUserMap.insert(currentServiceBookingsByUser.getValueAt(iterator)->getId(), currentServiceBookingsByUser.getValueAt(iterator)); + } + return readOnlyServiceBookingsByUserMap; } util::Map Controller::getUsers() diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h index 3aabb58..8512598 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h @@ -2,6 +2,7 @@ #include "Map.h" #include #include "Enums.h" +#include "ServiceManagementService.h" class Service; class ComboPackage; @@ -14,6 +15,8 @@ class Notification; class Controller { +private: + ServiceManagementService m_serviceManagementService; public: bool login(const std::string& username, const std::string& password); void logout(); diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp index 1fdfaf0..aeb7f4d 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp @@ -18,7 +18,7 @@ ServiceBooking::ServiceBooking( const std::string& vehicleBrand, const std::string& vehicleModel, const std::string& assignedTechnicianId, - const std::string& assignedTechnician, + const User* assignedTechnician, double discountPercentage ) : m_id("SRV" + std::to_string(++m_uid)), @@ -80,7 +80,7 @@ const std::string& ServiceBooking::getAssignedTechnicianId() const return m_assignedTechnicianId; } -const std::string& ServiceBooking::getAssignedTechnician() const +const User* ServiceBooking::getAssignedTechnician() const { return m_assignedTechnician; } @@ -135,7 +135,7 @@ void ServiceBooking::setAssignedTechnicianId(const std::string& assignedTechnici m_assignedTechnicianId = assignedTechnicianId; } -void ServiceBooking::setAssignedTechnician(const std::string& assignedTechnician) +void ServiceBooking::setAssignedTechnician(const User* assignedTechnician) { m_assignedTechnician = assignedTechnician; } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h index 5ecc1b0..79d909f 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h @@ -19,7 +19,7 @@ private: std::string m_vehicleBrand; std::string m_vehicleModel; std::string m_assignedTechnicianId; - std::string m_assignedTechnician; + const User* m_assignedTechnician; double m_discountPercentage; public: ServiceBooking(); @@ -34,7 +34,7 @@ public: const std::string& vehicleBrand, const std::string& vehicleModel, const std::string& assignedTechnicianId, - const std::string& assignedTechnician, + const User* assignedTechnician, double discountPercentage ); const std::string& getId() const; @@ -46,7 +46,7 @@ public: const std::string& getVehicleBrand() const; const std::string& getVehicleModel() const; const std::string& getAssignedTechnicianId() const; - const std::string& getAssignedTechnician() const; + const User* getAssignedTechnician() const; double getDiscountPercentage() const; void setId(const std::string& id); void setStatus(const util::ServiceJobStatus& status); @@ -57,6 +57,6 @@ public: void setVehicleBrand(const std::string& vehicleBrand); void setVehicleModel(const std::string& vehicleModel); void setAssignedTechnicianId(const std::string& assignedTechnicianId); - void setAssignedTechnician(const std::string& assignedTechnician); + void setAssignedTechnician(const User*); void setDiscountPercentage(double discountPercentage); }; \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp index 156c12b..cfc28c5 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp @@ -1 +1,25 @@ #include "ServiceManagementService.h" +#include "ServiceBooking.h" + +util::Map ServiceManagementService::getServiceBookings() +{ + return m_dataStore.getServiceBookings(); +} + +util::Map ServiceManagementService::getServiceBookings(const std::string& customerID) +{ + util::Map currentServiceBookings = getServiceBookings(); + util::Map currentUserServiceBookings; + if (currentServiceBookings.getSize() != 0) + { + for (int iterator = 0; iterator < currentServiceBookings.getSize(); iterator++) + { + auto currentServiceBooking = currentServiceBookings.getValueAt(iterator); + if (currentServiceBooking->getCustomerId() == customerID) + { + currentUserServiceBookings.insert(currentServiceBooking->getId(), currentServiceBooking); + } + } + } + return currentUserServiceBookings; +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp index 047f471..f2444b1 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp @@ -1,6 +1,10 @@ +#include #include "CustomerMenu.h" #include "InputHelper.h" #include "OutputHelper.h" +#include "User.h" +#include "ServiceBooking.h" +#include "Enums.h" void CustomerMenu::showMenu() { @@ -53,6 +57,44 @@ void CustomerMenu::selectComboPackage() void CustomerMenu::viewServiceHistory() { + util::clear(); + bool hasServiceHistory = false; + const User* currentUser = m_controller.getAuthenticatedUser(); + std::string currentUserID = currentUser->getId(); + util::Map serviceBookingsByCurrentUser = m_controller.getServiceBookingsByUser(currentUserID); + if (serviceBookingsByCurrentUser.getSize() != 0) + { + std::cout << std::left + << std::setw(12) << "Booking ID" + << std::setw(20) << "Technician" + << std::setw(15) << "Vehicle Brand" + << std::setw(15) << "Vehicle Number" + << std::setw(15) << "Vehicle Model" + << std::setw(10) << "Discount %" + << std::setw(12) << "Status" + << std::endl; + for (int iterator = 0; iterator < serviceBookingsByCurrentUser.getSize(); iterator++) + { + const ServiceBooking* currentBooking = serviceBookingsByCurrentUser.getValueAt(iterator); + std::string technicianName = currentBooking->getAssignedTechnician() == nullptr + ? "Not Assigned" + : currentBooking->getAssignedTechnician()->getName(); + std::cout << std::left + << std::setw(12) << currentBooking->getId() + << std::setw(20) << technicianName + << std::setw(15) << currentBooking->getVehicleBrand() + << std::setw(15) << currentBooking->getVehicleNumber() + << std::setw(15) << currentBooking->getVehicleModel() + << std::setw(10) << currentBooking->getDiscountPercentage() + << std::setw(12) << util::getServiceJobStatusString(currentBooking->getStatus()) + << std::endl; + hasServiceHistory = true; + } + } + if (!hasServiceHistory) + { + std::cout << "No history available." << std::endl; + } } void CustomerMenu::completePayments() From 8162a2fe3d5a9f76a6fa9de14fc6964d0c17bf8d Mon Sep 17 00:00:00 2001 From: Jissin Mathew Date: Wed, 20 May 2026 12:05:39 +0530 Subject: [PATCH 05/11] Implement Update Service Status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SER005: Update Service Status 1. Integrated Controller with ServiceManagementService to support job completion workflow. 2. Implemented ServiceManagementService::completeJob with validation for technician assignment, job existence, and status transition. 3. Enhanced TechnicianMenu with job selection helper to display assigned jobs, allow index-based selection, and handle invalid choices. 4. Updated TechnicianMenu::completeJob to mark job as completed via Controller and provide user feedback. 5. Added logic to check if all jobs in a booking are completed, triggering invoice generation and customer notification. Acceptance Criteria: 1. Status updates are visible to customers immediately after technician marks job as completed. Precondition: 1. Technician is logged into the system. 2. At least one active job card is assigned to the technician. 3. Datastore contains valid service bookings linked to jobs. Steps: 1. Navigate to Technician menu and choose "Complete Job". - Verify that the system lists active jobs with index-based selection. 2. Select a job card by index. - Verify that the job status changes from STARTED to COMPLETED. 3. Check customer view. - Verify that the updated status is reflected in the customer’s booking history. 4. If all jobs in the booking are completed: - Verify that an invoice is generated and a notification is sent to the customer. Sreeja Reghukumar, please review --- .../controllers/Controller.cpp | 12 ++- .../controllers/Controller.h | 3 + .../models/JobCard.cpp | 8 +- .../models/JobCard.h | 11 ++- .../services/ServiceManagementService.cpp | 88 +++++++++++++++++++ .../views/TechnicianMenu.cpp | 64 ++++++++++++++ 6 files changed, 175 insertions(+), 11 deletions(-) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp index d536e8a..0465e4b 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp @@ -1,4 +1,5 @@ #include "Controller.h" +#include "JobCard.h" bool Controller::login(const std::string& username, const std::string& password) { @@ -100,11 +101,20 @@ void Controller::removeService(const std::string& serviceID) util::Map Controller::getJobCardsByUser() { - return util::Map(); + const User* currentUser = getAuthenticatedUser(); + auto jobCardsAssignedToTechnician = m_serviceManagementService.getJobCards(currentUser->getId()); + util::Map readOnlyJobCardMap; + for (int iterator = 0; iterator < jobCardsAssignedToTechnician.getSize(); iterator++) + { + JobCard* currentJobCard = jobCardsAssignedToTechnician.getValueAt(iterator); + readOnlyJobCardMap.insert(currentJobCard->getId(), currentJobCard); + } + return readOnlyJobCardMap; } void Controller::completeJob(const std::string& jobID) { + m_serviceManagementService.completeJob(jobID); } void Controller::removeUser(const std::string& userID) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h index 3aabb58..8512598 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h @@ -2,6 +2,7 @@ #include "Map.h" #include #include "Enums.h" +#include "ServiceManagementService.h" class Service; class ComboPackage; @@ -14,6 +15,8 @@ class Notification; class Controller { +private: + ServiceManagementService m_serviceManagementService; public: bool login(const std::string& username, const std::string& password); void logout(); diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp index 04e9195..b9f1eee 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp @@ -7,7 +7,7 @@ JobCard::JobCard() m_booking(nullptr), m_service(nullptr), m_technician(nullptr), - m_status(ServiceJobStatus()) {} + m_status(util::ServiceJobStatus()) {} JobCard::JobCard(const std::string& bookingId, ServiceBooking* booking, @@ -16,7 +16,7 @@ JobCard::JobCard(const std::string& bookingId, const std::string& technicianId, User* technician, const util::Timestamp& assignedDate, - ServiceJobStatus status, + util::ServiceJobStatus status, const util::Timestamp& completionDate ) : m_id("JC" + std::to_string(++m_uid)), @@ -70,7 +70,7 @@ const util::Timestamp& JobCard::getAssignedDate() const return m_assignedDate; } -ServiceJobStatus JobCard::getStatus() const +util::ServiceJobStatus JobCard::getStatus() const { return m_status; } @@ -120,7 +120,7 @@ void JobCard::setAssignedDate(const util::Timestamp& assignedDate) m_assignedDate = assignedDate; } -void JobCard::setStatus(ServiceJobStatus status) +void JobCard::setStatus(util::ServiceJobStatus status) { m_status = status; } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h index 15a8a5d..9bd78aa 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h @@ -1,13 +1,12 @@ #pragma once #include #include "Timestamp.h" +#include "Enums.h" class ServiceBooking; class Service; class User; -enum class ServiceJobStatus : int; - class JobCard { private: @@ -20,7 +19,7 @@ private: std::string m_technicianId; User* m_technician; util::Timestamp m_assignedDate; - ServiceJobStatus m_status; + util::ServiceJobStatus m_status; util::Timestamp m_completionDate; public: @@ -32,7 +31,7 @@ public: const std::string& technicianId, User* technician, const util::Timestamp& assignedDate, - ServiceJobStatus status, + util::ServiceJobStatus status, const util::Timestamp& completionDate ); const std::string& getId() const; @@ -43,7 +42,7 @@ public: const std::string& getTechnicianId() const; User* getTechnician() const; const util::Timestamp& getAssignedDate() const; - ServiceJobStatus getStatus() const; + util::ServiceJobStatus getStatus() const; const util::Timestamp& getCompletionDate() const; void setId(const std::string& id); void setBookingId(const std::string& bookingId); @@ -53,6 +52,6 @@ public: void setTechnicianId(const std::string& technicianId); void setTechnician(User* technician); void setAssignedDate(const util::Timestamp& assignedDate); - void setStatus(ServiceJobStatus status); + void setStatus(util::ServiceJobStatus status); void setCompletionDate(const util::Timestamp& completionDate); }; \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp index 156c12b..dfa4d3b 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp @@ -1 +1,89 @@ #include "ServiceManagementService.h" +#include "AuthenticationManagementService.h" +#include "PaymentManagementService.h" +#include "NotificationManagementService.h" +#include "JobCard.h" +#include "User.h" +#include "Enums.h" +#include "ServiceBooking.h" +#include "Service.h" + +util::Map ServiceManagementService::getJobCards(const std::string& technicianID) +{ + util::Map jobCards = m_dataStore.getJobCards(); + util::Map technicianJobCards; + for (int iterator = 0; iterator < jobCards.getSize();iterator++) + { + JobCard* currentJobCard = jobCards.getValueAt(iterator); + if (currentJobCard->getTechnicianId() == technicianID) + { + technicianJobCards.insert(currentJobCard->getId(), currentJobCard); + } + } + return technicianJobCards; +} + +static bool hasAllJobCardsinServiceBookingCompleted(std::string bookingId, util::Map& currentAssignedJobs) +{ + for (int iterator = 0; iterator < currentAssignedJobs.getSize(); iterator++) + { + JobCard* currentJob = currentAssignedJobs.getValueAt(iterator); + if (currentJob->getBookingId() == bookingId) + { + if (currentJob->getStatus() == util::ServiceJobStatus::STARTED) + { + return false; + } + } + } + return true; +} + +void ServiceManagementService::completeJob(const std::string& jobID) +{ + AuthenticationManagementService authenticationManagementService; + PaymentManagementService paymentManagementService; + bool jobStatusUpdated = false, serviceBookingCompleted; + JobCard* currentJob; + User* currentTechnician = authenticationManagementService.getAuthenticatedUser(); + if (currentTechnician == nullptr) + { + throw std::runtime_error("Unable to fetch current technician."); + } + util::Map currentAssignedJobs = getJobCards(currentTechnician->getId()); + if (currentAssignedJobs.getSize() == 0) + { + throw std::runtime_error("No job cards assigned to the technician."); + } + if(currentAssignedJobs.find(jobID) != -1) + { + currentJob = currentAssignedJobs.getValueAt(currentAssignedJobs.find(jobID)); + if (currentJob == nullptr) + { + throw std::runtime_error("Unable to fetch current job."); + } + if (currentJob->getStatus() == util::ServiceJobStatus::STARTED) + { + currentJob->setStatus(util::ServiceJobStatus::COMPLETED); + jobStatusUpdated = true; + } + } + else + { + throw std::runtime_error("Failed to complete the job, some error occured or job already completed."); + } + if (!jobStatusUpdated) + { + throw std::runtime_error("Failed to complete the job, some error occured or job already completed."); + } + + serviceBookingCompleted = hasAllJobCardsinServiceBookingCompleted(currentJob->getBookingId(), currentAssignedJobs); + if (serviceBookingCompleted) + { + currentJob->getBooking()->setStatus(util::ServiceJobStatus::COMPLETED); + paymentManagementService.generateInvoice(currentJob->getBooking()); + std::string title = "Service Booking completed,Invoice Generated.\n"; + std::string message = "Services completed for the booking and invoice generated.\n"; + sendNotification(currentJob->getBooking()->getCustomer(), title, message); + } +} \ 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 d6c4d57..2b94fe3 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp @@ -1,6 +1,10 @@ +#include #include "TechnicianMenu.h" #include "InputHelper.h" #include "OutputHelper.h" +#include "JobCard.h" +#include "Enums.h" +#include "Service.h" void TechnicianMenu::showMenu() { @@ -31,8 +35,68 @@ bool TechnicianMenu::handleOperation(int choice) return false; } +static std::string selectJobCardToComplete(util::Map& assignedJobCards, util::Map& incompleteJobCards) +{ + int currentIndex = 1; + int choice; + bool hasIncompleteJobCard = false; + std::cout << std::left + << std::setw(6) << "Index" + << std::setw(12) << "BookingID" + << std::setw(12) << "JobID" + << std::setw(20) << "ServiceName" + << std::setw(12) << "ServiceID" + << std::endl; + for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++) + { + const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator); + if (currentJobCard && (currentJobCard->getStatus() == util::ServiceJobStatus::STARTED)) + { + std::cout << std::left << std::setw(6) << currentIndex + << std::setw(12) << currentJobCard->getBookingId() + << std::setw(12) << currentJobCard->getId() + << std::setw(20) << currentJobCard->getService()->getName() + << std::setw(12) << currentJobCard->getServiceId() + << std::endl; + hasIncompleteJobCard = true; + incompleteJobCards.insert(currentIndex++, currentJobCard); + } + } + if (!hasIncompleteJobCard) + { + std::cout << "No pending jobs are present.\n"; + return ""; + } + std::cout << "Select the Job Card to complete (Index): "; + util::read(choice); + int selectedJobCardIndex = incompleteJobCards.find(choice); + if (selectedJobCardIndex != -1) + { + const JobCard* selectedJobCard = incompleteJobCards.getValueAt(selectedJobCardIndex); + return selectedJobCard->getId(); + } + else + { + std::cout << "Invalid choice.\n"; + return ""; + } +} + void TechnicianMenu::completeJob() { + util::Map assignedJobCards = m_controller.getJobCardsByUser(); + util::Map incompleteJobCards; + std::cout << "Jobs to be completed.\n"; + std::string selectedJobID = selectJobCardToComplete(assignedJobCards, incompleteJobCards); + if (selectedJobID == "") + { + std::cout << "Failed to complete the job.\n"; + } + else + { + m_controller.completeJob(selectedJobID); + std::cout << "Job marked as completed.\n"; + } } void TechnicianMenu::viewNotifications() From cb3bed4050e54dc8a4b300aecb0388733c97a885 Mon Sep 17 00:00:00 2001 From: Jissin Mathew Date: Wed, 20 May 2026 17:48:41 +0530 Subject: [PATCH 06/11] Implement Complete Payments PAY002: Complete Payments 1. Integrated Controller with PaymentManagementService to support payment completion workflow. 2. Implemented PaymentManagementService::completePayment with validation for invoice ID, payment mode, and status update. 3. Enhanced CustomerMenu with helper functions to display pending invoices in tabular format and allow index-based selection. 4. Added CustomerMenu::selectPaymentMode to capture payment mode choice (OFFLINE/ONLINE). 5. Updated CustomerMenu::completePayments to handle invoice selection, payment mode input, and trigger payment completion via Controller. 6. Implemented notification logic to send confirmation to customers upon successful payment. Acceptance Criteria: 1. Payment status marked completed. 2. Confirmation message shown. 3. Confirmation notification sent. Precondition: 1. Customer is logged into the system. 2. At least one pending invoice exists for the customer. 3. Datastore is available for storing invoices and updating payment status. Steps: 1. Navigate to Customer menu and choose "Complete Payments". - Verify that the system lists pending invoices with tabular details. 2. Select an invoice by index. - Verify that the chosen invoice is retrieved correctly. 3. Enter payment mode (OFFLINE/ONLINE). - Verify that the selected mode is applied to the invoice. 4. Confirm payment completion. - Verify that the invoice status changes to COMPLETED. - Verify that a confirmation message is displayed. - Verify that a notification is sent to the customer. Sreeja Reghukumar, please review --- .../controllers/Controller.cpp | 13 ++- .../controllers/Controller.h | 5 + .../models/ServiceBooking.cpp | 6 +- .../models/ServiceBooking.h | 8 +- .../services/PaymentManagementService.cpp | 41 ++++++++ .../views/CustomerMenu.cpp | 95 +++++++++++++++++++ 6 files changed, 160 insertions(+), 8 deletions(-) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp index d536e8a..97a2b90 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp @@ -1,4 +1,6 @@ #include "Controller.h" +#include "User.h" +#include "Invoice.h" bool Controller::login(const std::string& username, const std::string& password) { @@ -121,11 +123,20 @@ void Controller::removeComboPackage(const std::string& comboPackageID) util::Map Controller::getInvoicesByUser() { - return util::Map(); + User* currentUser = m_authenticationManagementService.getAuthenticatedUser(); + util::Map currentUserInvoices = m_paymentManagementService.getInvoices(currentUser->getId()); + util::Map userInvoicesReadOnly; + for (int iterator = 0; iterator < currentUserInvoices.getSize(); iterator++) + { + Invoice* currentInvoice = currentUserInvoices.getValueAt(iterator); + userInvoicesReadOnly.insert(currentInvoice->getId(), currentInvoice); + } + return userInvoicesReadOnly; } void Controller::completePayment(const std::string& invoiceID, util::PaymentMode paymentMode) { + m_paymentManagementService.completePayment(invoiceID, paymentMode); } util::Vector Controller::getNotifications() diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h index 3aabb58..874d10a 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h @@ -2,6 +2,8 @@ #include "Map.h" #include #include "Enums.h" +#include "PaymentManagementService.h" +#include "AuthenticationManagementService.h" class Service; class ComboPackage; @@ -14,6 +16,9 @@ class Notification; class Controller { +private: + AuthenticationManagementService m_authenticationManagementService; + PaymentManagementService m_paymentManagementService; public: bool login(const std::string& username, const std::string& password); void logout(); diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp index 1fdfaf0..aeb7f4d 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp @@ -18,7 +18,7 @@ ServiceBooking::ServiceBooking( const std::string& vehicleBrand, const std::string& vehicleModel, const std::string& assignedTechnicianId, - const std::string& assignedTechnician, + const User* assignedTechnician, double discountPercentage ) : m_id("SRV" + std::to_string(++m_uid)), @@ -80,7 +80,7 @@ const std::string& ServiceBooking::getAssignedTechnicianId() const return m_assignedTechnicianId; } -const std::string& ServiceBooking::getAssignedTechnician() const +const User* ServiceBooking::getAssignedTechnician() const { return m_assignedTechnician; } @@ -135,7 +135,7 @@ void ServiceBooking::setAssignedTechnicianId(const std::string& assignedTechnici m_assignedTechnicianId = assignedTechnicianId; } -void ServiceBooking::setAssignedTechnician(const std::string& assignedTechnician) +void ServiceBooking::setAssignedTechnician(const User* assignedTechnician) { m_assignedTechnician = assignedTechnician; } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h index 5ecc1b0..8996d36 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h @@ -19,7 +19,7 @@ private: std::string m_vehicleBrand; std::string m_vehicleModel; std::string m_assignedTechnicianId; - std::string m_assignedTechnician; + const User* m_assignedTechnician; double m_discountPercentage; public: ServiceBooking(); @@ -34,7 +34,7 @@ public: const std::string& vehicleBrand, const std::string& vehicleModel, const std::string& assignedTechnicianId, - const std::string& assignedTechnician, + const User* assignedTechnician, double discountPercentage ); const std::string& getId() const; @@ -46,7 +46,7 @@ public: const std::string& getVehicleBrand() const; const std::string& getVehicleModel() const; const std::string& getAssignedTechnicianId() const; - const std::string& getAssignedTechnician() const; + const User* getAssignedTechnician() const; double getDiscountPercentage() const; void setId(const std::string& id); void setStatus(const util::ServiceJobStatus& status); @@ -57,6 +57,6 @@ public: void setVehicleBrand(const std::string& vehicleBrand); void setVehicleModel(const std::string& vehicleModel); void setAssignedTechnicianId(const std::string& assignedTechnicianId); - void setAssignedTechnician(const std::string& assignedTechnician); + void setAssignedTechnician(const User* assignedTechnician); void setDiscountPercentage(double discountPercentage); }; \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp index 786ebcf..185c362 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp @@ -1 +1,42 @@ #include "PaymentManagementService.h" +#include "Invoice.h" +#include "Enums.h" +#include "ServiceBooking.h" +#include "Timestamp.h" + +util::Map PaymentManagementService::getInvoices(const std::string& customerID) +{ + util::Map& currentInvoices = m_dataStore.getInvoices(); + util::Map currentUserInvoices; + for (int iterator = 0; iterator < currentInvoices.getSize(); iterator++) + { + Invoice* currentInvoice = currentInvoices.getValueAt(iterator); + if (currentInvoice->getBooking()->getCustomerId() == customerID) + { + currentUserInvoices.insert(currentInvoice->getId(), currentInvoice); + } + } + return currentUserInvoices; +} + +void PaymentManagementService::completePayment(const std::string& invoiceID, util::PaymentMode paymentMode) +{ + auto& currentInvoices = m_dataStore.getInvoices(); + int invoiceIndex = currentInvoices.find(invoiceID); + if (invoiceIndex != -1) + { + Invoice* invoice = currentInvoices.getValueAt(invoiceIndex); + User* currentUser = invoice->getBooking()->getCustomer(); + invoice->setPaymentMethod(paymentMode); + invoice->setPaymentDate(util::Timestamp()); + invoice->setStatus(util::PaymentStatus::COMPLETED); + std::string title, message; + title = "Payment successful"; + message = "Payment successful for invoice ID " + invoiceID; + sendNotification(currentUser, title, message); + } + else + { + throw std::runtime_error("Payment failed: invalid invoice ID."); + } +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp index 047f471..3a18df4 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp @@ -1,6 +1,13 @@ +#include +#include #include "CustomerMenu.h" #include "InputHelper.h" #include "OutputHelper.h" +#include "Invoice.h" +#include "Enums.h" +#include "ServiceBooking.h" +#include "User.h" +#include "Timestamp.h" void CustomerMenu::showMenu() { @@ -55,8 +62,96 @@ void CustomerMenu::viewServiceHistory() { } +static std::string selectInvoiceFromUserForPayment(const util::Map& currentInvoices) +{ + int currentIndex = 1, choice; + util::Map pendingInvoicesForPayment; + std::cout << std::left + << std::setw(6) << "Index" + << std::setw(12) << "BookingID" + << std::setw(15) << "VehicleBrand" + << std::setw(15) << "VehicleNumber" + << std::setw(12) << "TechID" + << std::setw(20) << "TechnicianName" + << std::setw(10) << "Discount(%)" + << std::setw(12) << "TotalAmount" + << std::setw(20) << "InvoiceDate" + << std::endl; + for (int iterator = 0; iterator < currentInvoices.getSize(); iterator++) + { + const Invoice* currentInvoice = currentInvoices.getValueAt(iterator); + if (currentInvoice && currentInvoice->getStatus() == util::PaymentStatus::PENDING) + { + std::cout << std::left + << std::setw(6) << currentIndex + << std::setw(12) << currentInvoice->getBookingId() + << std::setw(15) << currentInvoice->getBooking()->getVehicleBrand() + << std::setw(15) << currentInvoice->getBooking()->getVehicleNumber() + << std::setw(12) << currentInvoice->getBooking()->getAssignedTechnician()->getId() + << std::setw(20) << currentInvoice->getBooking()->getAssignedTechnician()->getName() + << std::setw(10) << currentInvoice->getDiscountPercentage() + << std::setw(12) << currentInvoice->getTotalAmount() + << std::setw(20) << currentInvoice->getInvoiceDate().toString() + << std::endl; + pendingInvoicesForPayment.insert(currentIndex++, currentInvoice); + } + } + if (pendingInvoicesForPayment.getSize() == 0) + { + std::cout << "No pending invoices available for payment.\n"; + return ""; + } + std::cout << "Select the Invoice to pay (Index): "; + util::read(choice); + int selectedIndex = pendingInvoicesForPayment.find(choice); + if (selectedIndex != -1) + { + const Invoice* selectedInvoice = pendingInvoicesForPayment.getValueAt(selectedIndex); + return selectedInvoice->getId(); + } + else + { + std::cout << "Invalid choice.\n"; + return ""; + } +} + +static util::PaymentMode selectPaymentMode() +{ + int choice; + std::cout << "Enter the payment Mode\n1.OFFLINE\n2.ONLINE\nChoice: "; + util::read(choice); + if (choice == 1) + { + std::cout << "Offline mode selected.\n"; + return util::PaymentMode::OFFLINE; + } + else if (choice == 2) + { + std::cout << "Online mode selected.\n"; + return util::PaymentMode::ONLINE; + } + else + { + std::cout << "Invalid choice, Offline mode selected.\n"; + return util::PaymentMode::OFFLINE; + } +} + void CustomerMenu::completePayments() { + util::clear(); + int paymentModeChoice; + util::Map currentInvoices = m_controller.getInvoicesByUser(); + std::string selectedID = selectInvoiceFromUserForPayment(currentInvoices); + if (selectedID == "") + { + std::cout << "Payment failed.\n"; + return; + } + util::PaymentMode paymentMode = selectPaymentMode(); + m_controller.completePayment(selectedID, paymentMode); + std::cout << "Payment completed successfully.\n"; } void CustomerMenu::viewInvoices() From 461857f97185a483763b04feac3af92fcf47ab5d Mon Sep 17 00:00:00 2001 From: Jissin Mathew Date: Wed, 20 May 2026 19:54:14 +0530 Subject: [PATCH 07/11] Implement View Invoices for Customer PAY003: View Invoices 1. Added CustomerMenu::viewInvoices to fetch invoices via Controller and display them to the customer. 2. Implemented displayInvoices helper to show invoice details including booking, vehicle, technician, discount, total amount, invoice date, and payment status. 3. Enhanced invoice display to include a tabular breakdown of inventory items (ItemName, Quantity, Price) used in the service. 4. Updated ServiceBooking to store assigned technician as a const User* for richer technician details in invoice output. Acceptance Criteria: 1. Invoice details should show total cost and discounts. 2. Invoice details should show list of parts used. Precondition: 1. Customer is logged into the system. 2. At least one invoice exists for the customer in the datastore. 3. Inventory items are linked to the invoice. Steps: 1. Navigate to Customer menu and choose "View Invoices". - Verify that the system lists invoice details including booking ID, vehicle info, technician, discount, total amount, invoice date, and payment status. 2. Check the parts list under each invoice. - Verify that inventory items are displayed in tabular form with ItemName, Quantity, and Price. 3. Confirm that discounts and total cost are shown correctly. Sreeja Reghukumar, please review --- .../models/ServiceBooking.cpp | 6 +- .../models/ServiceBooking.h | 8 +-- .../views/CustomerMenu.cpp | 60 +++++++++++++++++++ 3 files changed, 67 insertions(+), 7 deletions(-) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp index 1fdfaf0..aeb7f4d 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp @@ -18,7 +18,7 @@ ServiceBooking::ServiceBooking( const std::string& vehicleBrand, const std::string& vehicleModel, const std::string& assignedTechnicianId, - const std::string& assignedTechnician, + const User* assignedTechnician, double discountPercentage ) : m_id("SRV" + std::to_string(++m_uid)), @@ -80,7 +80,7 @@ const std::string& ServiceBooking::getAssignedTechnicianId() const return m_assignedTechnicianId; } -const std::string& ServiceBooking::getAssignedTechnician() const +const User* ServiceBooking::getAssignedTechnician() const { return m_assignedTechnician; } @@ -135,7 +135,7 @@ void ServiceBooking::setAssignedTechnicianId(const std::string& assignedTechnici m_assignedTechnicianId = assignedTechnicianId; } -void ServiceBooking::setAssignedTechnician(const std::string& assignedTechnician) +void ServiceBooking::setAssignedTechnician(const User* assignedTechnician) { m_assignedTechnician = assignedTechnician; } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h index 5ecc1b0..8996d36 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h @@ -19,7 +19,7 @@ private: std::string m_vehicleBrand; std::string m_vehicleModel; std::string m_assignedTechnicianId; - std::string m_assignedTechnician; + const User* m_assignedTechnician; double m_discountPercentage; public: ServiceBooking(); @@ -34,7 +34,7 @@ public: const std::string& vehicleBrand, const std::string& vehicleModel, const std::string& assignedTechnicianId, - const std::string& assignedTechnician, + const User* assignedTechnician, double discountPercentage ); const std::string& getId() const; @@ -46,7 +46,7 @@ public: const std::string& getVehicleBrand() const; const std::string& getVehicleModel() const; const std::string& getAssignedTechnicianId() const; - const std::string& getAssignedTechnician() const; + const User* getAssignedTechnician() const; double getDiscountPercentage() const; void setId(const std::string& id); void setStatus(const util::ServiceJobStatus& status); @@ -57,6 +57,6 @@ public: void setVehicleBrand(const std::string& vehicleBrand); void setVehicleModel(const std::string& vehicleModel); void setAssignedTechnicianId(const std::string& assignedTechnicianId); - void setAssignedTechnician(const std::string& assignedTechnician); + void setAssignedTechnician(const User* assignedTechnician); void setDiscountPercentage(double discountPercentage); }; \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp index 047f471..ae45dd7 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp @@ -1,6 +1,12 @@ +#include #include "CustomerMenu.h" #include "InputHelper.h" #include "OutputHelper.h" +#include "Invoice.h" +#include "Service.h" +#include "ServiceBooking.h" +#include "User.h" +#include "InventoryItem.h" void CustomerMenu::showMenu() { @@ -59,8 +65,62 @@ void CustomerMenu::completePayments() { } +static void displayInvoices(util::Map currentUserInvoices) +{ + if (currentUserInvoices.getSize() == 0) + { + std::cout << "No invoices found for this account." << std::endl; + util::pressEnter(); + return; + } + else + { + for (int index = 0; index < currentUserInvoices.getSize(); index++) + { + const Invoice* currentInvoice = currentUserInvoices.getValueAt(index); + if (currentInvoice) + { + std::cout << "\nInvoice Details\n"; + std::cout << "Booking ID: " << currentInvoice->getBookingId() << std::endl; + std::cout << "Vehicle Brand: " << currentInvoice->getBooking()->getVehicleBrand() << std::endl; + std::cout << "Vehicle Number: " << currentInvoice->getBooking()->getVehicleNumber() << std::endl; + std::cout << "Technician ID: " << currentInvoice->getBooking()->getAssignedTechnician()->getId() << std::endl; + std::cout << "Technician Name: " << currentInvoice->getBooking()->getAssignedTechnician()->getName() << std::endl; + std::cout << "Discount(%): " << currentInvoice->getDiscountPercentage() << std::endl; + std::cout << "Total Amount: " << currentInvoice->getTotalAmount() << std::endl; + std::cout << "Invoice Date: " << currentInvoice->getInvoiceDate().toString() << std::endl; + std::cout << "Payment Status: " << util::getPaymentStatusString(currentInvoice->getStatus()) << std::endl; + auto inventoryItemsInInvoice = currentInvoice->getParts(); + std::cout << "\nItems Used:\n"; + std::cout << std::left + << std::setw(20) << "ItemName" + << std::setw(10) << "Quantity" + << std::setw(10) << "Price" + << std::endl; + std::cout << std::string(40, '-') << std::endl; + for (int iterator = 0; iterator < inventoryItemsInInvoice.getSize(); iterator++) + { + InventoryItem* currentItem = inventoryItemsInInvoice.getValueAt(iterator); + std::cout << std::left + << std::setw(20) << currentItem->getPartName() + << std::setw(10) << currentItem->getQuantity() + << std::setw(10) << currentItem->getPrice() + << std::endl; + } + } + else + { + throw std::runtime_error("Null invoice encountered while displaying invoices."); + } + } + } +} + void CustomerMenu::viewInvoices() { + util::clear(); + util::Map currentUserInvoices = m_controller.getInvoicesByUser(); + displayInvoices(currentUserInvoices); } void CustomerMenu::viewNotifications() From 61f70a54f6ae2a71288b6b4ea14806fd55ea260c Mon Sep 17 00:00:00 2001 From: Jissin Mathew Date: Wed, 20 May 2026 14:57:10 +0530 Subject: [PATCH 08/11] Implement Generate Invoice PAY001: Generate Invoice 1. Added Utility.h to project configuration for supporting invoice generation utilities. 2. Updated Invoice model to use string-based keys for parts mapping instead of integer keys. 3. Implemented PaymentManagementService::generateInvoice to aggregate labour cost, parts cost, and apply discounts. 4. Integrated invoice creation with Factory to instantiate Invoice objects and persist them into datastore. 5. Enhanced Enums with PaymentMode::NOTSET to handle default invoice state. Acceptance Criteria: 1. Invoice auto-generates for each service booking once jobs are completed. 2. Invoice shows a clear breakdown of charges including labour cost, parts cost, discount, and total amount. Precondition: 1. Service booking exists with at least one service and required inventory items. 2. Datastore is available for storing invoices. 3. Payment mode and status enums are properly configured. Steps: 1. Complete all jobs in a service booking. - Verify that PaymentManagementService::generateInvoice is triggered. 2. Check datastore for newly created invoice. - Verify that invoice contains booking ID, labour cost, parts cost, discount, and total amount. 3. Inspect invoice details. - Verify that breakdown of charges is accurate and discount is applied correctly. 4. Confirm invoice status. - Verify that invoice is created with PaymentMode::NOTSET and PaymentStatus::PENDING. Sreeja Reghukumar, please review --- .../Trenser.VehicleServiceSystem.vcxproj | 1 + ...enser.VehicleServiceSystem.vcxproj.filters | 3 + .../models/Invoice.cpp | 7 ++- .../models/Invoice.h | 10 ++-- .../models/JobCard.cpp | 8 +-- .../models/JobCard.h | 10 ++-- .../services/PaymentManagementService.cpp | 56 +++++++++++++++++++ .../utilities/Enums.h | 5 +- .../utilities/Utility.h | 15 +++++ 9 files changed, 97 insertions(+), 18 deletions(-) create mode 100644 Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj index a65c46d..819264c 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj @@ -176,6 +176,7 @@ + diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters index 77d0509..7c17f4e 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters @@ -233,5 +233,8 @@ Header Files\Models + + Header Files\Utilities + \ 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 ba7bc84..507f274 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.cpp @@ -16,7 +16,8 @@ Invoice::Invoice( const std::string& bookingId, ServiceBooking* booking, const util::Timestamp& invoiceDate, - double laborCost, const util::Map& parts, double partsCost, double discountPercentage, @@ -63,7 +64,7 @@ double Invoice::getLaborCost() const return m_laborCost; } -const util::Map& Invoice::getParts() const +const util::Map& Invoice::getParts() const { return m_parts; } @@ -123,7 +124,7 @@ void Invoice::setLaborCost(double laborCost) m_laborCost = laborCost; } -void Invoice::setParts(const util::Map& parts) +void Invoice::setParts(const util::Map& parts) { m_parts = parts; } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.h index 212d33f..f78f7c9 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.h @@ -16,7 +16,7 @@ private: ServiceBooking* m_booking; util::Timestamp m_invoiceDate; double m_laborCost; - util::Map m_parts; + util::Map m_parts; double m_partsCost; double m_discountPercentage; double m_totalAmount; @@ -30,8 +30,8 @@ public: const std::string& bookingId, ServiceBooking* booking, const util::Timestamp& invoiceDate, - double laborCost, const util::Map& parts, + double laborCost, + const util::Map& parts, double partsCost, double discountPercentage, double totalAmount, @@ -44,7 +44,7 @@ public: ServiceBooking* getBooking() const; const util::Timestamp& getInvoiceDate() const; double getLaborCost() const; - const util::Map& getParts() const; + const util::Map& getParts() const; double getPartsCost() const; double getDiscountPercentage() const; double getTotalAmount() const; @@ -56,7 +56,7 @@ public: void setBooking(ServiceBooking* booking); void setInvoiceDate(const util::Timestamp& invoiceDate); void setLaborCost(double laborCost); - void setParts(const util::Map& parts); + void setParts(const util::Map& parts); void setPartsCost(double partsCost); void setDiscountPercentage(double discountPercentage); void setTotalAmount(double totalAmount); diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp index 04e9195..b9f1eee 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp @@ -7,7 +7,7 @@ JobCard::JobCard() m_booking(nullptr), m_service(nullptr), m_technician(nullptr), - m_status(ServiceJobStatus()) {} + m_status(util::ServiceJobStatus()) {} JobCard::JobCard(const std::string& bookingId, ServiceBooking* booking, @@ -16,7 +16,7 @@ JobCard::JobCard(const std::string& bookingId, const std::string& technicianId, User* technician, const util::Timestamp& assignedDate, - ServiceJobStatus status, + util::ServiceJobStatus status, const util::Timestamp& completionDate ) : m_id("JC" + std::to_string(++m_uid)), @@ -70,7 +70,7 @@ const util::Timestamp& JobCard::getAssignedDate() const return m_assignedDate; } -ServiceJobStatus JobCard::getStatus() const +util::ServiceJobStatus JobCard::getStatus() const { return m_status; } @@ -120,7 +120,7 @@ void JobCard::setAssignedDate(const util::Timestamp& assignedDate) m_assignedDate = assignedDate; } -void JobCard::setStatus(ServiceJobStatus status) +void JobCard::setStatus(util::ServiceJobStatus status) { m_status = status; } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h index 15a8a5d..880767a 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h @@ -1,12 +1,12 @@ #pragma once #include +#include "Enums.h" #include "Timestamp.h" class ServiceBooking; class Service; class User; -enum class ServiceJobStatus : int; class JobCard { @@ -20,7 +20,7 @@ private: std::string m_technicianId; User* m_technician; util::Timestamp m_assignedDate; - ServiceJobStatus m_status; + util::ServiceJobStatus m_status; util::Timestamp m_completionDate; public: @@ -32,7 +32,7 @@ public: const std::string& technicianId, User* technician, const util::Timestamp& assignedDate, - ServiceJobStatus status, + util::ServiceJobStatus status, const util::Timestamp& completionDate ); const std::string& getId() const; @@ -43,7 +43,7 @@ public: const std::string& getTechnicianId() const; User* getTechnician() const; const util::Timestamp& getAssignedDate() const; - ServiceJobStatus getStatus() const; + util::ServiceJobStatus getStatus() const; const util::Timestamp& getCompletionDate() const; void setId(const std::string& id); void setBookingId(const std::string& bookingId); @@ -53,6 +53,6 @@ public: void setTechnicianId(const std::string& technicianId); void setTechnician(User* technician); void setAssignedDate(const util::Timestamp& assignedDate); - void setStatus(ServiceJobStatus status); + void setStatus(util::ServiceJobStatus status); void setCompletionDate(const util::Timestamp& completionDate); }; \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp index 786ebcf..8f391c5 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp @@ -1 +1,57 @@ #include "PaymentManagementService.h" +#include "ServiceBooking.h" +#include "Service.h" +#include "InventoryItem.h" +#include "Utility.h" +#include "Factory.h" +#include "Timestamp.h" +#include "Invoice.h" +#include "JobCard.h" +#include "Enums.h" + +static void createInventoryItemsMap(util::Map& completeInventoryItemMapOfBooking, const Service* currentService) +{ + auto& currentRequiredInventoryItems = currentService->getRequiredInventoryItems(); + for (int iterator = 0; iterator < currentRequiredInventoryItems.getSize(); iterator++) + { + auto& currentRequiredInventoryItem = currentRequiredInventoryItems.getValueAt(iterator); + completeInventoryItemMapOfBooking.insert(currentRequiredInventoryItem->getId(), currentRequiredInventoryItem); + } +} + +void PaymentManagementService::generateInvoice(ServiceBooking* booking) +{ + if (!booking) + { + throw std::runtime_error("Invoice generation failed: booking is null."); + } + double totalLabourCost = 0, totalPartsCost = 0, totalServiceCost = 0; + double discountPercentage = booking->getDiscountPercentage(); + std::string bookingID = booking->getId(); + util::Map servicesInTheBookedService = booking->getServices(); + util::Map completeInventoryItemMapOfBooking; + util::Map currentJobCards = m_dataStore.getJobCards(); + for (int iterator = 0; iterator < currentJobCards.getSize(); iterator++) + { + JobCard* currentJobCard = currentJobCards.getValueAt(iterator); + if (currentJobCard->getBookingId() == bookingID && currentJobCard->getStatus() != util::ServiceJobStatus::COMPLETED) + { + throw std::runtime_error("Invoice generation failed: not all job cards are completed for booking '" + bookingID + "'."); + } + } + for (int iterator = 0; iterator < servicesInTheBookedService.getSize(); iterator++) + { + Service* currentService = servicesInTheBookedService.getValueAt(iterator); + if (currentService) + { + createInventoryItemsMap(completeInventoryItemMapOfBooking, currentService); + totalLabourCost += currentService->getLaborCost(); + totalPartsCost += calculatePartsCost(currentService); + } + } + totalServiceCost = totalLabourCost + totalPartsCost; + totalServiceCost -= (totalServiceCost * (discountPercentage / 100)); + Invoice* invoice = Factory::getObject(bookingID, booking, util::Timestamp(), totalLabourCost, completeInventoryItemMapOfBooking, totalPartsCost, discountPercentage, totalServiceCost, util::Timestamp(), util::PaymentMode::NOTSET, util::PaymentStatus::PENDING); + util::Map& currentInvoices = m_dataStore.getInvoices(); + currentInvoices.insert(invoice->getId(), invoice); +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h index 24bbdcd..5b615b5 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h @@ -13,7 +13,8 @@ namespace util enum class PaymentMode { ONLINE, - OFFLINE + OFFLINE, + NOTSET }; enum class PaymentStatus @@ -73,6 +74,8 @@ namespace util return "ONLINE"; case PaymentMode::OFFLINE: return "OFFLINE"; + case PaymentMode::NOTSET: + return "NOTSET"; } throw std::invalid_argument("Invalid PaymentMode"); } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h new file mode 100644 index 0000000..cb9b990 --- /dev/null +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h @@ -0,0 +1,15 @@ +#pragma once +#include "Service.h" +#include "InventoryItem.h" + +inline double calculatePartsCost(const Service* service) +{ + double cost = 0; + auto& requiredInventoryItems = service->getRequiredInventoryItems(); + int requiredInventoryItemsSize = requiredInventoryItems.getSize(); + for (int index = 0; index < requiredInventoryItemsSize; index++) + { + cost += requiredInventoryItems.getValueAt(index)->getPrice(); + } + return cost; +} \ No newline at end of file From 05196900437a275a4a6b1ff79a7308f2d8e1946c Mon Sep 17 00:00:00 2001 From: Jissin Mathew Date: Fri, 22 May 2026 13:11:11 +0530 Subject: [PATCH 09/11] Add documentation headers across system modules --- .../controllers/Controller.cpp | 76 +++++++++++++++ .../services/ServiceManagementService.cpp | 97 +++++++++++++++++++ .../views/AdminMenu.cpp | 78 +++++++++++++++ .../views/CustomerMenu.cpp | 9 ++ .../views/TechnicianMenu.cpp | 18 ++++ 5 files changed, 278 insertions(+) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp index c19e440..6292130 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp @@ -34,6 +34,14 @@ void Controller::updateUserDetails(const std::string& email, const std::string& { } +/* +Function: getServices +Description: Retrieves all available services in read-only form. +Parameters: + - None +Returns: + - util::Map containing all services +*/ util::Map Controller::getServices() { util::Map currentServices = m_serviceManagementService.getServices(); @@ -77,6 +85,14 @@ void Controller::removeInventoryItem(const std::string& inventoryItemID) { } +/* +Function: getServiceBookings +Description: Retrieves all service bookings in read-only form. +Parameters: + - None +Returns: + - util::Map containing service bookings +*/ util::Map Controller::getServiceBookings() { auto serviceBookings = m_serviceManagementService.getServiceBookings(); @@ -88,6 +104,14 @@ util::Map Controller::getServiceBookings() return readOnlyServiceBookings; } +/* +Function: getServiceBookingsByUser +Description: Retrieves all service bookings for a specific user. +Parameters: + - userID: std::string, the user ID +Returns: + - util::Map containing bookings for the user +*/ util::Map Controller::getServiceBookingsByUser(const std::string userID) { util::Map readOnlyServiceBookingsByUserMap; @@ -104,6 +128,14 @@ util::Map Controller::getUsers() return util::Map(); } +/* +Function: getUsers +Description: Retrieves users filtered by user type. +Parameters: + - userType: util::UserType, type of user (CUSTOMER, TECHNICIAN, ADMIN) +Returns: + - util::Map containing users of the specified type +*/ util::Map Controller::getUsers(util::UserType userType) { auto userMap = m_userManagementService.getUsers(userType); @@ -115,21 +147,57 @@ util::Map Controller::getUsers(util::UserType userType return readOnlyUserMap; } +/* +Function: createJobCard +Description: Creates a job card for a service booking assigned to a technician. +Parameters: + - bookingID: std::string, ID of the service booking + - technicianID: std::string, ID of the technician + - serviceID: std::string, ID of the service +Returns: + - void +*/ void Controller::createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID) { m_serviceManagementService.createJobCard(bookingID, technicianID, serviceID); } +/* +Function: createService +Description: Creates a new service with associated inventory items and labor cost. +Parameters: + - name: std::string, name of the service + - inventoryItemIDs: Vector of inventory item IDs + - laborCost: double, labor cost +Returns: + - void +*/ void Controller::createService(const std::string& name, const util::Vector& inventoryItemIDs, double laborCost) { m_serviceManagementService.createService(name, inventoryItemIDs, laborCost); } +/* +Function: removeService +Description: Removes a service from the system by ID. +Parameters: + - serviceID: std::string, ID of the service +Returns: + - void +*/ void Controller::removeService(const std::string& serviceID) { m_serviceManagementService.removeService(serviceID); } +/* +Function: getJobCardsByUser +Description: Retrieves job cards assigned to the authenticated technician. +Parameters: + - None +Returns: + - util::Map containing job cards +*/ util::Map Controller::getJobCardsByUser() { const User* currentUser = getAuthenticatedUser(); @@ -143,6 +211,14 @@ util::Map Controller::getJobCardsByUser() return readOnlyJobCardMap; } +/* +Function: completeJob +Description: Marks a job card as completed. +Parameters: + - jobID: std::string, ID of the job card +Returns: + - void +*/ void Controller::completeJob(const std::string& jobID) { m_serviceManagementService.completeJob(jobID); diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp index 4f67c0d..393fe8d 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp @@ -12,11 +12,27 @@ #include "NotificationManagementService.h" #include "User.h" +/* +Function: getServiceBookings +Description: Retrieves all service bookings from the datastore. +Parameters: + - None +Returns: + - util::Map containing all service bookings +*/ util::Map ServiceManagementService::getServiceBookings() { return m_dataStore.getServiceBookings(); } +/* +Function: getServiceBooking +Description: Retrieves a specific service booking by its ID. +Parameters: + - serviceID: std::string, ID of the service booking +Returns: + - ServiceBooking*: Pointer to the service booking, or nullptr if not found +*/ ServiceBooking* ServiceManagementService::getServiceBooking(const std::string& serviceID) { auto currentServiceBookings = getServiceBookings(); @@ -30,6 +46,19 @@ ServiceBooking* ServiceManagementService::getServiceBooking(const std::string& s return nullptr; } +/* +Function: createJobCard +Description: Creates a job card for a given service booking, service, and technician. + Validates booking, service, technician, and inventory availability before creation. +Parameters: + - bookingID: std::string, ID of the service booking + - technicianID: std::string, ID of the technician + - serviceID: std::string, ID of the service +Returns: + - void +Throws: + - std::runtime_error if booking, service, technician, or inventory validation fails +*/ void ServiceManagementService::createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID) { UserManagementService m_userManagementService; @@ -74,6 +103,19 @@ void ServiceManagementService::createJobCard(const std::string& bookingID, const sendNotification(selectedTechnician,title, message); } +/* +Function: createService +Description: Creates a new service with associated inventory items and labor cost. + Validates inventory items before creation. +Parameters: + - name: std::string, name of the service + - inventoryItemIDs: util::Vector, IDs of required inventory items + - laborCost: double, labor cost for the service +Returns: + - void +Throws: + - std::runtime_error if inventory items are not found or service creation fails +*/ void ServiceManagementService::createService(const std::string& name, const util::Vector& inventoryItemIDs, double laborCost) { util::Map currentServiceInventoryItems; @@ -110,11 +152,29 @@ void ServiceManagementService::createService(const std::string& name, const util currentServices.insert(newService->getId(), newService); } +/* +Function: getServices +Description: Retrieves all services from the datastore. +Parameters: + - None +Returns: + - util::Map containing all services +*/ util::Map ServiceManagementService::getServices() { return m_dataStore.getServices(); } +/* +Function: removeService +Description: Marks a service as inactive by its ID. +Parameters: + - serviceID: std::string, ID of the service +Returns: + - void +Throws: + - std::runtime_error if the service is not found +*/ void ServiceManagementService::removeService(const std::string& serviceID) { util::Map currentServices = getServices(); @@ -128,6 +188,14 @@ void ServiceManagementService::removeService(const std::string& serviceID) } } +/* +Function: getServiceBookings (overloaded) +Description: Retrieves all service bookings for a specific customer. +Parameters: + - customerID: std::string, ID of the customer +Returns: + - util::Map containing bookings for the customer +*/ util::Map ServiceManagementService::getServiceBookings(const std::string& customerID) { util::Map currentServiceBookings = getServiceBookings(); @@ -146,6 +214,14 @@ util::Map ServiceManagementService::getServiceBook return currentUserServiceBookings; } +/* +Function: getJobCards +Description: Retrieves all job cards assigned to a specific technician. +Parameters: + - technicianID: std::string, ID of the technician +Returns: + - util::Map containing job cards assigned to the technician +*/ util::Map ServiceManagementService::getJobCards(const std::string& technicianID) { util::Map jobCards = m_dataStore.getJobCards(); @@ -161,6 +237,15 @@ util::Map ServiceManagementService::getJobCards(const std return technicianJobCards; } +/* +Function: hasAllJobCardsinServiceBookingCompleted (static helper) +Description: Checks if all job cards for a given service booking are completed. +Parameters: + - bookingId: std::string, ID of the service booking + - currentAssignedJobs: util::Map&, map of assigned job cards +Returns: + - bool: True if all job cards are completed, False otherwise +*/ static bool hasAllJobCardsinServiceBookingCompleted(std::string bookingId, util::Map& currentAssignedJobs) { for (int iterator = 0; iterator < currentAssignedJobs.getSize(); iterator++) @@ -177,6 +262,18 @@ static bool hasAllJobCardsinServiceBookingCompleted(std::string bookingId, util: return true; } +/* +Function: completeJob +Description: Marks a job card as completed for the authenticated technician. + If all job cards in the booking are completed, marks the booking as completed + and generates an invoice. +Parameters: + - jobID: std::string, ID of the job card +Returns: + - void +Throws: + - std::runtime_error if technician is not authenticated, job card not found, or job already completed +*/ void ServiceManagementService::completeJob(const std::string& jobID) { AuthenticationManagementService authenticationManagementService; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp index dd9b1fa..b539aa8 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp @@ -62,6 +62,16 @@ void AdminMenu::checkStockAvailability() { } +/* +Function: listServiceBookings (static helper) +Description: Lists all pending service bookings and maps them to indices for selection. +Parameters: + - currentBookings: util::Map&, current bookings + - bookingsSize: int&, number of bookings + - serviceBookingsMap: util::Map&, map of indexed bookings +Returns: + - bool: True if pending services exist, False otherwise +*/ static bool listServiceBookings(util::Map& currentBookings, int& bookingsSize, util::Map& serviceBookingsMap) { int currentIndex = 1; @@ -107,6 +117,14 @@ static bool listServiceBookings(util::Map& c return true; } +/* +Function: selectPendingServiceBookings (static helper) +Description: Allows selection of a pending service booking by index. +Parameters: + - serviceBookingsMap: util::Map&, map of indexed bookings +Returns: + - const ServiceBooking*: Pointer to the selected booking, or nullptr if invalid +*/ static const ServiceBooking* selectPendingServiceBookings(util::Map& serviceBookingsMap) { int userInputIndex; @@ -123,6 +141,16 @@ static const ServiceBooking* selectPendingServiceBookings(util::Map, available technicians + - numberOfTechnicians: int, number of technicians + - currentAvailableTechniciansMap: util::Map&, map of indexed technicians +Returns: + - void +*/ static void listAvailableTechnicians( util::Map currentAvailableTechnicians, int numberOfTechnicians, util::Map& currentAvailableTechniciansMap) { bool hasTechnicians = false; @@ -153,6 +181,14 @@ static void listAvailableTechnicians( util::Map curren } } +/* +Function: selectTechnician (static helper) +Description: Allows selection of a technician by index. +Parameters: + - currentAvailableTechniciansMap: util::Map&, map of indexed technicians +Returns: + - const User*: Pointer to the selected technician, or nullptr if invalid +*/ static const User* selectTechnician(util::Map& currentAvailableTechniciansMap) { int userInputIndex; @@ -168,6 +204,15 @@ static const User* selectTechnician(util::Map& currentAvailabl } } +/* +Function: assignJob +Description: Allows the admin to assign pending service bookings to available technicians. + Creates job cards for selected services. +Parameters: + - None +Returns: + - void +*/ void AdminMenu::assignJob() { util::clear(); @@ -205,6 +250,15 @@ void AdminMenu::assignJob() } +/* +Function: selectInventoryItems (static helper) +Description: Allows selection of inventory items by index for creating a service. +Parameters: + - currentInventoryItems: util::Map&, available inventory items + - selectedInventoryItems: util::Vector&, vector to store selected item IDs +Returns: + - void +*/ static void selectInventoryItems(util::Map& currentInventoryItems, util::Vector& selectedInventoryItems) { bool doRun = true, hasInventoryItems = false; @@ -270,6 +324,14 @@ static void selectInventoryItems(util::Map& c } } +/* +Function: createService +Description: Allows the admin to create a new service by selecting inventory items and specifying labor cost. +Parameters: + - None +Returns: + - void +*/ void AdminMenu::createService() { util::clear(); @@ -286,6 +348,14 @@ void AdminMenu::createService() std::cout << "Service created sucessfully.\n"; } +/* +Function: selectServicesToRemove (static helper) +Description: Allows selection of a service to remove by index. +Parameters: + - currentServices: util::Map, available services +Returns: + - std::string: ID of the selected service, or empty string if invalid +*/ static std::string selectServicesToRemove(util::Map currentServices) { util::Map currentServicesMap; @@ -331,6 +401,14 @@ static std::string selectServicesToRemove(util::Map } } +/* +Function: removeService +Description: Allows the admin to remove an existing service by selecting from available services. +Parameters: + - None +Returns: + - void +*/ void AdminMenu::removeService() { util::clear(); diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp index f2444b1..38c3090 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp @@ -55,6 +55,15 @@ void CustomerMenu::selectComboPackage() { } +/* +Function: viewServiceHistory +Description: Displays the customer’s past service bookings in tabular format, + including booking ID, technician, vehicle details, discount percentage, and status. +Parameters: + - None +Returns: + - void +*/ void CustomerMenu::viewServiceHistory() { util::clear(); diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp index 2b94fe3..041877e 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp @@ -35,6 +35,15 @@ bool TechnicianMenu::handleOperation(int choice) return false; } +/* +Function: selectJobCardToComplete (static helper) +Description: Lists all incomplete job cards assigned to the technician and allows selection by index. +Parameters: + - assignedJobCards: util::Map&, job cards assigned to the technician + - incompleteJobCards: util::Map&, map of incomplete job cards indexed for selection +Returns: + - std::string: ID of the selected job card, or empty string if none selected +*/ static std::string selectJobCardToComplete(util::Map& assignedJobCards, util::Map& incompleteJobCards) { int currentIndex = 1; @@ -82,6 +91,15 @@ static std::string selectJobCardToComplete(util::Map assignedJobCards = m_controller.getJobCardsByUser(); From f1d146a37c645add49b3862fb8c9c161c1eeb1fe Mon Sep 17 00:00:00 2001 From: Jissin Mathew Date: Fri, 22 May 2026 13:21:51 +0530 Subject: [PATCH 10/11] Add documentation headers across system modules --- .../controllers/Controller.cpp | 21 ++++++++- .../services/PaymentManagementService.cpp | 41 +++++++++++++++++ .../views/CustomerMenu.cpp | 44 +++++++++++++++++++ 3 files changed, 104 insertions(+), 2 deletions(-) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp index 97a2b90..91f72fc 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp @@ -121,6 +121,15 @@ void Controller::removeComboPackage(const std::string& comboPackageID) { } +/* +Function: getInvoicesByUser +Description: Retrieves all invoices associated with the currently authenticated user. + Converts them into a read-only map before returning. +Parameters: + - None +Returns: + - util::Map containing the user’s invoices +*/ util::Map Controller::getInvoicesByUser() { User* currentUser = m_authenticationManagementService.getAuthenticatedUser(); @@ -134,6 +143,15 @@ util::Map Controller::getInvoicesByUser() return userInvoicesReadOnly; } +/* +Function: completePayment +Description: Completes payment for a specific invoice using the given payment mode. +Parameters: + - invoiceID: std::string, ID of the invoice to be paid + - paymentMode: util::PaymentMode, mode of payment (e.g., ONLINE, OFFLINE) +Returns: + - void +*/ void Controller::completePayment(const std::string& invoiceID, util::PaymentMode paymentMode) { m_paymentManagementService.completePayment(invoiceID, paymentMode); @@ -154,5 +172,4 @@ void Controller::configureNotifications(const std::string& userID, bool paymentN void Controller::runSystemChecks() { -} - +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp index 094e104..8b67c7d 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp @@ -9,6 +9,15 @@ #include "JobCard.h" #include "Enums.h" +/* +Function: createInventoryItemsMap (static helper) +Description: Builds a map of inventory items required for a given service and adds them to the booking’s inventory map. +Parameters: + - completeInventoryItemMapOfBooking: util::Map&, map to store inventory items for the booking + - currentService: const Service*, pointer to the current service +Returns: + - void +*/ static void createInventoryItemsMap(util::Map& completeInventoryItemMapOfBooking, const Service* currentService) { auto& currentRequiredInventoryItems = currentService->getRequiredInventoryItems(); @@ -19,6 +28,18 @@ static void createInventoryItemsMap(util::Map& comp } } +/* +Function: generateInvoice +Description: Generates an invoice for a completed service booking. + Validates that all job cards are completed, calculates labor and parts cost, applies discount, + and stores the invoice in the datastore. +Parameters: + - booking: ServiceBooking*, pointer to the service booking +Returns: + - void +Throws: + - std::runtime_error if booking is null or job cards are incomplete +*/ void PaymentManagementService::generateInvoice(ServiceBooking* booking) { if (!booking) @@ -56,6 +77,14 @@ void PaymentManagementService::generateInvoice(ServiceBooking* booking) currentInvoices.insert(invoice->getId(), invoice); } +/* +Function: getInvoices +Description: Retrieves all invoices associated with a specific customer. +Parameters: + - customerID: std::string, ID of the customer +Returns: + - util::Map containing the customer’s invoices +*/ util::Map PaymentManagementService::getInvoices(const std::string& customerID) { util::Map& currentInvoices = m_dataStore.getInvoices(); @@ -71,6 +100,18 @@ util::Map PaymentManagementService::getInvoices(const std return currentUserInvoices; } +/* +Function: completePayment +Description: Completes payment for a specific invoice. Updates payment method, date, and status, + then sends a notification to the customer. +Parameters: + - invoiceID: std::string, ID of the invoice + - paymentMode: util::PaymentMode, mode of payment (e.g., ONLINE, OFFLINE) +Returns: + - void +Throws: + - std::runtime_error if the invoice ID is invalid +*/ void PaymentManagementService::completePayment(const std::string& invoiceID, util::PaymentMode paymentMode) { auto& currentInvoices = m_dataStore.getInvoices(); diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp index a9f4d21..9f1d696 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp @@ -64,6 +64,14 @@ void CustomerMenu::viewServiceHistory() { } +/* +Function: selectInvoiceFromUserForPayment (static helper) +Description: Lists all pending invoices for the customer and allows selection by index. +Parameters: + - currentInvoices: util::Map&, map of customer invoices +Returns: + - std::string: ID of the selected invoice, or empty string if none selected +*/ static std::string selectInvoiceFromUserForPayment(const util::Map& currentInvoices) { int currentIndex = 1, choice; @@ -118,6 +126,14 @@ static std::string selectInvoiceFromUserForPayment(const util::Map, customer’s invoices +Returns: + - void +Throws: + - std::runtime_error if a null invoice is encountered +*/ static void displayInvoices(util::Map currentUserInvoices) { if (currentUserInvoices.getSize() == 0) @@ -206,6 +242,14 @@ static void displayInvoices(util::Map currentUserIn } } +/* +Function: viewInvoices +Description: Displays invoices associated with the customer by calling displayInvoices. +Parameters: + - None +Returns: + - void +*/ void CustomerMenu::viewInvoices() { util::clear(); From 1c717bb9fa6b9316ee74af78326f6105dcf8223f Mon Sep 17 00:00:00 2001 From: Jissin Mathew Date: Mon, 25 May 2026 17:31:20 +0530 Subject: [PATCH 11/11] Fix PR review comments Changes: 1. Added missing include for MenuHelper.h in project, AdminMenu, and CustomerMenu. 2. Updated PaymentManagementService::completePayment to guard against duplicate completion by checking status before updating. 3. Enhanced ServiceManagementService::createJobCard with null checks for inventory items and safe stock decrement logic. 4. Added null check for job card creation in ServiceManagementService and throw runtime error if creation fails. 5. Refactored ServiceManagementService::removeService to use m_dataStore.getServices() reference instead of getServices() copy. 6. Renamed helper function hasAllJobCardsinServiceBookingCompleted to hasCompletedAllJobs for clarity and updated usage in completeJob. 7. Fixed ServiceJobStatus string conversion in Enums.h to correctly return "PENDING" instead of "STARTED". 8. Added support for parsing "PENDING" string to ServiceJobStatus::PENDING in Enums.h. 9. Cleaned up AdminMenu.cpp by removing redundant static helper functions (listServiceBookings, selectPendingServiceBookings, listAvailableTechnicians, selectTechnician, selectInventoryItems, selectServicesToRemove). 10. Replaced removed helpers with shared MenuHelper usage and added util::pressEnter() calls for consistent user flow. 11. Simplified CustomerMenu.cpp by removing redundant static helpers (selectInvoiceFromUserForPayment, selectPaymentMode, displayInvoices) and moved logic to shared helpers. 12. General formatting and comment cleanup across AdminMenu.cpp and CustomerMenu.cpp for consistency. --- .../Trenser.VehicleServiceSystem.vcxproj | 1 + ...enser.VehicleServiceSystem.vcxproj.filters | 3 + .../services/PaymentManagementService.cpp | 19 +- .../services/ServiceManagementService.cpp | 27 +- .../utilities/Enums.h | 6 +- .../views/AdminMenu.cpp | 277 +--------- .../views/CustomerMenu.cpp | 160 +----- .../views/MenuHelper.h | 501 ++++++++++++++++++ .../views/TechnicianMenu.cpp | 60 +-- 9 files changed, 553 insertions(+), 501 deletions(-) create mode 100644 Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj index 819264c..fd7c056 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj @@ -181,6 +181,7 @@ + diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters index 7c17f4e..701e0c5 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters @@ -236,5 +236,8 @@ Header Files\Utilities + + Header Files\Views + \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp index 8b67c7d..c6e2f85 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp @@ -119,14 +119,17 @@ void PaymentManagementService::completePayment(const std::string& invoiceID, uti if (invoiceIndex != -1) { Invoice* invoice = currentInvoices.getValueAt(invoiceIndex); - User* currentUser = invoice->getBooking()->getCustomer(); - invoice->setPaymentMethod(paymentMode); - invoice->setPaymentDate(util::Timestamp()); - invoice->setStatus(util::PaymentStatus::COMPLETED); - std::string title, message; - title = "Payment successful"; - message = "Payment successful for invoice ID " + invoiceID; - sendNotification(currentUser, title, message); + if (invoice && invoice->getStatus() != util::PaymentStatus::COMPLETED) + { + User* currentUser = invoice->getBooking()->getCustomer(); + invoice->setPaymentMethod(paymentMode); + invoice->setPaymentDate(util::Timestamp()); + invoice->setStatus(util::PaymentStatus::COMPLETED); + std::string title, message; + title = "Payment successful"; + message = "Payment successful for invoice ID " + invoiceID; + sendNotification(currentUser, title, message); + } } else { diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp index 393fe8d..c9cb818 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp @@ -83,12 +83,16 @@ void ServiceManagementService::createJobCard(const std::string& bookingID, const for (int iterator = 0; iterator < inventoryItems.getSize(); iterator++) { InventoryItem* currentInventoryItem = inventoryItems.getValueAt(iterator); - if (currentInventoryItem->getQuantity() == 0) + if (currentInventoryItem && currentInventoryItem->getQuantity() == 0) { std::string errorMessage = "Failed to create job card, " + currentInventoryItem->getPartName() + " is out of stock."; throw std::runtime_error(errorMessage); } - else + } + for (int iterator = 0; iterator < inventoryItems.getSize(); iterator++) + { + InventoryItem* currentInventoryItem = inventoryItems.getValueAt(iterator); + if (currentInventoryItem) { int currentStockQuantity = currentInventoryItem->getQuantity(); currentInventoryItem->setQuantity(currentStockQuantity - 1); @@ -99,8 +103,15 @@ void ServiceManagementService::createJobCard(const std::string& bookingID, const std::string title = "Job card created"; std::string message = "Job card created for the service and you are assigned for that."; JobCard* jobCard = Factory::getObject(bookingID, currentBooking, currentService, serviceID, technicianID, selectedTechnician, util::Timestamp(), util::ServiceJobStatus::STARTED, util::Timestamp()); - currentJobCards.insert(jobCard->getId(), jobCard); - sendNotification(selectedTechnician,title, message); + if (jobCard) + { + currentJobCards.insert(jobCard->getId(), jobCard); + sendNotification(selectedTechnician, title, message); + } + else + { + throw std::runtime_error("Failed to create job card."); + } } /* @@ -177,7 +188,7 @@ Throws: */ void ServiceManagementService::removeService(const std::string& serviceID) { - util::Map currentServices = getServices(); + util::Map& currentServices = m_dataStore.getServices(); if (currentServices.find(serviceID) != -1) { currentServices.getValueAt(currentServices.find(serviceID))->setState(util::State::INACTIVE); @@ -238,7 +249,7 @@ util::Map ServiceManagementService::getJobCards(const std } /* -Function: hasAllJobCardsinServiceBookingCompleted (static helper) +Function: hasCompletedAllJobs (static helper) Description: Checks if all job cards for a given service booking are completed. Parameters: - bookingId: std::string, ID of the service booking @@ -246,7 +257,7 @@ Parameters: Returns: - bool: True if all job cards are completed, False otherwise */ -static bool hasAllJobCardsinServiceBookingCompleted(std::string bookingId, util::Map& currentAssignedJobs) +static bool hasCompletedAllJobs(std::string bookingId, util::Map& currentAssignedJobs) { for (int iterator = 0; iterator < currentAssignedJobs.getSize(); iterator++) { @@ -312,7 +323,7 @@ void ServiceManagementService::completeJob(const std::string& jobID) throw std::runtime_error("Failed to complete the job, some error occured or job already completed."); } - serviceBookingCompleted = hasAllJobCardsinServiceBookingCompleted(currentJob->getBookingId(), currentAssignedJobs); + serviceBookingCompleted = hasCompletedAllJobs(currentJob->getBookingId(), currentAssignedJobs); if (serviceBookingCompleted) { currentJob->getBooking()->setStatus(util::ServiceJobStatus::COMPLETED); diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h index f198108..7dda730 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h @@ -130,7 +130,7 @@ namespace util case ServiceJobStatus::COMPLETED: return "COMPLETED"; case ServiceJobStatus::PENDING: - return "STARTED"; + return "PENDING"; } throw std::invalid_argument("Invalid ServiceJobStatus"); } @@ -145,6 +145,10 @@ namespace util { return ServiceJobStatus::COMPLETED; } + if (value == "PENDING") + { + return ServiceJobStatus::PENDING; + } throw std::invalid_argument("Invalid ServiceJobStatus string"); } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp index b539aa8..43cccc1 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp @@ -1,11 +1,11 @@ #include #include "AdminMenu.h" +#include "MenuHelper.h" #include "Service.h" #include "InputHelper.h" #include "OutputHelper.h" #include "ServiceBooking.h" #include "Enums.h" -#include "Service.h" #include "InventoryItem.h" void AdminMenu::showMenu() @@ -62,148 +62,6 @@ void AdminMenu::checkStockAvailability() { } -/* -Function: listServiceBookings (static helper) -Description: Lists all pending service bookings and maps them to indices for selection. -Parameters: - - currentBookings: util::Map&, current bookings - - bookingsSize: int&, number of bookings - - serviceBookingsMap: util::Map&, map of indexed bookings -Returns: - - bool: True if pending services exist, False otherwise -*/ -static bool listServiceBookings(util::Map& currentBookings, int& bookingsSize, util::Map& serviceBookingsMap) -{ - int currentIndex = 1; - bool hasPendingService = false; - std::cout << std::left - << std::setw(10) << "Index" - << std::setw(10) << "ID" - << std::setw(12) << "Status" - << std::setw(12) << "CustID" - << std::setw(20) << "Customer" - << std::setw(15) << "VehicleNo" - << std::setw(15) << "Brand" - << std::setw(15) << "Model" - << std::setw(20) << "Technician" - << std::setw(15) << "TechID" - << std::endl; - for (int iterator = 0; iterator < bookingsSize; iterator++) - { - const ServiceBooking* currentBooking = currentBookings.getValueAt(iterator); - if (currentBooking && currentBooking->getStatus() == util::ServiceJobStatus::PENDING) - { - hasPendingService = true; - std::cout << std::left - << std::setw(10) << currentIndex - << std::setw(10) << currentBooking->getId() - << std::setw(12) << util::getServiceJobStatusString(currentBooking->getStatus()) - << std::setw(12) << currentBooking->getCustomerId() - << std::setw(20) << currentBooking->getCustomer()->getName() - << std::setw(15) << currentBooking->getVehicleNumber() - << std::setw(15) << currentBooking->getVehicleBrand() - << std::setw(15) << currentBooking->getVehicleModel() - << std::setw(20) << (currentBooking->getAssignedTechnician() == nullptr ? "Null" : currentBooking->getAssignedTechnician()->getName()) - << std::setw(15) << (currentBooking->getAssignedTechnicianId().empty() ? "Null" : currentBooking->getAssignedTechnicianId()) - << std::endl; - serviceBookingsMap.insert(currentIndex++, currentBooking); - } - } - if (!hasPendingService) - { - std::cout << "No pending service available." << std::endl; - return false; - } - return true; -} - -/* -Function: selectPendingServiceBookings (static helper) -Description: Allows selection of a pending service booking by index. -Parameters: - - serviceBookingsMap: util::Map&, map of indexed bookings -Returns: - - const ServiceBooking*: Pointer to the selected booking, or nullptr if invalid -*/ -static const ServiceBooking* selectPendingServiceBookings(util::Map& serviceBookingsMap) -{ - int userInputIndex; - std::cout << "Enter a valid service index: "; - util::read(userInputIndex); - if (serviceBookingsMap.find(userInputIndex) != -1) - { - return serviceBookingsMap.getValueAt(userInputIndex); - } - else - { - std::cout << "Enter a valid index."; - return nullptr; - } -} - -/* -Function: listAvailableTechnicians (static helper) -Description: Lists all available technicians and maps them to indices for selection. -Parameters: - - currentAvailableTechnicians: util::Map, available technicians - - numberOfTechnicians: int, number of technicians - - currentAvailableTechniciansMap: util::Map&, map of indexed technicians -Returns: - - void -*/ -static void listAvailableTechnicians( util::Map currentAvailableTechnicians, int numberOfTechnicians, util::Map& currentAvailableTechniciansMap) -{ - bool hasTechnicians = false; - int currentIndex = 1; - std::cout << std::left - << std::setw(6) << "Index" - << std::setw(15) << "Technician ID" - << std::setw(20) << "Name" - << std::endl; - for (int iterator = 0; iterator < numberOfTechnicians; iterator++) - { - const User* currentTechnician = currentAvailableTechnicians.getValueAt(iterator); - if (currentTechnician->getState() == util::State::INACTIVE) - { - continue; - } - hasTechnicians = true; - std::cout << std::left - << std::setw(6) << currentIndex - << std::setw(15) << currentTechnician->getId() - << std::setw(20) << currentTechnician->getName() - << std::endl; - currentAvailableTechniciansMap.insert(currentIndex++, currentTechnician); - } - if (!hasTechnicians) - { - std::cout << "No technicians currently available."; - } -} - -/* -Function: selectTechnician (static helper) -Description: Allows selection of a technician by index. -Parameters: - - currentAvailableTechniciansMap: util::Map&, map of indexed technicians -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; - } -} - /* Function: assignJob Description: Allows the admin to assign pending service bookings to available technicians. @@ -247,81 +105,7 @@ void AdminMenu::assignJob() } } } - -} - -/* -Function: selectInventoryItems (static helper) -Description: Allows selection of inventory items by index for creating a service. -Parameters: - - currentInventoryItems: util::Map&, available inventory items - - selectedInventoryItems: util::Vector&, vector to store selected item IDs -Returns: - - void -*/ -static void selectInventoryItems(util::Map& currentInventoryItems, util::Vector& selectedInventoryItems) -{ - bool doRun = true, hasInventoryItems = false; - util::Map currentInventoryMap; - int currentIndex = 1; - int choice; - if (currentInventoryItems.getSize() == 0) - { - std::cout << "Inventory empty."; - } - while (doRun) - { - bool hasInventoryItems = false; - int currentIndex = 1; - currentInventoryMap.clear(); - std::cout << std::left - << std::setw(6) << "Index" - << std::setw(12) << "Item ID" - << std::setw(20) << "Part Name" - << std::setw(10) << "Price" - << std::setw(10) << "Quantity" - << std::endl; - for (int iterator = 0; iterator < currentInventoryItems.getSize(); iterator++) - { - const InventoryItem* currentInventoryItem = currentInventoryItems.getValueAt(iterator); - if (currentInventoryItem->getState() == util::State::INACTIVE) - { - continue; - } - std::cout << std::left - << std::setw(6) << currentIndex - << std::setw(12) << currentInventoryItem->getId() - << std::setw(20) << currentInventoryItem->getPartName() - << std::setw(10) << currentInventoryItem->getPrice() - << std::setw(10) << currentInventoryItem->getQuantity() - << std::endl; - - hasInventoryItems = true; - currentInventoryMap.insert(currentIndex++, currentInventoryItem); - } - if (!hasInventoryItems) - { - std::cout << "No items present in the inventory." << std::endl; - doRun = false; - break; - } - std::cout << "Select the item (Index) or enter -1 to exit: "; - util::read(choice); - - if (choice == -1) - { - doRun = false; - } - else if (currentInventoryMap.find(choice) != -1) - { - selectedInventoryItems.push_back(currentInventoryMap.getValueAt(choice)->getId()); - std::cout << "Item added successfully." << std::endl; - } - else - { - std::cout << "Enter a valid integer." << std::endl; - } - } + util::pressEnter(); } /* @@ -346,59 +130,7 @@ void AdminMenu::createService() util::read(labourCost); m_controller.createService(serviceName, selectedInventoryItems, labourCost); std::cout << "Service created sucessfully.\n"; -} - -/* -Function: selectServicesToRemove (static helper) -Description: Allows selection of a service to remove by index. -Parameters: - - currentServices: util::Map, available services -Returns: - - std::string: ID of the selected service, or empty string if invalid -*/ -static std::string selectServicesToRemove(util::Map currentServices) -{ - util::Map currentServicesMap; - bool hasServices = false; - int currentIndex = 1, choice; - std::cout << std::left - << std::setw(6) << "Index" - << std::setw(12) << "Service ID" - << std::setw(20) << "Name" - << std::setw(10) << "Labor Cost" - << std::endl; - for (int iterator = 0; iterator < currentServices.getSize(); iterator++) - { - const Service* currentService = currentServices.getValueAt(iterator); - if (currentService->getState() == util::State::INACTIVE) - { - continue; - } - std::cout << std::left - << std::setw(6) << currentIndex - << std::setw(12) << currentService->getId() - << std::setw(20) << currentService->getName() - << std::setw(10) << currentService->getLaborCost() - << std::endl; - hasServices = true; - currentServicesMap.insert(currentIndex++, currentService); - } - if (!hasServices) - { - std::cout << "No services currently available." << std::endl; - return ""; - } - std::cout << "Enter your choice: "; - util::read(choice); - if (currentServicesMap.find(choice) != -1) - { - return currentServicesMap.getValueAt(currentServicesMap.find(choice))->getId(); - } - else - { - std::cout << "Invalid choice." << std::endl; - return ""; - } + util::pressEnter(); } /* @@ -424,6 +156,7 @@ void AdminMenu::removeService() { std::cout << "Failed to remove service."; } + util::pressEnter(); } void AdminMenu::addTechnician() @@ -444,4 +177,4 @@ void AdminMenu::removeComboPackage() void AdminMenu::viewNotifications() { -} +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp index 11f3706..dde094c 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp @@ -2,6 +2,7 @@ #include #include "CustomerMenu.h" #include "InputHelper.h" +#include "MenuHelper.h" #include "OutputHelper.h" #include "Invoice.h" #include "Enums.h" @@ -109,98 +110,7 @@ void CustomerMenu::viewServiceHistory() { std::cout << "No history available." << std::endl; } -} - -/* -Function: selectInvoiceFromUserForPayment (static helper) -Description: Lists all pending invoices for the customer and allows selection by index. -Parameters: - - currentInvoices: util::Map&, map of customer invoices -Returns: - - std::string: ID of the selected invoice, or empty string if none selected -*/ -static std::string selectInvoiceFromUserForPayment(const util::Map& currentInvoices) -{ - int currentIndex = 1, choice; - util::Map pendingInvoicesForPayment; - std::cout << std::left - << std::setw(6) << "Index" - << std::setw(12) << "BookingID" - << std::setw(15) << "VehicleBrand" - << std::setw(15) << "VehicleNumber" - << std::setw(12) << "TechID" - << std::setw(20) << "TechnicianName" - << std::setw(10) << "Discount(%)" - << std::setw(12) << "TotalAmount" - << std::setw(20) << "InvoiceDate" - << std::endl; - for (int iterator = 0; iterator < currentInvoices.getSize(); iterator++) - { - const Invoice* currentInvoice = currentInvoices.getValueAt(iterator); - if (currentInvoice && currentInvoice->getStatus() == util::PaymentStatus::PENDING) - { - std::cout << std::left - << std::setw(6) << currentIndex - << std::setw(12) << currentInvoice->getBookingId() - << std::setw(15) << currentInvoice->getBooking()->getVehicleBrand() - << std::setw(15) << currentInvoice->getBooking()->getVehicleNumber() - << std::setw(12) << currentInvoice->getBooking()->getAssignedTechnician()->getId() - << std::setw(20) << currentInvoice->getBooking()->getAssignedTechnician()->getName() - << std::setw(10) << currentInvoice->getDiscountPercentage() - << std::setw(12) << currentInvoice->getTotalAmount() - << std::setw(20) << currentInvoice->getInvoiceDate().toString() - << std::endl; - pendingInvoicesForPayment.insert(currentIndex++, currentInvoice); - } - } - if (pendingInvoicesForPayment.getSize() == 0) - { - std::cout << "No pending invoices available for payment.\n"; - return ""; - } - std::cout << "Select the Invoice to pay (Index): "; - util::read(choice); - int selectedIndex = pendingInvoicesForPayment.find(choice); - if (selectedIndex != -1) - { - const Invoice* selectedInvoice = pendingInvoicesForPayment.getValueAt(selectedIndex); - return selectedInvoice->getId(); - } - else - { - std::cout << "Invalid choice.\n"; - return ""; - } -} - -/* -Function: selectPaymentMode (static helper) -Description: Allows the customer to select a payment mode (ONLINE or OFFLINE). -Parameters: - - None -Returns: - - util::PaymentMode: Selected payment mode -*/ -static util::PaymentMode selectPaymentMode() -{ - int choice; - std::cout << "Enter the payment Mode\n1.OFFLINE\n2.ONLINE\nChoice: "; - util::read(choice); - if (choice == 1) - { - std::cout << "Offline mode selected.\n"; - return util::PaymentMode::OFFLINE; - } - else if (choice == 2) - { - std::cout << "Online mode selected.\n"; - return util::PaymentMode::ONLINE; - } - else - { - std::cout << "Invalid choice, Offline mode selected.\n"; - return util::PaymentMode::OFFLINE; - } + util::pressEnter(); } /* @@ -225,68 +135,7 @@ void CustomerMenu::completePayments() util::PaymentMode paymentMode = selectPaymentMode(); m_controller.completePayment(selectedID, paymentMode); std::cout << "Payment completed successfully.\n"; -} - -/* -Function: displayInvoices (static helper) -Description: Displays detailed information for all invoices associated with the customer, - including booking details, technician, discount, total amount, payment status, and items used. -Parameters: - - currentUserInvoices: util::Map, customer’s invoices -Returns: - - void -Throws: - - std::runtime_error if a null invoice is encountered -*/ -static void displayInvoices(util::Map currentUserInvoices) -{ - if (currentUserInvoices.getSize() == 0) - { - std::cout << "No invoices found for this account." << std::endl; - util::pressEnter(); - return; - } - else - { - for (int index = 0; index < currentUserInvoices.getSize(); index++) - { - const Invoice* currentInvoice = currentUserInvoices.getValueAt(index); - if (currentInvoice) - { - std::cout << "\nInvoice Details\n"; - std::cout << "Booking ID: " << currentInvoice->getBookingId() << std::endl; - std::cout << "Vehicle Brand: " << currentInvoice->getBooking()->getVehicleBrand() << std::endl; - std::cout << "Vehicle Number: " << currentInvoice->getBooking()->getVehicleNumber() << std::endl; - std::cout << "Technician ID: " << currentInvoice->getBooking()->getAssignedTechnician()->getId() << std::endl; - std::cout << "Technician Name: " << currentInvoice->getBooking()->getAssignedTechnician()->getName() << std::endl; - std::cout << "Discount(%): " << currentInvoice->getDiscountPercentage() << std::endl; - std::cout << "Total Amount: " << currentInvoice->getTotalAmount() << std::endl; - std::cout << "Invoice Date: " << currentInvoice->getInvoiceDate().toString() << std::endl; - std::cout << "Payment Status: " << util::getPaymentStatusString(currentInvoice->getStatus()) << std::endl; - auto inventoryItemsInInvoice = currentInvoice->getParts(); - std::cout << "\nItems Used:\n"; - std::cout << std::left - << std::setw(20) << "ItemName" - << std::setw(10) << "Quantity" - << std::setw(10) << "Price" - << std::endl; - std::cout << std::string(40, '-') << std::endl; - for (int iterator = 0; iterator < inventoryItemsInInvoice.getSize(); iterator++) - { - InventoryItem* currentItem = inventoryItemsInInvoice.getValueAt(iterator); - std::cout << std::left - << std::setw(20) << currentItem->getPartName() - << std::setw(10) << currentItem->getQuantity() - << std::setw(10) << currentItem->getPrice() - << std::endl; - } - } - else - { - throw std::runtime_error("Null invoice encountered while displaying invoices."); - } - } - } + util::pressEnter(); } /* @@ -302,6 +151,7 @@ void CustomerMenu::viewInvoices() util::clear(); util::Map currentUserInvoices = m_controller.getInvoicesByUser(); displayInvoices(currentUserInvoices); + util::pressEnter(); } void CustomerMenu::viewNotifications() @@ -310,4 +160,4 @@ void CustomerMenu::viewNotifications() void CustomerMenu::configureNotifications() { -} +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h new file mode 100644 index 0000000..975fcc7 --- /dev/null +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h @@ -0,0 +1,501 @@ +#include +#include "Service.h" +#include "Enums.h" +#include "User.h" +#include "JobCard.h" +#include "InventoryItem.h" +#include "Invoice.h" +#include "ServiceBooking.h" +#include "Map.h" +#include "Timestamp.h" +#include "InputHelper.h" +#include "OutputHelper.h" + +/* +Function: selectServicesToRemove (static helper) +Description: Allows selection of a service to remove by index. +Parameters: + - currentServices: util::Map, available services +Returns: + - std::string: ID of the selected service, or empty string if invalid +*/ +inline std::string selectServicesToRemove(util::Map currentServices) +{ + util::Map currentServicesMap; + bool hasServices = false; + int currentIndex = 1, choice; + std::cout << std::left + << std::setw(6) << "Index" + << std::setw(12) << "Service ID" + << std::setw(20) << "Name" + << std::setw(10) << "Labor Cost" + << std::endl; + for (int iterator = 0; iterator < currentServices.getSize(); iterator++) + { + const Service* currentService = currentServices.getValueAt(iterator); + if (currentService->getState() == util::State::INACTIVE) + { + continue; + } + std::cout << std::left + << std::setw(6) << currentIndex + << std::setw(12) << currentService->getId() + << std::setw(20) << currentService->getName() + << std::setw(10) << currentService->getLaborCost() + << std::endl; + hasServices = true; + currentServicesMap.insert(currentIndex++, currentService); + } + if (!hasServices) + { + std::cout << "No services currently available." << std::endl; + return ""; + } + std::cout << "Enter your choice: "; + util::read(choice); + if (currentServicesMap.find(choice) != -1) + { + return currentServicesMap.getValueAt(currentServicesMap.find(choice))->getId(); + } + else + { + std::cout << "Invalid choice." << std::endl; + return ""; + } +} + +/* +Function: selectInventoryItems (static helper) +Description: Allows selection of inventory items by index for creating a service. +Parameters: + - currentInventoryItems: util::Map&, available inventory items + - selectedInventoryItems: util::Vector&, vector to store selected item IDs +Returns: + - void +*/ +static void selectInventoryItems(util::Map& currentInventoryItems, util::Vector& selectedInventoryItems) +{ + bool doRun = true, hasInventoryItems = false; + util::Map currentInventoryMap; + int currentIndex = 1; + int choice; + if (currentInventoryItems.getSize() == 0) + { + std::cout << "Inventory empty."; + } + while (doRun) + { + bool hasInventoryItems = false; + int currentIndex = 1; + currentInventoryMap.clear(); + std::cout << std::left + << std::setw(6) << "Index" + << std::setw(12) << "Item ID" + << std::setw(20) << "Part Name" + << std::setw(10) << "Price" + << std::setw(10) << "Quantity" + << std::endl; + for (int iterator = 0; iterator < currentInventoryItems.getSize(); iterator++) + { + const InventoryItem* currentInventoryItem = currentInventoryItems.getValueAt(iterator); + if (currentInventoryItem->getState() == util::State::INACTIVE) + { + continue; + } + std::cout << std::left + << std::setw(6) << currentIndex + << std::setw(12) << currentInventoryItem->getId() + << std::setw(20) << currentInventoryItem->getPartName() + << std::setw(10) << currentInventoryItem->getPrice() + << std::setw(10) << currentInventoryItem->getQuantity() + << std::endl; + + hasInventoryItems = true; + currentInventoryMap.insert(currentIndex++, currentInventoryItem); + } + if (!hasInventoryItems) + { + std::cout << "No items present in the inventory." << std::endl; + doRun = false; + break; + } + std::cout << "Select the item (Index) or enter -1 to exit: "; + util::read(choice); + + if (choice == -1) + { + doRun = false; + } + else if (currentInventoryMap.find(choice) != -1) + { + selectedInventoryItems.push_back(currentInventoryMap.getValueAt(choice)->getId()); + std::cout << "Item added successfully." << std::endl; + } + else + { + std::cout << "Enter a valid integer." << std::endl; + } + } +} + +/* +Function: listServiceBookings (static helper) +Description: Lists all pending service bookings and maps them to indices for selection. +Parameters: + - currentBookings: util::Map&, current bookings + - bookingsSize: int&, number of bookings + - serviceBookingsMap: util::Map&, map of indexed bookings +Returns: + - bool: True if pending services exist, False otherwise +*/ +static bool listServiceBookings(util::Map& currentBookings, int& bookingsSize, util::Map& serviceBookingsMap) +{ + int currentIndex = 1; + bool hasPendingService = false; + std::cout << std::left + << std::setw(10) << "Index" + << std::setw(10) << "ID" + << std::setw(12) << "Status" + << std::setw(12) << "CustID" + << std::setw(20) << "Customer" + << std::setw(15) << "VehicleNo" + << std::setw(15) << "Brand" + << std::setw(15) << "Model" + << std::setw(20) << "Technician" + << std::setw(15) << "TechnicianID" + << 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::setw(10) << currentBooking->getId() + << std::setw(12) << util::getServiceJobStatusString(currentBooking->getStatus()) + << std::setw(12) << currentBooking->getCustomerId() + << std::setw(20) << currentBooking->getCustomer()->getName() + << std::setw(15) << currentBooking->getVehicleNumber() + << std::setw(15) << currentBooking->getVehicleBrand() + << std::setw(15) << currentBooking->getVehicleModel() + << std::setw(20) << ((currentAssignedTechnician == nullptr || currentAssignedTechnician->getName().empty()) ? "Null" : currentAssignedTechnician->getName()) + << std::setw(15) << ((currentAssignedTechnician == nullptr || currentAssignedTechnician->getId().empty()) ? "Null" : currentAssignedTechnician->getId()) + << std::endl; + serviceBookingsMap.insert(currentIndex++, currentBooking); + } + } + if (!hasPendingService) + { + std::cout << "No pending service available." << std::endl; + return false; + } + return true; +} + +/* +Function: selectPendingServiceBookings (static helper) +Description: Allows selection of a pending service booking by index. +Parameters: + - serviceBookingsMap: util::Map&, map of indexed bookings +Returns: + - const ServiceBooking*: Pointer to the selected booking, or nullptr if invalid +*/ +static const ServiceBooking* selectPendingServiceBookings(util::Map& serviceBookingsMap) +{ + int userInputIndex; + std::cout << "Enter a valid service index: "; + util::read(userInputIndex); + if (serviceBookingsMap.find(userInputIndex) != -1) + { + return serviceBookingsMap.getValueAt(userInputIndex); + } + else + { + std::cout << "Enter a valid index."; + return nullptr; + } +} + +/* +Function: listAvailableTechnicians (static helper) +Description: Lists all available technicians and maps them to indices for selection. +Parameters: + - currentAvailableTechnicians: util::Map, available technicians + - numberOfTechnicians: int, number of technicians + - currentAvailableTechniciansMap: util::Map&, map of indexed technicians +Returns: + - void +*/ +static void listAvailableTechnicians(util::Map currentAvailableTechnicians, int numberOfTechnicians, util::Map& currentAvailableTechniciansMap) +{ + bool hasTechnicians = false; + int currentIndex = 1; + std::cout << std::left + << std::setw(6) << "Index" + << std::setw(15) << "Technician ID" + << std::setw(20) << "Name" + << std::endl; + for (int iterator = 0; iterator < numberOfTechnicians; iterator++) + { + const User* currentTechnician = currentAvailableTechnicians.getValueAt(iterator); + if (currentTechnician->getState() == util::State::INACTIVE) + { + continue; + } + hasTechnicians = true; + std::cout << std::left + << std::setw(6) << currentIndex + << std::setw(15) << currentTechnician->getId() + << std::setw(20) << currentTechnician->getName() + << std::endl; + currentAvailableTechniciansMap.insert(currentIndex++, currentTechnician); + } + if (!hasTechnicians) + { + std::cout << "No technicians currently available."; + } +} + +/* +Function: selectTechnician (static helper) +Description: Allows selection of a technician by index. +Parameters: + - currentAvailableTechniciansMap: util::Map&, map of indexed technicians +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; + } +} + +/* +Function: selectInvoiceFromUserForPayment (static helper) +Description: Lists all pending invoices for the customer and allows selection by index. +Parameters: + - currentInvoices: util::Map&, map of customer invoices +Returns: + - std::string: ID of the selected invoice, or empty string if none selected +*/ +static std::string selectInvoiceFromUserForPayment(const util::Map& currentInvoices) +{ + int currentIndex = 1, choice; + util::Map pendingInvoicesForPayment; + std::cout << std::left + << std::setw(6) << "Index" + << std::setw(12) << "BookingID" + << std::setw(15) << "VehicleBrand" + << std::setw(15) << "VehicleNumber" + << std::setw(12) << "TechID" + << std::setw(20) << "TechnicianName" + << std::setw(10) << "Discount(%)" + << std::setw(12) << "TotalAmount" + << std::setw(20) << "InvoiceDate" + << std::endl; + for (int iterator = 0; iterator < currentInvoices.getSize(); iterator++) + { + const Invoice* currentInvoice = currentInvoices.getValueAt(iterator); + if (currentInvoice && currentInvoice->getStatus() == util::PaymentStatus::PENDING) + { + const User* currentTechnician = currentInvoice->getBooking()->getAssignedTechnician(); + std::cout << std::left + << std::setw(6) << currentIndex + << std::setw(12) << currentInvoice->getBookingId() + << std::setw(15) << currentInvoice->getBooking()->getVehicleBrand() + << std::setw(15) << currentInvoice->getBooking()->getVehicleNumber() + << std::setw(12) << ((currentTechnician != nullptr && currentTechnician->getId() != "") ? + currentTechnician->getId() : "Null") + << std::setw(20) << ((currentTechnician != nullptr && currentTechnician->getName() != "") ? + currentTechnician->getName() : "Null") + << std::setw(10) << currentInvoice->getDiscountPercentage() + << std::setw(12) << currentInvoice->getTotalAmount() + << std::setw(20) << currentInvoice->getInvoiceDate().toString() + << std::endl; + pendingInvoicesForPayment.insert(currentIndex++, currentInvoice); + } + } + if (pendingInvoicesForPayment.getSize() == 0) + { + std::cout << "No pending invoices available for payment.\n"; + return ""; + } + std::cout << "Select the Invoice to pay (Index): "; + util::read(choice); + int selectedIndex = pendingInvoicesForPayment.find(choice); + if (selectedIndex != -1) + { + const Invoice* selectedInvoice = pendingInvoicesForPayment.getValueAt(selectedIndex); + return selectedInvoice->getId(); + } + else + { + std::cout << "Invalid choice.\n"; + return ""; + } +} + +/* +Function: selectPaymentMode (static helper) +Description: Allows the customer to select a payment mode (ONLINE or OFFLINE). +Parameters: + - None +Returns: + - util::PaymentMode: Selected payment mode +*/ +static util::PaymentMode selectPaymentMode() +{ + int choice; + std::cout << "Enter the payment Mode\n1.OFFLINE\n2.ONLINE\nChoice: "; + util::read(choice); + if (choice == 1) + { + std::cout << "Offline mode selected.\n"; + return util::PaymentMode::OFFLINE; + } + else if (choice == 2) + { + std::cout << "Online mode selected.\n"; + return util::PaymentMode::ONLINE; + } + else + { + std::cout << "Invalid choice, Offline mode selected.\n"; + return util::PaymentMode::OFFLINE; + } +} + +/* +Function: displayInvoices (static helper) +Description: Displays detailed information for all invoices associated with the customer, + including booking details, technician, discount, total amount, payment status, and items used. +Parameters: + - currentUserInvoices: util::Map, customer’s invoices +Returns: + - void +Throws: + - std::runtime_error if a null invoice is encountered +*/ +static void displayInvoices(util::Map currentUserInvoices) +{ + if (currentUserInvoices.getSize() == 0) + { + std::cout << "No invoices found for this account." << std::endl; + util::pressEnter(); + return; + } + else + { + for (int index = 0; index < currentUserInvoices.getSize(); index++) + { + const Invoice* currentInvoice = currentUserInvoices.getValueAt(index); + if (currentInvoice) + { + const User* currentTechnician = currentInvoice->getBooking()->getAssignedTechnician(); + std::cout << "\nInvoice Details\n"; + std::cout << "Booking ID: " << currentInvoice->getBookingId() << std::endl; + std::cout << "Vehicle Brand: " << currentInvoice->getBooking()->getVehicleBrand() << std::endl; + std::cout << "Vehicle Number: " << currentInvoice->getBooking()->getVehicleNumber() << std::endl; + std::cout << "Technician ID: " << + ((currentTechnician != nullptr && currentTechnician->getId() != "") ? + currentTechnician->getId() : "Null") << std::endl; + std::cout << "Technician Name: " << + ((currentTechnician != nullptr && currentTechnician->getName() != "") ? + currentTechnician->getName() : "Null") << std::endl; + std::cout << "Discount(%): " << currentInvoice->getDiscountPercentage() << std::endl; + std::cout << "Total Amount: " << currentInvoice->getTotalAmount() << std::endl; + std::cout << "Invoice Date: " << currentInvoice->getInvoiceDate().toString() << std::endl; + std::cout << "Payment Status: " << util::getPaymentStatusString(currentInvoice->getStatus()) << std::endl; + auto inventoryItemsInInvoice = currentInvoice->getParts(); + std::cout << "\nItems Used:\n"; + std::cout << std::left + << std::setw(20) << "ItemName" + << std::setw(10) << "Quantity" + << std::setw(10) << "Price" + << std::endl; + std::cout << std::string(40, '-') << std::endl; + for (int iterator = 0; iterator < inventoryItemsInInvoice.getSize(); iterator++) + { + InventoryItem* currentItem = inventoryItemsInInvoice.getValueAt(iterator); + std::cout << std::left + << std::setw(20) << currentItem->getPartName() + << std::setw(10) << currentItem->getQuantity() + << std::setw(10) << currentItem->getPrice() + << std::endl; + } + } + else + { + throw std::runtime_error("Null invoice encountered while displaying invoices."); + util::pressEnter(); + } + } + } +} + +/* +Function: selectJobCardToComplete (static helper) +Description: Lists all incomplete job cards assigned to the technician and allows selection by index. +Parameters: + - assignedJobCards: util::Map&, job cards assigned to the technician + - incompleteJobCards: util::Map&, map of incomplete job cards indexed for selection +Returns: + - std::string: ID of the selected job card, or empty string if none selected +*/ +static std::string selectJobCardToComplete(util::Map& assignedJobCards, util::Map& incompleteJobCards) +{ + int currentIndex = 1; + int choice; + bool hasIncompleteJobCard = false; + std::cout << std::left + << std::setw(6) << "Index" + << std::setw(12) << "BookingID" + << std::setw(12) << "JobID" + << std::setw(20) << "ServiceName" + << std::setw(12) << "ServiceID" + << std::endl; + for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++) + { + const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator); + if (currentJobCard && (currentJobCard->getStatus() == util::ServiceJobStatus::STARTED)) + { + std::cout << std::left << std::setw(6) << currentIndex + << std::setw(12) << currentJobCard->getBookingId() + << std::setw(12) << currentJobCard->getId() + << std::setw(20) << currentJobCard->getService()->getName() + << std::setw(12) << currentJobCard->getServiceId() + << std::endl; + hasIncompleteJobCard = true; + incompleteJobCards.insert(currentIndex++, currentJobCard); + } + } + if (!hasIncompleteJobCard) + { + std::cout << "No pending jobs are present.\n"; + return ""; + } + std::cout << "Select the Job Card to complete (Index): "; + util::read(choice); + int selectedJobCardIndex = incompleteJobCards.find(choice); + if (selectedJobCardIndex != -1) + { + const JobCard* selectedJobCard = incompleteJobCards.getValueAt(selectedJobCardIndex); + return selectedJobCard->getId(); + } + else + { + std::cout << "Invalid choice.\n"; + return ""; + } +} \ 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 041877e..1779ff5 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp @@ -1,6 +1,7 @@ #include #include "TechnicianMenu.h" #include "InputHelper.h" +#include "MenuHelper.h" #include "OutputHelper.h" #include "JobCard.h" #include "Enums.h" @@ -35,62 +36,6 @@ bool TechnicianMenu::handleOperation(int choice) return false; } -/* -Function: selectJobCardToComplete (static helper) -Description: Lists all incomplete job cards assigned to the technician and allows selection by index. -Parameters: - - assignedJobCards: util::Map&, job cards assigned to the technician - - incompleteJobCards: util::Map&, map of incomplete job cards indexed for selection -Returns: - - std::string: ID of the selected job card, or empty string if none selected -*/ -static std::string selectJobCardToComplete(util::Map& assignedJobCards, util::Map& incompleteJobCards) -{ - int currentIndex = 1; - int choice; - bool hasIncompleteJobCard = false; - std::cout << std::left - << std::setw(6) << "Index" - << std::setw(12) << "BookingID" - << std::setw(12) << "JobID" - << std::setw(20) << "ServiceName" - << std::setw(12) << "ServiceID" - << std::endl; - for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++) - { - const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator); - if (currentJobCard && (currentJobCard->getStatus() == util::ServiceJobStatus::STARTED)) - { - std::cout << std::left << std::setw(6) << currentIndex - << std::setw(12) << currentJobCard->getBookingId() - << std::setw(12) << currentJobCard->getId() - << std::setw(20) << currentJobCard->getService()->getName() - << std::setw(12) << currentJobCard->getServiceId() - << std::endl; - hasIncompleteJobCard = true; - incompleteJobCards.insert(currentIndex++, currentJobCard); - } - } - if (!hasIncompleteJobCard) - { - std::cout << "No pending jobs are present.\n"; - return ""; - } - std::cout << "Select the Job Card to complete (Index): "; - util::read(choice); - int selectedJobCardIndex = incompleteJobCards.find(choice); - if (selectedJobCardIndex != -1) - { - const JobCard* selectedJobCard = incompleteJobCards.getValueAt(selectedJobCardIndex); - return selectedJobCard->getId(); - } - else - { - std::cout << "Invalid choice.\n"; - return ""; - } -} - /* Function: completeJob Description: Allows the technician to mark a selected job card as completed. @@ -115,8 +60,9 @@ void TechnicianMenu::completeJob() m_controller.completeJob(selectedJobID); std::cout << "Job marked as completed.\n"; } + util::pressEnter(); } void TechnicianMenu::viewNotifications() { -} +} \ No newline at end of file