/* File: PaymentManagementService.cpp Description: Implements the PaymentManagementService class which manages payment-related operations in the Vehicle Service Management System. Provides functionality for attaching/detaching observers, sending notifications, and issuing payment reminders based on invoice status and thresholds. Author: Trenser Date: 20-May-2026 */ #include #include "Config.h" #include "Enums.h" #include "Factory.h" #include "FileManager.h" #include "Invoice.h" #include "PaymentManagementService.h" #include "ServiceBooking.h" #include "Timestamp.h" #include "User.h" #include "Utility.h" util::Map PaymentManagementService::m_observers{}; /* Function: attach Description: Attaches a user as an observer to the PaymentManagementService for receiving notifications. Parameters: - user: Pointer to the User object to be attached. Returns: - void */ void PaymentManagementService::attach(User* user) { if (user) { const std::string& userID = user->getId(); if (m_observers.find(userID) == -1) { m_observers[userID] = user; } } } /* Function: detach Description: Detaches a user from the observer list of the PaymentManagementService. Parameters: - user: Pointer to the User object to be detached. Returns: - void */ void PaymentManagementService::detach(User* user) { if (user) { const std::string& userID = user->getId(); if (m_observers.find(userID) != -1) { m_observers.remove(userID); } } } /* Function: sendNotification Description: Sends a notification to a user if they are registered as an observer. Parameters: - user: Pointer to the User object to receive the notification. - title: Title of the notification. - message: Message content of the notification. Returns: - void Throws: - std::runtime_error if notification creation fails. */ void PaymentManagementService::sendNotification(User* user, const std::string& title, const std::string& message) { if (user) { if (m_observers.find(user->getId()) != -1) { Notification* notification = Factory::getObject( user->getId(), user, "PaymentManagementService: " + title, message, util::Timestamp() ); if (notification) { user->addNotification(notification); } else { throw std::runtime_error("Failed to create notification"); } } } } /* Function: sendPaymentReminders Description: Iterates through all invoices in the datastore and sends payment reminders to customers whose invoices are pending beyond the configured threshold duration. Parameters: - None Returns: - void */ void PaymentManagementService::sendPaymentReminders() { auto& invoicesMap = m_dataStore.getInvoices(); int invoicesMapSize = invoicesMap.getSize(); for (int index = 0; index < invoicesMapSize; index++) { const Invoice* invoice = invoicesMap.getValueAt(index); if (invoice && invoice->getStatus() == util::PaymentStatus::PENDING) { util::Timestamp invoiceCreationTimestamp = invoice->getInvoiceDate(); util::Timestamp currentTimestamp; if (util::Timestamp::getDurationInHours(invoiceCreationTimestamp, currentTimestamp) >= config::threshold::PAYMENT_REMINDER_THRESHOLD_HOURS) { const ServiceBooking* serviceBooking = invoice->getBooking(); if (serviceBooking) { User* customer = serviceBooking->getCustomer(); if (customer) { std::string title = "Payment Reminder"; std::string message = "Your payment for Invoice ID " + invoice->getId() + " is still pending. Please complete the payment."; sendNotification(customer, title, message); } } } } } } /* Function: getObserverIDs Description: Retrieves the IDs of all observers currently attached to the PaymentManagementService. Parameters: - None Returns: - util::Vector: Vector of observer user IDs */ util::Vector PaymentManagementService::getObserverIDs() { util::Vector observerIDs; int numberOfObservers = m_observers.getSize(); for (int index = 0; index < numberOfObservers; index++) { User* observer = m_observers.getValueAt(index); if (observer) { observerIDs.push_back(observer->getId()); } } return observerIDs; } /* Function: loadInvoices Description: Loads invoices from persistent storage into the datastore. Validates associated service bookings and inventory parts before attaching them to each invoice. Throws exceptions if invalid IDs are encountered. Parameters: - None Returns: - void Throws: - std::runtime_error if a booking ID or part ID is invalid */ void PaymentManagementService::loadInvoices() { util::FileManager invoiceFileManager(config::file::INVOICE_FILE); auto& invoices = m_dataStore.getInvoices(); auto& serviceBookings = m_dataStore.getServiceBookings(); auto& inventoryItems = m_dataStore.getInventoryItems(); auto invoicesMap = invoiceFileManager.load(); for (int invoiceIndex = 0; invoiceIndex < invoicesMap.getSize(); invoiceIndex++) { Invoice* invoice = invoicesMap.getValueAt(invoiceIndex); int bookingIndex = serviceBookings.find(invoice->getBookingId()); if (bookingIndex == -1) { throw std::runtime_error("Invalid Booking ID"); } ServiceBooking* booking = serviceBookings.getValueAt(bookingIndex); invoice->setBooking(booking); util::Map invoiceParts; auto& partIDs = invoice->getPartIDs(); for (int partIndex = 0; partIndex < partIDs.getSize(); partIndex++) { const std::string& partID = partIDs[partIndex]; int inventoryIndex = inventoryItems.find(partID); if (inventoryIndex == -1) { throw std::runtime_error("Invalid Part ID"); } invoiceParts[partID] = inventoryItems.getValueAt(inventoryIndex); } invoice->setParts(invoiceParts); invoices[invoice->getId()] = invoice; } } /* Function: saveInvoices Description: Saves invoices from the datastore to persistent storage. Uses FileManager to serialize invoices into the configured file. Parameters: - None Returns: - void */ void PaymentManagementService::saveInvoices() { util::FileManager invoiceFileManager(config::file::INVOICE_FILE); auto& invoices = m_dataStore.getInvoices(); invoiceFileManager.save(invoices); } /* Function: loadObservers Description: Loads observer IDs from persistent storage and attaches corresponding users as observers to the PaymentManagementService. Parameters: - None Returns: - void Throws: - std::runtime_error if an observer ID is invalid (not found in datastore) */ void PaymentManagementService::loadObservers() { util::loadObservers(config::file::PAYMENTMANAGEMENTOBSERVERS, this, m_dataStore); } /* Function: saveObservers Description: Saves the current observer IDs of the PaymentManagementService to persistent storage for future retrieval. Parameters: - None Returns: - void */ void PaymentManagementService::saveObservers() { util::saveObservers(config::file::PAYMENTMANAGEMENTOBSERVERS, this); }