diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj index a65c46d..819264c 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj @@ -176,6 +176,7 @@ + diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters index 77d0509..7c17f4e 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters @@ -233,5 +233,8 @@ Header Files\Models + + Header Files\Utilities + \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp index 6292130..058f0d2 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp @@ -3,6 +3,8 @@ #include "Service.h" #include "ServiceBooking.h" #include "JobCard.h" +#include "User.h" +#include "Invoice.h" bool Controller::login(const std::string& username, const std::string& password) { @@ -236,13 +238,40 @@ void Controller::removeComboPackage(const std::string& comboPackageID) { } +/* +Function: getInvoicesByUser +Description: Retrieves all invoices associated with the currently authenticated user. + Converts them into a read-only map before returning. +Parameters: + - None +Returns: + - util::Map containing the user’s invoices +*/ util::Map Controller::getInvoicesByUser() { - 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); } util::Vector Controller::getNotifications() @@ -260,5 +289,4 @@ void Controller::configureNotifications(const std::string& userID, bool paymentN void Controller::runSystemChecks() { -} - +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h index eec7cbb..7a47874 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h @@ -2,6 +2,8 @@ #include "Map.h" #include #include "Enums.h" +#include "PaymentManagementService.h" +#include "AuthenticationManagementService.h" #include "ServiceManagementService.h" #include "UserManagementService.h" #include "InventoryManagementService.h" @@ -18,6 +20,8 @@ class Notification; class Controller { private: + AuthenticationManagementService m_authenticationManagementService; + PaymentManagementService m_paymentManagementService; ServiceManagementService m_serviceManagementService; UserManagementService m_userManagementService; public: diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.cpp index ba7bc84..507f274 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.cpp @@ -16,7 +16,8 @@ Invoice::Invoice( const std::string& bookingId, ServiceBooking* booking, const util::Timestamp& invoiceDate, - double laborCost, const util::Map& parts, double partsCost, double discountPercentage, @@ -63,7 +64,7 @@ double Invoice::getLaborCost() const return m_laborCost; } -const util::Map& Invoice::getParts() const +const util::Map& Invoice::getParts() const { return m_parts; } @@ -123,7 +124,7 @@ void Invoice::setLaborCost(double laborCost) m_laborCost = laborCost; } -void Invoice::setParts(const util::Map& parts) +void Invoice::setParts(const util::Map& parts) { m_parts = parts; } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.h index 212d33f..f78f7c9 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.h @@ -16,7 +16,7 @@ private: ServiceBooking* m_booking; util::Timestamp m_invoiceDate; double m_laborCost; - util::Map m_parts; + util::Map m_parts; double m_partsCost; double m_discountPercentage; double m_totalAmount; @@ -30,8 +30,8 @@ public: const std::string& bookingId, ServiceBooking* booking, const util::Timestamp& invoiceDate, - double laborCost, const util::Map& parts, + double laborCost, + const util::Map& parts, double partsCost, double discountPercentage, double totalAmount, @@ -44,7 +44,7 @@ public: ServiceBooking* getBooking() const; const util::Timestamp& getInvoiceDate() const; double getLaborCost() const; - const util::Map& getParts() const; + const util::Map& getParts() const; double getPartsCost() const; double getDiscountPercentage() const; double getTotalAmount() const; @@ -56,7 +56,7 @@ public: void setBooking(ServiceBooking* booking); void setInvoiceDate(const util::Timestamp& invoiceDate); void setLaborCost(double laborCost); - void setParts(const util::Map& parts); + void setParts(const util::Map& parts); void setPartsCost(double partsCost); void setDiscountPercentage(double discountPercentage); void setTotalAmount(double totalAmount); diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h index 9bd78aa..40699c0 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h @@ -1,7 +1,7 @@ #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 786ebcf..8b67c7d 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp @@ -1 +1,135 @@ #include "PaymentManagementService.h" +#include "ServiceBooking.h" +#include "Service.h" +#include "InventoryItem.h" +#include "Utility.h" +#include "Factory.h" +#include "Timestamp.h" +#include "Invoice.h" +#include "JobCard.h" +#include "Enums.h" + +/* +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); + 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/utilities/Enums.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h index 5353467..f198108 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h @@ -13,7 +13,8 @@ namespace util enum class PaymentMode { ONLINE, - OFFLINE + OFFLINE, + NOTSET }; enum class PaymentStatus @@ -74,6 +75,8 @@ namespace util return "ONLINE"; case PaymentMode::OFFLINE: return "OFFLINE"; + case PaymentMode::NOTSET: + return "NOTSET"; } throw std::invalid_argument("Invalid PaymentMode"); } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h new file mode 100644 index 0000000..cb9b990 --- /dev/null +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h @@ -0,0 +1,15 @@ +#pragma once +#include "Service.h" +#include "InventoryItem.h" + +inline double calculatePartsCost(const Service* service) +{ + double cost = 0; + auto& requiredInventoryItems = service->getRequiredInventoryItems(); + int requiredInventoryItemsSize = requiredInventoryItems.getSize(); + for (int index = 0; index < requiredInventoryItemsSize; index++) + { + cost += requiredInventoryItems.getValueAt(index)->getPrice(); + } + return cost; +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp index 38c3090..11f3706 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp @@ -1,10 +1,15 @@ #include +#include #include "CustomerMenu.h" #include "InputHelper.h" #include "OutputHelper.h" -#include "User.h" -#include "ServiceBooking.h" +#include "Invoice.h" #include "Enums.h" +#include "ServiceBooking.h" +#include "User.h" +#include "Timestamp.h" +#include "Service.h" +#include "InventoryItem.h" void CustomerMenu::showMenu() { @@ -106,12 +111,197 @@ void CustomerMenu::viewServiceHistory() } } -void CustomerMenu::completePayments() +/* +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; + } +} + +/* +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"; +} + +/* +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."); + } + } + } +} + +/* +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); } void CustomerMenu::viewNotifications()