Fix Service Removal and Combo Package Management Issues
- Added ComboPackage dependency check in removeService; deactivates related packages when a service is removed. - Added filterActiveServices helper to list only active services. - Updated removeService and removeComboPackage with headings, empty-state checks, and consistent success/error messages. - Enhanced createComboPackages: - Uses active services only. - Added cancel option and confirmation after first selection. - Prevented duplicate selection and infinite loop when limited services exist. - Improved feedback when all available services are selected. - Updated selectServicesToRemove and selectComboPackage to handle empty states gracefully without exceptions. Fixes #1749
This commit is contained in:
+19
@@ -26,6 +26,7 @@ Date:19-May-2026
|
|||||||
#include "User.h"
|
#include "User.h"
|
||||||
#include "UserManagementService.h"
|
#include "UserManagementService.h"
|
||||||
#include "Utility.h"
|
#include "Utility.h"
|
||||||
|
#include "ComboPackage.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: purchaseService
|
Function: purchaseService
|
||||||
@@ -909,9 +910,27 @@ Throws:
|
|||||||
void ServiceManagementService::removeService(const std::string& serviceID)
|
void ServiceManagementService::removeService(const std::string& serviceID)
|
||||||
{
|
{
|
||||||
util::Map<std::string, Service*>& currentServices = m_dataStore.getServices();
|
util::Map<std::string, Service*>& currentServices = m_dataStore.getServices();
|
||||||
|
util::Map<std::string, ComboPackage*>& currentComboPackages = m_dataStore.getComboPackages();
|
||||||
if (currentServices.find(serviceID) != -1)
|
if (currentServices.find(serviceID) != -1)
|
||||||
{
|
{
|
||||||
currentServices.getValueAt(currentServices.find(serviceID))->setState(util::State::INACTIVE);
|
currentServices.getValueAt(currentServices.find(serviceID))->setState(util::State::INACTIVE);
|
||||||
|
for (int iterator = 0; iterator < currentComboPackages.getSize(); iterator++)
|
||||||
|
{
|
||||||
|
ComboPackage* currentComboPackage = currentComboPackages.getValueAt(iterator);
|
||||||
|
if (currentComboPackage && currentComboPackage->getState() == util::State::ACTIVE)
|
||||||
|
{
|
||||||
|
util::Map<std::string, Service*> currentServices = currentComboPackage->getServices();
|
||||||
|
for (int iterator = 0; iterator < currentServices.getSize(); iterator++)
|
||||||
|
{
|
||||||
|
auto currentService = currentServices.getValueAt(iterator);
|
||||||
|
if (currentService->getId() == serviceID)
|
||||||
|
{
|
||||||
|
currentComboPackage->setState(util::State::INACTIVE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -420,17 +420,19 @@ Returns:
|
|||||||
void AdminMenu::removeService()
|
void AdminMenu::removeService()
|
||||||
{
|
{
|
||||||
util::clear();
|
util::clear();
|
||||||
|
std::cout << "Remove Service\n";
|
||||||
std::string selectedServiceID;
|
std::string selectedServiceID;
|
||||||
util::Map<std::string, const Service*> currentServices = m_controller.getServices();
|
util::Map<std::string, const Service*> currentServices = m_controller.getServices();
|
||||||
selectedServiceID = selectServicesToRemove(currentServices);
|
util::Map<std::string, const Service*> currentActiveServices = filterActiveServices(currentServices);
|
||||||
|
selectedServiceID = selectServicesToRemove(currentActiveServices);
|
||||||
if (selectedServiceID != "")
|
if (selectedServiceID != "")
|
||||||
{
|
{
|
||||||
m_controller.removeService(selectedServiceID);
|
m_controller.removeService(selectedServiceID);
|
||||||
std::cout << "Service removed sucessfully.";
|
std::cout << "Service removed sucessfully.\n\n";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cout << "Failed to remove service.";
|
std::cout << "Failed to remove service.\n\n";
|
||||||
}
|
}
|
||||||
util::pressEnter();
|
util::pressEnter();
|
||||||
}
|
}
|
||||||
@@ -527,7 +529,10 @@ Return type: void
|
|||||||
void AdminMenu::createComboPackages()
|
void AdminMenu::createComboPackages()
|
||||||
{
|
{
|
||||||
util::clear();
|
util::clear();
|
||||||
|
std::cout << "Create Combo Packages\n";
|
||||||
auto serviceList = m_controller.getServices();
|
auto serviceList = m_controller.getServices();
|
||||||
|
auto activeServices = filterActiveServices(serviceList);
|
||||||
|
int currentActiveServicesCount = activeServices.getSize();
|
||||||
const int NUMBER_OF_SERVICE_PER_PACKAGE = 2;
|
const int NUMBER_OF_SERVICE_PER_PACKAGE = 2;
|
||||||
util::Vector<std::string> selectedServiceID;
|
util::Vector<std::string> selectedServiceID;
|
||||||
for (int iterator = 0; iterator < NUMBER_OF_SERVICE_PER_PACKAGE; iterator++)
|
for (int iterator = 0; iterator < NUMBER_OF_SERVICE_PER_PACKAGE; iterator++)
|
||||||
@@ -535,10 +540,10 @@ void AdminMenu::createComboPackages()
|
|||||||
const Service* chosenService = nullptr;
|
const Service* chosenService = nullptr;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
chosenService = selectServiceFromServices(serviceList);
|
chosenService = selectServiceFromServices(activeServices);
|
||||||
if (chosenService == nullptr)
|
if (chosenService == nullptr)
|
||||||
{
|
{
|
||||||
std::cout << "Failed to create combo package!";
|
std::cout << "Failed to create combo package!\n\n";
|
||||||
util::pressEnter();
|
util::pressEnter();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -553,13 +558,21 @@ void AdminMenu::createComboPackages()
|
|||||||
}
|
}
|
||||||
if (alreadyChosen)
|
if (alreadyChosen)
|
||||||
{
|
{
|
||||||
|
if (currentActiveServicesCount < 2)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
std::cout << "Service already selected. Please choose a different one." << std::endl;
|
std::cout << "Service already selected. Please choose a different one." << std::endl;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
selectedServiceID.push_back(chosenService->getId());
|
selectedServiceID.push_back(chosenService->getId());
|
||||||
util::clear();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (currentActiveServicesCount < 2)
|
||||||
|
{
|
||||||
|
std::cout << "All the available services selected\n\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
std::string packageName;
|
std::string packageName;
|
||||||
double discountPercentage;
|
double discountPercentage;
|
||||||
@@ -587,16 +600,17 @@ Return type: void
|
|||||||
void AdminMenu::removeComboPackage()
|
void AdminMenu::removeComboPackage()
|
||||||
{
|
{
|
||||||
util::clear();
|
util::clear();
|
||||||
|
std::cout << "Remove Combo Package\n";
|
||||||
util::Map<std::string, const ComboPackage*> currentComboPackages = m_controller.getComboPackages();
|
util::Map<std::string, const ComboPackage*> currentComboPackages = m_controller.getComboPackages();
|
||||||
std::string selectedComboPackageID = selectComboPackage(currentComboPackages);
|
std::string selectedComboPackageID = selectComboPackage(currentComboPackages);
|
||||||
if (selectedComboPackageID != "")
|
if (!selectedComboPackageID.empty())
|
||||||
{
|
{
|
||||||
m_controller.removeComboPackage(selectedComboPackageID);
|
m_controller.removeComboPackage(selectedComboPackageID);
|
||||||
std::cout << "Combo Package removed successfully.\n";
|
std::cout << "Combo Package removed successfully.\n\n";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cout << "Combo package removal failed.\n";
|
std::cout << "Combo package removal failed.\n\n";
|
||||||
}
|
}
|
||||||
util::pressEnter();
|
util::pressEnter();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,8 +39,12 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
inline std::string selectServicesToRemove(util::Map<std::string, const Service*> currentServices)
|
inline std::string selectServicesToRemove(util::Map<std::string, const Service*> currentServices)
|
||||||
{
|
{
|
||||||
|
if (currentServices.getSize() == 0)
|
||||||
|
{
|
||||||
|
std::cout << "No Services Currently Available.\n";
|
||||||
|
return "";
|
||||||
|
}
|
||||||
util::Map<int, const Service*> currentServicesMap;
|
util::Map<int, const Service*> currentServicesMap;
|
||||||
bool hasServices = false;
|
|
||||||
int currentIndex = 1, choice;
|
int currentIndex = 1, choice;
|
||||||
std::cout << std::left
|
std::cout << std::left
|
||||||
<< std::setw(6) << "Index"
|
<< std::setw(6) << "Index"
|
||||||
@@ -51,23 +55,17 @@ inline std::string selectServicesToRemove(util::Map<std::string, const Service*>
|
|||||||
for (int iterator = 0; iterator < currentServices.getSize(); iterator++)
|
for (int iterator = 0; iterator < currentServices.getSize(); iterator++)
|
||||||
{
|
{
|
||||||
const Service* currentService = currentServices.getValueAt(iterator);
|
const Service* currentService = currentServices.getValueAt(iterator);
|
||||||
if (currentService->getState() == util::State::INACTIVE)
|
if (currentService == nullptr || currentService->getState() == util::State::INACTIVE)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
std::cout << std::left
|
std::cout << std::left
|
||||||
<< std::setw(6) << currentIndex
|
<< std::setw(6) << currentIndex
|
||||||
<< std::setw(12) << currentService->getId()
|
<< std::setw(12) << currentService->getId()
|
||||||
<< std::setw(20) << currentService->getName()
|
<< std::setw(20) << currentService->getName()
|
||||||
<< std::setw(10) << currentService->getLaborCost()
|
<< std::setw(10) << currentService->getLaborCost()
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
hasServices = true;
|
|
||||||
currentServicesMap.insert(currentIndex++, currentService);
|
currentServicesMap.insert(currentIndex++, currentService);
|
||||||
}
|
|
||||||
if (!hasServices)
|
|
||||||
{
|
|
||||||
std::cout << "No services currently available." << std::endl;
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
std::cout << "Enter your choice: ";
|
std::cout << "Enter your choice: ";
|
||||||
util::read(choice);
|
util::read(choice);
|
||||||
@@ -744,6 +742,28 @@ inline void displayAllActiveUsers(util::Map<std::string, const User*>& activeUse
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: filterActiveServices
|
||||||
|
Description: Filters the given list of services and returns only those that are active.
|
||||||
|
Parameters:
|
||||||
|
- serviceList: Map of service IDs to Service pointers.
|
||||||
|
Returns:
|
||||||
|
- util::Map<std::string, const Service*> containing only active services.
|
||||||
|
*/
|
||||||
|
inline util::Map<std::string, const Service*> filterActiveServices(util::Map<std::string, const Service*> serviceList)
|
||||||
|
{
|
||||||
|
util::Map<std::string, const Service*> activeServices;
|
||||||
|
for (int iterator = 0; iterator < serviceList.getSize(); iterator++)
|
||||||
|
{
|
||||||
|
const Service* currentService = serviceList.getValueAt(iterator);
|
||||||
|
if (currentService && currentService->getState() == util::State::ACTIVE)
|
||||||
|
{
|
||||||
|
activeServices.insert(currentService->getId(), currentService);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return activeServices;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: selectServiceFromServices
|
Function: selectServiceFromServices
|
||||||
Description: Displays active services and allows the customer to select one by index.
|
Description: Displays active services and allows the customer to select one by index.
|
||||||
@@ -752,9 +772,15 @@ Return type: const Service* - selected service
|
|||||||
*/
|
*/
|
||||||
inline const Service* selectServiceFromServices(const util::Map<std::string, const Service*>& services)
|
inline const Service* selectServiceFromServices(const util::Map<std::string, const Service*>& services)
|
||||||
{
|
{
|
||||||
|
if (services.getSize() == 0)
|
||||||
|
{
|
||||||
|
std::cout << "No active services available." << std::endl;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
util::Map<int, const Service*> activeServicesMap;
|
util::Map<int, const Service*> activeServicesMap;
|
||||||
int currentIndex = 1;
|
int currentIndex = 1;
|
||||||
int userInputIndex;
|
int userInputIndex;
|
||||||
|
std::cout << std::endl;
|
||||||
std::cout << std::left
|
std::cout << std::left
|
||||||
<< std::setw(10) << "Index"
|
<< std::setw(10) << "Index"
|
||||||
<< std::setw(15) << "Service ID"
|
<< std::setw(15) << "Service ID"
|
||||||
@@ -1030,7 +1056,8 @@ inline std::string selectComboPackage(util::Map<std::string, const ComboPackage*
|
|||||||
util::Map<int, const ComboPackage*> currentComboPackageIndexMap;
|
util::Map<int, const ComboPackage*> currentComboPackageIndexMap;
|
||||||
if (currentComboPackages.getSize() == 0)
|
if (currentComboPackages.getSize() == 0)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("No combo packages are available.\n");
|
std::cout << "No combo packages are available.\n";
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
int currentIndex = 1, choice, selectedIndex;
|
int currentIndex = 1, choice, selectedIndex;
|
||||||
for (int iterator = 0; iterator < currentComboPackages.getSize(); iterator++)
|
for (int iterator = 0; iterator < currentComboPackages.getSize(); iterator++)
|
||||||
@@ -1043,7 +1070,8 @@ inline std::string selectComboPackage(util::Map<std::string, const ComboPackage*
|
|||||||
}
|
}
|
||||||
if (currentComboPackageIndexMap.getSize() == 0)
|
if (currentComboPackageIndexMap.getSize() == 0)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("No combo packages currently active.");
|
std::cout << "No combo packages currently active.\n";
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
displayComboPackagesWithIndex(currentComboPackageIndexMap);
|
displayComboPackagesWithIndex(currentComboPackageIndexMap);
|
||||||
std::cout << "Enter your choice(Index): ";
|
std::cout << "Enter your choice(Index): ";
|
||||||
|
|||||||
Reference in New Issue
Block a user