From 2ea77bf9b6a445ba53fbff2cfe609e4b0c35afc1 Mon Sep 17 00:00:00 2001 From: Jissin Mathew Date: Fri, 29 May 2026 13:18:11 +0530 Subject: [PATCH 1/7] Implement Update Job Status for technician MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SER1798: Update Job Status 1. Renamed Controller and ServiceManagementService methods from completeJob to updateJobStatus for clarity and flexibility. 2. Enhanced ServiceManagementService::updateJobStatus to support transitions: - STARTED → INPROGRESS - INPROGRESS → COMPLETED (with invoice generation and customer notification). 3. Added INPROGRESS state to ServiceJobStatus enum and updated string conversion utilities. 4. Introduced filterJobCards helper to generalize job filtering by status. 5. Updated TechnicianMenu to allow technicians to select job type (Started/Inprogress) and update status accordingly. 6. Improved job display to show current status and truncated service names for readability. Acceptance Criteria: 1. Technician can select a job with status STARTED and update it to INPROGRESS. 2. Technician can select a job with status INPROGRESS and update it to COMPLETED. 3. Completed bookings automatically generate invoices and send notifications to customers. 4. Job status updates are reflected in the technician’s job list and customer view. Precondition: 1. Technician is logged into the system. 2. Assigned job cards exist with valid statuses (STARTED or INPROGRESS). 3. Datastore and payment service are available. Steps: 1. Navigate to Technician menu and choose "Update Job Status". - Verify that the system prompts for job type selection (Started/Inprogress). 2. Select a job card from the filtered list. - Verify that the job card details are displayed with status. 3. Confirm update. - Verify that the job status changes correctly. 4. For jobs updated to COMPLETED: - Verify that the booking status is updated, invoice is generated, and notification is sent. Sreeja Reghukumar, please review #1798 --- .../controllers/Controller.cpp | 4 +- .../controllers/Controller.h | 2 +- .../services/ServiceManagementService.cpp | 34 ++++++---- .../services/ServiceManagementService.h | 2 +- .../utilities/Enums.h | 7 ++ .../views/MenuHelper.h | 67 ++++++++++++++++--- .../views/TechnicianMenu.cpp | 41 ++++++++---- .../views/TechnicianMenu.h | 2 +- .../views/UserInterface.h | 2 +- 9 files changed, 120 insertions(+), 41 deletions(-) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp index 3b674ed..d27635e 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp @@ -392,9 +392,9 @@ Parameters: Returns: - void */ -void Controller::completeJob(const std::string& jobID) +void Controller::updateJobStatus(const std::string& jobID) { - m_serviceManagementService.completeJob(jobID); + m_serviceManagementService.updateJobStatus(jobID); } /* diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h index e75ebd4..a0a70bc 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h @@ -59,7 +59,7 @@ public: void createService(const std::string& name, const util::Vector& inventoryItemIDs, double laborCost); void removeService(const std::string& serviceID); util::Map getJobCardsByUser(); - void completeJob(const std::string& jobID); + void updateJobStatus(const std::string& jobID); void removeUser(const std::string& userID); void createComboPackage(const std::string& name, const util::Vector& serviceIDs, double discountPercentage); void removeComboPackage(const std::string& comboPackageID); diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp index 5cd870b..0308ced 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp @@ -1080,7 +1080,7 @@ static bool hasCompletedAllJobs(std::string bookingId, util::MapgetBookingId() == bookingId) { - if (currentJob->getStatus() == util::ServiceJobStatus::STARTED) + if (currentJob->getStatus() == util::ServiceJobStatus::STARTED || currentJob->getStatus() == util::ServiceJobStatus::INPROGRESS) { return false; } @@ -1101,7 +1101,7 @@ Returns: Throws: - std::runtime_error if technician is not authenticated, job card not found, or job already completed */ -void ServiceManagementService::completeJob(const std::string& jobID) +void ServiceManagementService::updateJobStatus(const std::string& jobID) { AuthenticationManagementService authenticationManagementService; PaymentManagementService paymentManagementService; @@ -1126,26 +1126,32 @@ void ServiceManagementService::completeJob(const std::string& jobID) } if (currentJob->getStatus() == util::ServiceJobStatus::STARTED) { - currentJob->setStatus(util::ServiceJobStatus::COMPLETED); + currentJob->setStatus(util::ServiceJobStatus::INPROGRESS); jobStatusUpdated = true; } + else if (currentJob->getStatus() == util::ServiceJobStatus::INPROGRESS) + { + currentJob->setStatus(util::ServiceJobStatus::COMPLETED); + jobStatusUpdated = true; + serviceBookingCompleted = hasCompletedAllJobs(currentJob->getBookingId(), currentAssignedJobs); + if (serviceBookingCompleted) + { + currentJob->getBooking()->setStatus(util::ServiceJobStatus::COMPLETED); + paymentManagementService.generateInvoice(currentJob->getBooking()); + std::string title = "Service Booking completed. Invoice Generated."; + std::string message = "Services completed for the booking and invoice generated."; + sendNotification(currentJob->getBooking()->getCustomer(), title, message); + } + } } else { - throw std::runtime_error("Failed to complete the job, some error occurred or job already completed."); + throw std::runtime_error("Failed to update the job."); } if (!jobStatusUpdated) { - throw std::runtime_error("Failed to complete the job, some error occurred or job already completed."); + throw std::runtime_error("Failed to update the job"); } - serviceBookingCompleted = hasCompletedAllJobs(currentJob->getBookingId(), currentAssignedJobs); - if (serviceBookingCompleted) - { - currentJob->getBooking()->setStatus(util::ServiceJobStatus::COMPLETED); - paymentManagementService.generateInvoice(currentJob->getBooking()); - std::string title = "Service Booking completed. Invoice Generated."; - std::string message = "Services completed for the booking and invoice generated."; - sendNotification(currentJob->getBooking()->getCustomer(), 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 2fdcc93..b2a4384 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h @@ -37,7 +37,7 @@ public: void createService(const std::string& name, const util::Vector& inventoryItemIDs, double laborCost); void removeService(const std::string& serviceID); util::Map getJobCards(const std::string& technicianID); - void completeJob(const std::string& jobID); + void updateJobStatus(const std::string& jobID); void cancelCustomerServiceBookings(const std::string& customerID); void cancelTechnicianJobs(const std::string& technicianID); void createComboPackage(const std::string& packageName, const util::Vector& serviceIDs, double discountPercentage); diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h index 16490f1..01c4660 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h @@ -37,6 +37,7 @@ namespace util PENDING, STARTED, COMPLETED, + INPROGRESS, CANCELLED }; @@ -209,6 +210,8 @@ namespace util return "COMPLETED"; case ServiceJobStatus::CANCELLED: return "CANCELLED"; + case ServiceJobStatus::INPROGRESS: + return "INPROGRESS"; } throw std::invalid_argument("Invalid ServiceJobStatus"); } @@ -241,6 +244,10 @@ namespace util { return ServiceJobStatus::CANCELLED; } + if (value == "INPROGRESS") + { + return ServiceJobStatus::INPROGRESS; + } throw std::invalid_argument("Invalid ServiceJobStatus string"); } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h index f65c1f4..5cabad3 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h @@ -646,7 +646,37 @@ inline util::Map filterStartedJobCards(util::MapgetStatus() == util::ServiceJobStatus::STARTED) + if (currentJobCard && (currentJobCard->getStatus() == util::ServiceJobStatus::STARTED || currentJobCard->getStatus() == util::ServiceJobStatus::INPROGRESS)) + { + startedJobCards.insert(currentJobCard->getId(), currentJobCard); + } + } + return startedJobCards; +} + +/* +Function: filterJobCards +Description: + Filters the given list of job cards and returns only those + whose status matches the specified ServiceJobStatus. + +Parameters: + - assignedJobCards: util::Map& + Map of job card IDs to JobCard pointers assigned to the technician. + - selectedJobStatus: util::ServiceJobStatus + The status type to filter job cards by. + +Returns: + - util::Map + A map containing only job cards with the specified status. +*/ +inline util::Map filterJobCards(util::Map& assignedJobCards, util::ServiceJobStatus selectedJobStatus) +{ + util::Map startedJobCards; + for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++) + { + const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator); + if (currentJobCard && currentJobCard->getStatus() == selectedJobStatus) { startedJobCards.insert(currentJobCard->getId(), currentJobCard); } @@ -675,16 +705,18 @@ inline void displayAllJobs(util::Map& assignedJobCa << std::setw(12) << "JobID" << std::setw(20) << "ServiceName" << std::setw(12) << "ServiceID" + << std::setw(12) << "Status" << std::endl; for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++) { const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator); - if (currentJobCard && (currentJobCard->getStatus() == util::ServiceJobStatus::STARTED)) + if (currentJobCard && (currentJobCard->getStatus() == util::ServiceJobStatus::STARTED || currentJobCard->getStatus() == util::ServiceJobStatus::INPROGRESS)) { std::cout << std::left << std::setw(12) << currentJobCard->getBookingId() << std::setw(12) << currentJobCard->getId() - << std::setw(20) << currentJobCard->getService()->getName() + << std::setw(20) << util::truncateString(currentJobCard->getService()->getName(), 15) << std::setw(12) << currentJobCard->getServiceId() + << std::setw(12) << util::getServiceJobStatusString(currentJobCard->getStatus()) << std::endl; } } @@ -698,16 +730,31 @@ Parameters: Returns: - std::string: ID of the selected job card, or empty string if none selected */ -inline std::string selectJobCardToComplete(util::Map& assignedJobCards) +inline std::string selectJobCardToUpdate(util::Map& assignedJobCards, util::ServiceJobStatus selectedJobStatusType) { util::Map incompleteJobCards; if (assignedJobCards.getSize() == 0) { - std::cout << "No started jobs available to complete.\n"; + std::cout << "No jobs available.\n\n"; return ""; } int currentIndex = 1; int choice; + if (selectedJobStatusType == util::ServiceJobStatus::STARTED) + { + util::clear(); + std::cout << "Select a job to update to Inprogress\n"; + } + else if (selectedJobStatusType == util::ServiceJobStatus::INPROGRESS) + { + util::clear(); + std::cout << "Select a job to update to Completed\n"; + } + else + { + std::cout << "Unable to update completed or pending jobs.\n\n"; + return ""; + } std::cout << std::endl; std::cout << std::left << std::setw(6) << "Index" @@ -715,22 +762,24 @@ inline std::string selectJobCardToComplete(util::MapgetStatus() == util::ServiceJobStatus::STARTED)) + if (currentJobCard && (currentJobCard->getStatus() == selectedJobStatusType)) { 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(20) << util::truncateString(currentJobCard->getService()->getName(), 15) << std::setw(12) << currentJobCard->getServiceId() + << std::setw(12) << util::getServiceJobStatusString(currentJobCard->getStatus()) << std::endl; incompleteJobCards.insert(currentIndex++, currentJobCard); } } - std::cout << "Select the Job Card to complete (Index): "; + std::cout << "Select the Job Card to Update (Index): "; util::read(choice); int selectedJobCardIndex = incompleteJobCards.find(choice); if (selectedJobCardIndex != -1) @@ -741,7 +790,7 @@ inline std::string selectJobCardToComplete(util::Map assignedJobCards = m_controller.getJobCardsByUser(); - util::Map startedJobCards = filterStartedJobCards(assignedJobCards); - displayAllJobs(startedJobCards); + util::Map jobCards = filterStartedJobCards(assignedJobCards); + displayAllJobs(jobCards); util::pressEnter(); } /* -Function: completeJob -Description: Allows the technician to mark a selected job card as completed. +Function: updateJobStatus +Description: Allows the technician to update a selected job card. Validates selection and updates job status through the controller. Parameters: - None Returns: - void */ -void TechnicianMenu::completeJob() +void TechnicianMenu::updateJobStatus() { util::clear(); - std::cout << "Complete Job\n"; + std::cout << "Update Job Status\n"; + int choice; + std::string selectedJobID; + util::ServiceJobStatus selectedJobStatus; util::Map assignedJobCards = m_controller.getJobCardsByUser(); - util::Map startedJobCards = filterStartedJobCards(assignedJobCards); - std::string selectedJobID = selectJobCardToComplete(startedJobCards); + std::cout << "Select the type of job you want to update\n1.Started\n2.Inprogress\nChoice: "; + util::read(choice); + if (choice == 1) + { + selectedJobStatus = util::ServiceJobStatus::STARTED; + } + else if (choice == 2) + { + selectedJobStatus = util::ServiceJobStatus::INPROGRESS; + } + else + { + throw std::runtime_error("Invalid Index"); + } + util::Map selectedTypeJobCard = filterJobCards(assignedJobCards, selectedJobStatus); + selectedJobID = selectJobCardToUpdate(selectedTypeJobCard, selectedJobStatus); if (!selectedJobID.empty()) { - m_controller.completeJob(selectedJobID); - std::cout << "\nJob marked as completed.\n\n"; + m_controller.updateJobStatus(selectedJobID); + std::cout << "\nJob status updated.\n\n"; } util::pressEnter(); } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.h index d0c5ca9..a17ccb1 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.h @@ -18,7 +18,7 @@ private: public: void showMenu(); void displayJobs(); - void completeJob(); + void updateJobStatus(); void viewNotifications(); void logout(); void changePassword(); diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.h index 501cfce..4a485de 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.h @@ -27,4 +27,4 @@ public: void run(); void login(); void registerCustomer(); -}; +}; \ No newline at end of file From 70ec47df04d6537369e025a641d433c8a9f5540a Mon Sep 17 00:00:00 2001 From: Jissin Mathew Date: Mon, 1 Jun 2026 12:17:35 +0530 Subject: [PATCH 2/7] Fix review comments --- .../services/ServiceManagementService.cpp | 29 +++++++++---------- .../utilities/Enums.h | 10 +++---- .../views/MenuHelper.h | 9 ++---- .../views/TechnicianMenu.cpp | 8 +++-- 4 files changed, 27 insertions(+), 29 deletions(-) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp index 0308ced..f6d3905 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp @@ -1080,7 +1080,7 @@ static bool hasCompletedAllJobs(std::string bookingId, util::MapgetBookingId() == bookingId) { - if (currentJob->getStatus() == util::ServiceJobStatus::STARTED || currentJob->getStatus() == util::ServiceJobStatus::INPROGRESS) + if (currentJob->getStatus() != util::ServiceJobStatus::COMPLETED && currentJob->getStatus() != util::ServiceJobStatus::CANCELLED) { return false; } @@ -1090,16 +1090,17 @@ static bool hasCompletedAllJobs(std::string bookingId, util::MapgetStatus() == util::ServiceJobStatus::STARTED) { - currentJob->setStatus(util::ServiceJobStatus::INPROGRESS); + currentJob->setStatus(util::ServiceJobStatus::IN_PROGRESS); jobStatusUpdated = true; } - else if (currentJob->getStatus() == util::ServiceJobStatus::INPROGRESS) + else if (currentJob->getStatus() == util::ServiceJobStatus::IN_PROGRESS) { currentJob->setStatus(util::ServiceJobStatus::COMPLETED); jobStatusUpdated = true; @@ -1146,12 +1147,10 @@ void ServiceManagementService::updateJobStatus(const std::string& jobID) } else { - throw std::runtime_error("Failed to update the job."); + throw std::runtime_error("Failed to update job status. Job may already be completed."); } if (!jobStatusUpdated) { - throw std::runtime_error("Failed to update the job"); + throw std::runtime_error("Failed to update job status. Job may already be completed."); } - - } \ 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 01c4660..c167b28 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h @@ -37,7 +37,7 @@ namespace util PENDING, STARTED, COMPLETED, - INPROGRESS, + IN_PROGRESS, CANCELLED }; @@ -210,8 +210,8 @@ namespace util return "COMPLETED"; case ServiceJobStatus::CANCELLED: return "CANCELLED"; - case ServiceJobStatus::INPROGRESS: - return "INPROGRESS"; + case ServiceJobStatus::IN_PROGRESS: + return "IN_PROGRESS"; } throw std::invalid_argument("Invalid ServiceJobStatus"); } @@ -244,9 +244,9 @@ namespace util { return ServiceJobStatus::CANCELLED; } - if (value == "INPROGRESS") + if (value == "IN_PROGRESS") { - return ServiceJobStatus::INPROGRESS; + return ServiceJobStatus::IN_PROGRESS; } throw std::invalid_argument("Invalid ServiceJobStatus string"); } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h index 5cabad3..0a4136a 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h @@ -627,7 +627,6 @@ inline void displayInvoices(util::Map currentUserIn std::cout << "Unable to fetch the selected invoice\n"; doRun = false; } - } while (doRun); } } @@ -646,7 +645,7 @@ inline util::Map filterStartedJobCards(util::MapgetStatus() == util::ServiceJobStatus::STARTED || currentJobCard->getStatus() == util::ServiceJobStatus::INPROGRESS)) + if (currentJobCard && (currentJobCard->getStatus() == util::ServiceJobStatus::STARTED || currentJobCard->getStatus() == util::ServiceJobStatus::IN_PROGRESS)) { startedJobCards.insert(currentJobCard->getId(), currentJobCard); } @@ -659,13 +658,11 @@ Function: filterJobCards Description: Filters the given list of job cards and returns only those whose status matches the specified ServiceJobStatus. - Parameters: - assignedJobCards: util::Map& Map of job card IDs to JobCard pointers assigned to the technician. - selectedJobStatus: util::ServiceJobStatus The status type to filter job cards by. - Returns: - util::Map A map containing only job cards with the specified status. @@ -710,7 +707,7 @@ inline void displayAllJobs(util::Map& assignedJobCa for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++) { const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator); - if (currentJobCard && (currentJobCard->getStatus() == util::ServiceJobStatus::STARTED || currentJobCard->getStatus() == util::ServiceJobStatus::INPROGRESS)) + if (currentJobCard && (currentJobCard->getStatus() == util::ServiceJobStatus::STARTED || currentJobCard->getStatus() == util::ServiceJobStatus::IN_PROGRESS)) { std::cout << std::left << std::setw(12) << currentJobCard->getBookingId() << std::setw(12) << currentJobCard->getId() @@ -745,7 +742,7 @@ inline std::string selectJobCardToUpdate(util::Map& util::clear(); std::cout << "Select a job to update to Inprogress\n"; } - else if (selectedJobStatusType == util::ServiceJobStatus::INPROGRESS) + else if (selectedJobStatusType == util::ServiceJobStatus::IN_PROGRESS) { util::clear(); std::cout << "Select a job to update to Completed\n"; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp index e358f88..5d125cc 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp @@ -119,7 +119,7 @@ void TechnicianMenu::updateJobStatus() std::cout << "Update Job Status\n"; int choice; std::string selectedJobID; - util::ServiceJobStatus selectedJobStatus; + util::ServiceJobStatus selectedJobStatus = util::ServiceJobStatus::PENDING; util::Map assignedJobCards = m_controller.getJobCardsByUser(); std::cout << "Select the type of job you want to update\n1.Started\n2.Inprogress\nChoice: "; util::read(choice); @@ -129,11 +129,13 @@ void TechnicianMenu::updateJobStatus() } else if (choice == 2) { - selectedJobStatus = util::ServiceJobStatus::INPROGRESS; + selectedJobStatus = util::ServiceJobStatus::IN_PROGRESS; } else { - throw std::runtime_error("Invalid Index"); + std::cout << "Invalid choice. Please try again.\n"; + util::pressEnter(); + return; } util::Map selectedTypeJobCard = filterJobCards(assignedJobCards, selectedJobStatus); selectedJobID = selectJobCardToUpdate(selectedTypeJobCard, selectedJobStatus); From 1032fc64bd0e51e2cc23bd223372053e376497cb Mon Sep 17 00:00:00 2001 From: Avinash Rajesh Date: Mon, 1 Jun 2026 17:30:27 +0530 Subject: [PATCH 3/7] Commit aee6356e: Implement Confirm Payment Functionality MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Complete Payments - 1797 1. Added Controller::getAllInvoices - Retrieves all invoices from PaymentManagementService and returns them as a read-only map. 2. Implemented Controller::confirmPayment - Delegates payment confirmation for a given invoice ID to PaymentManagementService. 3. Introduced PaymentManagementService::getAllInvoice - Provides access to all invoices stored in the datastore. 4. Added PaymentManagementService::confirmPayment - Confirms payment for a specific invoice, updates payment date and status, and sends notification. 5. Extended util::PaymentStatus enum - Added PAID status and updated string conversion. 6. Integrated AdminMenu::confirmPayment - Validates invoice list, filters by status, allows selection, and confirms payment. 7. Updated CustomerMenu::completePayments - Uses parameterized status filtering for invoice selection. 8. Enhanced MenuHelper::selectInvoiceFromUserForPayment - Accepts requiredStatus parameter for flexible filtering. 9. Adjusted AdminMenu options - Added "Confirm Payment" before Logout. Acceptance Criteria: 1. Admin selects "Confirm Payment" from menu. - Verify system prompts and displays invoices filtered by status. 2. Admin selects invoice with status = PAID. - Verify payment confirmation updates date, sets status, and sends notification. 3. Admin attempts confirmation with empty invoice list. - Verify error message: "No pending invoices available for confirmation." 4. Customer completes payment. - Verify selection uses util::PaymentStatus::PENDING and payment flow works correctly. 5. Invalid invoice ID entered. - Verify system throws runtime_error with "Payment failed: invalid invoice ID." Precondition: 1. Admin logged into system. 2. At least one invoice exists in datastore. 3. Notification system available. Steps: 1. Navigate to Admin menu → Confirm Payment. 2. Select invoice with PAID status. 3. Confirm payment and check notification. 4. Attempt with empty invoice list. 5. Attempt with invalid invoice ID. Sreeja Reghukumar --- .../controllers/Controller.cpp | 32 +++++++++++ .../controllers/Controller.h | 2 + .../services/PaymentManagementService.cpp | 48 +++++++++++++++- .../services/PaymentManagementService.h | 2 + .../utilities/Enums.h | 5 +- .../views/AdminMenu.cpp | 56 ++++++++++++++++++- .../views/AdminMenu.h | 1 + .../views/CustomerMenu.cpp | 2 +- .../views/MenuHelper.h | 16 ++++-- 9 files changed, 152 insertions(+), 12 deletions(-) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp index d27635e..e3a85b0 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp @@ -462,6 +462,38 @@ util::Map Controller::getInvoicesByUser() return userInvoicesReadOnly; } +/* +Function: getAllInvoices +Description: Retrieves all invoices from the PaymentManagementService and returns them as a read-only map. +Parameters: + - none +Returns: + - util::Map: Map of invoice IDs to invoice objects +*/ +util::Map Controller::getAllInvoices() +{ + auto invoices = m_paymentManagementService.getAllInvoices(); + util::Map readOnlyInvoice; + for (int iterator = 0; iterator < invoices.getSize(); iterator++) + { + readOnlyInvoice.insert(invoices.getKeyAt(iterator), invoices.getValueAt(iterator)); + } + return readOnlyInvoice; +} + +/* +Function: confirmPayment +Description: Delegates payment confirmation for a given invoice ID to the PaymentManagementService. +Parameters: + - invoiceID: std::string, ID of the invoice to confirm +Returns: + - void +*/ +void Controller::confirmPayment(const std::string& invoiceID) +{ + m_paymentManagementService.confirmPayment(invoiceID); +} + /* Function: completePayment Description: Completes payment for a specific invoice using the given payment mode. diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h index a0a70bc..35241a0 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h @@ -64,6 +64,8 @@ public: void createComboPackage(const std::string& name, const util::Vector& serviceIDs, double discountPercentage); void removeComboPackage(const std::string& comboPackageID); util::Map getInvoicesByUser(); + util::Map getAllInvoices(); + void confirmPayment(const std::string& invoiceID); void completePayment(const std::string& invoiceID, util::PaymentMode paymentMode); util::Vector getNotifications(); void deleteNotification(const std::string& notificationID); diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp index 2733577..1fc1ff8 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp @@ -368,12 +368,12 @@ void PaymentManagementService::completePayment(const std::string& invoiceID, uti if (invoiceIndex != -1) { Invoice* invoice = currentInvoices.getValueAt(invoiceIndex); - if (invoice && invoice->getStatus() != util::PaymentStatus::COMPLETED) + if (invoice && invoice->getStatus() != util::PaymentStatus::PAID) { User* currentUser = invoice->getBooking()->getCustomer(); invoice->setPaymentMethod(paymentMode); invoice->setPaymentDate(util::Timestamp()); - invoice->setStatus(util::PaymentStatus::COMPLETED); + invoice->setStatus(util::PaymentStatus::PAID); std::string title, message; title = "Payment successful"; message = "Payment successful for Invoice ID " + invoiceID; @@ -384,4 +384,48 @@ void PaymentManagementService::completePayment(const std::string& invoiceID, uti { throw std::runtime_error("Payment failed: invalid invoice ID."); } +} + +/* +Function: getAllInvoice +Description: Provides access to all invoices stored in the data store. +Parameters: + - none +Returns: + - util::Map&: Map of invoice IDs to invoice objects +*/ +util::Map& PaymentManagementService::getAllInvoices() +{ + return m_dataStore.getInvoices(); +} + +/* +Function: confirmPayment +Description: Confirms payment for a specific invoice. Updates payment date and status, + then sends a notification to the customer. +Parameters: + - invoiceID: std::string, ID of the invoice to confirm +Returns: + - void +Throws: + - std::runtime_error if the invoice ID is invalid +*/ +void PaymentManagementService::confirmPayment(const std::string& invoiceID) +{ + auto& currentInvoices = m_dataStore.getInvoices(); + int invoiceIndex = currentInvoices.find(invoiceID); + if (invoiceIndex == -1) + { + throw std::runtime_error("Payment confirmation failed: invalid invoice ID."); + } + Invoice* invoice = currentInvoices.getValueAt(invoiceIndex); + if (!invoice || invoice->getStatus() != util::PaymentStatus::PAID) + { + throw std::runtime_error("Payment confirmation failed: invoice is not awaiting confirmation."); + } + User* currentUser = invoice->getBooking()->getCustomer(); + invoice->setStatus(util::PaymentStatus::COMPLETED); + std::string title = "Payment Confirmed"; + std::string message = "Payment Confirmed for Invoice ID " + invoiceID; + sendNotification(currentUser, title, message); } \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.h index 14b8c11..8961a2d 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.h @@ -28,6 +28,8 @@ public: void generateInvoice(ServiceBooking* booking); util::Map getInvoices(const std::string& customerID); void completePayment(const std::string& invoiceID, util::PaymentMode paymentMode); + util::Map& getAllInvoices(); + void confirmPayment(const std::string& invoiceID); void sendPaymentReminders(); void sendNotification(User* user, const std::string& title, const std::string& message) override; void attach(User* user) override; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h index c167b28..7585abc 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h @@ -29,7 +29,8 @@ namespace util enum class PaymentStatus { PENDING, - COMPLETED + COMPLETED, + PAID }; enum class ServiceJobStatus @@ -161,6 +162,8 @@ namespace util return "PENDING"; case PaymentStatus::COMPLETED: return "COMPLETED"; + case PaymentStatus::PAID: + return "PAID"; } throw std::invalid_argument("Invalid PaymentStatus"); } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp index e7ee48a..76a1901 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp @@ -53,7 +53,8 @@ void AdminMenu::showMenu() << "\n14. Remove Combo Package" << "\n15. View Notifications" << "\n16. Change Password" - << "\n17. Logout" + << "\n17. Confirm Payment" + << "\n18. Logout" << "\nEnter a choice: "; util::read(choice); if (!handleOperation(choice)) @@ -127,7 +128,10 @@ bool AdminMenu::handleOperation(int choice) case 16: changePassword(); break; - case 17: + case 17: + confirmPayment(); + break; + case 18: logout(); return false; default: @@ -496,6 +500,54 @@ void AdminMenu::displayUsers() util::pressEnter(); } +/* +Function: confirmPayment +Description: Confirms payment for a selected invoice. Validates invoice status, updates payment date, + sets status to COMPLETED, and sends a notification to the customer. +Parameters: + - invoiceID: std::string, ID of the invoice to confirm +Returns: + - void +*/ +void AdminMenu::confirmPayment() +{ + util::clear(); + std::cout << "Confirm Payment\n"; + auto invoiceList = m_controller.getAllInvoices(); + if (invoiceList.isEmpty()) + { + std::cout << "No pending invoices available for confirmation."; + util::pressEnter(); + return; + } + bool hasConfirmableInvoice = false; + for (int index = 0; index < invoiceList.getSize(); ++index) + { + const Invoice* invoice = invoiceList.getValueAt(index); + if (invoice && invoice->getStatus() == util::PaymentStatus::PAID) + { + hasConfirmableInvoice = true; + break; + } + } + if (!hasConfirmableInvoice) + { + std::cout << "No invoices awaiting confirmation.\n"; + util::pressEnter(); + return; + } + std::string selectedID = selectInvoiceFromUserForPayment(invoiceList, util::PaymentStatus::PAID); + if (selectedID == "") + { + std::cout << "Payment failed.\n"; + util::pressEnter(); + return; + } + m_controller.confirmPayment(selectedID); + std::cout << "Payment Confirmed successfully.\n"; + util::pressEnter(); +} + /* Function: addTechnician Description: Adds a new technician after validating username, password, email, and phone number. diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.h index 2fe2283..bdffcb6 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.h @@ -28,6 +28,7 @@ public: void createService(); void removeService(); void displayUsers(); + void confirmPayment(); void addTechnician(); void removeUser(); void displayComboPackages(); diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp index 022885f..3e56d99 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp @@ -338,7 +338,7 @@ void CustomerMenu::completePayments() util::pressEnter(); return; } - std::string selectedID = selectInvoiceFromUserForPayment(currentInvoices); + std::string selectedID = selectInvoiceFromUserForPayment(currentInvoices, util::PaymentStatus::PENDING); if (selectedID == "") { std::cout << "Payment failed.\n"; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h index 0a4136a..372b003 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h @@ -364,14 +364,18 @@ inline const User* selectTechnician(util::Map& currentAvailabl } /* -Function: selectInvoiceFromUserForPayment -Description: Lists all pending invoices for the customer and allows selection by index. +Function: selectInvoiceFromUserForPayment +Description: Displays a list of invoices filtered by the required payment status. + Allows the user to select an invoice by index and returns the corresponding invoice ID. Parameters: - - currentInvoices: util::Map&, map of customer invoices + - currentInvoices: const util::Map&, + map of all invoices keyed by invoice ID + - requiredStatus: util::PaymentStatus, + the status to filter invoices (e.g., PENDING, PAID, COMPLETED) Returns: - - std::string: ID of the selected invoice, or empty string if none selected + - std::string: ID of the selected invoice, or empty string if none selected or invalid index */ -inline std::string selectInvoiceFromUserForPayment(const util::Map& currentInvoices) +inline std::string selectInvoiceFromUserForPayment(const util::Map& currentInvoices, util::PaymentStatus requiredStatus) { int currentIndex = 1, choice; util::Map pendingInvoicesForPayment; @@ -389,7 +393,7 @@ inline std::string selectInvoiceFromUserForPayment(const util::MapgetStatus() == util::PaymentStatus::PENDING) + if (currentInvoice && currentInvoice->getStatus() == requiredStatus) { const User* currentTechnician = currentInvoice->getBooking()->getAssignedTechnician(); std::cout << std::left From dd29c7324fb0308893da43ac24415bac9e641ebf Mon Sep 17 00:00:00 2001 From: Joel Thomas Date: Mon, 1 Jun 2026 17:40:27 +0530 Subject: [PATCH 4/7] Fix: Prevent duplicate usernames across all user states Changes: - Updated username duplicate validation to consider all existing users. - Prevented reuse of usernames belonging to deleted/disabled accounts. - Fixed authentication conflicts caused by duplicate usernames. Fixes #1809 --- .../Trenser.VehicleServiceSystem/utilities/Validator.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Validator.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Validator.cpp index f56d660..e8968d9 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Validator.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Validator.cpp @@ -116,15 +116,13 @@ bool util::isPasswordValid(const std::string& password) * usersMap - map of user objects keyed by identifier * Returns: * bool - true if the username is already in use by an active user, false otherwise - * Notes: - * - Only considers users with state util::State::ACTIVE */ bool util::isUsernameDuplicate(const std::string& username, const util::Map& usersMap) { int index = usersMap.findIf( [&](const std::string&, User* user) { - return (user->getUserName() == username && user->getState() == util::State::ACTIVE); + return (user->getUserName() == username); } ); return index != -1; From 20475ace73ac2ba051225352e984930af23313ad Mon Sep 17 00:00:00 2001 From: Avinash Rajesh Date: Mon, 1 Jun 2026 17:46:55 +0530 Subject: [PATCH 5/7] Fix Duplicate Customer Notification Sent When Assigned Technician Is Removed - Refactored processBookingCancellation to simplify parameters and remove redundant notification arguments. - Added util::UserType parameter to differentiate cancellation flows for CUSTOMER vs TECHNICIAN. - Updated cancelCustomerServiceBookings to use processBookingCancellation with util::UserType::CUSTOMER. - Updated cancelTechnicianJobs to use processBookingCancellation with util::UserType::TECHNICIAN. - Enhanced booking status handling by including IN_PROGRESS status in cancellation checks. - Ensured job cards are consistently marked CANCELLED and inventory restored. - Fixed duplicate notification issue where customers received multiple alerts when technician was removed. Fixes #1807 --- .../services/ServiceManagementService.cpp | 98 +++++++++---------- 1 file changed, 44 insertions(+), 54 deletions(-) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp index f6d3905..e12d9a3 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp @@ -541,52 +541,55 @@ static void restoreInventory(ServiceBooking* booking) } } -/* -Function: processBookingCancellation -Description: Cancels jobs and updates the status of a given booking. Sends notifications to the - specified user, resets technician assignment if needed, and restores inventory items. -Parameter: ServiceBooking* booking - Pointer to the booking being cancelled - util::ServiceJobStatus newServiceBookingStatus - New status to assign to the booking - const std::string& notificationTitle - Title of the booking cancellation notification - const std::string& notificationMessage - Message body of the booking cancellation notification - User* notifyUser - User to notify about the cancellation - util::ServiceJobStatus jobCardStatus - New status to assign to associated job cards - const std::string& jobNotificationTitle - Title of the job cancellation notification - const std::string& jobNotificationMessage - Message body of the job cancellation notification - util::Map& jobs - Collection of job cards to update - ServiceManagementService& currentService - Reference to the service for sending notifications -Return type: void -*/ static void processBookingCancellation(ServiceBooking* booking, - util::ServiceJobStatus newServiceBookingStatus, - const std::string& notificationTitle, - const std::string& notificationMessage, - User* notifyUser, - util::ServiceJobStatus jobCardStatus, - const std::string& jobNotificationTitle, - const std::string& jobNotificationMessage, - util::Map& jobs, ServiceManagementService& currentService) + util::Map& jobs, + ServiceManagementService& currentService, + util::UserType userType) { - if (!booking || !notifyUser) + if (!booking) { return; } for (int jobIterator = 0; jobIterator < jobs.getSize(); ++jobIterator) { JobCard* jobCard = jobs.getValueAt(jobIterator); - if (jobCard && jobCard->getBookingId() == booking->getId()) + if (!jobCard || jobCard->getBookingId() != booking->getId() || jobCard->getStatus() == util::ServiceJobStatus::CANCELLED) { - jobCard->setStatus(jobCardStatus); - currentService.sendNotification(notifyUser, jobNotificationTitle, jobNotificationMessage); + continue; + } + jobCard->setStatus(util::ServiceJobStatus::CANCELLED); + if (userType == util::UserType::CUSTOMER) + { + if (User* technician = booking->getAssignedTechnician()) + { + const std::string jobTitle = "Job Cancelled"; + const std::string jobMessage = "Your job card has been cancelled and the inventory has been restocked."; + currentService.sendNotification(technician, jobTitle, jobMessage); + } } } - booking->setStatus(newServiceBookingStatus); - currentService.sendNotification(notifyUser, notificationTitle, notificationMessage); - if (newServiceBookingStatus == util::ServiceJobStatus::PENDING) + if (userType == util::UserType::CUSTOMER) { - booking->setAssignedTechnician(nullptr); - booking->setAssignedTechnicianId(""); + booking->setStatus(util::ServiceJobStatus::CANCELLED); + if (User* technician = booking->getAssignedTechnician()) + { + const std::string title = "Customer Service Cancelled"; + const std::string message = "Your assigned job card has been cancelled and the inventory has been restocked."; + currentService.sendNotification(technician, title, message); + } } + else if (userType == util::UserType::TECHNICIAN) + { + booking->setStatus(util::ServiceJobStatus::PENDING); + if (User* customer = booking->getCustomer()) + { + const std::string title = "Technician Unavailable"; + const std::string message = "Your booking has been reset to pending and we will reassign a new technician shortly."; + currentService.sendNotification(customer, title, message); + } + } + booking->setAssignedTechnician(nullptr); + booking->setAssignedTechnicianId(""); restoreInventory(booking); } @@ -624,21 +627,13 @@ void ServiceManagementService::cancelCustomerServiceBookings(const std::string& { continue; } - if (booking->getStatus() != util::ServiceJobStatus::PENDING && booking->getStatus() != util::ServiceJobStatus::STARTED) + if (booking->getStatus() != util::ServiceJobStatus::PENDING && + booking->getStatus() != util::ServiceJobStatus::STARTED && + booking->getStatus() != util::ServiceJobStatus::IN_PROGRESS) { continue; } - User* assignedTechnician = booking->getAssignedTechnician(); - std::string titleToTechnician = "Customer Service Cancelled"; - std::string messageToTechnician = "The customer has cancelled their service booking. Your assigned job card has been cancelled and the inventory has been restocked."; - std::string jobTitle = "Job Cancelled"; - std::string jobMessage = "The job has been cancelled. Your job card has been cancelled and the inventory has been restocked."; - processBookingCancellation(booking, - util::ServiceJobStatus::CANCELLED, - titleToTechnician, messageToTechnician, assignedTechnician, - util::ServiceJobStatus::CANCELLED, - jobTitle, jobMessage, jobs, *this - ); + processBookingCancellation(booking, jobs, *this, util::UserType::CUSTOMER); } } @@ -676,7 +671,9 @@ void ServiceManagementService::cancelTechnicianJobs(const std::string& technicia { continue; } - if (booking->getStatus() != util::ServiceJobStatus::PENDING && booking->getStatus() != util::ServiceJobStatus::STARTED) + if (booking->getStatus() != util::ServiceJobStatus::PENDING && + booking->getStatus() != util::ServiceJobStatus::STARTED && + booking->getStatus() != util::ServiceJobStatus::IN_PROGRESS) { continue; } @@ -685,14 +682,7 @@ void ServiceManagementService::cancelTechnicianJobs(const std::string& technicia { continue; } - std::string title = "Technician Unavailable"; - std::string message = "Your assigned technician is no longer available. Your booking has been reset to pending and we will reassign a new technician shortly."; - processBookingCancellation(booking, - util::ServiceJobStatus::PENDING, - title, message, customer, - util::ServiceJobStatus::CANCELLED, - title, message, jobs, *this - ); + processBookingCancellation(booking, jobs, *this, util::UserType::TECHNICIAN); } } From ce50467816405ecd3628a3426dc653436bbfe215 Mon Sep 17 00:00:00 2001 From: Jissin Mathew Date: Mon, 1 Jun 2026 18:00:27 +0530 Subject: [PATCH 6/7] Fix Technician Job Status Update Screen UI and Formatting Issues - Corrected inconsistent status label formatting: replaced "Inprogress" with "In Progress" in TechnicianMenu and MenuHelper. - Updated headings in selectJobCardToUpdate to clearer phrasing: - "Select a job to mark as In Progress" - "Select a job to mark as Completed". - Added spacing before and after the "No jobs available" message to improve readability and provide clear separation from headings. - Replaced duplicated prompt "Select the Job Card to Update (Index):" with concise "Enter the job index to update:". - Improved TechnicianMenu option display to show "In Progress" instead of "Inprogress". Fixes #1808 --- .../Trenser.VehicleServiceSystem/views/MenuHelper.h | 8 ++++---- .../Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h index 372b003..83720c0 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h @@ -736,7 +736,7 @@ inline std::string selectJobCardToUpdate(util::Map& util::Map incompleteJobCards; if (assignedJobCards.getSize() == 0) { - std::cout << "No jobs available.\n\n"; + std::cout << "\nNo jobs available.\n\n"; return ""; } int currentIndex = 1; @@ -744,12 +744,12 @@ inline std::string selectJobCardToUpdate(util::Map& if (selectedJobStatusType == util::ServiceJobStatus::STARTED) { util::clear(); - std::cout << "Select a job to update to Inprogress\n"; + std::cout << "Select a job to mark as In Progress\n"; } else if (selectedJobStatusType == util::ServiceJobStatus::IN_PROGRESS) { util::clear(); - std::cout << "Select a job to update to Completed\n"; + std::cout << "Select a job to mark as Completed\n"; } else { @@ -780,7 +780,7 @@ inline std::string selectJobCardToUpdate(util::Map& incompleteJobCards.insert(currentIndex++, currentJobCard); } } - std::cout << "Select the Job Card to Update (Index): "; + std::cout << "Enter the job index to update: "; util::read(choice); int selectedJobCardIndex = incompleteJobCards.find(choice); if (selectedJobCardIndex != -1) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp index 5d125cc..8ff3e12 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp @@ -121,7 +121,7 @@ void TechnicianMenu::updateJobStatus() std::string selectedJobID; util::ServiceJobStatus selectedJobStatus = util::ServiceJobStatus::PENDING; util::Map assignedJobCards = m_controller.getJobCardsByUser(); - std::cout << "Select the type of job you want to update\n1.Started\n2.Inprogress\nChoice: "; + std::cout << "Select the type of job you want to update:\n1.Started\n2.In Progress\nChoice: "; util::read(choice); if (choice == 1) { From c64f3cff72afc47b5fc0486e98888eb619d85d6f Mon Sep 17 00:00:00 2001 From: Avinash Rajesh Date: Mon, 1 Jun 2026 18:13:11 +0530 Subject: [PATCH 7/7] Implemented Review Fixes --- .../services/ServiceManagementService.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp index e12d9a3..1a9f753 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp @@ -541,6 +541,18 @@ static void restoreInventory(ServiceBooking* booking) } } +/* +Function: processBookingCancellation +Description: Handles cancellation or reassignment of a service booking based on user type. + Cancels associated job cards, updates booking status, clears technician assignments, + restores inventory, and sends appropriate notifications. +Parameters: + ServiceBooking* booking - The booking to cancel or reset + util::Map& jobs - Collection of job cards to update + ServiceManagementService& currentService - Service layer for notifications + util::UserType userType - Type of user initiating cancellation (CUSTOMER or TECHNICIAN) +Return type: void +*/ static void processBookingCancellation(ServiceBooking* booking, util::Map& jobs, ServiceManagementService& currentService,