diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp index 77d5a21..f1ca400 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp @@ -6,12 +6,16 @@ Description: Implementation file containing the method definitions of the Author: Trenser Date:19-May-2026 */ -#include +#include "ComboPackage.h" #include "Controller.h" #include "Enums.h" +#include "InventoryItem.h" +#include "Invoice.h" +#include "JobCard.h" +#include "Service.h" +#include "ServiceBooking.h" #include "User.h" -#include "ComboPackage.h" -#include "User.h" +#include /* Function: login @@ -106,9 +110,23 @@ void Controller::updateUserDetails(const std::string& email, const std::string& m_userManagementService.updateUserDetails(authenticatedUser->getId(), email, phone); } +/* +Function: getServices +Description: Retrieves all available services in read-only form. +Parameters: + - None +Returns: + - util::Map containing all services +*/ util::Map Controller::getServices() { - return util::Map(); + util::Map currentServices = m_serviceManagementService.getServices(); + util::Map readOnlyServices; + for (int iterator = 0; iterator < currentServices.getSize(); iterator++) + { + readOnlyServices.insert(currentServices.getValueAt(iterator)->getId(), currentServices.getValueAt(iterator)); + } + return readOnlyServices; } /* @@ -227,14 +245,42 @@ void Controller::addInventoryItemStock(const std::string& selectedItemId, int qu m_inventoryManagementService.addInventoryItemStock(selectedItemId, quantity); } +/* +Function: getServiceBookings +Description: Retrieves all service bookings in read-only form. +Parameters: + - None +Returns: + - util::Map containing service bookings +*/ util::Map Controller::getServiceBookings() { - return util::Map(); + auto serviceBookings = m_serviceManagementService.getServiceBookings(); + util::Map readOnlyServiceBookings; + for (int iterator = 0; iterator < serviceBookings.getSize(); iterator++) + { + readOnlyServiceBookings.insert(serviceBookings.getKeyAt(iterator), serviceBookings.getValueAt(iterator)); + } + return readOnlyServiceBookings; } +/* +Function: getServiceBookingsByUser +Description: Retrieves all service bookings for a specific user. +Parameters: + - userID: std::string, the user ID +Returns: + - util::Map containing bookings for the user +*/ util::Map Controller::getServiceBookingsByUser(const std::string userID) { - return util::Map(); + util::Map readOnlyServiceBookingsByUserMap; + util::Map currentServiceBookingsByUser = m_serviceManagementService.getServiceBookings(userID); + for (int iterator = 0; iterator < currentServiceBookingsByUser.getSize(); iterator++) + { + readOnlyServiceBookingsByUserMap.insert(currentServiceBookingsByUser.getValueAt(iterator)->getId(), currentServiceBookingsByUser.getValueAt(iterator)); + } + return readOnlyServiceBookingsByUserMap; } /* @@ -255,30 +301,100 @@ util::Map Controller::getUsers() return readOnlyUserList; } +/* +Function: getUsers +Description: Retrieves users filtered by user type. +Parameters: + - userType: util::UserType, type of user (CUSTOMER, TECHNICIAN, ADMIN) +Returns: + - util::Map containing users of the specified type +*/ util::Map Controller::getUsers(util::UserType userType) { - return util::Map(); + auto userMap = m_userManagementService.getUsers(userType); + util::Map readOnlyUserMap; + for (int iterator = 0; iterator < userMap.getSize(); iterator++) + { + readOnlyUserMap.insert(userMap.getKeyAt(iterator), userMap.getValueAt(iterator)); + } + return readOnlyUserMap; } +/* +Function: createJobCard +Description: Creates a job card for a service booking assigned to a technician. +Parameters: + - bookingID: std::string, ID of the service booking + - technicianID: std::string, ID of the technician + - serviceID: std::string, ID of the service +Returns: + - void +*/ void Controller::createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID) { + m_serviceManagementService.createJobCard(bookingID, technicianID, serviceID); } +/* +Function: createService +Description: Creates a new service with associated inventory items and labor cost. +Parameters: + - name: std::string, name of the service + - inventoryItemIDs: Vector of inventory item IDs + - laborCost: double, labor cost +Returns: + - void +*/ void Controller::createService(const std::string& name, const util::Vector& inventoryItemIDs, double laborCost) { + m_serviceManagementService.createService(name, inventoryItemIDs, laborCost); } +/* +Function: removeService +Description: Removes a service from the system by ID. +Parameters: + - serviceID: std::string, ID of the service +Returns: + - void +*/ void Controller::removeService(const std::string& serviceID) { + m_serviceManagementService.removeService(serviceID); } +/* +Function: getJobCardsByUser +Description: Retrieves job cards assigned to the authenticated technician. +Parameters: + - None +Returns: + - util::Map containing job cards +*/ util::Map Controller::getJobCardsByUser() { - return util::Map(); + const User* currentUser = getAuthenticatedUser(); + auto jobCardsAssignedToTechnician = m_serviceManagementService.getJobCards(currentUser->getId()); + util::Map readOnlyJobCardMap; + for (int iterator = 0; iterator < jobCardsAssignedToTechnician.getSize(); iterator++) + { + JobCard* currentJobCard = jobCardsAssignedToTechnician.getValueAt(iterator); + readOnlyJobCardMap.insert(currentJobCard->getId(), currentJobCard); + } + return readOnlyJobCardMap; } +/* +Function: completeJob +Description: Marks a job card as completed. +Parameters: + - jobID: std::string, ID of the job card +Returns: + - void +*/ void Controller::completeJob(const std::string& jobID) { + m_serviceManagementService.completeJob(jobID); } /* @@ -326,13 +442,40 @@ void Controller::removeComboPackage(const std::string& comboPackageID) m_serviceManagementService.removeComboPackage(comboPackageID); } +/* +Function: getInvoicesByUser +Description: Retrieves all invoices associated with the currently authenticated user. + Converts them into a read-only map before returning. +Parameters: + - None +Returns: + - util::Map containing the user’s invoices +*/ util::Map Controller::getInvoicesByUser() { - return util::Map(); + User* currentUser = m_authenticationManagementService.getAuthenticatedUser(); + util::Map currentUserInvoices = m_paymentManagementService.getInvoices(currentUser->getId()); + util::Map userInvoicesReadOnly; + for (int iterator = 0; iterator < currentUserInvoices.getSize(); iterator++) + { + Invoice* currentInvoice = currentUserInvoices.getValueAt(iterator); + userInvoicesReadOnly.insert(currentInvoice->getId(), currentInvoice); + } + return userInvoicesReadOnly; } +/* +Function: completePayment +Description: Completes payment for a specific invoice using the given payment mode. +Parameters: + - invoiceID: std::string, ID of the invoice to be paid + - paymentMode: util::PaymentMode, mode of payment (e.g., ONLINE, OFFLINE) +Returns: + - void +*/ void Controller::completePayment(const std::string& invoiceID, util::PaymentMode paymentMode) { + m_paymentManagementService.completePayment(invoiceID, paymentMode); } /* diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h index 9f17d20..e75ebd4 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h @@ -8,19 +8,14 @@ Date:19-May-2026 */ #pragma once +#include #include "AuthenticationManagementService.h" #include "Enums.h" #include "InventoryManagementService.h" #include "Map.h" #include "PaymentManagementService.h" -#include "PaymentManagementService.h" -#include "ServiceManagementService.h" -#include "ServiceManagementService.h" #include "ServiceManagementService.h" #include "UserManagementService.h" -#include "UserManagementService.h" -#include "UserManagementService.h" -#include class Service; class ComboPackage; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.cpp index d1dc0c4..f24a013 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.cpp @@ -58,8 +58,8 @@ Invoice::Invoice( const std::string& bookingId, ServiceBooking* booking, const util::Timestamp& invoiceDate, - double laborCost, const util::Map& parts, + double laborCost, + const util::Map& parts, double partsCost, double discountPercentage, double totalAmount, @@ -87,7 +87,6 @@ Invoice::Invoice( m_partIDs.push_back(partPointers[index]->getId()); } } - Invoice::Invoice( const std::string& id, const std::string& bookingId, diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.h index a226038..3374de9 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.h @@ -40,8 +40,8 @@ public: const std::string& bookingId, ServiceBooking* booking, const util::Timestamp& invoiceDate, - double laborCost, const util::Map& parts, + double laborCost, + const util::Map& parts, double partsCost, double discountPercentage, double totalAmount, diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h index da15959..a845263 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h @@ -9,8 +9,8 @@ Date:19-May-2026 #pragma once #include -#include "Timestamp.h" #include "Enums.h" +#include "Timestamp.h" class ServiceBooking; class Service; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp index 7cdd80a..a922f31 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp @@ -12,8 +12,11 @@ Date: 20-May-2026 #include "Enums.h" #include "Factory.h" #include "FileManager.h" +#include "InventoryItem.h" #include "Invoice.h" +#include "JobCard.h" #include "PaymentManagementService.h" +#include "Service.h" #include "ServiceBooking.h" #include "Timestamp.h" #include "User.h" @@ -252,4 +255,132 @@ Returns: void PaymentManagementService::saveObservers() { util::saveObservers(config::file::PAYMENTMANAGEMENTOBSERVERS, this); +} + +/* +Function: createInventoryItemsMap (static helper) +Description: Builds a map of inventory items required for a given service and adds them to the booking’s inventory map. +Parameters: + - completeInventoryItemMapOfBooking: util::Map&, map to store inventory items for the booking + - currentService: const Service*, pointer to the current service +Returns: + - void +*/ +static void createInventoryItemsMap(util::Map& completeInventoryItemMapOfBooking, const Service* currentService) +{ + auto& currentRequiredInventoryItems = currentService->getRequiredInventoryItems(); + for (int iterator = 0; iterator < currentRequiredInventoryItems.getSize(); iterator++) + { + auto& currentRequiredInventoryItem = currentRequiredInventoryItems.getValueAt(iterator); + completeInventoryItemMapOfBooking.insert(currentRequiredInventoryItem->getId(), currentRequiredInventoryItem); + } +} + +/* +Function: generateInvoice +Description: Generates an invoice for a completed service booking. + Validates that all job cards are completed, calculates labor and parts cost, applies discount, + and stores the invoice in the datastore. +Parameters: + - booking: ServiceBooking*, pointer to the service booking +Returns: + - void +Throws: + - std::runtime_error if booking is null or job cards are incomplete +*/ +void PaymentManagementService::generateInvoice(ServiceBooking* booking) +{ + if (!booking) + { + throw std::runtime_error("Invoice generation failed: booking is null."); + } + double totalLabourCost = 0, totalPartsCost = 0, totalServiceCost = 0; + double discountPercentage = booking->getDiscountPercentage(); + std::string bookingID = booking->getId(); + util::Map servicesInTheBookedService = booking->getServices(); + util::Map completeInventoryItemMapOfBooking; + util::Map currentJobCards = m_dataStore.getJobCards(); + for (int iterator = 0; iterator < currentJobCards.getSize(); iterator++) + { + JobCard* currentJobCard = currentJobCards.getValueAt(iterator); + if (currentJobCard->getBookingId() == bookingID && currentJobCard->getStatus() != util::ServiceJobStatus::COMPLETED) + { + throw std::runtime_error("Invoice generation failed: not all job cards are completed for booking '" + bookingID + "'."); + } + } + for (int iterator = 0; iterator < servicesInTheBookedService.getSize(); iterator++) + { + Service* currentService = servicesInTheBookedService.getValueAt(iterator); + if (currentService) + { + createInventoryItemsMap(completeInventoryItemMapOfBooking, currentService); + totalLabourCost += currentService->getLaborCost(); + totalPartsCost += calculatePartsCost(currentService); + } + } + totalServiceCost = totalLabourCost + totalPartsCost; + totalServiceCost -= (totalServiceCost * (discountPercentage / 100)); + Invoice* invoice = Factory::getObject(bookingID, booking, util::Timestamp(), totalLabourCost, completeInventoryItemMapOfBooking, totalPartsCost, discountPercentage, totalServiceCost, util::Timestamp(), util::PaymentMode::NOTSET, util::PaymentStatus::PENDING); + util::Map& currentInvoices = m_dataStore.getInvoices(); + currentInvoices.insert(invoice->getId(), invoice); +} + +/* +Function: getInvoices +Description: Retrieves all invoices associated with a specific customer. +Parameters: + - customerID: std::string, ID of the customer +Returns: + - util::Map containing the customer’s invoices +*/ +util::Map PaymentManagementService::getInvoices(const std::string& customerID) +{ + util::Map& currentInvoices = m_dataStore.getInvoices(); + util::Map currentUserInvoices; + for (int iterator = 0; iterator < currentInvoices.getSize(); iterator++) + { + Invoice* currentInvoice = currentInvoices.getValueAt(iterator); + if (currentInvoice->getBooking()->getCustomerId() == customerID) + { + currentUserInvoices.insert(currentInvoice->getId(), currentInvoice); + } + } + return currentUserInvoices; +} + +/* +Function: completePayment +Description: Completes payment for a specific invoice. Updates payment method, date, and status, + then sends a notification to the customer. +Parameters: + - invoiceID: std::string, ID of the invoice + - paymentMode: util::PaymentMode, mode of payment (e.g., ONLINE, OFFLINE) +Returns: + - void +Throws: + - std::runtime_error if the invoice ID is invalid +*/ +void PaymentManagementService::completePayment(const std::string& invoiceID, util::PaymentMode paymentMode) +{ + auto& currentInvoices = m_dataStore.getInvoices(); + int invoiceIndex = currentInvoices.find(invoiceID); + if (invoiceIndex != -1) + { + Invoice* invoice = currentInvoices.getValueAt(invoiceIndex); + 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 + { + throw std::runtime_error("Payment failed: invalid invoice ID."); + } } \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp index a6b97df..55920d5 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp @@ -12,17 +12,20 @@ Date:19-May-2026 #include "ComboPackage.h" #include "Config.h" #include "DataStore.h" +#include "Enums.h" #include "Factory.h" #include "FileManager.h" #include "InventoryItem.h" #include "JobCard.h" +#include "NotificationManagementService.h" +#include "PaymentManagementService.h" #include "Service.h" #include "ServiceBooking.h" -#include "ServiceBooking.h" - #include "ServiceManagementService.h" #include "Timestamp.h" +#include "Timestamp.h" #include "User.h" +#include "UserManagementService.h" #include "Utility.h" /* @@ -725,3 +728,325 @@ void ServiceManagementService::removeComboPackage(const std::string& comboPackag throw std::runtime_error("Combo package with ID '" + comboPackageID + "' not found."); } } + +/* +Function: getServiceBookings +Description: Retrieves all service bookings from the datastore. +Parameters: + - None +Returns: + - util::Map containing all service bookings +*/ +util::Map ServiceManagementService::getServiceBookings() +{ + return m_dataStore.getServiceBookings(); +} + +/* +Function: getServiceBooking +Description: Retrieves a specific service booking by its ID. +Parameters: + - serviceID: std::string, ID of the service booking +Returns: + - ServiceBooking*: Pointer to the service booking, or nullptr if not found +*/ +ServiceBooking* ServiceManagementService::getServiceBooking(const std::string& serviceID) +{ + auto currentServiceBookings = getServiceBookings(); + for (int iterator = 0; iterator < currentServiceBookings.getSize(); iterator++) + { + if (currentServiceBookings.getValueAt(iterator)->getId() == serviceID) + { + return currentServiceBookings.getValueAt(iterator); + } + } + return nullptr; +} + +/* +Function: createJobCard +Description: Creates a job card for a given service booking, service, and technician. + Validates booking, service, technician, and inventory availability before creation. +Parameters: + - bookingID: std::string, ID of the service booking + - technicianID: std::string, ID of the technician + - serviceID: std::string, ID of the service +Returns: + - void +Throws: + - std::runtime_error if booking, service, technician, or inventory validation fails +*/ +void ServiceManagementService::createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID) +{ + UserManagementService m_userManagementService; + ServiceBooking* currentBooking = getServiceBooking(bookingID); + auto& currentJobCards = m_dataStore.getJobCards(); + if (currentBooking == nullptr) + { + throw std::runtime_error("Service Booking not available"); + } + auto& currentServices = currentBooking->getServices(); + if (currentServices.find(serviceID) == -1) + { + throw std::runtime_error("Invalid service Id"); + } + Service* currentService = currentServices.getValueAt(currentServices.find(serviceID)); + User* selectedTechnician = m_userManagementService.getUser(technicianID); + if (selectedTechnician == nullptr) + { + throw std::runtime_error("Technician not available"); + } + auto& inventoryItems = currentService->getRequiredInventoryItems(); + for (int iterator = 0; iterator < inventoryItems.getSize(); iterator++) + { + InventoryItem* currentInventoryItem = inventoryItems.getValueAt(iterator); + if (currentInventoryItem && currentInventoryItem->getQuantity() == 0) + { + std::string errorMessage = "Failed to create job card, " + currentInventoryItem->getPartName() + " is out of stock."; + throw std::runtime_error(errorMessage); + } + } + for (int iterator = 0; iterator < inventoryItems.getSize(); iterator++) + { + InventoryItem* currentInventoryItem = inventoryItems.getValueAt(iterator); + if (currentInventoryItem) + { + int currentStockQuantity = currentInventoryItem->getQuantity(); + currentInventoryItem->setQuantity(currentStockQuantity - 1); + } + } + currentBooking->setAssignedTechnician(selectedTechnician); + currentBooking->setAssignedTechnicianId(selectedTechnician->getId()); + std::string title = "Job card created"; + std::string message = "Job card created for the service and you are assigned for that."; + JobCard* jobCard = Factory::getObject(bookingID, currentBooking, currentService, serviceID, technicianID, selectedTechnician, util::Timestamp(), util::ServiceJobStatus::STARTED, util::Timestamp()); + if (jobCard) + { + currentJobCards.insert(jobCard->getId(), jobCard); + sendNotification(selectedTechnician, title, message); + } + else + { + throw std::runtime_error("Failed to create job card."); + } +} + +/* +Function: createService +Description: Creates a new service with associated inventory items and labor cost. + Validates inventory items before creation. +Parameters: + - name: std::string, name of the service + - inventoryItemIDs: util::Vector, IDs of required inventory items + - laborCost: double, labor cost for the service +Returns: + - void +Throws: + - std::runtime_error if inventory items are not found or service creation fails +*/ +void ServiceManagementService::createService(const std::string& name, const util::Vector& inventoryItemIDs, double laborCost) +{ + util::Map currentServiceInventoryItems; + auto inventoryItems = m_dataStore.getInventoryItems(); + for (int iteratorOne =0; iteratorOne < inventoryItemIDs.getSize(); iteratorOne++) + { + std::string currentItemID = inventoryItemIDs[iteratorOne]; + bool itemFound = false; + for (int iteratorTwo = 0; iteratorTwo < inventoryItems.getSize(); iteratorTwo++) + { + InventoryItem* currentInventoryItem = inventoryItems.getValueAt(iteratorTwo); + if (currentInventoryItem && currentInventoryItem->getId() == currentItemID) + { + itemFound = true; + currentServiceInventoryItems.insert(currentInventoryItem->getId(), currentInventoryItem); + break; + } + } + if (!itemFound) + { + throw std::runtime_error("Inventory item with ID '" + currentItemID + "' not found."); + } + } + Service* newService = Factory::getObject(name, currentServiceInventoryItems, laborCost); + if (newService == nullptr) + { + throw std::runtime_error("Unable to create new service."); + } + util::Map& currentServices = m_dataStore.getServices(); + if (currentServices.find(newService->getId()) != -1) + { + throw std::runtime_error("Service with this ID Already exists."); + } + currentServices.insert(newService->getId(), newService); +} + +/* +Function: getServices +Description: Retrieves all services from the datastore. +Parameters: + - None +Returns: + - util::Map containing all services +*/ +util::Map ServiceManagementService::getServices() +{ + return m_dataStore.getServices(); +} + +/* +Function: removeService +Description: Marks a service as inactive by its ID. +Parameters: + - serviceID: std::string, ID of the service +Returns: + - void +Throws: + - std::runtime_error if the service is not found +*/ +void ServiceManagementService::removeService(const std::string& serviceID) +{ + util::Map& currentServices = m_dataStore.getServices(); + if (currentServices.find(serviceID) != -1) + { + currentServices.getValueAt(currentServices.find(serviceID))->setState(util::State::INACTIVE); + } + else + { + throw std::runtime_error("Service not found."); + } +} + +/* +Function: getServiceBookings (overloaded) +Description: Retrieves all service bookings for a specific customer. +Parameters: + - customerID: std::string, ID of the customer +Returns: + - util::Map containing bookings for the customer +*/ +util::Map ServiceManagementService::getServiceBookings(const std::string& customerID) +{ + util::Map currentServiceBookings = getServiceBookings(); + util::Map currentUserServiceBookings; + if (currentServiceBookings.getSize() != 0) + { + for (int iterator = 0; iterator < currentServiceBookings.getSize(); iterator++) + { + auto currentServiceBooking = currentServiceBookings.getValueAt(iterator); + if (currentServiceBooking->getCustomerId() == customerID) + { + currentUserServiceBookings.insert(currentServiceBooking->getId(), currentServiceBooking); + } + } + } + return currentUserServiceBookings; +} + +/* +Function: getJobCards +Description: Retrieves all job cards assigned to a specific technician. +Parameters: + - technicianID: std::string, ID of the technician +Returns: + - util::Map containing job cards assigned to the technician +*/ +util::Map ServiceManagementService::getJobCards(const std::string& technicianID) +{ + util::Map jobCards = m_dataStore.getJobCards(); + util::Map technicianJobCards; + for (int iterator = 0; iterator < jobCards.getSize(); iterator++) + { + JobCard* currentJobCard = jobCards.getValueAt(iterator); + if (currentJobCard->getTechnicianId() == technicianID) + { + technicianJobCards.insert(currentJobCard->getId(), currentJobCard); + } + } + return technicianJobCards; +} + +/* +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 + - currentAssignedJobs: util::Map&, map of assigned job cards +Returns: + - bool: True if all job cards are completed, False otherwise +*/ +static bool hasCompletedAllJobs(std::string bookingId, util::Map& currentAssignedJobs) +{ + for (int iterator = 0; iterator < currentAssignedJobs.getSize(); iterator++) + { + JobCard* currentJob = currentAssignedJobs.getValueAt(iterator); + if (currentJob->getBookingId() == bookingId) + { + if (currentJob->getStatus() == util::ServiceJobStatus::STARTED) + { + return false; + } + } + } + return true; +} + +/* +Function: completeJob +Description: Marks a job card as completed for the authenticated technician. + If all job cards in the booking are completed, marks the booking as completed + and generates an invoice. +Parameters: + - jobID: std::string, ID of the job card +Returns: + - void +Throws: + - std::runtime_error if technician is not authenticated, job card not found, or job already completed +*/ +void ServiceManagementService::completeJob(const std::string& jobID) +{ + AuthenticationManagementService authenticationManagementService; + PaymentManagementService paymentManagementService; + bool jobStatusUpdated = false, serviceBookingCompleted; + JobCard* currentJob; + User* currentTechnician = authenticationManagementService.getAuthenticatedUser(); + if (currentTechnician == nullptr) + { + throw std::runtime_error("Unable to fetch current technician."); + } + util::Map currentAssignedJobs = getJobCards(currentTechnician->getId()); + if (currentAssignedJobs.getSize() == 0) + { + throw std::runtime_error("No job cards assigned to the technician."); + } + if (currentAssignedJobs.find(jobID) != -1) + { + currentJob = currentAssignedJobs.getValueAt(currentAssignedJobs.find(jobID)); + if (currentJob == nullptr) + { + throw std::runtime_error("Unable to fetch current job."); + } + if (currentJob->getStatus() == util::ServiceJobStatus::STARTED) + { + currentJob->setStatus(util::ServiceJobStatus::COMPLETED); + jobStatusUpdated = true; + } + } + else + { + throw std::runtime_error("Failed to complete the job, some error occured or job already completed."); + } + if (!jobStatusUpdated) + { + throw std::runtime_error("Failed to complete the job, some error occured or job already completed."); + } + + serviceBookingCompleted = hasCompletedAllJobs(currentJob->getBookingId(), currentAssignedJobs); + if (serviceBookingCompleted) + { + currentJob->getBooking()->setStatus(util::ServiceJobStatus::COMPLETED); + paymentManagementService.generateInvoice(currentJob->getBooking()); + std::string title = "Service Booking completed,Invoice Generated.\n"; + std::string message = "Services completed for the booking and invoice generated.\n"; + sendNotification(currentJob->getBooking()->getCustomer(), title, message); + } +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h index bee1dd5..2fdcc93 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h @@ -32,6 +32,7 @@ public: void purchaseComboPackage(const std::string& comboPackageID, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel); util::Map getServiceBookings(); util::Map getServiceBookings(const std::string& customerID); + ServiceBooking* getServiceBooking(const std::string& serviceID); void createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID); void createService(const std::string& name, const util::Vector& inventoryItemIDs, double laborCost); void removeService(const std::string& serviceID); diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp index 8267144..7518d52 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp @@ -6,6 +6,8 @@ Description: Implementation file containing the method definitions of the Author: Trenser Date:19-May-2026 */ + +#include #include "Config.h" #include "Enums.h" #include "Factory.h" @@ -17,7 +19,6 @@ Date:19-May-2026 #include "User.h" #include "UserManagementService.h" #include "Vector.h" -#include /* @@ -289,4 +290,33 @@ void UserManagementService::removeUser(const std::string& userID) user->setState(util::State::INACTIVE); } } -} \ No newline at end of file +} + +util::Map UserManagementService::getUsers(util::UserType type) +{ + util::Map& currentUsers = m_dataStore.getUsers(); + util::Map filteredUsersMap; + for (int iterator = 0; iterator < currentUsers.getSize(); iterator++) + { + User* currentUser = currentUsers.getValueAt(iterator); + if (currentUser->getUserType() == type) + { + filteredUsersMap.insert(currentUser->getId(), currentUser); + } + } + return filteredUsersMap; +} + +User* UserManagementService::getUser(const std::string& userID) +{ + util::Map& currentUsers = m_dataStore.getUsers(); + for (int iterator = 0; iterator < currentUsers.getSize(); iterator++) + { + User* currentUser = currentUsers.getValueAt(iterator); + if (currentUser->getId() == userID) + { + return currentUser; + } + } + return nullptr; +} diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h index c738baa..e410eff 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h @@ -22,7 +22,8 @@ namespace util enum class PaymentMode { ONLINE, - OFFLINE + OFFLINE, + NOTSET }; enum class PaymentStatus @@ -110,6 +111,8 @@ namespace util return "ONLINE"; case PaymentMode::OFFLINE: return "OFFLINE"; + case PaymentMode::NOTSET: + return "NOTSET"; } throw std::invalid_argument("Invalid PaymentMode"); } @@ -279,4 +282,4 @@ namespace util } throw std::invalid_argument("Invalid State string"); } -} +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h index 6f473fd..300d5c4 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h @@ -10,7 +10,6 @@ Date:19-May-2026 #include "DataStore.h" #include "FileHelper.h" #include "InventoryItem.h" -#include "InventoryItem.h" #include "NotificationManagementService.h" #include "Service.h" @@ -100,4 +99,4 @@ namespace util auto observerIDs = service->getObserverIDs(); util::saveRecords(filePath, observerIDs); } -} +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp index 3c21e74..275b9b0 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/AdminMenu.cpp @@ -10,14 +10,13 @@ Date: 19-May-2026 #include #include -#include "AdminMenu.h" -#include "ComboPackage.h" #include "Enums.h" #include "InputHelper.h" #include "InventoryItem.h" #include "MenuHelper.h" #include "OutputHelper.h" #include "Service.h" +#include "ServiceBooking.h" #include "User.h" #include "Utility.h" #include "Validator.h" @@ -290,16 +289,101 @@ void AdminMenu::checkStockAvailability() util::pressEnter(); } +/* +Function: assignJob +Description: Allows the admin to assign pending service bookings to available technicians. + Creates job cards for selected services. +Parameters: + - None +Returns: + - void +*/ void AdminMenu::assignJob() { + util::clear(); + std::string selectedService; + bool hasPendingService = false; + auto currentBookings = m_controller.getServiceBookings(); + auto availableTechnicians = m_controller.getUsers(util::UserType::TECHNICIAN); + int bookingsSize = currentBookings.getSize(); + util::Map serviceBookingsMap; + util::Map currentAvailableTechniciansMap; + if (listServiceBookings(currentBookings, bookingsSize, serviceBookingsMap)) + { + const ServiceBooking* selectedService = selectPendingServiceBookings(serviceBookingsMap); + if (selectedService) + { + if (availableTechnicians.getSize() != 0) + { + listAvailableTechnicians(availableTechnicians, availableTechnicians.getSize(), currentAvailableTechniciansMap); + const User* selectedTechnician = selectTechnician(currentAvailableTechniciansMap); + if (selectedTechnician) + { + auto& servicesInBooking = selectedService->getServices(); + for (int iterator = 0; iterator < servicesInBooking.getSize(); iterator++) + { + m_controller.createJobCard(selectedService->getId(), selectedTechnician->getId(), servicesInBooking.getValueAt(iterator)->getId()); + } + } + } + else + { + std::cout << "No technicians are currently available."; + } + } + } + util::pressEnter(); } +/* +Function: createService +Description: Allows the admin to create a new service by selecting inventory items and specifying labor cost. +Parameters: + - None +Returns: + - void +*/ void AdminMenu::createService() { + util::clear(); + std::string serviceName; + double labourCost; + std::cout << "Enter the service name: "; + util::read(serviceName); + util::Map currentInventoryItems = m_controller.getInventoryItems(); + util::Vector selectedInventoryItems; + selectInventoryItems(currentInventoryItems,selectedInventoryItems); + std::cout << "Enter the labour cost: "; + util::read(labourCost); + m_controller.createService(serviceName, selectedInventoryItems, labourCost); + std::cout << "Service created sucessfully.\n"; + util::pressEnter(); } +/* +Function: removeService +Description: Allows the admin to remove an existing service by selecting from available services. +Parameters: + - None +Returns: + - void +*/ void AdminMenu::removeService() { + util::clear(); + std::string selectedServiceID; + util::Map currentServices = m_controller.getServices(); + selectedServiceID = selectServicesToRemove(currentServices); + if (selectedServiceID != "") + { + m_controller.removeService(selectedServiceID); + std::cout << "Service removed sucessfully."; + } + else + { + std::cout << "Failed to remove service."; + } + util::pressEnter(); } /* diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp index dbbf27c..20f538c 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp @@ -6,15 +6,19 @@ Description: Implementation file containing the method definitions of the Author: Trenser Date:19-May-2026 */ + #include #include "ComboPackage.h" #include "CustomerMenu.h" +#include "Enums.h" #include "InputHelper.h" #include "InventoryItem.h" +#include "Invoice.h" #include "Map.h" -#include "MenuHelper.h" -#include "OutputHelper.h" #include "Service.h" +#include "ServiceBooking.h" +#include "Timestamp.h" +#include "User.h" #include "Validator.h" #include "Vector.h" @@ -223,16 +227,97 @@ void CustomerMenu::selectComboPackage() util::pressEnter(); } +/* +Function: viewServiceHistory +Description: Displays the customer’s past service bookings in tabular format, + including booking ID, technician, vehicle details, discount percentage, and status. +Parameters: + - None +Returns: + - void +*/ void CustomerMenu::viewServiceHistory() { + util::clear(); + bool hasServiceHistory = false; + const User* currentUser = m_controller.getAuthenticatedUser(); + std::string currentUserID = currentUser->getId(); + util::Map serviceBookingsByCurrentUser = m_controller.getServiceBookingsByUser(currentUserID); + if (serviceBookingsByCurrentUser.getSize() != 0) + { + std::cout << std::left + << std::setw(12) << "Booking ID" + << std::setw(20) << "Technician" + << std::setw(15) << "Vehicle Brand" + << std::setw(15) << "Vehicle Number" + << std::setw(15) << "Vehicle Model" + << std::setw(10) << "Discount %" + << std::setw(12) << "Status" + << std::endl; + for (int iterator = 0; iterator < serviceBookingsByCurrentUser.getSize(); iterator++) + { + const ServiceBooking* currentBooking = serviceBookingsByCurrentUser.getValueAt(iterator); + std::string technicianName = currentBooking->getAssignedTechnician() == nullptr + ? "Not Assigned" + : currentBooking->getAssignedTechnician()->getName(); + std::cout << std::left + << std::setw(12) << currentBooking->getId() + << std::setw(20) << technicianName + << std::setw(15) << currentBooking->getVehicleBrand() + << std::setw(15) << currentBooking->getVehicleNumber() + << std::setw(15) << currentBooking->getVehicleModel() + << std::setw(10) << currentBooking->getDiscountPercentage() + << std::setw(12) << util::getServiceJobStatusString(currentBooking->getStatus()) + << std::endl; + hasServiceHistory = true; + } + } + if (!hasServiceHistory) + { + std::cout << "No history available." << std::endl; + } + util::pressEnter(); } +/* +Function: completePayments +Description: Allows the customer to complete pending payments for invoices. + Validates invoice selection and payment mode before completing payment. +Parameters: + - None +Returns: + - void +*/ void CustomerMenu::completePayments() { + util::clear(); + util::Map currentInvoices = m_controller.getInvoicesByUser(); + std::string selectedID = selectInvoiceFromUserForPayment(currentInvoices); + if (selectedID == "") + { + std::cout << "Payment failed.\n"; + return; + } + util::PaymentMode paymentMode = selectPaymentMode(); + m_controller.completePayment(selectedID, paymentMode); + std::cout << "Payment completed successfully.\n"; + util::pressEnter(); } +/* +Function: viewInvoices +Description: Displays invoices associated with the customer by calling displayInvoices. +Parameters: + - None +Returns: + - void +*/ void CustomerMenu::viewInvoices() { + util::clear(); + util::Map currentUserInvoices = m_controller.getInvoicesByUser(); + displayInvoices(currentUserInvoices); + util::pressEnter(); } /* diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h index 9dfc41d..6dcb97d 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h @@ -8,20 +8,516 @@ Date: 21-May-2026 */ #pragma once -#include #include +#include #include -#include "Utility.h" +#include "ComboPackage.h" #include "Controller.h" +#include "Enums.h" #include "InputHelper.h" +#include "InventoryItem.h" +#include "Invoice.h" +#include "JobCard.h" #include "Map.h" #include "Notification.h" #include "OutputHelper.h" -#include "Vector.h" -#include "Validator.h" #include "Service.h" -#include "ComboPackage.h" +#include "ServiceBooking.h" +#include "Timestamp.h" +#include "User.h" #include "Utility.h" +#include "Validator.h" +#include "Vector.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 ""; + } +} /* Function: selectNotification @@ -106,15 +602,15 @@ Returns: inline void viewAndDeleteNotification(Controller& controller) { util::clear(); - auto notifications = controller.getNotifications(); - const Notification* selectedNotification = selectNotification(notifications); - if (!selectedNotification) - { - std::cout << "Failed to display notification!"; - util::pressEnter(); - return; - } - displayNotification(selectedNotification); + auto notifications = controller.getNotifications(); + const Notification* selectedNotification = selectNotification(notifications); + if (!selectedNotification) + { + std::cout << "Failed to display notification!"; + util::pressEnter(); + return; + } + displayNotification(selectedNotification); controller.deleteNotification(selectedNotification->getId()); util::pressEnter(); } @@ -526,4 +1022,4 @@ inline std::string selectComboPackage(util::Map assignedJobCards = m_controller.getJobCardsByUser(); + util::Map incompleteJobCards; + std::cout << "Jobs to be completed.\n"; + std::string selectedJobID = selectJobCardToComplete(assignedJobCards, incompleteJobCards); + if (selectedJobID == "") + { + std::cout << "Failed to complete the job.\n"; + } + else + { + m_controller.completeJob(selectedJobID); + std::cout << "Job marked as completed.\n"; + } + util::pressEnter(); } /*