Files
Jissin Mathew 61f70a54f6 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>
2026-05-21 16:05:10 +05:30

173 lines
3.7 KiB
C++

#pragma once
#include <stdexcept>
namespace util
{
enum class UserType
{
ADMIN,
TECHNICIAN,
CUSTOMER
};
enum class PaymentMode
{
ONLINE,
OFFLINE,
NOTSET
};
enum class PaymentStatus
{
PENDING,
COMPLETED
};
enum class ServiceJobStatus
{
STARTED,
COMPLETED
};
enum class State
{
ACTIVE,
INACTIVE
};
inline std::string getUserTypeString(UserType type)
{
switch (type)
{
case UserType::ADMIN:
return "ADMIN";
case UserType::TECHNICIAN:
return "TECHNICIAN";
case UserType::CUSTOMER:
return "CUSTOMER";
}
throw std::invalid_argument("Invalid UserType");
}
inline UserType getUserType(const std::string& value)
{
if (value == "ADMIN")
{
return UserType::ADMIN;
}
if (value == "TECHNICIAN")
{
return UserType::TECHNICIAN;
}
if (value == "CUSTOMER")
{
return UserType::CUSTOMER;
}
throw std::invalid_argument("Invalid UserType string");
}
inline std::string getPaymentModeString(PaymentMode mode)
{
switch (mode)
{
case PaymentMode::ONLINE:
return "ONLINE";
case PaymentMode::OFFLINE:
return "OFFLINE";
case PaymentMode::NOTSET:
return "NOTSET";
}
throw std::invalid_argument("Invalid PaymentMode");
}
inline PaymentMode getPaymentMode(const std::string& value)
{
if (value == "ONLINE")
{
return PaymentMode::ONLINE;
}
if (value == "OFFLINE")
{
return PaymentMode::OFFLINE;
}
throw std::invalid_argument("Invalid PaymentMode string");
}
inline std::string getPaymentStatusString(PaymentStatus status)
{
switch (status)
{
case PaymentStatus::PENDING:
return "PENDING";
case PaymentStatus::COMPLETED:
return "COMPLETED";
}
throw std::invalid_argument("Invalid PaymentStatus");
}
inline PaymentStatus getPaymentStatus(const std::string& value)
{
if (value == "PENDING")
{
return PaymentStatus::PENDING;
}
if (value == "COMPLETED")
{
return PaymentStatus::COMPLETED;
}
throw std::invalid_argument("Invalid PaymentStatus string");
}
inline std::string getServiceJobStatusString(ServiceJobStatus status)
{
switch (status)
{
case ServiceJobStatus::STARTED:
return "STARTED";
case ServiceJobStatus::COMPLETED:
return "COMPLETED";
}
throw std::invalid_argument("Invalid ServiceJobStatus");
}
inline ServiceJobStatus getServiceJobStatus(const std::string& value)
{
if (value == "STARTED")
{
return ServiceJobStatus::STARTED;
}
if (value == "COMPLETED")
{
return ServiceJobStatus::COMPLETED;
}
throw std::invalid_argument("Invalid ServiceJobStatus string");
}
inline std::string getStateString(State status)
{
switch (status)
{
case State::ACTIVE:
return "STARTED";
case State::INACTIVE:
return "COMPLETED";
}
throw std::invalid_argument("Invalid State");
}
inline State getState(const std::string& value)
{
if (value == "ACTIVE")
{
return State::ACTIVE;
}
if (value == "COMPLETED")
{
return State::INACTIVE;
}
throw std::invalid_argument("Invalid State string");
}
}