1444 lines
52 KiB
C++
1444 lines
52 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: displayAllServices
|
|
Description: Displays all active services
|
|
Parameters:
|
|
- currentServices: util::Map<std::string, const Service*>, available services
|
|
Returns:
|
|
- void;
|
|
*/
|
|
inline void displayAllServices(util::Map<std::string, const Service*> currentServices)
|
|
{
|
|
if (currentServices.getSize() == 0)
|
|
{
|
|
std::cout << "No Services Currently Available.\n";
|
|
return;
|
|
}
|
|
std::cout << std::left
|
|
<< std::setw(12) << "Service ID"
|
|
<< std::setw(35) << "Name"
|
|
<< std::setw(10) << "Labor Cost"
|
|
<< std::endl;
|
|
for (int iterator = 0; iterator < currentServices.getSize(); iterator++)
|
|
{
|
|
const Service* currentService = currentServices.getValueAt(iterator);
|
|
if (currentService == nullptr || currentService->getState() == util::State::INACTIVE)
|
|
{
|
|
continue;
|
|
}
|
|
std::cout << std::left
|
|
<< std::setw(12) << currentService->getId()
|
|
<< std::setw(35) << util::truncateString(currentService->getName(), 30)
|
|
<< std::setw(10) << currentService->getLaborCost()
|
|
<< std::endl;
|
|
}
|
|
}
|
|
|
|
/*
|
|
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)
|
|
{
|
|
if (currentServices.getSize() == 0)
|
|
{
|
|
std::cout << "No Services Currently Available.\n";
|
|
return "";
|
|
}
|
|
util::Map<int, const Service*> currentServicesMap;
|
|
int currentIndex = 1, choice;
|
|
std::cout << std::left
|
|
<< std::setw(6) << "Index"
|
|
<< std::setw(12) << "Service ID"
|
|
<< std::setw(35) << "Name"
|
|
<< std::setw(10) << "Labor Cost"
|
|
<< std::endl;
|
|
for (int iterator = 0; iterator < currentServices.getSize(); iterator++)
|
|
{
|
|
const Service* currentService = currentServices.getValueAt(iterator);
|
|
if (currentService == nullptr || currentService->getState() == util::State::INACTIVE)
|
|
{
|
|
continue;
|
|
}
|
|
std::cout << std::left
|
|
<< std::setw(6) << currentIndex
|
|
<< std::setw(12) << currentService->getId()
|
|
<< std::setw(35) << util::truncateString(currentService->getName(), 30)
|
|
<< std::setw(10) << currentService->getLaborCost()
|
|
<< std::endl;
|
|
currentServicesMap.insert(currentIndex++, currentService);
|
|
}
|
|
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;
|
|
util::Map<int, const InventoryItem*> currentInventoryMap;
|
|
int choice;
|
|
if (currentInventoryItems.isEmpty())
|
|
{
|
|
std::cout << "No Items Present, Inventory empty.\n";
|
|
return;
|
|
}
|
|
while (doRun)
|
|
{
|
|
util::clear();
|
|
std::cout << "Create Service\n";
|
|
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;
|
|
}
|
|
bool alreadySelected = false;
|
|
for (int iteratorOne = 0; iteratorOne < selectedInventoryItems.getSize(); iteratorOne++)
|
|
{
|
|
if (selectedInventoryItems[iteratorOne] == currentInventoryItem->getId())
|
|
{
|
|
alreadySelected = true;
|
|
break;
|
|
}
|
|
}
|
|
if (alreadySelected)
|
|
{
|
|
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;
|
|
}
|
|
if (!hasInventoryItems)
|
|
{
|
|
break;
|
|
}
|
|
std::cout << "Select the item (Index) or enter 0 to exit: ";
|
|
util::read(choice);
|
|
if (choice == 0)
|
|
{
|
|
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;
|
|
util::pressEnter();
|
|
}
|
|
else
|
|
{
|
|
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.
|
|
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)
|
|
{
|
|
if (currentBookings.getSize() == 0)
|
|
{
|
|
return false;
|
|
}
|
|
int currentIndex = 1;
|
|
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::endl;
|
|
for (int iterator = 0; iterator < bookingsSize; iterator++)
|
|
{
|
|
const ServiceBooking* currentBooking = currentBookings.getValueAt(iterator);
|
|
if (currentBooking && currentBooking->getStatus() == util::ServiceJobStatus::PENDING)
|
|
{
|
|
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::endl;
|
|
serviceBookingsMap.insert(currentIndex++, currentBooking);
|
|
}
|
|
}
|
|
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 << "\nEnter a service index: ";
|
|
util::read(userInputIndex);
|
|
if (serviceBookingsMap.find(userInputIndex) != -1)
|
|
{
|
|
return serviceBookingsMap.getValueAt(serviceBookingsMap.find(userInputIndex));
|
|
}
|
|
else
|
|
{
|
|
std::cout << "Enter a valid index.\n\n";
|
|
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 << "\nSelect Technician\n";
|
|
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.\n\n";
|
|
}
|
|
}
|
|
|
|
/*
|
|
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;
|
|
std::cout << "\nEnter technician index: ";
|
|
util::read(userInputIndex);
|
|
if (currentAvailableTechniciansMap.find(userInputIndex) != -1)
|
|
{
|
|
return currentAvailableTechniciansMap.getValueAt(currentAvailableTechniciansMap.find(userInputIndex));
|
|
}
|
|
else
|
|
{
|
|
std::cout << "Enter a valid index.\n\n";
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
/*
|
|
Function: selectInvoiceFromUserForPayment
|
|
Description: Displays a list of invoices filtered by the required payment status.
|
|
Allows the user to select an invoice by index and returns the corresponding invoice ID.
|
|
Parameters:
|
|
- currentInvoices: const util::Map<std::string, const Invoice*>&,
|
|
map of all invoices keyed by invoice ID
|
|
- requiredStatus: util::PaymentStatus,
|
|
the status to filter invoices (e.g., PENDING, PAID, COMPLETED)
|
|
Returns:
|
|
- std::string: ID of the selected invoice, or empty string if none selected or invalid index
|
|
*/
|
|
inline std::string selectInvoiceFromUserForPayment(const util::Map<std::string, const Invoice*>& currentInvoices, util::PaymentStatus requiredStatus)
|
|
{
|
|
int currentIndex = 1, choice;
|
|
util::Map<int, const Invoice*> pendingInvoicesForPayment;
|
|
std::cout << std::left
|
|
<< std::setw(8) << "Index"
|
|
<< std::setw(15) << "Booking ID"
|
|
<< std::setw(20) << "Vehicle Brand"
|
|
<< std::setw(20) << "Vehicle Number"
|
|
<< std::setw(18) << "Technician ID"
|
|
<< std::setw(25) << "Technician Name"
|
|
<< std::setw(15) << "Discount(%)"
|
|
<< std::setw(15) << "TotalAmount"
|
|
<< std::setw(22) << "Invoice Timestamp"
|
|
<< std::endl;
|
|
for (int iterator = 0; iterator < currentInvoices.getSize(); iterator++)
|
|
{
|
|
const Invoice* currentInvoice = currentInvoices.getValueAt(iterator);
|
|
if (currentInvoice && currentInvoice->getStatus() == requiredStatus)
|
|
{
|
|
const User* currentTechnician = currentInvoice->getBooking()->getAssignedTechnician();
|
|
std::cout << std::left
|
|
<< std::setw(8) << currentIndex
|
|
<< std::setw(15) << currentInvoice->getBookingId()
|
|
<< std::setw(20) << currentInvoice->getBooking()->getVehicleBrand()
|
|
<< std::setw(20) << currentInvoice->getBooking()->getVehicleNumber()
|
|
<< std::setw(18) << ((currentTechnician != nullptr && currentTechnician->getId() != "") ?
|
|
currentTechnician->getId() : "Null")
|
|
<< std::setw(25) << ((currentTechnician != nullptr && currentTechnician->getName() != "") ?
|
|
currentTechnician->getName() : "Null")
|
|
<< std::setw(15) << currentInvoice->getDiscountPercentage()
|
|
<< std::setw(15) << currentInvoice->getTotalAmount()
|
|
<< std::setw(22) << 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;
|
|
while (true)
|
|
{
|
|
util::clear();
|
|
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. Try again.\n";
|
|
util::pressEnter();
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
Function: displayInvoicesInTabularForm
|
|
Description:
|
|
Displays all invoices in a tabular format. Each row shows booking details,
|
|
vehicle info, technician details, discount, total amount, invoice date,
|
|
and payment status. If inventory items exist for an invoice, they are
|
|
displayed in a separate table below the invoice row.
|
|
Parameters:
|
|
- currentInvoices: util::Map<std::string, const Invoice*>
|
|
Map of invoice IDs to Invoice pointers.
|
|
Returns:
|
|
- void
|
|
*/
|
|
inline const Invoice* selectInvoiceToDisplay(util::Map<std::string, const Invoice*>& currentInvoices)
|
|
{
|
|
int currentIndex = 1, choice;
|
|
util::Map<int, const Invoice*> currentInvoicesIndexMap;
|
|
if (currentInvoices.isEmpty())
|
|
{
|
|
std::cout << "No invoices available.\n\n";
|
|
return nullptr;
|
|
}
|
|
std::cout
|
|
<< std::left
|
|
<< std::setw(10) << "Index"
|
|
<< std::setw(12) << "BookingID"
|
|
<< std::setw(20) << "Vehicle Number"
|
|
<< std::setw(20) << "Technician Name"
|
|
<< std::setw(15) << "Total Amount"
|
|
<< std::setw(25) << "Invoice Date"
|
|
<< std::setw(20) << "Payment Status"
|
|
<< std::setw(15) << "Payment Mode"
|
|
<< std::endl;
|
|
for (int iterator = 0; iterator < currentInvoices.getSize(); iterator++)
|
|
{
|
|
const Invoice* currentInvoice = currentInvoices.getValueAt(iterator);
|
|
if (!currentInvoice)
|
|
{
|
|
continue;
|
|
}
|
|
const User* currentTechnician = currentInvoice->getBooking()->getAssignedTechnician();
|
|
std::cout << std::left
|
|
<< std::setw(10) << currentIndex
|
|
<< std::setw(12) << currentInvoice->getBookingId()
|
|
<< std::setw(20) << currentInvoice->getBooking()->getVehicleNumber()
|
|
<< std::setw(20) << ((currentTechnician && !currentTechnician->getName().empty()) ? currentTechnician->getName() : "NULL")
|
|
<< std::setw(15) << currentInvoice->getTotalAmount()
|
|
<< std::setw(25) << currentInvoice->getInvoiceDate().toString()
|
|
<< std::setw(20) << util::getPaymentStatusString(currentInvoice->getStatus())
|
|
<< std::setw(15) << util::getPaymentModeString(currentInvoice->getPaymentMethod())
|
|
<< std::endl;
|
|
currentInvoicesIndexMap.insert(currentIndex++, currentInvoice);
|
|
}
|
|
std::cout << "Enter an index: ";
|
|
util::read(choice);
|
|
int currentSelectedIndex = currentInvoicesIndexMap.find(choice);
|
|
if (currentSelectedIndex != -1)
|
|
{
|
|
return currentInvoicesIndexMap.getValueAt(currentSelectedIndex);
|
|
}
|
|
else
|
|
{
|
|
std::cout << "Enter a valid index.\n";
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
/*
|
|
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)
|
|
{
|
|
std::cout << std::endl;
|
|
if (currentUserInvoices.getSize() == 0)
|
|
{
|
|
std::cout << "No invoices found for this account.\n\n";
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
bool doRun = true;
|
|
do
|
|
{
|
|
const Invoice* selectedInvoice;
|
|
int choice;
|
|
selectedInvoice = selectInvoiceToDisplay(currentUserInvoices);
|
|
if (selectedInvoice)
|
|
{
|
|
const User* currentTechnician = selectedInvoice->getBooking()->getAssignedTechnician();
|
|
util::clear();
|
|
std::cout << "Invoice Details\n";
|
|
std::cout << std::left << std::setw(20) << "Booking ID:"
|
|
<< selectedInvoice->getBookingId() << std::endl;
|
|
std::cout << std::left << std::setw(20) << "Vehicle Brand:"
|
|
<< selectedInvoice->getBooking()->getVehicleBrand() << std::endl;
|
|
std::cout << std::left << std::setw(20) << "Vehicle Number:"
|
|
<< selectedInvoice->getBooking()->getVehicleNumber() << std::endl;
|
|
std::cout << std::left << std::setw(20) << "Technician ID:"
|
|
<< ((currentTechnician != nullptr && !currentTechnician->getId().empty())
|
|
? currentTechnician->getId() : "NULL") << std::endl;
|
|
std::cout << std::left << std::setw(20) << "Technician Name:"
|
|
<< ((currentTechnician != nullptr && !currentTechnician->getName().empty())
|
|
? currentTechnician->getName() : "NULL") << std::endl;
|
|
std::cout << std::left << std::setw(20) << "Discount(%):"
|
|
<< selectedInvoice->getDiscountPercentage() << std::endl;
|
|
std::cout << std::left << std::setw(20) << "Total Amount:"
|
|
<< selectedInvoice->getTotalAmount() << std::endl;
|
|
std::cout << std::left << std::setw(20) << "Invoice Date:"
|
|
<< selectedInvoice->getInvoiceDate().toString() << std::endl;
|
|
std::cout << std::left << std::setw(20) << "Payment Status:"
|
|
<< util::getPaymentStatusString(selectedInvoice->getStatus()) << std::endl;
|
|
std::cout << std::left << std::setw(20) << "Payment Mode:"
|
|
<< util::getPaymentModeString(selectedInvoice->getPaymentMethod()) << std::endl;
|
|
auto inventoryItemsInInvoice = selectedInvoice->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;
|
|
}
|
|
std::cout << "\n\nDo you want to display another Invoice (1-Yes, 2-No): ";
|
|
util::read(choice);
|
|
if (choice == 1)
|
|
{
|
|
doRun = true;
|
|
util::clear();
|
|
}
|
|
else if (choice == 2)
|
|
{
|
|
doRun = false;
|
|
}
|
|
else
|
|
{
|
|
std::cout << "Invalid choice\n";
|
|
doRun = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::cout << "Unable to fetch the selected invoice\n";
|
|
doRun = false;
|
|
}
|
|
} while (doRun);
|
|
}
|
|
}
|
|
|
|
/*
|
|
Function: filterStartedJobCards
|
|
Description: Filters the given list of job cards and returns only those with status STARTED.
|
|
Parameters:
|
|
- assignedJobCards: Map of job card IDs to JobCard pointers.
|
|
Returns:
|
|
- util::Map<std::string, const JobCard*> containing only job cards with status STARTED.
|
|
*/
|
|
inline util::Map<std::string, const JobCard*> filterStartedJobCards(util::Map<std::string, const JobCard*>& assignedJobCards)
|
|
{
|
|
util::Map<std::string, const JobCard*> startedJobCards;
|
|
for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++)
|
|
{
|
|
const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator);
|
|
if (currentJobCard && (currentJobCard->getStatus() == util::ServiceJobStatus::STARTED || currentJobCard->getStatus() == util::ServiceJobStatus::IN_PROGRESS))
|
|
{
|
|
startedJobCards.insert(currentJobCard->getId(), currentJobCard);
|
|
}
|
|
}
|
|
return startedJobCards;
|
|
}
|
|
|
|
/*
|
|
Function: filterJobCards
|
|
Description:
|
|
Filters the given list of job cards and returns only those
|
|
whose status matches the specified ServiceJobStatus.
|
|
Parameters:
|
|
- assignedJobCards: util::Map<std::string, const JobCard*>&
|
|
Map of job card IDs to JobCard pointers assigned to the technician.
|
|
- selectedJobStatus: util::ServiceJobStatus
|
|
The status type to filter job cards by.
|
|
Returns:
|
|
- util::Map<std::string, const JobCard*>
|
|
A map containing only job cards with the specified status.
|
|
*/
|
|
inline util::Map<std::string, const JobCard*> filterJobCards(util::Map<std::string, const JobCard*>& assignedJobCards, util::ServiceJobStatus selectedJobStatus)
|
|
{
|
|
util::Map<std::string, const JobCard*> startedJobCards;
|
|
for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++)
|
|
{
|
|
const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator);
|
|
if (currentJobCard && currentJobCard->getStatus() == selectedJobStatus)
|
|
{
|
|
startedJobCards.insert(currentJobCard->getId(), currentJobCard);
|
|
}
|
|
}
|
|
return startedJobCards;
|
|
}
|
|
|
|
/*
|
|
Function: displayAllJobs
|
|
Description: Displays all Jobs assigned to a Technician
|
|
Parameters:
|
|
- assignedJobCards: util::Map<std::string, const JobCard*>&, job cards assigned to the technician
|
|
Returns:
|
|
- std::string: ID of the selected job card, or empty string if none selected
|
|
*/
|
|
inline void displayAllJobs(util::Map<std::string, const JobCard*>& assignedJobCards)
|
|
{
|
|
if (assignedJobCards.getSize() == 0)
|
|
{
|
|
std::cout << "No active jobs assigned.\n";
|
|
return;
|
|
}
|
|
std::cout << std::endl;
|
|
std::cout << std::left
|
|
<< std::setw(12) << "BookingID"
|
|
<< std::setw(12) << "JobID"
|
|
<< std::setw(20) << "ServiceName"
|
|
<< std::setw(12) << "ServiceID"
|
|
<< std::setw(12) << "Status"
|
|
<< std::endl;
|
|
for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++)
|
|
{
|
|
const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator);
|
|
if (currentJobCard && (currentJobCard->getStatus() == util::ServiceJobStatus::STARTED || currentJobCard->getStatus() == util::ServiceJobStatus::IN_PROGRESS))
|
|
{
|
|
std::cout << std::left << std::setw(12) << currentJobCard->getBookingId()
|
|
<< std::setw(12) << currentJobCard->getId()
|
|
<< std::setw(20) << util::truncateString(currentJobCard->getService()->getName(), 15)
|
|
<< std::setw(12) << currentJobCard->getServiceId()
|
|
<< std::setw(12) << util::getServiceJobStatusString(currentJobCard->getStatus())
|
|
<< std::endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
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
|
|
Returns:
|
|
- std::string: ID of the selected job card, or empty string if none selected
|
|
*/
|
|
inline std::string selectJobCardToUpdate(util::Map<std::string, const JobCard*>& assignedJobCards, util::ServiceJobStatus selectedJobStatusType)
|
|
{
|
|
util::Map<int, const JobCard* > incompleteJobCards;
|
|
if (assignedJobCards.getSize() == 0)
|
|
{
|
|
std::cout << "\nNo jobs available.\n\n";
|
|
return "";
|
|
}
|
|
int currentIndex = 1;
|
|
int choice;
|
|
if (selectedJobStatusType == util::ServiceJobStatus::STARTED)
|
|
{
|
|
util::clear();
|
|
std::cout << "Select a job to mark as In Progress\n";
|
|
}
|
|
else if (selectedJobStatusType == util::ServiceJobStatus::IN_PROGRESS)
|
|
{
|
|
util::clear();
|
|
std::cout << "Select a job to mark as Completed\n";
|
|
}
|
|
else
|
|
{
|
|
std::cout << "Unable to update completed or pending jobs.\n\n";
|
|
return "";
|
|
}
|
|
std::cout << std::endl;
|
|
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::setw(12) << "JobStatus"
|
|
<< std::endl;
|
|
for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++)
|
|
{
|
|
const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator);
|
|
if (currentJobCard && (currentJobCard->getStatus() == selectedJobStatusType))
|
|
{
|
|
std::cout << std::left << std::setw(6) << currentIndex
|
|
<< std::setw(12) << currentJobCard->getBookingId()
|
|
<< std::setw(12) << currentJobCard->getId()
|
|
<< std::setw(20) << util::truncateString(currentJobCard->getService()->getName(), 15)
|
|
<< std::setw(12) << currentJobCard->getServiceId()
|
|
<< std::setw(12) << util::getServiceJobStatusString(currentJobCard->getStatus())
|
|
<< std::endl;
|
|
incompleteJobCards.insert(currentIndex++, currentJobCard);
|
|
}
|
|
}
|
|
std::cout << "Enter the job index to update: ";
|
|
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";
|
|
std::cout << "Failed to update job.\n\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)
|
|
{
|
|
util::Map<int, const Notification*> indexedNotifications;
|
|
std::cout << std::left
|
|
<< std::setw(10) << "Index"
|
|
<< std::setw(15) << "ID"
|
|
<< std::setw(35) << "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(10) << currentIndex
|
|
<< std::setw(15) << currentNotification->getId()
|
|
<< std::setw(35) << util::truncateString(currentNotification->getTitle(), 30)
|
|
<< 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();
|
|
std::cout << "View and Delete Notification" << std::endl;
|
|
if (notifications.getSize() == 0)
|
|
{
|
|
std::cout << "No notifications available." << std::endl;
|
|
util::pressEnter();
|
|
return;
|
|
}
|
|
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::readPassword(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::readPassword(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 && user->getUserType() != util::UserType::ADMIN)
|
|
{
|
|
activeUsers.insert(user->getId(), user);
|
|
}
|
|
}
|
|
return activeUsers;
|
|
}
|
|
|
|
/*
|
|
Function: displayAllUsers
|
|
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
|
|
Return type: void
|
|
*/
|
|
inline void displayAllUsers(util::Map<std::string, const User*>& activeUsers)
|
|
{
|
|
int activeUserCount = activeUsers.getSize();
|
|
std::cout << std::left << std::setw(10) << "Index"
|
|
<< std::setw(15) << "User ID"
|
|
<< std::setw(25) << "Username"
|
|
<< std::setw(25) << "Full Name"
|
|
<< 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) << user->getName()
|
|
<< std::setw(25) << util::getUserTypeString(user->getUserType())
|
|
<< std::endl;
|
|
}
|
|
else
|
|
{
|
|
std::cout << "No users found.\n";
|
|
util::pressEnter();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
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.
|
|
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)
|
|
{
|
|
if (services.getSize() == 0)
|
|
{
|
|
std::cout << "No active services available." << std::endl;
|
|
return nullptr;
|
|
}
|
|
std::cout << std::endl;
|
|
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: filterComboPackages
|
|
Description:
|
|
Filters the given list of combo packages and returns only those that are ACTIVE.
|
|
Parameters:
|
|
- comboPackages: util::Map<std::string, const ComboPackage*>&
|
|
Map of combo package IDs to ComboPackage pointers.
|
|
Returns:
|
|
- util::Map<std::string, const ComboPackage*>
|
|
Map containing only active combo packages.
|
|
*/
|
|
inline util::Map<std::string, const ComboPackage*> filterComboPackages(util::Map<std::string, const ComboPackage*>& comboPackages)
|
|
{
|
|
util::Map<std::string, const ComboPackage*> activeComboPackages;
|
|
for (int iterator = 0; iterator < comboPackages.getSize(); iterator++)
|
|
{
|
|
const ComboPackage* currentComboPackage = comboPackages.getValueAt(iterator);
|
|
if (currentComboPackage && currentComboPackage->getState() == util::State::ACTIVE)
|
|
{
|
|
activeComboPackages.insert(currentComboPackage->getId(), currentComboPackage);
|
|
}
|
|
}
|
|
return activeComboPackages;
|
|
}
|
|
|
|
/*
|
|
Function: displayAllComboPackages
|
|
Description: Displays all active combo packages
|
|
Parameters:
|
|
- currentComboPackages: util::Map<std::string, const ComboPackage*>, available combo packages
|
|
Returns:
|
|
- void;
|
|
*/
|
|
inline void displayAllComboPackages(util::Map<std::string, const ComboPackage*> comboPackages)
|
|
{
|
|
std::cout << std::endl;
|
|
if (comboPackages.getSize() == 0)
|
|
{
|
|
std::cout << "No active combo packages available." << std::endl;
|
|
return;
|
|
}
|
|
std::cout << std::left
|
|
<< std::setw(15) << "Combo ID"
|
|
<< std::setw(35) << "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 && currentComboPackage->getState() != util::State::ACTIVE)
|
|
{
|
|
continue;
|
|
}
|
|
std::cout << std::left
|
|
<< std::setw(15) << currentComboPackage->getId()
|
|
<< std::setw(35) << util::truncateString(currentComboPackage->getPackageName(), 30)
|
|
<< std::setw(15) << util::calculateComboServiceEstimatedCost(currentComboPackage)
|
|
<< std::endl;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
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::endl;
|
|
std::cout << std::left
|
|
<< std::setw(10) << "Index"
|
|
<< std::setw(15) << "Combo ID"
|
|
<< std::setw(35) << "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 && 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(35) << util::truncateString(currentComboPackage->getPackageName(), 30)
|
|
<< 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 && 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;
|
|
}
|
|
}
|
|
std::cout << 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 << "\nNo active items available in Inventory" << std::endl << 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 << "\nInvalid index selected." << std::endl << 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 << "\nUpdated " << selectedItem->getPartName()
|
|
<< " stock. New quantity: " << selectedItem->getQuantity()
|
|
<< std::endl
|
|
<< std::endl;
|
|
}
|
|
else
|
|
{
|
|
std::cout << "\nError: Selected item could not be found." << std::endl << 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 combo package.\n");
|
|
}
|
|
if (iterator == 0)
|
|
{
|
|
std::cout << std::left
|
|
<< std::setw(8) << "Index"
|
|
<< std::setw(10) << "ID"
|
|
<< std::setw(35) << "Package Name"
|
|
<< std::setw(15) << "Discount (%)"
|
|
<< "\n";
|
|
}
|
|
std::cout << std::left
|
|
<< std::setw(8) << currentComboPackageIndexMap.getKeyAt(iterator)
|
|
<< std::setw(10) << currentComboPackage->getId()
|
|
<< std::setw(35) << util::truncateString(currentComboPackage->getPackageName(), 30)
|
|
<< 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)
|
|
{
|
|
std::cout << "No combo packages are available.\n";
|
|
return "";
|
|
}
|
|
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)
|
|
{
|
|
std::cout << "No combo packages currently active.\n";
|
|
return "";
|
|
}
|
|
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 "";
|
|
}
|
|
}
|
|
|
|
/*
|
|
Function: displayNewNotification
|
|
Description: Displays the most recent notification from the supplied
|
|
notification collection.
|
|
Parameter: util::Vector<const Notification*> notifications -
|
|
collection of notifications
|
|
Return type: void
|
|
*/
|
|
inline void displayNewNotification(util::Vector<const Notification*> notifications)
|
|
{
|
|
const Notification* notification = nullptr;
|
|
size_t numberOfNotifications = notifications.getSize();
|
|
for (int index = 0; index < numberOfNotifications; index++)
|
|
{
|
|
if (!notification)
|
|
{
|
|
notification = notifications[index];
|
|
}
|
|
else
|
|
{
|
|
if (notification->getId() < notifications[index]->getId())
|
|
{
|
|
notification = notifications[index];
|
|
}
|
|
}
|
|
}
|
|
MessageBoxA(
|
|
GetConsoleWindow(),
|
|
notification->getMessage().c_str(),
|
|
notification->getTitle().c_str(),
|
|
MB_OK |
|
|
MB_ICONINFORMATION);
|
|
} |