Implement Generate Invoice

<UserStory> PAY001: Generate Invoice </UserStory>

<Changes>
    1. Added Utility.h to project configuration for supporting invoice generation utilities.
    2. Updated Invoice model to use string-based keys for parts mapping instead of integer keys.
    3. Implemented PaymentManagementService::generateInvoice to aggregate labour cost, parts cost, and apply discounts.
    4. Integrated invoice creation with Factory to instantiate Invoice objects and persist them into datastore.
    5. Enhanced Enums with PaymentMode::NOTSET to handle default invoice state.
</Changes>

<Test>

 Acceptance Criteria:
 1. Invoice auto-generates for each service booking once jobs are completed.
 2. Invoice shows a clear breakdown of charges including labour cost, parts cost, discount, and total amount.

 Precondition:
  1. Service booking exists with at least one service and required inventory items.
  2. Datastore is available for storing invoices.
  3. Payment mode and status enums are properly configured.

 Steps:
  1. Complete all jobs in a service booking.
    - Verify that PaymentManagementService::generateInvoice is triggered.
  2. Check datastore for newly created invoice.
    - Verify that invoice contains booking ID, labour cost, parts cost, discount, and total amount.
  3. Inspect invoice details.
    - Verify that breakdown of charges is accurate and discount is applied correctly.
  4. Confirm invoice status.
    - Verify that invoice is created with PaymentMode::NOTSET and PaymentStatus::PENDING.
</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
This commit is contained in:
Jissin Mathew
2026-05-20 14:57:10 +05:30
parent 56c5c2dc70
commit 61f70a54f6
9 changed files with 97 additions and 18 deletions
@@ -1 +1,57 @@
#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"
static void createInventoryItemsMap(util::Map<std::string, InventoryItem*>& 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);
}
}
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<std::string, Service*> servicesInTheBookedService = booking->getServices();
util::Map<std::string, InventoryItem*> completeInventoryItemMapOfBooking;
util::Map<std::string, JobCard*> 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<Invoice>(bookingID, booking, util::Timestamp(), totalLabourCost, completeInventoryItemMapOfBooking, totalPartsCost, discountPercentage, totalServiceCost, util::Timestamp(), util::PaymentMode::NOTSET, util::PaymentStatus::PENDING);
util::Map<std::string, Invoice*>& currentInvoices = m_dataStore.getInvoices();
currentInvoices.insert(invoice->getId(), invoice);
}