Merged PR 1114: Fix Admin Menu, Service Management, Technician Assignment, and Invoice Display Issues
**Changes:** - Fixed booking status flow (PENDING → STARTED) during job card creation - Updated purchaseService to initialize bookings with PENDING status - Filtered active users and services before listing/selection - Improved Assign Job flow: pending bookings only, clearer technician prompts, consistent feedback - Enhanced View Invoices: reference parameter, empty items handling, improved formatting - Added filterActiveServices helper for consistent active service filtering - Fixed Remove Service to also deactivate dependent combo packages - Improved Create Combo Packages: cancel option, confirmation step, duplicate/edge case handling - Updated Remove Combo Package to handle empty states gracefully without exceptions Related work items: #1646, #1740, #1744, #1745, #1747, #1749, #1752
This commit is contained in:
+23
-1
@@ -23,10 +23,10 @@ Date:19-May-2026
|
||||
#include "ServiceBooking.h"
|
||||
#include "ServiceManagementService.h"
|
||||
#include "Timestamp.h"
|
||||
#include "Timestamp.h"
|
||||
#include "User.h"
|
||||
#include "UserManagementService.h"
|
||||
#include "Utility.h"
|
||||
#include "ComboPackage.h"
|
||||
|
||||
/*
|
||||
Function: purchaseService
|
||||
@@ -817,6 +817,10 @@ void ServiceManagementService::createJobCard(const std::string& bookingID, const
|
||||
}
|
||||
currentBooking->setAssignedTechnician(selectedTechnician);
|
||||
currentBooking->setAssignedTechnicianId(selectedTechnician->getId());
|
||||
if (currentBooking->getStatus() == util::ServiceJobStatus::PENDING)
|
||||
{
|
||||
currentBooking->setStatus(util::ServiceJobStatus::STARTED);
|
||||
}
|
||||
std::string title = "Job card created";
|
||||
std::string message = "Job card created for the service and you are assigned for that.";
|
||||
JobCard* jobCard = Factory::getObject<JobCard>(bookingID, currentBooking, currentService, serviceID, technicianID, selectedTechnician, util::Timestamp(), util::ServiceJobStatus::STARTED, util::Timestamp());
|
||||
@@ -906,9 +910,27 @@ Throws:
|
||||
void ServiceManagementService::removeService(const std::string& serviceID)
|
||||
{
|
||||
util::Map<std::string, Service*>& currentServices = m_dataStore.getServices();
|
||||
util::Map<std::string, ComboPackage*>& currentComboPackages = m_dataStore.getComboPackages();
|
||||
if (currentServices.find(serviceID) != -1)
|
||||
{
|
||||
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
|
||||
{
|
||||
|
||||
+1
-1
@@ -315,7 +315,7 @@ util::Map<std::string, User*> UserManagementService::getUsers(util::UserType typ
|
||||
for (int iterator = 0; iterator < currentUsers.getSize(); iterator++)
|
||||
{
|
||||
User* currentUser = currentUsers.getValueAt(iterator);
|
||||
if (currentUser->getUserType() == type)
|
||||
if (currentUser && currentUser->getState() == util::State::ACTIVE && currentUser->getUserType() == type)
|
||||
{
|
||||
filteredUsersMap.insert(currentUser->getId(), currentUser);
|
||||
}
|
||||
|
||||
@@ -218,13 +218,15 @@ void AdminMenu::addInventoryItem()
|
||||
int choice, quantity;
|
||||
double price;
|
||||
std::string partName;
|
||||
std::cout << "1. Add new item \n2. Add Quantity\nEnter your choice : ";
|
||||
std::cout << "Add Inventory Item\n";
|
||||
std::cout << "1. Add new item \n2. Restock Item\n\nEnter your choice : ";
|
||||
util::read(choice);
|
||||
switch (choice)
|
||||
{
|
||||
case 1:
|
||||
case 1:
|
||||
{
|
||||
std::cout << "--------Enter Item Details----------\n";
|
||||
util::clear();
|
||||
std::cout << "Enter Item Details\n";
|
||||
std::cout << "Part Name : ";
|
||||
util::read(partName);
|
||||
std::cout << "Quantity : ";
|
||||
@@ -232,15 +234,21 @@ void AdminMenu::addInventoryItem()
|
||||
std::cout << "Price : ";
|
||||
util::read(price);
|
||||
m_controller.addInventoryItem(partName, quantity, price);
|
||||
std::cout << "New Item " << partName << " added to the Inventory.\n";
|
||||
std::cout << "\nNew Item " << partName << " added to the Inventory.\n\n";
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
util::clear();
|
||||
std::cout << "Select Item to Restock\n";
|
||||
auto inventoryItems = m_controller.getInventoryItems();
|
||||
addQuantityToItem(inventoryItems, m_controller);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
std::cout << "\nEnter a valid choice.\n\n";
|
||||
}
|
||||
}
|
||||
util::pressEnter();
|
||||
}
|
||||
@@ -333,14 +341,16 @@ Returns:
|
||||
void AdminMenu::assignJob()
|
||||
{
|
||||
util::clear();
|
||||
std::cout << "Assign Job to Technician\n";
|
||||
std::string selectedService;
|
||||
bool hasPendingService = false;
|
||||
auto currentBookings = m_controller.getServiceBookings();
|
||||
auto pendingServiceBookings = filterActiveServiceBookings(currentBookings);
|
||||
auto availableTechnicians = m_controller.getUsers(util::UserType::TECHNICIAN);
|
||||
int bookingsSize = currentBookings.getSize();
|
||||
int bookingsSize = pendingServiceBookings.getSize();
|
||||
util::Map<int, const ServiceBooking*> serviceBookingsMap;
|
||||
util::Map<int, const User*> currentAvailableTechniciansMap;
|
||||
if (listServiceBookings(currentBookings, bookingsSize, serviceBookingsMap))
|
||||
if (listServiceBookings(pendingServiceBookings, bookingsSize, serviceBookingsMap))
|
||||
{
|
||||
const ServiceBooking* selectedService = selectPendingServiceBookings(serviceBookingsMap);
|
||||
if (selectedService)
|
||||
@@ -356,14 +366,19 @@ void AdminMenu::assignJob()
|
||||
{
|
||||
m_controller.createJobCard(selectedService->getId(), selectedTechnician->getId(), servicesInBooking.getValueAt(iterator)->getId());
|
||||
}
|
||||
std::cout << "Job card created for each service and technician successfully assigned.\n\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "No technicians are currently available.";
|
||||
std::cout << "No technicians are currently available.\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "No pending service bookings available.\n\n";
|
||||
}
|
||||
util::pressEnter();
|
||||
}
|
||||
|
||||
@@ -378,17 +393,19 @@ Returns:
|
||||
void AdminMenu::createService()
|
||||
{
|
||||
util::clear();
|
||||
std::cout << "Create Service\n";
|
||||
std::string serviceName;
|
||||
double labourCost;
|
||||
std::cout << "Enter the service name: ";
|
||||
util::read(serviceName);
|
||||
util::Map<std::string, const InventoryItem*> currentInventoryItems = m_controller.getInventoryItems();
|
||||
util::Map<std::string, const InventoryItem*> activeInventoryItems = filterActiveItems(currentInventoryItems);
|
||||
util::Vector<std::string> selectedInventoryItems;
|
||||
selectInventoryItems(currentInventoryItems,selectedInventoryItems);
|
||||
std::cout << "Enter the labour cost: ";
|
||||
selectInventoryItems(activeInventoryItems,selectedInventoryItems);
|
||||
std::cout << "\nEnter the labour cost: ";
|
||||
util::read(labourCost);
|
||||
m_controller.createService(serviceName, selectedInventoryItems, labourCost);
|
||||
std::cout << "Service created sucessfully.\n";
|
||||
std::cout << "\nService created sucessfully.\n\n";
|
||||
util::pressEnter();
|
||||
}
|
||||
|
||||
@@ -403,17 +420,19 @@ Returns:
|
||||
void AdminMenu::removeService()
|
||||
{
|
||||
util::clear();
|
||||
std::cout << "Remove Service\n";
|
||||
std::string selectedServiceID;
|
||||
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 != "")
|
||||
{
|
||||
m_controller.removeService(selectedServiceID);
|
||||
std::cout << "Service removed sucessfully.";
|
||||
std::cout << "Service removed sucessfully.\n\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Failed to remove service.";
|
||||
std::cout << "Failed to remove service.\n\n";
|
||||
}
|
||||
util::pressEnter();
|
||||
}
|
||||
@@ -428,36 +447,37 @@ void AdminMenu::addTechnician()
|
||||
{
|
||||
util::clear();
|
||||
std::string username, name, password, email, phoneNumber;
|
||||
std::cout << std::left << std::setw(25) << "Enter Technician Username: ";
|
||||
std::cout << "Add Technician\n";
|
||||
std::cout << "Enter Technician Username: ";
|
||||
util::read(username);
|
||||
std::cout << std::left << std::setw(25) << "Enter Technician Name: ";
|
||||
std::cout << "Enter Technician Name: ";
|
||||
util::read(name);
|
||||
std::cout << std::setw(25) << "Enter Technician Password: ";
|
||||
std::cout << "Enter Technician Password: ";
|
||||
util::read(password);
|
||||
if(!util::isPasswordValid(password))
|
||||
{
|
||||
std::cout << "Error: Password is invalid!";
|
||||
std::cout << "\nError: Password is invalid!\n\n";
|
||||
util::pressEnter();
|
||||
return;
|
||||
}
|
||||
std::cout << std::setw(25) << "Enter Technician Email: ";
|
||||
std::cout << "Enter Technician Email: ";
|
||||
util::read(email);
|
||||
if(!util::isEmailValid(email))
|
||||
{
|
||||
std::cout << "Error: Email is invalid!";
|
||||
std::cout << "\nError: Email is invalid!\n\n";
|
||||
util::pressEnter();
|
||||
return;
|
||||
}
|
||||
std::cout << std::setw(25) << "Enter Technician Phone: ";
|
||||
std::cout << "Enter Technician Phone: ";
|
||||
util::read(phoneNumber);
|
||||
if(!util::isPhoneNumberValid(phoneNumber))
|
||||
{
|
||||
std::cout << "Error: Phone Number is invalid!";
|
||||
std::cout << "\nError: Phone Number is invalid!\n\n";
|
||||
util::pressEnter();
|
||||
return;
|
||||
}
|
||||
m_controller.createTechnician(username, name, password, email, phoneNumber);
|
||||
std::cout << "\nTechnician Added Successfully.\n";
|
||||
std::cout << "\nTechnician Added Successfully.\n\n";
|
||||
util::pressEnter();
|
||||
}
|
||||
|
||||
@@ -509,7 +529,10 @@ Return type: void
|
||||
void AdminMenu::createComboPackages()
|
||||
{
|
||||
util::clear();
|
||||
std::cout << "Create Combo Packages\n";
|
||||
auto serviceList = m_controller.getServices();
|
||||
auto activeServices = filterActiveServices(serviceList);
|
||||
int currentActiveServicesCount = activeServices.getSize();
|
||||
const int NUMBER_OF_SERVICE_PER_PACKAGE = 2;
|
||||
util::Vector<std::string> selectedServiceID;
|
||||
for (int iterator = 0; iterator < NUMBER_OF_SERVICE_PER_PACKAGE; iterator++)
|
||||
@@ -517,10 +540,10 @@ void AdminMenu::createComboPackages()
|
||||
const Service* chosenService = nullptr;
|
||||
while (true)
|
||||
{
|
||||
chosenService = selectServiceFromServices(serviceList);
|
||||
chosenService = selectServiceFromServices(activeServices);
|
||||
if (chosenService == nullptr)
|
||||
{
|
||||
std::cout << "Failed to create combo package!";
|
||||
std::cout << "Failed to create combo package!\n\n";
|
||||
util::pressEnter();
|
||||
return;
|
||||
}
|
||||
@@ -535,13 +558,21 @@ void AdminMenu::createComboPackages()
|
||||
}
|
||||
if (alreadyChosen)
|
||||
{
|
||||
if (currentActiveServicesCount < 2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
std::cout << "Service already selected. Please choose a different one." << std::endl;
|
||||
continue;
|
||||
}
|
||||
selectedServiceID.push_back(chosenService->getId());
|
||||
util::clear();
|
||||
break;
|
||||
}
|
||||
if (currentActiveServicesCount < 2)
|
||||
{
|
||||
std::cout << "All the available services selected\n\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::string packageName;
|
||||
double discountPercentage;
|
||||
@@ -569,16 +600,17 @@ Return type: void
|
||||
void AdminMenu::removeComboPackage()
|
||||
{
|
||||
util::clear();
|
||||
std::cout << "Remove Combo Package\n";
|
||||
util::Map<std::string, const ComboPackage*> currentComboPackages = m_controller.getComboPackages();
|
||||
std::string selectedComboPackageID = selectComboPackage(currentComboPackages);
|
||||
if (selectedComboPackageID != "")
|
||||
if (!selectedComboPackageID.empty())
|
||||
{
|
||||
m_controller.removeComboPackage(selectedComboPackageID);
|
||||
std::cout << "Combo Package removed successfully.\n";
|
||||
std::cout << "Combo Package removed successfully.\n\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Combo package removal failed.\n";
|
||||
std::cout << "Combo package removal failed.\n\n";
|
||||
}
|
||||
util::pressEnter();
|
||||
}
|
||||
|
||||
@@ -358,6 +358,7 @@ Returns:
|
||||
void CustomerMenu::viewInvoices()
|
||||
{
|
||||
util::clear();
|
||||
std::cout << "View Invoices\n";
|
||||
util::Map<std::string, const Invoice*> currentUserInvoices = m_controller.getInvoicesByUser();
|
||||
displayInvoices(currentUserInvoices);
|
||||
util::pressEnter();
|
||||
@@ -393,4 +394,4 @@ void CustomerMenu::configureNotifications()
|
||||
util::clear();
|
||||
std::cout << "Notification preferences updated successfully.\n";
|
||||
util::pressEnter();
|
||||
}
|
||||
}
|
||||
@@ -39,8 +39,12 @@ Returns:
|
||||
*/
|
||||
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;
|
||||
bool hasServices = false;
|
||||
int currentIndex = 1, choice;
|
||||
std::cout << std::left
|
||||
<< 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++)
|
||||
{
|
||||
const Service* currentService = currentServices.getValueAt(iterator);
|
||||
if (currentService->getState() == util::State::INACTIVE)
|
||||
if (currentService == nullptr || currentService->getState() == util::State::INACTIVE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
std::cout << std::left
|
||||
<< std::setw(6) << currentIndex
|
||||
std::cout << std::left
|
||||
<< std::setw(6) << currentIndex
|
||||
<< std::setw(12) << currentService->getId()
|
||||
<< std::setw(20) << currentService->getName()
|
||||
<< std::setw(10) << currentService->getLaborCost()
|
||||
<< std::endl;
|
||||
hasServices = true;
|
||||
<< std::endl;
|
||||
currentServicesMap.insert(currentIndex++, currentService);
|
||||
}
|
||||
if (!hasServices)
|
||||
{
|
||||
std::cout << "No services currently available." << std::endl;
|
||||
return "";
|
||||
}
|
||||
std::cout << "Enter your choice: ";
|
||||
util::read(choice);
|
||||
@@ -93,69 +91,89 @@ Returns:
|
||||
*/
|
||||
inline void selectInventoryItems(util::Map<std::string, const InventoryItem*>& currentInventoryItems, util::Vector<std::string>& selectedInventoryItems)
|
||||
{
|
||||
bool doRun = true, hasInventoryItems = false;
|
||||
util::Map<int, const InventoryItem*> currentInventoryMap;
|
||||
int currentIndex = 1;
|
||||
int choice;
|
||||
if (currentInventoryItems.getSize() == 0)
|
||||
{
|
||||
std::cout << "Inventory empty.";
|
||||
}
|
||||
while (doRun)
|
||||
{
|
||||
bool hasInventoryItems = false;
|
||||
int currentIndex = 1;
|
||||
currentInventoryMap.clear();
|
||||
std::cout << std::left
|
||||
<< std::setw(6) << "Index"
|
||||
<< std::setw(12) << "Item ID"
|
||||
<< std::setw(20) << "Part Name"
|
||||
<< std::setw(10) << "Price"
|
||||
<< std::setw(10) << "Quantity"
|
||||
<< std::endl;
|
||||
for (int iterator = 0; iterator < currentInventoryItems.getSize(); iterator++)
|
||||
bool doRun = true;
|
||||
util::Map<int, const InventoryItem*> currentInventoryMap;
|
||||
int choice;
|
||||
if (currentInventoryItems.getSize() == 0)
|
||||
{
|
||||
const InventoryItem* currentInventoryItem = currentInventoryItems.getValueAt(iterator);
|
||||
if (currentInventoryItem->getState() == util::State::INACTIVE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
std::cout << std::left
|
||||
<< std::setw(6) << currentIndex
|
||||
<< std::setw(12) << currentInventoryItem->getId()
|
||||
<< std::setw(20) << currentInventoryItem->getPartName()
|
||||
<< std::setw(10) << currentInventoryItem->getPrice()
|
||||
<< std::setw(10) << currentInventoryItem->getQuantity()
|
||||
<< std::endl;
|
||||
|
||||
hasInventoryItems = true;
|
||||
currentInventoryMap.insert(currentIndex++, currentInventoryItem);
|
||||
}
|
||||
if (!hasInventoryItems)
|
||||
{
|
||||
std::cout << "No items present in the inventory." << std::endl;
|
||||
doRun = false;
|
||||
break;
|
||||
std::cout << "No Items Present, Inventory empty.\n";
|
||||
return;
|
||||
}
|
||||
std::cout << "Select the item (Index) or enter -1 to exit: ";
|
||||
util::read(choice);
|
||||
|
||||
if (choice == -1)
|
||||
{
|
||||
doRun = false;
|
||||
while (doRun)
|
||||
{
|
||||
std::cout << "\nSelect Required Items\n";
|
||||
bool hasInventoryItems = false;
|
||||
int currentIndex = 1;
|
||||
currentInventoryMap.clear();
|
||||
std::cout << std::left
|
||||
<< std::setw(6) << "Index"
|
||||
<< std::setw(12) << "Item ID"
|
||||
<< std::setw(20) << "Part Name"
|
||||
<< std::setw(10) << "Price"
|
||||
<< std::setw(10) << "Quantity"
|
||||
<< std::endl;
|
||||
for (int iterator = 0; iterator < currentInventoryItems.getSize(); iterator++)
|
||||
{
|
||||
const InventoryItem* currentInventoryItem = currentInventoryItems.getValueAt(iterator);
|
||||
if (currentInventoryItem == nullptr || currentInventoryItem->getState() == util::State::INACTIVE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
std::cout << std::left
|
||||
<< std::setw(6) << currentIndex
|
||||
<< std::setw(12) << currentInventoryItem->getId()
|
||||
<< std::setw(20) << currentInventoryItem->getPartName()
|
||||
<< std::setw(10) << currentInventoryItem->getPrice()
|
||||
<< std::setw(10) << currentInventoryItem->getQuantity()
|
||||
<< std::endl;
|
||||
currentInventoryMap.insert(currentIndex++, currentInventoryItem);
|
||||
hasInventoryItems = true;
|
||||
}
|
||||
else if (currentInventoryMap.find(choice) != -1)
|
||||
{
|
||||
selectedInventoryItems.push_back(currentInventoryMap.getValueAt(choice)->getId());
|
||||
std::cout << "Item added successfully." << std::endl;
|
||||
if (!hasInventoryItems)
|
||||
{
|
||||
break;
|
||||
}
|
||||
std::cout << "Select the item (Index) or enter -1 to exit: ";
|
||||
util::read(choice);
|
||||
|
||||
if (choice == -1)
|
||||
{
|
||||
doRun = false;
|
||||
}
|
||||
else if (currentInventoryMap.find(choice) != -1)
|
||||
{
|
||||
selectedInventoryItems.push_back(currentInventoryMap.getValueAt(currentInventoryMap.find(choice))->getId());
|
||||
std::cout << "Item added successfully.\n" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Enter a valid integer." << std::endl;
|
||||
std::cout << "Enter a valid integer.\n" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Function: filterActiveServiceBookings
|
||||
Description: Filters the given service bookings and returns only bookings with PENDING status.
|
||||
Parameters:
|
||||
- currentBookings: util::Map<std::string, const ServiceBooking*>, collection of current service bookings
|
||||
Returns:
|
||||
- util::Map<std::string, const ServiceBooking*>: map containing only active (PENDING) service bookings
|
||||
*/
|
||||
inline util::Map<std::string, const ServiceBooking*> filterActiveServiceBookings(util::Map<std::string, const ServiceBooking*> currentBookings)
|
||||
{
|
||||
util::Map<std::string, const ServiceBooking*> activeServiceBookings;
|
||||
for (int iterator = 0; iterator < currentBookings.getSize(); iterator++)
|
||||
{
|
||||
const ServiceBooking* currentServiceBooking = currentBookings.getValueAt(iterator);
|
||||
if (currentServiceBooking && currentServiceBooking->getStatus() == util::ServiceJobStatus::PENDING)
|
||||
{
|
||||
activeServiceBookings.insert(currentServiceBooking->getId(), currentServiceBooking);
|
||||
}
|
||||
}
|
||||
return activeServiceBookings;
|
||||
}
|
||||
|
||||
/*
|
||||
Function: listServiceBookings
|
||||
Description: Lists all pending service bookings and maps them to indices for selection.
|
||||
@@ -168,48 +186,46 @@ Returns:
|
||||
*/
|
||||
inline bool listServiceBookings(util::Map<std::string, const ServiceBooking*>& currentBookings, int& bookingsSize, util::Map<int, const ServiceBooking*>& serviceBookingsMap)
|
||||
{
|
||||
if (currentBookings.getSize() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int currentIndex = 1;
|
||||
bool hasPendingService = false;
|
||||
std::cout << "\nSelect Service Booking" << std::endl;
|
||||
std::cout << std::left
|
||||
<< std::setw(10) << "Index"
|
||||
<< std::setw(10) << "ID"
|
||||
<< std::setw(12) << "Status"
|
||||
<< std::setw(12) << "CustID"
|
||||
<< std::setw(20) << "Customer"
|
||||
<< std::setw(15) << "VehicleNo"
|
||||
<< std::setw(15) << "Brand"
|
||||
<< std::setw(15) << "Model"
|
||||
<< std::setw(20) << "Technician"
|
||||
<< std::setw(15) << "TechnicianID"
|
||||
<< std::setw(10) << "ID"
|
||||
<< std::setw(12) << "Status"
|
||||
<< std::setw(12) << "CustID"
|
||||
<< std::setw(20) << "Customer"
|
||||
<< std::setw(15) << "VehicleNo"
|
||||
<< std::setw(15) << "Brand"
|
||||
<< std::setw(15) << "Model"
|
||||
<< std::setw(20) << "Technician"
|
||||
<< std::setw(15) << "TechnicianID"
|
||||
<< std::endl;
|
||||
for (int iterator = 0; iterator < bookingsSize; iterator++)
|
||||
for (int iterator = 0; iterator < bookingsSize; iterator++)
|
||||
{
|
||||
const ServiceBooking* currentBooking = currentBookings.getValueAt(iterator);
|
||||
if (currentBooking && currentBooking->getStatus() == util::ServiceJobStatus::PENDING)
|
||||
const ServiceBooking* currentBooking = currentBookings.getValueAt(iterator);
|
||||
if (currentBooking && currentBooking->getStatus() == util::ServiceJobStatus::PENDING)
|
||||
{
|
||||
hasPendingService = true;
|
||||
const User* currentAssignedTechnician = currentBooking->getAssignedTechnician();
|
||||
std::cout << std::left
|
||||
<< std::setw(10) << currentIndex
|
||||
<< std::setw(10) << currentBooking->getId()
|
||||
<< std::setw(12) << util::getServiceJobStatusString(currentBooking->getStatus())
|
||||
<< std::setw(12) << currentBooking->getCustomerId()
|
||||
<< std::setw(20) << currentBooking->getCustomer()->getName()
|
||||
<< std::setw(15) << currentBooking->getVehicleNumber()
|
||||
<< std::setw(15) << currentBooking->getVehicleBrand()
|
||||
<< std::setw(15) << currentBooking->getVehicleModel()
|
||||
<< std::setw(20) << ((currentAssignedTechnician == nullptr || currentAssignedTechnician->getName().empty()) ? "Null" : currentAssignedTechnician->getName())
|
||||
<< std::setw(15) << ((currentAssignedTechnician == nullptr || currentAssignedTechnician->getId().empty()) ? "Null" : currentAssignedTechnician->getId())
|
||||
<< std::endl;
|
||||
serviceBookingsMap.insert(currentIndex++, currentBooking);
|
||||
const User* currentAssignedTechnician = currentBooking->getAssignedTechnician();
|
||||
std::cout << std::left
|
||||
<< std::setw(10) << currentIndex
|
||||
<< std::setw(10) << currentBooking->getId()
|
||||
<< std::setw(12) << util::getServiceJobStatusString(currentBooking->getStatus())
|
||||
<< std::setw(12) << currentBooking->getCustomerId()
|
||||
<< std::setw(20) << currentBooking->getCustomer()->getName()
|
||||
<< std::setw(15) << currentBooking->getVehicleNumber()
|
||||
<< std::setw(15) << currentBooking->getVehicleBrand()
|
||||
<< std::setw(15) << currentBooking->getVehicleModel()
|
||||
<< std::setw(20) << ((currentAssignedTechnician == nullptr || currentAssignedTechnician->getName().empty()) ? "NULL" : currentAssignedTechnician->getName())
|
||||
<< std::setw(15) << ((currentAssignedTechnician == nullptr || currentAssignedTechnician->getId().empty()) ? "NULL" : currentAssignedTechnician->getId())
|
||||
<< std::endl;
|
||||
serviceBookingsMap.insert(currentIndex++, currentBooking);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!hasPendingService)
|
||||
{
|
||||
std::cout << "No pending service available." << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -223,15 +239,15 @@ Returns:
|
||||
inline const ServiceBooking* selectPendingServiceBookings(util::Map<int, const ServiceBooking*>& serviceBookingsMap)
|
||||
{
|
||||
int userInputIndex;
|
||||
std::cout << "Enter a valid service index: ";
|
||||
std::cout << "\nEnter a valid service index: ";
|
||||
util::read(userInputIndex);
|
||||
if (serviceBookingsMap.find(userInputIndex) != -1)
|
||||
{
|
||||
return serviceBookingsMap.getValueAt(userInputIndex);
|
||||
return serviceBookingsMap.getValueAt(serviceBookingsMap.find(userInputIndex));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Enter a valid index.";
|
||||
std::cout << "Enter a valid index.\n\n";
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -250,6 +266,7 @@ inline void listAvailableTechnicians(util::Map<std::string, const User*> current
|
||||
{
|
||||
bool hasTechnicians = false;
|
||||
int currentIndex = 1;
|
||||
std::cout << "\nSelect Technician\n";
|
||||
std::cout << std::left
|
||||
<< std::setw(6) << "Index"
|
||||
<< std::setw(15) << "Technician ID"
|
||||
@@ -272,7 +289,7 @@ inline void listAvailableTechnicians(util::Map<std::string, const User*> current
|
||||
}
|
||||
if (!hasTechnicians)
|
||||
{
|
||||
std::cout << "No technicians currently available.";
|
||||
std::cout << "No technicians currently available.\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,17 +302,18 @@ Returns:
|
||||
- const User*: Pointer to the selected technician, or nullptr if invalid
|
||||
*/
|
||||
inline const User* selectTechnician(util::Map<int, const User*>& currentAvailableTechniciansMap)
|
||||
{
|
||||
int userInputIndex;
|
||||
std::cout << "\nEnter valid technician index: ";
|
||||
util::read(userInputIndex);
|
||||
if (currentAvailableTechniciansMap.find(userInputIndex) != -1)
|
||||
{
|
||||
int userInputIndex;
|
||||
util::read(userInputIndex);
|
||||
if (currentAvailableTechniciansMap.find(userInputIndex) != -1)
|
||||
{
|
||||
return currentAvailableTechniciansMap.getValueAt(userInputIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Enter a valid index.";
|
||||
return nullptr;
|
||||
return currentAvailableTechniciansMap.getValueAt(currentAvailableTechniciansMap.find(userInputIndex));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Enter a valid index.\n\n";
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,59 +426,63 @@ Throws:
|
||||
*/
|
||||
inline void displayInvoices(util::Map<std::string, const Invoice*> currentUserInvoices)
|
||||
{
|
||||
if (currentUserInvoices.getSize() == 0)
|
||||
if (currentUserInvoices.getSize() == 0)
|
||||
{
|
||||
std::cout << "No invoices found for this account." << std::endl;
|
||||
util::pressEnter();
|
||||
std::cout << "No invoices found for this account." << std::endl << std::endl;
|
||||
return;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
for (int index = 0; index < currentUserInvoices.getSize(); index++)
|
||||
{
|
||||
const Invoice* currentInvoice = currentUserInvoices.getValueAt(index);
|
||||
if (currentInvoice)
|
||||
{
|
||||
const User* currentTechnician = currentInvoice->getBooking()->getAssignedTechnician();
|
||||
std::cout << "\nInvoice Details\n";
|
||||
std::cout << "Booking ID: " << currentInvoice->getBookingId() << std::endl;
|
||||
std::cout << "Vehicle Brand: " << currentInvoice->getBooking()->getVehicleBrand() << std::endl;
|
||||
std::cout << "Vehicle Number: " << currentInvoice->getBooking()->getVehicleNumber() << std::endl;
|
||||
std::cout << "Technician ID: " <<
|
||||
((currentTechnician != nullptr && currentTechnician->getId() != "") ?
|
||||
currentTechnician->getId() : "Null") << std::endl;
|
||||
std::cout << "Technician Name: " <<
|
||||
((currentTechnician != nullptr && currentTechnician->getName() != "") ?
|
||||
currentTechnician->getName() : "Null") << std::endl;
|
||||
std::cout << "Discount(%): " << currentInvoice->getDiscountPercentage() << std::endl;
|
||||
std::cout << "Total Amount: " << currentInvoice->getTotalAmount() << std::endl;
|
||||
std::cout << "Invoice Date: " << currentInvoice->getInvoiceDate().toString() << std::endl;
|
||||
std::cout << "Payment Status: " << util::getPaymentStatusString(currentInvoice->getStatus()) << std::endl;
|
||||
auto inventoryItemsInInvoice = currentInvoice->getParts();
|
||||
std::cout << "\nItems Used:\n";
|
||||
std::cout << std::left
|
||||
<< std::setw(20) << "ItemName"
|
||||
<< std::setw(10) << "Quantity"
|
||||
<< std::setw(10) << "Price"
|
||||
<< std::endl;
|
||||
std::cout << std::string(40, '-') << std::endl;
|
||||
for (int iterator = 0; iterator < inventoryItemsInInvoice.getSize(); iterator++)
|
||||
{
|
||||
InventoryItem* currentItem = inventoryItemsInInvoice.getValueAt(iterator);
|
||||
std::cout << std::left
|
||||
<< std::setw(20) << currentItem->getPartName()
|
||||
<< std::setw(10) << currentItem->getQuantity()
|
||||
<< std::setw(10) << currentItem->getPrice()
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
for (int index = 0; index < currentUserInvoices.getSize(); index++)
|
||||
{
|
||||
throw std::runtime_error("Null invoice encountered while displaying invoices.");
|
||||
util::pressEnter();
|
||||
}
|
||||
const Invoice* currentInvoice = currentUserInvoices.getValueAt(index);
|
||||
if (currentInvoice)
|
||||
{
|
||||
const User* currentTechnician = currentInvoice->getBooking()->getAssignedTechnician();
|
||||
std::cout << "\nInvoice Details\n";
|
||||
std::cout << "Booking ID: " << currentInvoice->getBookingId() << std::endl;
|
||||
std::cout << "Vehicle Brand: " << currentInvoice->getBooking()->getVehicleBrand() << std::endl;
|
||||
std::cout << "Vehicle Number: " << currentInvoice->getBooking()->getVehicleNumber() << std::endl;
|
||||
std::cout << "Technician ID: " <<
|
||||
((currentTechnician != nullptr && currentTechnician->getId() != "") ?
|
||||
currentTechnician->getId() : "Null") << std::endl;
|
||||
std::cout << "Technician Name: " <<
|
||||
((currentTechnician != nullptr && currentTechnician->getName() != "") ?
|
||||
currentTechnician->getName() : "Null") << std::endl;
|
||||
std::cout << "Discount(%): " << currentInvoice->getDiscountPercentage() << std::endl;
|
||||
std::cout << "Total Amount: " << currentInvoice->getTotalAmount() << std::endl;
|
||||
std::cout << "Invoice Date: " << currentInvoice->getInvoiceDate().toString() << std::endl;
|
||||
std::cout << "Payment Status: " << util::getPaymentStatusString(currentInvoice->getStatus()) << std::endl;
|
||||
auto inventoryItemsInInvoice = currentInvoice->getParts();
|
||||
if (inventoryItemsInInvoice.isEmpty())
|
||||
{
|
||||
std::cout << "No inventory items used.\n\n";
|
||||
continue;
|
||||
}
|
||||
std::cout << "\nItems Used:\n";
|
||||
std::cout << std::left
|
||||
<< std::setw(20) << "ItemName"
|
||||
<< std::setw(10) << "Quantity"
|
||||
<< std::setw(10) << "Price"
|
||||
<< std::endl;
|
||||
std::cout << std::string(40, '-') << std::endl;
|
||||
for (int iterator = 0; iterator < inventoryItemsInInvoice.getSize(); iterator++)
|
||||
{
|
||||
InventoryItem* currentItem = inventoryItemsInInvoice.getValueAt(iterator);
|
||||
std::cout << std::left
|
||||
<< std::setw(20) << currentItem->getPartName()
|
||||
<< std::setw(10) << currentItem->getQuantity()
|
||||
<< std::setw(10) << currentItem->getPrice()
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("Null invoice encountered while displaying invoices.");
|
||||
}
|
||||
}
|
||||
}
|
||||
util::pressEnter();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -720,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
|
||||
Description: Displays active services and allows the customer to select one by index.
|
||||
@@ -728,9 +772,15 @@ Return type: const Service* - selected service
|
||||
*/
|
||||
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;
|
||||
int currentIndex = 1;
|
||||
int userInputIndex;
|
||||
std::cout << std::endl;
|
||||
std::cout << std::left
|
||||
<< std::setw(10) << "Index"
|
||||
<< std::setw(15) << "Service ID"
|
||||
@@ -908,6 +958,7 @@ inline void displayInventoryWithItems(util::Map<std::string, const InventoryItem
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -927,7 +978,7 @@ inline void addQuantityToItem(util::Map<std::string, const InventoryItem*>& inve
|
||||
int activeSize = activeItems.getSize();
|
||||
if (activeSize == 0)
|
||||
{
|
||||
std::cout << "No active items available in Inventory" << std::endl;
|
||||
std::cout << "\nNo active items available in Inventory" << std::endl << std::endl;
|
||||
return;
|
||||
}
|
||||
displayInventoryWithItems(activeItems);
|
||||
@@ -935,7 +986,7 @@ inline void addQuantityToItem(util::Map<std::string, const InventoryItem*>& inve
|
||||
util::read(itemIndex);
|
||||
if (itemIndex < 1 || itemIndex > activeSize)
|
||||
{
|
||||
std::cout << "Invalid index selected." << std::endl;
|
||||
std::cout << "\nInvalid index selected." << std::endl << std::endl;
|
||||
return;
|
||||
}
|
||||
std::cout << "Enter quantity to add: ";
|
||||
@@ -950,13 +1001,14 @@ inline void addQuantityToItem(util::Map<std::string, const InventoryItem*>& inve
|
||||
{
|
||||
std::string selectedItemId = selectedItem->getId();
|
||||
m_controller.addInventoryItemStock(selectedItemId, quantity);
|
||||
std::cout << "Updated " << selectedItem->getPartName()
|
||||
std::cout << "\nUpdated " << selectedItem->getPartName()
|
||||
<< " stock. New quantity: " << selectedItem->getQuantity()
|
||||
<< std::endl
|
||||
<< std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Error: Selected item could not be found." << std::endl;
|
||||
std::cout << "\nError: Selected item could not be found." << std::endl << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1004,7 +1056,8 @@ inline std::string selectComboPackage(util::Map<std::string, const ComboPackage*
|
||||
util::Map<int, const ComboPackage*> currentComboPackageIndexMap;
|
||||
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;
|
||||
for (int iterator = 0; iterator < currentComboPackages.getSize(); iterator++)
|
||||
@@ -1017,7 +1070,8 @@ inline std::string selectComboPackage(util::Map<std::string, const ComboPackage*
|
||||
}
|
||||
if (currentComboPackageIndexMap.getSize() == 0)
|
||||
{
|
||||
throw std::runtime_error("No combo packages currently active.");
|
||||
std::cout << "No combo packages currently active.\n";
|
||||
return "";
|
||||
}
|
||||
displayComboPackagesWithIndex(currentComboPackageIndexMap);
|
||||
std::cout << "Enter your choice(Index): ";
|
||||
|
||||
@@ -6,6 +6,7 @@ Description: Implementation file containing the method definitions of the
|
||||
Author: Trenser
|
||||
Date:19-May-2026
|
||||
*/
|
||||
|
||||
#include "Enums.h"
|
||||
#include "InputHelper.h"
|
||||
#include "JobCard.h"
|
||||
|
||||
Reference in New Issue
Block a user