9439202c5a
- add Select a Combo Package header - show message when no combo packages are available - improve combo package table header labels Fixes #1743
1033 lines
36 KiB
C++
1033 lines
36 KiB
C++
/*
|
||
File: MenuHelper.h
|
||
Description: Header file declaring the MenuHelper class, which provides
|
||
utility functions for menu-driven operations such as
|
||
notification selection and display.
|
||
Author: Trenser
|
||
Date: 21-May-2026
|
||
*/
|
||
|
||
#pragma once
|
||
#include <iomanip>
|
||
#include <iostream>
|
||
#include <string>
|
||
#include "ComboPackage.h"
|
||
#include "Controller.h"
|
||
#include "Enums.h"
|
||
#include "InputHelper.h"
|
||
#include "InventoryItem.h"
|
||
#include "Invoice.h"
|
||
#include "JobCard.h"
|
||
#include "Map.h"
|
||
#include "Notification.h"
|
||
#include "OutputHelper.h"
|
||
#include "Service.h"
|
||
#include "ServiceBooking.h"
|
||
#include "Timestamp.h"
|
||
#include "User.h"
|
||
#include "Utility.h"
|
||
#include "Validator.h"
|
||
#include "Vector.h"
|
||
|
||
/*
|
||
Function: selectServicesToRemove
|
||
Description: Allows selection of a service to remove by index.
|
||
Parameters:
|
||
- currentServices: util::Map<std::string, const Service*>, available services
|
||
Returns:
|
||
- std::string: ID of the selected service, or empty string if invalid
|
||
*/
|
||
inline std::string selectServicesToRemove(util::Map<std::string, const Service*> currentServices)
|
||
{
|
||
util::Map<int, const Service*> currentServicesMap;
|
||
bool hasServices = false;
|
||
int currentIndex = 1, choice;
|
||
std::cout << std::left
|
||
<< std::setw(6) << "Index"
|
||
<< std::setw(12) << "Service ID"
|
||
<< std::setw(20) << "Name"
|
||
<< std::setw(10) << "Labor Cost"
|
||
<< std::endl;
|
||
for (int iterator = 0; iterator < currentServices.getSize(); iterator++)
|
||
{
|
||
const Service* currentService = currentServices.getValueAt(iterator);
|
||
if (currentService->getState() == util::State::INACTIVE)
|
||
{
|
||
continue;
|
||
}
|
||
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;
|
||
currentServicesMap.insert(currentIndex++, currentService);
|
||
}
|
||
if (!hasServices)
|
||
{
|
||
std::cout << "No services currently available." << std::endl;
|
||
return "";
|
||
}
|
||
std::cout << "Enter your choice: ";
|
||
util::read(choice);
|
||
if (currentServicesMap.find(choice) != -1)
|
||
{
|
||
return currentServicesMap.getValueAt(currentServicesMap.find(choice))->getId();
|
||
}
|
||
else
|
||
{
|
||
std::cout << "Invalid index." << std::endl;
|
||
return "";
|
||
}
|
||
}
|
||
|
||
/*
|
||
Function: selectInventoryItems
|
||
Description: Allows selection of inventory items by index for creating a service.
|
||
Parameters:
|
||
- currentInventoryItems: util::Map<std::string, const InventoryItem*>&, available inventory items
|
||
- selectedInventoryItems: util::Vector<std::string>&, vector to store selected item IDs
|
||
Returns:
|
||
- void
|
||
*/
|
||
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++)
|
||
{
|
||
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 << "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(choice)->getId());
|
||
std::cout << "Item added successfully." << std::endl;
|
||
}
|
||
else
|
||
{
|
||
std::cout << "Enter a valid integer." << std::endl;
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
Function: listServiceBookings
|
||
Description: Lists all pending service bookings and maps them to indices for selection.
|
||
Parameters:
|
||
- currentBookings: util::Map<std::string, const ServiceBooking*>&, current bookings
|
||
- bookingsSize: int&, number of bookings
|
||
- serviceBookingsMap: util::Map<int, const ServiceBooking*>&, map of indexed bookings
|
||
Returns:
|
||
- bool: True if pending services exist, False otherwise
|
||
*/
|
||
inline bool listServiceBookings(util::Map<std::string, const ServiceBooking*>& currentBookings, int& bookingsSize, util::Map<int, const ServiceBooking*>& serviceBookingsMap)
|
||
{
|
||
int currentIndex = 1;
|
||
bool hasPendingService = false;
|
||
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::endl;
|
||
for (int iterator = 0; iterator < bookingsSize; iterator++)
|
||
{
|
||
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);
|
||
}
|
||
}
|
||
if (!hasPendingService)
|
||
{
|
||
std::cout << "No pending service available." << std::endl;
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/*
|
||
Function: selectPendingServiceBookings
|
||
Description: Allows selection of a pending service booking by index.
|
||
Parameters:
|
||
- serviceBookingsMap: util::Map<int, const ServiceBooking*>&, map of indexed bookings
|
||
Returns:
|
||
- const ServiceBooking*: Pointer to the selected booking, or nullptr if invalid
|
||
*/
|
||
inline const ServiceBooking* selectPendingServiceBookings(util::Map<int, const ServiceBooking*>& serviceBookingsMap)
|
||
{
|
||
int userInputIndex;
|
||
std::cout << "Enter a valid service index: ";
|
||
util::read(userInputIndex);
|
||
if (serviceBookingsMap.find(userInputIndex) != -1)
|
||
{
|
||
return serviceBookingsMap.getValueAt(userInputIndex);
|
||
}
|
||
else
|
||
{
|
||
std::cout << "Enter a valid index.";
|
||
return nullptr;
|
||
}
|
||
}
|
||
|
||
/*
|
||
Function: listAvailableTechnicians
|
||
Description: Lists all available technicians and maps them to indices for selection.
|
||
Parameters:
|
||
- currentAvailableTechnicians: util::Map<std::string, const User*>, available technicians
|
||
- numberOfTechnicians: int, number of technicians
|
||
- currentAvailableTechniciansMap: util::Map<int, const User*>&, map of indexed technicians
|
||
Returns:
|
||
- void
|
||
*/
|
||
inline void listAvailableTechnicians(util::Map<std::string, const User*> currentAvailableTechnicians, int numberOfTechnicians, util::Map<int, const User*>& currentAvailableTechniciansMap)
|
||
{
|
||
bool hasTechnicians = false;
|
||
int currentIndex = 1;
|
||
std::cout << std::left
|
||
<< std::setw(6) << "Index"
|
||
<< std::setw(15) << "Technician ID"
|
||
<< std::setw(20) << "Name"
|
||
<< std::endl;
|
||
for (int iterator = 0; iterator < numberOfTechnicians; iterator++)
|
||
{
|
||
const User* currentTechnician = currentAvailableTechnicians.getValueAt(iterator);
|
||
if (currentTechnician->getState() == util::State::INACTIVE)
|
||
{
|
||
continue;
|
||
}
|
||
hasTechnicians = true;
|
||
std::cout << std::left
|
||
<< std::setw(6) << currentIndex
|
||
<< std::setw(15) << currentTechnician->getId()
|
||
<< std::setw(20) << currentTechnician->getName()
|
||
<< std::endl;
|
||
currentAvailableTechniciansMap.insert(currentIndex++, currentTechnician);
|
||
}
|
||
if (!hasTechnicians)
|
||
{
|
||
std::cout << "No technicians currently available.";
|
||
}
|
||
}
|
||
|
||
/*
|
||
Function: selectTechnician
|
||
Description: Allows selection of a technician by index.
|
||
Parameters:
|
||
- currentAvailableTechniciansMap: util::Map<int, const User*>&, map of indexed technicians
|
||
Returns:
|
||
- const User*: Pointer to the selected technician, or nullptr if invalid
|
||
*/
|
||
inline const User* selectTechnician(util::Map<int, const User*>& currentAvailableTechniciansMap)
|
||
{
|
||
int userInputIndex;
|
||
util::read(userInputIndex);
|
||
if (currentAvailableTechniciansMap.find(userInputIndex) != -1)
|
||
{
|
||
return currentAvailableTechniciansMap.getValueAt(userInputIndex);
|
||
}
|
||
else
|
||
{
|
||
std::cout << "Enter a valid index.";
|
||
return nullptr;
|
||
}
|
||
}
|
||
|
||
/*
|
||
Function: selectInvoiceFromUserForPayment
|
||
Description: Lists all pending invoices for the customer and allows selection by index.
|
||
Parameters:
|
||
- currentInvoices: util::Map<std::string, const Invoice*>&, map of customer invoices
|
||
Returns:
|
||
- std::string: ID of the selected invoice, or empty string if none selected
|
||
*/
|
||
inline std::string selectInvoiceFromUserForPayment(const util::Map<std::string, const Invoice*>& currentInvoices)
|
||
{
|
||
int currentIndex = 1, choice;
|
||
util::Map<int, const Invoice*> pendingInvoicesForPayment;
|
||
std::cout << std::left
|
||
<< std::setw(6) << "Index"
|
||
<< std::setw(12) << "BookingID"
|
||
<< std::setw(15) << "VehicleBrand"
|
||
<< std::setw(15) << "VehicleNumber"
|
||
<< std::setw(12) << "TechID"
|
||
<< std::setw(20) << "TechnicianName"
|
||
<< std::setw(10) << "Discount(%)"
|
||
<< std::setw(12) << "TotalAmount"
|
||
<< std::setw(20) << "InvoiceDate"
|
||
<< std::endl;
|
||
for (int iterator = 0; iterator < currentInvoices.getSize(); iterator++)
|
||
{
|
||
const Invoice* currentInvoice = currentInvoices.getValueAt(iterator);
|
||
if (currentInvoice && currentInvoice->getStatus() == util::PaymentStatus::PENDING)
|
||
{
|
||
const User* currentTechnician = currentInvoice->getBooking()->getAssignedTechnician();
|
||
std::cout << std::left
|
||
<< std::setw(6) << currentIndex
|
||
<< std::setw(12) << currentInvoice->getBookingId()
|
||
<< std::setw(15) << currentInvoice->getBooking()->getVehicleBrand()
|
||
<< std::setw(15) << currentInvoice->getBooking()->getVehicleNumber()
|
||
<< std::setw(12) << ((currentTechnician != nullptr && currentTechnician->getId() != "") ?
|
||
currentTechnician->getId() : "Null")
|
||
<< std::setw(20) << ((currentTechnician != nullptr && currentTechnician->getName() != "") ?
|
||
currentTechnician->getName() : "Null")
|
||
<< std::setw(10) << currentInvoice->getDiscountPercentage()
|
||
<< std::setw(12) << currentInvoice->getTotalAmount()
|
||
<< std::setw(20) << currentInvoice->getInvoiceDate().toString()
|
||
<< std::endl;
|
||
pendingInvoicesForPayment.insert(currentIndex++, currentInvoice);
|
||
}
|
||
}
|
||
if (pendingInvoicesForPayment.getSize() == 0)
|
||
{
|
||
std::cout << "No pending invoices available for payment.\n";
|
||
return "";
|
||
}
|
||
std::cout << "Select the Invoice to pay (Index): ";
|
||
util::read(choice);
|
||
int selectedIndex = pendingInvoicesForPayment.find(choice);
|
||
if (selectedIndex != -1)
|
||
{
|
||
const Invoice* selectedInvoice = pendingInvoicesForPayment.getValueAt(selectedIndex);
|
||
return selectedInvoice->getId();
|
||
}
|
||
else
|
||
{
|
||
std::cout << "Invalid index.\n";
|
||
return "";
|
||
}
|
||
}
|
||
|
||
/*
|
||
Function: selectPaymentMode
|
||
Description: Allows the customer to select a payment mode (ONLINE or OFFLINE).
|
||
Parameters:
|
||
- None
|
||
Returns:
|
||
- util::PaymentMode: Selected payment mode
|
||
*/
|
||
inline util::PaymentMode selectPaymentMode()
|
||
{
|
||
int choice;
|
||
std::cout << "Enter the payment Mode\n1.OFFLINE\n2.ONLINE\nChoice: ";
|
||
util::read(choice);
|
||
if (choice == 1)
|
||
{
|
||
std::cout << "Offline mode selected.\n";
|
||
return util::PaymentMode::OFFLINE;
|
||
}
|
||
else if (choice == 2)
|
||
{
|
||
std::cout << "Online mode selected.\n";
|
||
return util::PaymentMode::ONLINE;
|
||
}
|
||
else
|
||
{
|
||
std::cout << "Invalid choice. Offline mode selected.\n";
|
||
return util::PaymentMode::OFFLINE;
|
||
}
|
||
}
|
||
|
||
/*
|
||
Function: displayInvoices
|
||
Description: Displays detailed information for all invoices associated with the customer,
|
||
including booking details, technician, discount, total amount, payment status, and items used.
|
||
Parameters:
|
||
- currentUserInvoices: util::Map<std::string, const Invoice*>, customer’s invoices
|
||
Returns:
|
||
- void
|
||
Throws:
|
||
- std::runtime_error if a null invoice is encountered
|
||
*/
|
||
inline void displayInvoices(util::Map<std::string, const Invoice*> currentUserInvoices)
|
||
{
|
||
if (currentUserInvoices.getSize() == 0)
|
||
{
|
||
std::cout << "No invoices found for this account." << std::endl;
|
||
util::pressEnter();
|
||
return;
|
||
}
|
||
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
|
||
{
|
||
throw std::runtime_error("Null invoice encountered while displaying invoices.");
|
||
util::pressEnter();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
Function: selectJobCardToComplete
|
||
Description: Lists all incomplete job cards assigned to the technician and allows selection by index.
|
||
Parameters:
|
||
- assignedJobCards: util::Map<std::string, const JobCard*>&, job cards assigned to the technician
|
||
- incompleteJobCards: util::Map<int, const JobCard*>&, map of incomplete job cards indexed for selection
|
||
Returns:
|
||
- std::string: ID of the selected job card, or empty string if none selected
|
||
*/
|
||
inline std::string selectJobCardToComplete(util::Map<std::string, const JobCard*>& assignedJobCards, util::Map<int, const JobCard*>& incompleteJobCards)
|
||
{
|
||
int currentIndex = 1;
|
||
int choice;
|
||
bool hasIncompleteJobCard = false;
|
||
std::cout << std::left
|
||
<< std::setw(6) << "Index"
|
||
<< std::setw(12) << "BookingID"
|
||
<< std::setw(12) << "JobID"
|
||
<< std::setw(20) << "ServiceName"
|
||
<< std::setw(12) << "ServiceID"
|
||
<< std::endl;
|
||
for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++)
|
||
{
|
||
const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator);
|
||
if (currentJobCard && (currentJobCard->getStatus() == util::ServiceJobStatus::STARTED))
|
||
{
|
||
std::cout << std::left << std::setw(6) << currentIndex
|
||
<< std::setw(12) << currentJobCard->getBookingId()
|
||
<< std::setw(12) << currentJobCard->getId()
|
||
<< std::setw(20) << currentJobCard->getService()->getName()
|
||
<< std::setw(12) << currentJobCard->getServiceId()
|
||
<< std::endl;
|
||
hasIncompleteJobCard = true;
|
||
incompleteJobCards.insert(currentIndex++, currentJobCard);
|
||
}
|
||
}
|
||
if (!hasIncompleteJobCard)
|
||
{
|
||
std::cout << "No pending jobs are present.\n";
|
||
return "";
|
||
}
|
||
std::cout << "Select the Job Card to complete (Index): ";
|
||
util::read(choice);
|
||
int selectedJobCardIndex = incompleteJobCards.find(choice);
|
||
if (selectedJobCardIndex != -1)
|
||
{
|
||
const JobCard* selectedJobCard = incompleteJobCards.getValueAt(selectedJobCardIndex);
|
||
return selectedJobCard->getId();
|
||
}
|
||
else
|
||
{
|
||
std::cout << "Invalid index.\n";
|
||
return "";
|
||
}
|
||
}
|
||
|
||
/*
|
||
Function: selectNotification
|
||
Description: Displays a list of notifications with index, ID, title, and timestamp.
|
||
Allows the user to select a notification by index. Returns the selected
|
||
notification or nullptr if the selection is invalid.
|
||
Parameter: const util::Vector<const Notification*>& notifications - list of notifications
|
||
Return type: const Notification* - pointer to the selected notification
|
||
*/
|
||
inline const Notification* selectNotification(const util::Vector<const Notification*>& notifications)
|
||
{
|
||
if (notifications.getSize() == 0)
|
||
{
|
||
std::cout << "No notifications available." << std::endl;
|
||
return nullptr;
|
||
}
|
||
util::Map<int, const Notification*> indexedNotifications;
|
||
std::cout << std::left
|
||
<< std::setw(6) << "Index"
|
||
<< std::setw(15) << "ID"
|
||
<< std::setw(30) << "Title"
|
||
<< std::setw(25) << "Timestamp"
|
||
<< std::endl;
|
||
int currentIndex = 1;
|
||
for (int index = 0; index < notifications.getSize(); index++)
|
||
{
|
||
const Notification* currentNotification = notifications[index];
|
||
if (currentNotification)
|
||
{
|
||
std::cout << std::left
|
||
<< std::setw(6) << currentIndex
|
||
<< std::setw(15) << currentNotification->getId()
|
||
<< std::setw(30) << currentNotification->getTitle()
|
||
<< std::setw(25) << currentNotification->getCreatedAt().toString()
|
||
<< std::endl;
|
||
indexedNotifications.insert(currentIndex, currentNotification);
|
||
currentIndex++;
|
||
}
|
||
}
|
||
int selectedIndex;
|
||
std::cout << "Select notification: ";
|
||
util::read(selectedIndex);
|
||
if (!indexedNotifications.containsKey(selectedIndex))
|
||
{
|
||
std::cout << "Invalid index." << std::endl;
|
||
return nullptr;
|
||
}
|
||
return indexedNotifications[selectedIndex];
|
||
}
|
||
|
||
/*
|
||
Function: displayNotification
|
||
Description: Displays detailed information about a single notification, including ID, title, timestamp, and message.
|
||
Parameters:
|
||
- notification: Pointer to the Notification object to be displayed.
|
||
Returns:
|
||
- void
|
||
*/
|
||
inline void displayNotification(const Notification* notification)
|
||
{
|
||
util::clear();
|
||
if (!notification)
|
||
{
|
||
std::cout << "Notification not found." << std::endl;
|
||
return;
|
||
}
|
||
std::cout << "Notification Details" << std::endl;
|
||
std::cout << "ID : " << notification->getId() << std::endl;
|
||
std::cout << "Title : " << notification->getTitle() << std::endl;
|
||
std::cout << "Timestamp : " << notification->getCreatedAt().toString() << std::endl;
|
||
std::cout << "Message : " << notification->getMessage() << std::endl;
|
||
}
|
||
|
||
/*
|
||
Function: viewAndDeleteNotification
|
||
Description: Allows the user to view a notification and then delete it from the system using the controller.
|
||
Parameters:
|
||
- controller: Reference to the Controller object used to manage notifications.
|
||
Returns:
|
||
- void
|
||
*/
|
||
inline void viewAndDeleteNotification(Controller& controller)
|
||
{
|
||
util::clear();
|
||
auto notifications = controller.getNotifications();
|
||
const Notification* selectedNotification = selectNotification(notifications);
|
||
if (!selectedNotification)
|
||
{
|
||
std::cout << "Failed to display notification!";
|
||
util::pressEnter();
|
||
return;
|
||
}
|
||
displayNotification(selectedNotification);
|
||
controller.deleteNotification(selectedNotification->getId());
|
||
util::pressEnter();
|
||
}
|
||
|
||
/*
|
||
Function: changePassword
|
||
Description: Helper function to change password
|
||
Parameter: controller: Reference to the Controller object used to manage notifications.
|
||
Return type: void
|
||
*/
|
||
inline void changePasswordHelper(Controller& controller)
|
||
{
|
||
util::clear();
|
||
const User* authenticatedUser = controller.getAuthenticatedUser();
|
||
if (!authenticatedUser)
|
||
{
|
||
throw std::runtime_error("No user is currently logged in!");
|
||
}
|
||
std::string newPassword, confirmedPassword;
|
||
while (true)
|
||
{
|
||
util::clear();
|
||
std::cout << "Change Password\n";
|
||
std::cout << "Enter new password: ";
|
||
util::read(newPassword);
|
||
if (!util::isPasswordValid(newPassword))
|
||
{
|
||
std::cout << "Error: Password is not strong enough!\n";
|
||
util::pressEnter();
|
||
continue;
|
||
}
|
||
if (newPassword == authenticatedUser->getPassword())
|
||
{
|
||
std::cout << "New password cannot be same as old password. Try again\n";
|
||
util::pressEnter();
|
||
continue;
|
||
}
|
||
std::cout << "Confirm new password: ";
|
||
util::read(confirmedPassword);
|
||
if (confirmedPassword != newPassword)
|
||
{
|
||
std::cout << "Passwords are different. Try again\n";
|
||
util::pressEnter();
|
||
continue;
|
||
}
|
||
controller.changePassword(newPassword);
|
||
std::cout << "Password changed successfully\n";
|
||
util::pressEnter();
|
||
break;
|
||
}
|
||
}
|
||
|
||
/*
|
||
Function: filterActiveUsers
|
||
Description: Filters out inactive users and returns a map of active users.
|
||
Parameter: const util::Map<std::string, const User*>& listOfUsers - all users
|
||
Return type: util::Map<std::string, const User*>
|
||
*/
|
||
inline util::Map<std::string, const User*> filterActiveUsers(const util::Map<std::string, const User*>& listOfUsers)
|
||
{
|
||
util::Map<std::string, const User*> activeUsers;
|
||
int inventorySize = listOfUsers.getSize();
|
||
for (int index = 0; index < inventorySize; index++)
|
||
{
|
||
const User* user = listOfUsers.getValueAt(index);
|
||
if (user != nullptr && user->getState() != util::State::INACTIVE)
|
||
{
|
||
activeUsers.insert(user->getId(), user);
|
||
}
|
||
}
|
||
return activeUsers;
|
||
}
|
||
|
||
/*
|
||
Function: displayAllActiveUsers
|
||
Description: Displays all active users in a tabular format with index, ID, username, and type.
|
||
Parameter: util::Map<std::string, const User*>& activeUsers - active users list
|
||
int activeUserCount - number of active users
|
||
Return type: void
|
||
*/
|
||
inline void displayAllActiveUsers(util::Map<std::string, const User*>& activeUsers, int activeUserCount)
|
||
{
|
||
std::cout << std::left << std::setw(10) << "Index"
|
||
<< std::setw(15) << "User ID"
|
||
<< std::setw(25) << "Username"
|
||
<< std::setw(25) << "User Type"
|
||
<< std::endl;
|
||
for (int iterator = 0; iterator < activeUserCount; iterator++)
|
||
{
|
||
const User* user = activeUsers.getValueAt(iterator);
|
||
if (user != nullptr)
|
||
{
|
||
std::cout << std::left << std::setw(10) << (iterator + 1)
|
||
<< std::setw(15) << user->getId()
|
||
<< std::setw(25) << user->getUserName()
|
||
<< std::setw(25) << util::getUserTypeString(user->getUserType())
|
||
<< std::endl;
|
||
}
|
||
else
|
||
{
|
||
std::cout << "No users found.\n";
|
||
util::pressEnter();
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
Function: selectServiceFromServices
|
||
Description: Displays active services and allows the customer to select one by index.
|
||
Parameter: const util::Map<std::string, const Service*>& services - list of services
|
||
Return type: const Service* - selected service
|
||
*/
|
||
inline const Service* selectServiceFromServices(const util::Map<std::string, const Service*>& services)
|
||
{
|
||
util::Map<int, const Service*> activeServicesMap;
|
||
int currentIndex = 1;
|
||
int userInputIndex;
|
||
std::cout << std::left
|
||
<< std::setw(10) << "Index"
|
||
<< std::setw(15) << "Service ID"
|
||
<< std::setw(25) << "Service Name"
|
||
<< std::setw(15) << "Estimated Cost"
|
||
<< std::endl;
|
||
for (int index = 0; index < services.getSize(); index++)
|
||
{
|
||
const Service* currentService = services.getValueAt(index);
|
||
if (currentService == nullptr)
|
||
{
|
||
throw std::runtime_error("Warning: Encountered a null service\n");
|
||
continue;
|
||
}
|
||
if (currentService->getState() != util::State::ACTIVE)
|
||
{
|
||
continue;
|
||
}
|
||
activeServicesMap.insert(currentIndex, currentService);
|
||
double partsCost = util::calculatePartsCost(currentService);
|
||
std::cout << std::left
|
||
<< std::setw(10) << currentIndex
|
||
<< std::setw(15) << currentService->getId()
|
||
<< std::setw(25) << currentService->getName()
|
||
<< std::setw(15) << (currentService->getLaborCost() + partsCost)
|
||
<< std::endl;
|
||
currentIndex++;
|
||
}
|
||
if (activeServicesMap.getSize() == 0)
|
||
{
|
||
std::cout << "No active services available." << std::endl;
|
||
return nullptr;
|
||
}
|
||
std::cout << "Enter service index: ";
|
||
util::read(userInputIndex);
|
||
if (activeServicesMap.find(userInputIndex) == -1)
|
||
{
|
||
std::cout << "Invalid service index." << std::endl;
|
||
return nullptr;
|
||
}
|
||
return activeServicesMap[userInputIndex];
|
||
}
|
||
|
||
/*
|
||
Function: selectComboPackageFromPackages
|
||
Description: Displays active combo packages and allows the customer to select one by index.
|
||
Parameter: const util::Map<std::string, const ComboPackage*>& comboPackages - list of combo packages
|
||
Return type: const ComboPackage* - selected combo package
|
||
*/
|
||
inline 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 ID"
|
||
<< std::setw(15) << "Combo 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) << util::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];
|
||
}
|
||
|
||
/*
|
||
Function: getNotificationPreference
|
||
Description: Helper function to configure notification preferences for a specific service.
|
||
Parameters:
|
||
- serviceName: Name of the service for which notifications are being configured.
|
||
Returns:
|
||
- bool: True if notifications are enabled, False if disabled.
|
||
*/
|
||
inline bool getNotificationPreference(const std::string& serviceName)
|
||
{
|
||
int choice;
|
||
while (true)
|
||
{
|
||
util::clear();
|
||
std::cout << " Configure Notification Preferences\n";
|
||
std::cout << "\n" << serviceName << " Notifications\n";
|
||
std::cout << "1. Enable Notifications\n";
|
||
std::cout << "2. Disable Notifications\n";
|
||
std::cout << "Enter your choice: ";
|
||
util::read(choice);
|
||
if (choice == 1)
|
||
{
|
||
return true;
|
||
}
|
||
if (choice == 2)
|
||
{
|
||
return false;
|
||
}
|
||
std::cout << "\nInvalid choice. Please enter 1 or 2.\n";
|
||
util::pressEnter();
|
||
}
|
||
}
|
||
|
||
/*
|
||
Function: filterActiveItems
|
||
Description: Filters out inactive inventory items and returns a map
|
||
containing only active items.
|
||
Parameter: const util::Map<std::string, const InventoryItem*>& inventoryItems -
|
||
map of all inventory items
|
||
Return type: util::Map<std::string, const InventoryItem*>
|
||
*/
|
||
inline util::Map<std::string, const InventoryItem*> filterActiveItems(const util::Map<std::string, const InventoryItem*>& inventoryItems)
|
||
{
|
||
util::Map<std::string, const InventoryItem*> activeItems;
|
||
int inventorySize = inventoryItems.getSize();
|
||
for (int index = 0; index < inventorySize; index++)
|
||
{
|
||
const InventoryItem* item = inventoryItems.getValueAt(index);
|
||
if (item != nullptr && item->getState() != util::State::INACTIVE)
|
||
{
|
||
activeItems.insert(item->getId(), item);
|
||
}
|
||
}
|
||
return activeItems;
|
||
}
|
||
|
||
/*
|
||
Function: displayInventoryWithItems
|
||
Description: Displays inventory items in a tabular format with index, ID,
|
||
part name, quantity, and price.
|
||
Parameter: util::Map<std::string, const InventoryItem*>& inventoryItems -
|
||
map of inventory items to display
|
||
Return type: void
|
||
*/
|
||
inline void displayInventoryWithItems(util::Map<std::string, const InventoryItem*>& inventoryItems)
|
||
{
|
||
int inventorySize = inventoryItems.getSize();
|
||
std::cout << std::left << std::setw(10) << "Index"
|
||
<< std::setw(15) << "Item ID"
|
||
<< std::setw(25) << "Part Name"
|
||
<< std::setw(10) << "Quantity"
|
||
<< std::setw(10) << "Price"
|
||
<< std::endl;
|
||
for (int iterator = 0; iterator < inventorySize; iterator++)
|
||
{
|
||
const InventoryItem* item = inventoryItems.getValueAt(iterator);
|
||
if (item != nullptr)
|
||
{
|
||
std::cout << std::left << std::setw(10) << (iterator + 1)
|
||
<< std::setw(15) << item->getId()
|
||
<< std::setw(25) << item->getPartName()
|
||
<< std::setw(10) << item->getQuantity()
|
||
<< std::setw(10) << item->getPrice()
|
||
<< std::endl;
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
Function: addQuantityToItem
|
||
Description: Allows the admin to select an active inventory item and
|
||
increase its stock quantity.
|
||
Parameter: util::Map<std::string, const InventoryItem*>& inventoryItems -
|
||
map of inventory items
|
||
Controller& m_controller - controller instance to update stock
|
||
Return type: void
|
||
*/
|
||
inline void addQuantityToItem(util::Map<std::string, const InventoryItem*>& inventoryItems, Controller& m_controller)
|
||
{
|
||
int itemIndex;
|
||
int quantity;
|
||
auto activeItems = filterActiveItems(inventoryItems);
|
||
int activeSize = activeItems.getSize();
|
||
if (activeSize == 0)
|
||
{
|
||
std::cout << "No active items available in Inventory" << std::endl;
|
||
return;
|
||
}
|
||
displayInventoryWithItems(activeItems);
|
||
std::cout << "Enter the index of the item to update: ";
|
||
util::read(itemIndex);
|
||
if (itemIndex < 1 || itemIndex > activeSize)
|
||
{
|
||
std::cout << "Invalid index selected." << std::endl;
|
||
return;
|
||
}
|
||
std::cout << "Enter quantity to add: ";
|
||
util::read(quantity);
|
||
if (quantity < 0)
|
||
{
|
||
std::cout << "The quantity should be Greater than 0." << std::endl;
|
||
return;
|
||
}
|
||
const InventoryItem* selectedItem = activeItems.getValueAt(itemIndex - 1);
|
||
if (selectedItem != nullptr)
|
||
{
|
||
std::string selectedItemId = selectedItem->getId();
|
||
m_controller.addInventoryItemStock(selectedItemId, quantity);
|
||
std::cout << "Updated " << selectedItem->getPartName()
|
||
<< " stock. New quantity: " << selectedItem->getQuantity()
|
||
<< std::endl;
|
||
}
|
||
else
|
||
{
|
||
std::cout << "Error: Selected item could not be found." << std::endl;
|
||
}
|
||
}
|
||
|
||
/*
|
||
Function: displayComboPackagesWithIndex
|
||
Description: Displays combo packages with index, ID, name, and discount percentage.
|
||
Parameter: util::Map<int, const ComboPackage*>& currentComboPackageIndexMap - combo packages map
|
||
Return type: void
|
||
*/
|
||
inline void displayComboPackagesWithIndex(util::Map<int, const ComboPackage*>& currentComboPackageIndexMap)
|
||
{
|
||
for (int iterator = 0; iterator < currentComboPackageIndexMap.getSize(); iterator++)
|
||
{
|
||
const ComboPackage* currentComboPackage = currentComboPackageIndexMap.getValueAt(iterator);
|
||
if (currentComboPackage == nullptr)
|
||
{
|
||
throw std::runtime_error("Error accessing the combopackage.\n");
|
||
}
|
||
if (iterator == 0)
|
||
{
|
||
std::cout << std::left
|
||
<< std::setw(8) << "Index"
|
||
<< std::setw(10) << "ID"
|
||
<< std::setw(20) << "Package Name"
|
||
<< std::setw(15) << "Discount (%)"
|
||
<< "\n";
|
||
}
|
||
std::cout << std::left
|
||
<< std::setw(8) << currentComboPackageIndexMap.getKeyAt(iterator)
|
||
<< std::setw(10) << currentComboPackage->getId()
|
||
<< std::setw(20) << currentComboPackage->getPackageName()
|
||
<< std::setw(15) << currentComboPackage->getDiscountPercentage()
|
||
<< "\n";
|
||
}
|
||
}
|
||
|
||
/*
|
||
Function: selectComboPackage
|
||
Description: Allows the admin to select an active combo package by index.
|
||
Parameter: util::Map<std::string, const ComboPackage*>& currentComboPackages - combo packages list
|
||
Return type: std::string - ID of the selected combo package
|
||
*/
|
||
inline std::string selectComboPackage(util::Map<std::string, const ComboPackage*>& currentComboPackages)
|
||
{
|
||
util::Map<int, const ComboPackage*> currentComboPackageIndexMap;
|
||
if (currentComboPackages.getSize() == 0)
|
||
{
|
||
throw std::runtime_error("No combo packages are available.\n");
|
||
}
|
||
int currentIndex = 1, choice, selectedIndex;
|
||
for (int iterator = 0; iterator < currentComboPackages.getSize(); iterator++)
|
||
{
|
||
if (currentComboPackages.getValueAt(iterator)->getState() == util::State::INACTIVE)
|
||
{
|
||
continue;
|
||
}
|
||
currentComboPackageIndexMap.insert(currentIndex++, currentComboPackages.getValueAt(iterator));
|
||
}
|
||
if (currentComboPackageIndexMap.getSize() == 0)
|
||
{
|
||
throw std::runtime_error("No combo packages currently active.");
|
||
}
|
||
displayComboPackagesWithIndex(currentComboPackageIndexMap);
|
||
std::cout << "Enter your choice(Index): ";
|
||
util::read(choice);
|
||
selectedIndex = currentComboPackageIndexMap.find(choice);
|
||
if (selectedIndex != -1)
|
||
{
|
||
std::string selectedComboPackageID = currentComboPackageIndexMap.getValueAt(selectedIndex)->getId();
|
||
return selectedComboPackageID;
|
||
}
|
||
else
|
||
{
|
||
std::cout << "Enter a valid choice.\n";
|
||
return "";
|
||
}
|
||
} |