diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp index c0478fc..b4fbc22 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp @@ -26,7 +26,6 @@ Date:19-May-2026 #include "User.h" #include "UserManagementService.h" #include "Utility.h" -#include "ComboPackage.h" /* Function: purchaseService @@ -100,7 +99,7 @@ void ServiceManagementService::purchaseComboPackage(const std::string& comboPack } const ComboPackage* comboPackage = comboPackagesMap[comboPackageID]; util::Map selectedServices = comboPackage->getServices(); - ServiceBooking* serviceBooking = Factory::getObject(util::ServiceJobStatus::STARTED, selectedServices, authenticatedUser->getId(), authenticatedUser, vehicleNumber, vehicleBrand, vehicleModel, comboPackage->getDiscountPercentage()); + ServiceBooking* serviceBooking = Factory::getObject(util::ServiceJobStatus::PENDING, selectedServices, authenticatedUser->getId(), authenticatedUser, vehicleNumber, vehicleBrand, vehicleModel, comboPackage->getDiscountPercentage()); if (serviceBooking == nullptr) { throw std::runtime_error("Failed to create combo package service booking"); diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp index 05f85cf..022885f 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp @@ -220,20 +220,24 @@ void CustomerMenu::selectComboPackage() util::clear(); std::cout << "Select a Combo Package\n"; auto comboPackages = m_controller.getComboPackages(); - if (comboPackages.isEmpty()) + util::Map activeComboPackages = filterComboPackages(comboPackages); + if (activeComboPackages.isEmpty()) { - std::cout << "No combo packages available!"; + std::cout << "No combo packages available!\n\n"; util::pressEnter(); return; } - const ComboPackage* selectedComboPackage = selectComboPackageFromPackages(comboPackages); + const ComboPackage* selectedComboPackage = selectComboPackageFromPackages(activeComboPackages); if (selectedComboPackage == nullptr) { - std::cout << "Failed to book combo package!"; + std::cout << "Failed to book combo package!\n\n"; util::pressEnter(); return; } + std::cout << "Combo Package selected\n"; + util::pressEnter(); util::clear(); + std::cout << "Enter the vehicle details\n"; std::cout << "Enter vehicle number: "; util::read(vehicleNumber); std::cout << "Enter vehicle brand: "; @@ -241,7 +245,7 @@ void CustomerMenu::selectComboPackage() std::cout << "Enter vehicle model: "; util::read(vehicleModel); m_controller.purchaseComboPackage(selectedComboPackage->getId(), vehicleNumber, vehicleBrand, vehicleModel); - std::cout << "Combo Package has been booked successfully"; + std::cout << "Combo Package has been booked successfully\n\n"; util::pressEnter(); } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h index a4cfe33..9703042 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h @@ -160,7 +160,7 @@ Parameters: Returns: - util::Map: map containing only active (PENDING) service bookings */ -inline util::Map filterActiveServiceBookings(util::Map currentBookings) +inline util::Map filterActiveServiceBookings(util::Map& currentBookings) { util::Map activeServiceBookings; for (int iterator = 0; iterator < currentBookings.getSize(); iterator++) @@ -201,8 +201,6 @@ inline bool listServiceBookings(util::Map& c << 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++) { @@ -219,8 +217,6 @@ inline bool listServiceBookings(util::Map& c << 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); } @@ -239,7 +235,7 @@ Returns: inline const ServiceBooking* selectPendingServiceBookings(util::Map& serviceBookingsMap) { int userInputIndex; - std::cout << "\nEnter a valid service index: "; + std::cout << "\nEnter a service index: "; util::read(userInputIndex); if (serviceBookingsMap.find(userInputIndex) != -1) { @@ -304,7 +300,7 @@ Returns: inline const User* selectTechnician(util::Map& currentAvailableTechniciansMap) { int userInputIndex; - std::cout << "\nEnter valid technician index: "; + std::cout << "\nEnter technician index: "; util::read(userInputIndex); if (currentAvailableTechniciansMap.find(userInputIndex) != -1) { @@ -416,6 +412,73 @@ inline util::PaymentMode selectPaymentMode() } } +/* +Function: displayInvoicesInTabularForm +Description: + Displays all invoices in a tabular format. Each row shows booking details, + vehicle info, technician details, discount, total amount, invoice date, + and payment status. If inventory items exist for an invoice, they are + displayed in a separate table below the invoice row. +Parameters: + - currentInvoices: util::Map + Map of invoice IDs to Invoice pointers. +Returns: + - void +*/ +inline const Invoice* selectInvoiceToDisplay(util::Map& currentInvoices) +{ + int currentIndex = 1, choice; + util::Map currentInvoicesIndexMap; + if (currentInvoices.isEmpty()) + { + std::cout << "No invoices available.\n\n"; + return nullptr; + } + std::cout + << std::left + << std::setw(10) << "Index" + << std::setw(12) << "BookingID" + << std::setw(15) << "VehicleNumber" + << std::setw(20) << "TechnicianName" + << std::setw(15) << "TotalAmount" + << std::setw(25) << "InvoiceDate" + << std::setw(15) << "PaymentStatus" + << std::setw(15) << "PaymentMode" + << std::endl; + for (int iterator = 0; iterator < currentInvoices.getSize(); iterator++) + { + const Invoice* currentInvoice = currentInvoices.getValueAt(iterator); + if (!currentInvoice) + { + continue; + } + const User* currentTechnician = currentInvoice->getBooking()->getAssignedTechnician(); + std::cout << std::left + << std::setw(10) << currentIndex + << std::setw(12) << currentInvoice->getBookingId() + << std::setw(15) << currentInvoice->getBooking()->getVehicleNumber() + << std::setw(20) << ((currentTechnician && !currentTechnician->getName().empty()) ? currentTechnician->getName() : "NULL") + << std::setw(15) << currentInvoice->getTotalAmount() + << std::setw(25) << currentInvoice->getInvoiceDate().toString() + << std::setw(15) << util::getPaymentStatusString(currentInvoice->getStatus()) + << std::setw(15) << util::getPaymentModeString(currentInvoice->getPaymentMethod()) + << std::endl; + currentInvoicesIndexMap.insert(currentIndex++, currentInvoice); + } + std::cout << "Enter an index: "; + util::read(choice); + int currentSelectedIndex = currentInvoicesIndexMap.find(choice); + if (currentSelectedIndex != -1) + { + return currentInvoicesIndexMap.getValueAt(currentSelectedIndex); + } + else + { + std::cout << "Enter a valid index.\n"; + return nullptr; + } +} + /* Function: displayInvoices Description: Displays detailed information for all invoices associated with the customer, @@ -429,34 +492,48 @@ Throws: */ inline void displayInvoices(util::Map currentUserInvoices) { + std::cout << std::endl; if (currentUserInvoices.getSize() == 0) { - std::cout << "No invoices found for this account." << std::endl << std::endl; + std::cout << "No invoices found for this account.\n\n"; return; } else { - for (int index = 0; index < currentUserInvoices.getSize(); index++) + bool doRun = true; + do { - const Invoice* currentInvoice = currentUserInvoices.getValueAt(index); - if (currentInvoice) + const Invoice* selectedInvoice; + int choice; + selectedInvoice = selectInvoiceToDisplay(currentUserInvoices); + if (selectedInvoice) { - 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(); + const User* currentTechnician = selectedInvoice->getBooking()->getAssignedTechnician(); + util::clear(); + std::cout << "Invoice Details\n"; + std::cout << std::left << std::setw(20) << "Booking ID:" + << selectedInvoice->getBookingId() << std::endl; + std::cout << std::left << std::setw(20) << "Vehicle Brand:" + << selectedInvoice->getBooking()->getVehicleBrand() << std::endl; + std::cout << std::left << std::setw(20) << "Vehicle Number:" + << selectedInvoice->getBooking()->getVehicleNumber() << std::endl; + std::cout << std::left << std::setw(20) << "Technician ID:" + << ((currentTechnician != nullptr && !currentTechnician->getId().empty()) + ? currentTechnician->getId() : "NULL") << std::endl; + std::cout << std::left << std::setw(20) << "Technician Name:" + << ((currentTechnician != nullptr && !currentTechnician->getName().empty()) + ? currentTechnician->getName() : "NULL") << std::endl; + std::cout << std::left << std::setw(20) << "Discount(%):" + << selectedInvoice->getDiscountPercentage() << std::endl; + std::cout << std::left << std::setw(20) << "Total Amount:" + << selectedInvoice->getTotalAmount() << std::endl; + std::cout << std::left << std::setw(20) << "Invoice Date:" + << selectedInvoice->getInvoiceDate().toString() << std::endl; + std::cout << std::left << std::setw(20) << "Payment Status:" + << util::getPaymentStatusString(selectedInvoice->getStatus()) << std::endl; + std::cout << std::left << std::setw(20) << "Payment Mode:" + << util::getPaymentModeString(selectedInvoice->getPaymentMethod()) << std::endl; + auto inventoryItemsInInvoice = selectedInvoice->getParts(); if (inventoryItemsInInvoice.isEmpty()) { std::cout << "No inventory items used.\n\n"; @@ -478,14 +555,53 @@ inline void displayInvoices(util::Map currentUserIn << std::setw(10) << currentItem->getPrice() << std::endl; } + std::cout << "\n\nDo you want to display another Invoice (1-Yes, 2-No): "; + util::read(choice); + if (choice == 1) + { + doRun = true; + util::clear(); + } + else if (choice == 2) + { + doRun = false; + } + else + { + std::cout << "Invalid choice\n"; + doRun = false; + } } else { - throw std::runtime_error("Null invoice encountered while displaying invoices."); + std::cout << "Unable to fetch the selected invoice\n"; + doRun = false; } + + } while (doRun); + } +} + +/* +Function: filterStartedJobCards +Description: Filters the given list of job cards and returns only those with status STARTED. +Parameters: + - assignedJobCards: Map of job card IDs to JobCard pointers. +Returns: + - util::Map containing only job cards with status STARTED. +*/ +inline util::Map filterStartedJobCards(util::Map& assignedJobCards) +{ + util::Map startedJobCards; + for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++) + { + const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator); + if (currentJobCard && currentJobCard->getStatus() == util::ServiceJobStatus::STARTED) + { + startedJobCards.insert(currentJobCard->getId(), currentJobCard); } } - util::pressEnter(); + return startedJobCards; } /* @@ -497,49 +613,50 @@ Parameters: Returns: - std::string: ID of the selected job card, or empty string if none selected */ -inline std::string selectJobCardToComplete(util::Map& assignedJobCards, util::Map& incompleteJobCards) +inline std::string selectJobCardToComplete(util::Map& assignedJobCards) +{ + util::Map incompleteJobCards; + if (assignedJobCards.getSize() == 0) { - 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++) + std::cout << "No started jobs available to complete.\n"; + return ""; + } + int currentIndex = 1; + int choice; + std::cout << std::endl; + 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)) + 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); + 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; + incompleteJobCards.insert(currentIndex++, currentJobCard); } } - if (!hasIncompleteJobCard) - { - std::cout << "No pending jobs are present.\n"; - return ""; - } - std::cout << "Select the Job Card to complete (Index): "; + std::cout << "Select the Job Card to complete (Index): "; util::read(choice); - int selectedJobCardIndex = incompleteJobCards.find(choice); - if (selectedJobCardIndex != -1) + int selectedJobCardIndex = incompleteJobCards.find(choice); + if (selectedJobCardIndex != -1) { - const JobCard* selectedJobCard = incompleteJobCards.getValueAt(selectedJobCardIndex); - return selectedJobCard->getId(); + const JobCard* selectedJobCard = incompleteJobCards.getValueAt(selectedJobCardIndex); + return selectedJobCard->getId(); } else { - std::cout << "Invalid index.\n"; + std::cout << "Invalid index.\n"; + std::cout << "Failed to complete jobs.\n\n"; return ""; } } @@ -753,7 +870,7 @@ Parameters: Returns: - util::Map containing only active services. */ -inline util::Map filterActiveServices(util::Map serviceList) +inline util::Map filterActiveServices(util::Map& serviceList) { util::Map activeServices; for (int iterator = 0; iterator < serviceList.getSize(); iterator++) @@ -780,6 +897,7 @@ inline const Service* selectServiceFromServices(const util::Map activeServicesMap; int currentIndex = 1; int userInputIndex; @@ -826,6 +944,31 @@ inline const Service* selectServiceFromServices(const util::Map& + Map of combo package IDs to ComboPackage pointers. +Returns: + - util::Map + Map containing only active combo packages. +*/ +inline util::Map filterComboPackages(util::Map& comboPackages) +{ + util::Map activeComboPackages; + for (int iterator = 0; iterator < comboPackages.getSize(); iterator++) + { + const ComboPackage* currentComboPackage = comboPackages.getValueAt(iterator); + if (currentComboPackage && currentComboPackage->getState() == util::State::ACTIVE) + { + activeComboPackages.insert(currentComboPackage->getId(), currentComboPackage); + } + } + return activeComboPackages; +} + /* Function: selectComboPackageFromPackages Description: Displays active combo packages and allows the customer to select one by index. @@ -837,10 +980,11 @@ inline const ComboPackage* selectComboPackageFromPackages(const util::Map activeComboPackages; int currentIndex = 1; int userInputIndex; + std::cout << std::endl; std::cout << std::left << std::setw(10) << "Index" << std::setw(15) << "Combo ID" - << std::setw(15) << "Combo Name" + << std::setw(35) << "Combo Name" << std::setw(15) << "Estimate Cost" << std::endl; for (int index = 0; index < comboPackages.getSize(); index++) @@ -854,7 +998,7 @@ inline const ComboPackage* selectComboPackageFromPackages(const util::MapgetId() - << std::setw(25) << currentComboPackage->getPackageName() + << std::setw(35) << util::truncateString(currentComboPackage->getPackageName(), 30) << std::setw(15) << util::calculateComboServiceEstimatedCost(currentComboPackage) << std::endl; currentIndex++; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp index d50c73e..38264bf 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.cpp @@ -93,18 +93,15 @@ Returns: */ void TechnicianMenu::completeJob() { + util::clear(); + std::cout << "Complete Job\n"; util::Map assignedJobCards = m_controller.getJobCardsByUser(); - util::Map incompleteJobCards; - std::cout << "Jobs to be completed.\n"; - std::string selectedJobID = selectJobCardToComplete(assignedJobCards, incompleteJobCards); - if (selectedJobID == "") - { - std::cout << "Failed to complete the job.\n"; - } - else + util::Map startedJobCards = filterStartedJobCards(assignedJobCards); + std::string selectedJobID = selectJobCardToComplete(startedJobCards); + if (!selectedJobID.empty()) { m_controller.completeJob(selectedJobID); - std::cout << "Job marked as completed.\n"; + std::cout << "\nJob marked as completed.\n\n"; } util::pressEnter(); }