Implement Purchase Combo functionality
<UserStory> CUS007: Purchase Combo Package </UserStory>
<Changes>
1. Added combo package selection flow in CustomerMenu to list all active combo packages with estimated cost and allow customer selection.
2. Implemented Controller::purchaseComboPackage to delegate combo package booking requests to ServiceManagementService.
3. Added ServiceManagementService::purchaseComboPackage logic to validate authenticated user, fetch selected combo package, create a ServiceBooking, persist it in DataStore, and send booking confirmation notification.
4. Added helper functions in CustomerMenu to calculate combo package estimated cost based on included services and required inventory items.
5. Updated ServiceBooking model to use User* reference for assigned technician and simplified constructor to align booking model with object references.
</Changes>
<Test>
Precondition:
1. Customer account exists and is logged into the system.
2. Active combo packages are available in the system.
3. Combo package contains one or more active services.
4. Service bookings and notifications can be created successfully.
Steps:
1. Navigate to Customer Menu and select the combo package booking option.
2. View the list of available combo packages.
- Verify that all active combo packages are displayed with their details.
3. Select one combo package and enter vehicle number, vehicle brand, and vehicle model.
- Verify that a booking request is generated successfully.
4. Complete the booking flow.
- Verify that a confirmation message is displayed to the customer.
5. Check customer notifications.
- Verify that a booking confirmation notification is received.
</Test>
<Review>
Sreeja Reghukumar, please review
</Review>
This commit is contained in:
+1
@@ -176,6 +176,7 @@
|
||||
<ClInclude Include="utilities\Map.h" />
|
||||
<ClInclude Include="utilities\OutputHelper.h" />
|
||||
<ClInclude Include="utilities\Timestamp.h" />
|
||||
<ClInclude Include="utilities\Utility.h" />
|
||||
<ClInclude Include="utilities\Validator.h" />
|
||||
<ClInclude Include="utilities\Vector.h" />
|
||||
<ClInclude Include="views\AdminMenu.h" />
|
||||
|
||||
@@ -46,6 +46,7 @@ void Controller::purchaseService(const util::Vector<std::string>& serviceIDs, co
|
||||
|
||||
void Controller::purchaseComboPackage(const std::string& comboPackageID, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel)
|
||||
{
|
||||
m_serviceManagementService.purchaseComboPackage(comboPackageID, vehicleNumber, vehicleBrand, vehicleModel);
|
||||
}
|
||||
|
||||
util::Map<std::string, const InventoryItem*> Controller::getInventoryItems()
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "Map.h"
|
||||
#include <string>
|
||||
#include "Enums.h"
|
||||
#include "ServiceManagementService.h"
|
||||
|
||||
class Service;
|
||||
class ComboPackage;
|
||||
@@ -14,6 +15,8 @@ class Notification;
|
||||
|
||||
class Controller
|
||||
{
|
||||
private:
|
||||
ServiceManagementService m_serviceManagementService;
|
||||
public:
|
||||
bool login(const std::string& username, const std::string& password);
|
||||
void logout();
|
||||
|
||||
@@ -5,10 +5,11 @@ int ServiceBooking::m_uid = 0;
|
||||
ServiceBooking::ServiceBooking()
|
||||
: m_id("SRV" + std::to_string(++m_uid)),
|
||||
m_customer(nullptr),
|
||||
m_discountPercentage(0.0) {}
|
||||
m_assignedTechnician(nullptr),
|
||||
m_discountPercentage(0.0) {
|
||||
}
|
||||
|
||||
ServiceBooking::ServiceBooking(
|
||||
const std::string& id,
|
||||
util::ServiceJobStatus status,
|
||||
const util::Map<std::string,
|
||||
Service*>& services,
|
||||
@@ -17,8 +18,6 @@ ServiceBooking::ServiceBooking(
|
||||
const std::string& vehicleNumber,
|
||||
const std::string& vehicleBrand,
|
||||
const std::string& vehicleModel,
|
||||
const std::string& assignedTechnicianId,
|
||||
const std::string& assignedTechnician,
|
||||
double discountPercentage
|
||||
)
|
||||
: m_id("SRV" + std::to_string(++m_uid)),
|
||||
@@ -29,8 +28,8 @@ ServiceBooking::ServiceBooking(
|
||||
m_vehicleNumber(vehicleNumber),
|
||||
m_vehicleBrand(vehicleBrand),
|
||||
m_vehicleModel(vehicleModel),
|
||||
m_assignedTechnicianId(assignedTechnicianId),
|
||||
m_assignedTechnician(assignedTechnician),
|
||||
m_assignedTechnicianId(""),
|
||||
m_assignedTechnician(nullptr),
|
||||
m_discountPercentage(discountPercentage)
|
||||
{
|
||||
}
|
||||
@@ -80,7 +79,7 @@ const std::string& ServiceBooking::getAssignedTechnicianId() const
|
||||
return m_assignedTechnicianId;
|
||||
}
|
||||
|
||||
const std::string& ServiceBooking::getAssignedTechnician() const
|
||||
User* ServiceBooking::getAssignedTechnician() const
|
||||
{
|
||||
return m_assignedTechnician;
|
||||
}
|
||||
@@ -135,7 +134,7 @@ void ServiceBooking::setAssignedTechnicianId(const std::string& assignedTechnici
|
||||
m_assignedTechnicianId = assignedTechnicianId;
|
||||
}
|
||||
|
||||
void ServiceBooking::setAssignedTechnician(const std::string& assignedTechnician)
|
||||
void ServiceBooking::setAssignedTechnician(User* assignedTechnician)
|
||||
{
|
||||
m_assignedTechnician = assignedTechnician;
|
||||
}
|
||||
|
||||
@@ -19,12 +19,11 @@ private:
|
||||
std::string m_vehicleBrand;
|
||||
std::string m_vehicleModel;
|
||||
std::string m_assignedTechnicianId;
|
||||
std::string m_assignedTechnician;
|
||||
User* m_assignedTechnician;
|
||||
double m_discountPercentage;
|
||||
public:
|
||||
ServiceBooking();
|
||||
ServiceBooking(
|
||||
const std::string& id,
|
||||
util::ServiceJobStatus status,
|
||||
const util::Map<std::string,
|
||||
Service*>& services,
|
||||
@@ -33,8 +32,6 @@ public:
|
||||
const std::string& vehicleNumber,
|
||||
const std::string& vehicleBrand,
|
||||
const std::string& vehicleModel,
|
||||
const std::string& assignedTechnicianId,
|
||||
const std::string& assignedTechnician,
|
||||
double discountPercentage
|
||||
);
|
||||
const std::string& getId() const;
|
||||
@@ -46,7 +43,7 @@ public:
|
||||
const std::string& getVehicleBrand() const;
|
||||
const std::string& getVehicleModel() const;
|
||||
const std::string& getAssignedTechnicianId() const;
|
||||
const std::string& getAssignedTechnician() const;
|
||||
User* getAssignedTechnician() const;
|
||||
double getDiscountPercentage() const;
|
||||
void setId(const std::string& id);
|
||||
void setStatus(const util::ServiceJobStatus& status);
|
||||
@@ -57,6 +54,6 @@ public:
|
||||
void setVehicleBrand(const std::string& vehicleBrand);
|
||||
void setVehicleModel(const std::string& vehicleModel);
|
||||
void setAssignedTechnicianId(const std::string& assignedTechnicianId);
|
||||
void setAssignedTechnician(const std::string& assignedTechnician);
|
||||
void setAssignedTechnician(User* assignedTechnician);
|
||||
void setDiscountPercentage(double discountPercentage);
|
||||
};
|
||||
+33
@@ -1 +1,34 @@
|
||||
#include "ServiceManagementService.h"
|
||||
#include "AuthenticationManagementService.h"
|
||||
#include "ComboPackage.h"
|
||||
#include "ServiceBooking.h"
|
||||
#include "Factory.h"
|
||||
|
||||
void ServiceManagementService::purchaseComboPackage(const std::string& comboPackageID, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel)
|
||||
{
|
||||
AuthenticationManagementService m_authenticationManagementService;
|
||||
auto authenticatedUser = m_authenticationManagementService.getAuthenticatedUser();
|
||||
if (authenticatedUser == nullptr)
|
||||
{
|
||||
throw std::runtime_error("No user is currently logged in!");
|
||||
}
|
||||
auto& comboPackagesMap = m_dataStore.getComboPackages();
|
||||
auto& serviceBookingMap = m_dataStore.getServiceBookings();
|
||||
int comboPackageIndex = comboPackagesMap.find(comboPackageID);
|
||||
if (comboPackageIndex == -1)
|
||||
{
|
||||
throw std::runtime_error("Combo Package not found!");
|
||||
}
|
||||
const ComboPackage* comboPackage = comboPackagesMap[comboPackageID];
|
||||
util::Map<std::string, Service*> selectedServices = comboPackage->getServices();
|
||||
ServiceBooking* serviceBooking = Factory::getObject<ServiceBooking>(util::ServiceJobStatus::STARTED, selectedServices, authenticatedUser->getId(), authenticatedUser, vehicleNumber, vehicleBrand, vehicleModel, comboPackage->getDiscountPercentage());
|
||||
if (serviceBooking == nullptr)
|
||||
{
|
||||
throw std::runtime_error("Failed to create combo package service booking");
|
||||
}
|
||||
serviceBookingMap[serviceBooking->getId()] = serviceBooking;
|
||||
sendNotification(authenticatedUser,
|
||||
"Combo Package Service Booking succeeded",
|
||||
"Your service booking for the combo package has been successfully placed with ID " + serviceBooking->getId());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#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;
|
||||
}
|
||||
|
||||
inline double calculateComboServiceEstimatedCost(const ComboPackage* comboPackage)
|
||||
{
|
||||
double cost = 0;
|
||||
auto& services = comboPackage->getServices();
|
||||
int servicesSize = services.getSize();
|
||||
for (int index = 0; index < servicesSize; index++)
|
||||
{
|
||||
const Service* service = services.getValueAt(index);
|
||||
cost += calculatePartsCost(service) + service->getLaborCost();
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
@@ -1,6 +1,11 @@
|
||||
#include <iomanip>
|
||||
#include "CustomerMenu.h"
|
||||
#include "ComboPackage.h"
|
||||
#include "Service.h"
|
||||
#include "InventoryItem.h"
|
||||
#include "InputHelper.h"
|
||||
#include "OutputHelper.h"
|
||||
#include "Utility.h"
|
||||
|
||||
void CustomerMenu::showMenu()
|
||||
{
|
||||
@@ -47,8 +52,70 @@ void CustomerMenu::selectService()
|
||||
{
|
||||
}
|
||||
|
||||
static const ComboPackage* selectComboPackageFromPackages(const util::Map<std::string, const ComboPackage*>& comboPackages)
|
||||
{
|
||||
util::Map<int, const ComboPackage*> activeComboPackages;
|
||||
int currentIndex = 1;
|
||||
int userInputIndex;
|
||||
std::cout << std::left
|
||||
<< std::setw(10) << "Index"
|
||||
<< std::setw(15) << "Combo Package ID"
|
||||
<< std::setw(15) << "Combo Package Name"
|
||||
<< std::setw(15) << "Estimate Cost"
|
||||
<< std::endl;
|
||||
for (int index = 0; index < comboPackages.getSize(); index++)
|
||||
{
|
||||
const ComboPackage* currentComboPackage = comboPackages.getValueAt(index);
|
||||
if (currentComboPackage->getState() != util::State::ACTIVE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
activeComboPackages.insert(currentIndex, currentComboPackage);
|
||||
std::cout << std::left
|
||||
<< std::setw(10) << currentIndex
|
||||
<< std::setw(15) << currentComboPackage->getId()
|
||||
<< std::setw(25) << currentComboPackage->getPackageName()
|
||||
<< std::setw(15) << calculateComboServiceEstimatedCost(currentComboPackage)
|
||||
<< std::endl;
|
||||
currentIndex++;
|
||||
}
|
||||
if (activeComboPackages.getSize() == 0)
|
||||
{
|
||||
std::cout << "No active combo packages available." << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
std::cout << "Enter combo package index: ";
|
||||
util::read(userInputIndex);
|
||||
if (activeComboPackages.find(userInputIndex) == -1)
|
||||
{
|
||||
std::cout << "Invalid combo package index." << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
return activeComboPackages[userInputIndex];
|
||||
}
|
||||
|
||||
void CustomerMenu::selectComboPackage()
|
||||
{
|
||||
std::string vehicleNumber, vehicleBrand, vehicleModel;
|
||||
auto comboPackages = m_controller.getComboPackages();
|
||||
util::clear();
|
||||
const ComboPackage* selectedComboPackage = selectComboPackageFromPackages(comboPackages);
|
||||
if (selectedComboPackage == nullptr)
|
||||
{
|
||||
std::cout << "Failed to book combo package!";
|
||||
util::pressEnter();
|
||||
return;
|
||||
}
|
||||
util::clear();
|
||||
std::cout << "Enter vehicle number: ";
|
||||
util::read(vehicleNumber);
|
||||
std::cout << "Enter vehicle brand: ";
|
||||
util::read(vehicleBrand);
|
||||
std::cout << "Enter vehicle model: ";
|
||||
util::read(vehicleModel);
|
||||
m_controller.purchaseComboPackage(selectedComboPackage->getId(), vehicleNumber, vehicleBrand, vehicleModel);
|
||||
std::cout << "Combo Package has been booked successfully";
|
||||
util::pressEnter();
|
||||
}
|
||||
|
||||
void CustomerMenu::viewServiceHistory()
|
||||
|
||||
Reference in New Issue
Block a user