From 1c717bb9fa6b9316ee74af78326f6105dcf8223f Mon Sep 17 00:00:00 2001 From: Jissin Mathew Date: Mon, 25 May 2026 17:31:20 +0530 Subject: [PATCH] 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