Merge branch 'feature' into feature-1552-1560
This commit is contained in:
+496
-7
@@ -1,20 +1,509 @@
|
||||
/*
|
||||
File: ServiceManagementService.cpp
|
||||
Description: Implementation file containing the method definitions of the
|
||||
ServiceManagementService class, including service booking cancellation,
|
||||
job card management, combo package creation, and removal logic.
|
||||
ServiceManagementService class, including service and combo package
|
||||
purchasing logic, booking creation, and notification handling.
|
||||
Author: Trenser
|
||||
Date:19-May-2026
|
||||
*/
|
||||
|
||||
#include "ServiceManagementService.h"
|
||||
#include <stdexcept>
|
||||
#include "AuthenticationManagementService.h"
|
||||
#include "ComboPackage.h"
|
||||
#include "Config.h"
|
||||
#include "DataStore.h"
|
||||
#include "ServiceBooking.h"
|
||||
#include "Factory.h"
|
||||
#include "FileManager.h"
|
||||
#include "InventoryItem.h"
|
||||
#include "JobCard.h"
|
||||
#include "Service.h"
|
||||
#include "InventoryItem.h"
|
||||
#include "Factory.h"
|
||||
#include "ComboPackage.h"
|
||||
#include "ServiceBooking.h"
|
||||
#include "ServiceBooking.h"
|
||||
|
||||
#include "ServiceManagementService.h"
|
||||
#include "Timestamp.h"
|
||||
#include "User.h"
|
||||
#include "Utility.h"
|
||||
|
||||
/*
|
||||
Function: purchaseService
|
||||
Description: Creates a new service booking for the authenticated user. Validates
|
||||
service IDs, retrieves services from the DataStore, and generates a
|
||||
booking. Sends a notification upon successful booking.
|
||||
Parameter: const util::Vector<std::string>& serviceIDs - IDs of services to purchase
|
||||
const std::string& vehicleNumber - vehicle registration number
|
||||
const std::string& vehicleBrand - brand of the vehicle
|
||||
const std::string& vehicleModel - model of the vehicle
|
||||
Return type: void
|
||||
*/
|
||||
void ServiceManagementService::purchaseService(const util::Vector<std::string>& serviceIDs, 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& servicesMap = m_dataStore.getServices();
|
||||
auto& serviceBookingMap = m_dataStore.getServiceBookings();
|
||||
util::Map<std::string, Service*> selectedServices;
|
||||
int selectedServicesCount = serviceIDs.getSize();
|
||||
for (int index = 0; index < selectedServicesCount; index++)
|
||||
{
|
||||
int serviceIndex = servicesMap.find(serviceIDs[index]);
|
||||
if (serviceIndex == -1)
|
||||
{
|
||||
throw std::runtime_error("Service not found!");
|
||||
}
|
||||
Service* service = servicesMap.getValueAt(serviceIndex);
|
||||
selectedServices[service->getId()] = service;
|
||||
}
|
||||
ServiceBooking* serviceBooking = Factory::getObject<ServiceBooking>(util::ServiceJobStatus::STARTED, selectedServices, authenticatedUser->getId(), authenticatedUser, vehicleNumber, vehicleBrand, vehicleModel, 0);
|
||||
if (serviceBooking == nullptr)
|
||||
{
|
||||
throw std::runtime_error("Failed to create service booking");
|
||||
}
|
||||
serviceBookingMap[serviceBooking->getId()] = serviceBooking;
|
||||
std::string title = "Service Booking succeeded";
|
||||
std::string message = "Your service booking has been successfully placed with ID " + serviceBooking->getId();
|
||||
sendNotification(authenticatedUser, title, message);
|
||||
}
|
||||
|
||||
/*
|
||||
Function: purchaseComboPackage
|
||||
Description: Creates a new service booking for a combo package. Validates the combo
|
||||
package ID, retrieves services from the package, and generates a booking
|
||||
with the applicable discount. Sends a notification upon successful booking.
|
||||
Parameter: const std::string& comboPackageID - ID of the combo package
|
||||
const std::string& vehicleNumber - vehicle registration number
|
||||
const std::string& vehicleBrand - brand of the vehicle
|
||||
const std::string& vehicleModel - model of the vehicle
|
||||
Return type: void
|
||||
*/
|
||||
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;
|
||||
std::string title = "Combo Package Service Booking succeeded";
|
||||
std::string message = "Your service booking for the combo package has been successfully placed with ID " + serviceBooking->getId();
|
||||
sendNotification(authenticatedUser, title, message);
|
||||
}
|
||||
|
||||
util::Map<std::string, User*> ServiceManagementService::m_observers{};
|
||||
|
||||
/*
|
||||
Function: attach
|
||||
Description: Attaches a user as an observer to the ServiceManagementService for receiving notifications.
|
||||
Parameters:
|
||||
- user: Pointer to the User object to be attached.
|
||||
Returns:
|
||||
- void
|
||||
*/
|
||||
void ServiceManagementService::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 ServiceManagementService.
|
||||
Parameters:
|
||||
- user: Pointer to the User object to be detached.
|
||||
Returns:
|
||||
- void
|
||||
*/
|
||||
void ServiceManagementService::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 ServiceManagementService::sendNotification(User* user, const std::string& title, const std::string& message)
|
||||
{
|
||||
if (user)
|
||||
{
|
||||
if (m_observers.find(user->getId()) != -1)
|
||||
{
|
||||
Notification* notification =
|
||||
Factory::getObject<Notification>(
|
||||
user->getId(),
|
||||
user,
|
||||
"ServiceManagementService: " + title,
|
||||
message,
|
||||
util::Timestamp()
|
||||
);
|
||||
if (notification)
|
||||
{
|
||||
user->addNotification(notification);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("Failed to create notification");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Function: getObserverIDs
|
||||
Description: Retrieves the IDs of all observers currently attached to the
|
||||
ServiceManagementService.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- util::Vector<std::string>: Vector of observer user IDs
|
||||
*/
|
||||
util::Vector<std::string> ServiceManagementService::getObserverIDs()
|
||||
{
|
||||
util::Vector<std::string> 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: loadServices
|
||||
Description: Loads services from persistent storage into the datastore.
|
||||
Validates required inventory items and attaches them to each service.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
Throws:
|
||||
- std::runtime_error if an inventory item ID is invalid
|
||||
*/
|
||||
void ServiceManagementService::loadServices()
|
||||
{
|
||||
util::FileManager<Service> serviceFileManager(config::file::SERVICE_FILE);
|
||||
auto& services = m_dataStore.getServices();
|
||||
auto& inventoryItems = m_dataStore.getInventoryItems();
|
||||
auto servicesMap = serviceFileManager.load();
|
||||
for (int serviceIndex = 0; serviceIndex < servicesMap.getSize(); serviceIndex++)
|
||||
{
|
||||
Service* service = servicesMap.getValueAt(serviceIndex);
|
||||
services[service->getId()] = service;
|
||||
util::Map<std::string, InventoryItem*> inventoryItemsMap;
|
||||
auto& inventoryItemIDs = service->getRequiredInventoryItemIDs();
|
||||
for (int inventoryItemIndex = 0; inventoryItemIndex < inventoryItemIDs.getSize(); inventoryItemIndex++)
|
||||
{
|
||||
const std::string& inventoryItemID = inventoryItemIDs[inventoryItemIndex];
|
||||
int index = inventoryItems.find(inventoryItemID);
|
||||
if (index == -1)
|
||||
{
|
||||
throw std::runtime_error("Invalid Inventory Item ID");
|
||||
}
|
||||
inventoryItemsMap[inventoryItemID] = inventoryItems.getValueAt(index);
|
||||
}
|
||||
service->setRequiredInventoryItems(inventoryItemsMap);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Function: saveServices
|
||||
Description: Saves services from the datastore to persistent storage.
|
||||
Uses FileManager to serialize services into the configured file.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
*/
|
||||
void ServiceManagementService::saveServices()
|
||||
{
|
||||
util::FileManager<Service> serviceFileManager(config::file::SERVICE_FILE);
|
||||
auto& services = m_dataStore.getServices();
|
||||
serviceFileManager.save(services);
|
||||
}
|
||||
|
||||
/*
|
||||
Function: loadComboPackages
|
||||
Description: Loads combo packages from persistent storage into the datastore.
|
||||
Validates associated services and attaches them to each package.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
Throws:
|
||||
- std::runtime_error if a service ID is invalid
|
||||
*/
|
||||
void ServiceManagementService::loadComboPackages()
|
||||
{
|
||||
util::FileManager<ComboPackage> comboPackageFileManager(config::file::COMBOPACKAGE_FILE);
|
||||
auto& comboPackages = m_dataStore.getComboPackages();
|
||||
auto& services = m_dataStore.getServices();
|
||||
auto comboPackagesMap = comboPackageFileManager.load();
|
||||
for (int packageIndex = 0; packageIndex < comboPackagesMap.getSize(); packageIndex++)
|
||||
{
|
||||
ComboPackage* comboPackage = comboPackagesMap.getValueAt(packageIndex);
|
||||
util::Map<std::string, Service*> packageServices;
|
||||
auto& serviceIDs = comboPackage->getServiceIDs();
|
||||
for (int serviceIndex = 0; serviceIndex < serviceIDs.getSize(); serviceIndex++)
|
||||
{
|
||||
const std::string& serviceID = serviceIDs[serviceIndex];
|
||||
int serviceMapIndex = services.find(serviceID);
|
||||
if (serviceMapIndex == -1)
|
||||
{
|
||||
throw std::runtime_error("Invalid Service ID");
|
||||
}
|
||||
packageServices[serviceID] = services.getValueAt(serviceMapIndex);
|
||||
}
|
||||
comboPackage->setServices(packageServices);
|
||||
comboPackages[comboPackage->getId()] = comboPackage;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Function: saveComboPackages
|
||||
Description: Saves combo packages from the datastore to persistent storage.
|
||||
Uses FileManager to serialize combo packages into the configured file.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
*/
|
||||
void ServiceManagementService::saveComboPackages()
|
||||
{
|
||||
util::FileManager<ComboPackage> comboPackageFileManager(config::file::COMBOPACKAGE_FILE);
|
||||
auto& comboPackages = m_dataStore.getComboPackages();
|
||||
comboPackageFileManager.save(comboPackages);
|
||||
}
|
||||
|
||||
/*
|
||||
Function: loadServiceBookings
|
||||
Description: Loads service bookings from persistent storage into the datastore.
|
||||
Validates associated services, customers, and technicians before
|
||||
attaching them to each booking.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
Throws:
|
||||
- std::runtime_error if a service ID, customer ID, or technician ID is invalid
|
||||
- std::runtime_error if a user is not of the expected type (customer/technician)
|
||||
*/
|
||||
void ServiceManagementService::loadServiceBookings()
|
||||
{
|
||||
util::FileManager<ServiceBooking> bookingFileManager(config::file::SERVICEBOOKING_FILE);
|
||||
auto& serviceBookings = m_dataStore.getServiceBookings();
|
||||
auto& services = m_dataStore.getServices();
|
||||
auto& users = m_dataStore.getUsers();
|
||||
auto bookingsMap = bookingFileManager.load();
|
||||
for (int bookingIndex = 0; bookingIndex < bookingsMap.getSize(); bookingIndex++)
|
||||
{
|
||||
ServiceBooking* booking = bookingsMap.getValueAt(bookingIndex);
|
||||
util::Map<std::string, Service*> bookingServices;
|
||||
auto& serviceIDs = booking->getServiceIDs();
|
||||
for (int serviceIndex = 0; serviceIndex < serviceIDs.getSize(); serviceIndex++)
|
||||
{
|
||||
const std::string& serviceID = serviceIDs[serviceIndex];
|
||||
int serviceMapIndex = services.find(serviceID);
|
||||
if (serviceMapIndex == -1)
|
||||
{
|
||||
throw std::runtime_error("Invalid Service ID");
|
||||
}
|
||||
|
||||
bookingServices[serviceID] = services.getValueAt(serviceMapIndex);
|
||||
}
|
||||
booking->setServices(bookingServices);
|
||||
int customerIndex = users.find(booking->getCustomerId());
|
||||
if (customerIndex == -1)
|
||||
{
|
||||
throw std::runtime_error("Invalid Customer ID");
|
||||
}
|
||||
User* customer = users.getValueAt(customerIndex);
|
||||
if (customer->getUserType() != util::UserType::CUSTOMER)
|
||||
{
|
||||
throw std::runtime_error("User is not a customer");
|
||||
}
|
||||
booking->setCustomer(customer);
|
||||
const std::string& technicianId = booking->getAssignedTechnicianId();
|
||||
if (!technicianId.empty())
|
||||
{
|
||||
int technicianIndex = users.find(technicianId);
|
||||
if (technicianIndex == -1)
|
||||
{
|
||||
throw std::runtime_error("Invalid Technician ID");
|
||||
}
|
||||
User* technician = users.getValueAt(technicianIndex);
|
||||
if (technician->getUserType() != util::UserType::TECHNICIAN)
|
||||
{
|
||||
throw std::runtime_error("User is not a technician");
|
||||
}
|
||||
booking->setAssignedTechnician(technician);
|
||||
}
|
||||
serviceBookings[booking->getId()] = booking;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Function: saveServiceBookings
|
||||
Description: Saves service bookings from the datastore to persistent storage.
|
||||
Uses FileManager to serialize bookings into the configured file.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
*/
|
||||
void ServiceManagementService::saveServiceBookings()
|
||||
{
|
||||
util::FileManager<ServiceBooking> bookingFileManager(config::file::SERVICEBOOKING_FILE);
|
||||
auto& serviceBookings = m_dataStore.getServiceBookings();
|
||||
bookingFileManager.save(serviceBookings);
|
||||
}
|
||||
|
||||
/*
|
||||
Function: loadJobCards
|
||||
Description: Loads job cards from persistent storage into the datastore.
|
||||
Validates associated bookings, services, and technicians before
|
||||
attaching them to each job card.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
Throws:
|
||||
- std::runtime_error if a booking ID, service ID, or technician ID is invalid
|
||||
- std::runtime_error if a service does not belong to the booking
|
||||
- std::runtime_error if a user is not a technician
|
||||
*/
|
||||
void ServiceManagementService::loadJobCards()
|
||||
{
|
||||
util::FileManager<JobCard> jobCardFileManager(config::file::JOBCARD_FILE);
|
||||
auto& jobCards = m_dataStore.getJobCards();
|
||||
auto& serviceBookings = m_dataStore.getServiceBookings();
|
||||
auto& services = m_dataStore.getServices();
|
||||
auto& users = m_dataStore.getUsers();
|
||||
auto jobCardsMap = jobCardFileManager.load();
|
||||
for (int jobCardIndex = 0; jobCardIndex < jobCardsMap.getSize(); jobCardIndex++)
|
||||
{
|
||||
JobCard* jobCard = jobCardsMap.getValueAt(jobCardIndex);
|
||||
int bookingIndex = serviceBookings.find(jobCard->getBookingId());
|
||||
if (bookingIndex == -1)
|
||||
{
|
||||
throw std::runtime_error("Invalid Booking ID");
|
||||
}
|
||||
ServiceBooking* booking = serviceBookings.getValueAt(bookingIndex);
|
||||
jobCard->setBooking(booking);
|
||||
int serviceIndex = services.find(jobCard->getServiceId());
|
||||
if (serviceIndex == -1)
|
||||
{
|
||||
throw std::runtime_error("Invalid Service ID");
|
||||
}
|
||||
Service* service = services.getValueAt(serviceIndex);
|
||||
if (booking->getServices().find(jobCard->getServiceId()) == -1)
|
||||
{
|
||||
throw std::runtime_error("Service does not belong to booking");
|
||||
}
|
||||
jobCard->setService(service);
|
||||
int technicianIndex = users.find(jobCard->getTechnicianId());
|
||||
if (technicianIndex == -1)
|
||||
{
|
||||
throw std::runtime_error("Invalid Technician ID");
|
||||
}
|
||||
User* technician = users.getValueAt(technicianIndex);
|
||||
if (technician->getUserType() != util::UserType::TECHNICIAN)
|
||||
{
|
||||
throw std::runtime_error("User is not a technician");
|
||||
}
|
||||
jobCard->setTechnician(technician);
|
||||
jobCards[jobCard->getId()] = jobCard;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Function: saveJobCards
|
||||
Description: Saves job cards from the datastore to persistent storage.
|
||||
Uses FileManager to serialize job cards into the configured file.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
*/
|
||||
void ServiceManagementService::saveJobCards()
|
||||
{
|
||||
util::FileManager<JobCard> jobCardFileManager(config::file::JOBCARD_FILE);
|
||||
auto& jobCards = m_dataStore.getJobCards();
|
||||
jobCardFileManager.save(jobCards);
|
||||
}
|
||||
|
||||
/*
|
||||
Function: loadObservers
|
||||
Description: Loads observer IDs from persistent storage and attaches corresponding
|
||||
users as observers to the ServiceManagementService.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
Throws:
|
||||
- std::runtime_error if an observer ID is invalid (not found in datastore)
|
||||
*/
|
||||
void ServiceManagementService::loadObservers()
|
||||
{
|
||||
util::loadObservers(config::file::SERVICEMANAGEMENTOBSERVERS, this, m_dataStore);
|
||||
}
|
||||
|
||||
/*
|
||||
Function: saveObservers
|
||||
Description: Saves the current observer IDs of the ServiceManagementService
|
||||
to persistent storage for future retrieval.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
*/
|
||||
void ServiceManagementService::saveObservers()
|
||||
{
|
||||
util::saveObservers(config::file::SERVICEMANAGEMENTOBSERVERS, this);
|
||||
}
|
||||
|
||||
/*
|
||||
Function: cancelCustomerServiceBookings
|
||||
|
||||
Reference in New Issue
Block a user