Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b7bc1f574d | |||
| b25b3d59cf | |||
| c1bd2a6ef1 | |||
| 859f7bbeaa | |||
| d6cc6fc04f | |||
| 62cd7dcc89 | |||
| c67bf962c1 | |||
| efd8b32a5f | |||
| 01596e825e | |||
| fb50aeba47 | |||
| defee9aa15 |
+1
-3
@@ -409,10 +409,8 @@ void Controller::removeUser(const std::string& userID)
|
||||
User* user = m_userManagementService.getUser(userID);
|
||||
if (!user)
|
||||
{
|
||||
throw std::runtime_error("Error User not Found.\n");
|
||||
throw std::runtime_error("Error: User not Found.\n");
|
||||
}
|
||||
m_serviceManagementService.cancelCustomerServiceBookings(userID);
|
||||
m_serviceManagementService.cancelTechnicianJobs(userID);
|
||||
m_userManagementService.removeUser(userID);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,9 +24,10 @@ Parameters: None
|
||||
Returns: A new ServiceBooking object.
|
||||
*/
|
||||
ServiceBooking::ServiceBooking()
|
||||
: m_id("SRV" + std::to_string(++m_uid)),
|
||||
: m_id("SBK" + std::to_string(++m_uid)),
|
||||
m_customer(nullptr),
|
||||
m_assignedTechnician(nullptr),
|
||||
m_status(util::ServiceJobStatus::PENDING),
|
||||
m_discountPercentage(0.0) {}
|
||||
|
||||
/*
|
||||
@@ -56,7 +57,7 @@ ServiceBooking::ServiceBooking(
|
||||
const std::string& vehicleModel,
|
||||
double discountPercentage
|
||||
)
|
||||
: m_id("SRV" + std::to_string(++m_uid)),
|
||||
: m_id("SBK" + std::to_string(++m_uid)),
|
||||
m_status(status),
|
||||
m_services(services),
|
||||
m_customerId(customerId),
|
||||
|
||||
+161
-84
@@ -26,7 +26,6 @@ Date:19-May-2026
|
||||
#include "User.h"
|
||||
#include "UserManagementService.h"
|
||||
#include "Utility.h"
|
||||
#include "ComboPackage.h"
|
||||
|
||||
/*
|
||||
Function: purchaseService
|
||||
@@ -100,7 +99,7 @@ void ServiceManagementService::purchaseComboPackage(const std::string& comboPack
|
||||
}
|
||||
const ComboPackage* comboPackage = comboPackagesMap[comboPackageID];
|
||||
util::Map<std::string, Service*> selectedServices = comboPackage->getServices();
|
||||
ServiceBooking* serviceBooking = Factory::getObject<ServiceBooking>(util::ServiceJobStatus::STARTED, selectedServices, authenticatedUser->getId(), authenticatedUser, vehicleNumber, vehicleBrand, vehicleModel, comboPackage->getDiscountPercentage());
|
||||
ServiceBooking* serviceBooking = Factory::getObject<ServiceBooking>(util::ServiceJobStatus::PENDING, selectedServices, authenticatedUser->getId(), authenticatedUser, vehicleNumber, vehicleBrand, vehicleModel, comboPackage->getDiscountPercentage());
|
||||
if (serviceBooking == nullptr)
|
||||
{
|
||||
throw std::runtime_error("Failed to create combo package service booking");
|
||||
@@ -508,6 +507,89 @@ void ServiceManagementService::saveObservers()
|
||||
util::saveObservers(config::file::SERVICEMANAGEMENTOBSERVERS, this);
|
||||
}
|
||||
|
||||
/*
|
||||
Function: restoreInventory
|
||||
Description: Restores inventory quantities for all required items in the services associated
|
||||
with a given booking. Each item's quantity is incremented by a fixed value.
|
||||
Parameter: ServiceBooking* booking - Pointer to the booking whose inventory items need to be restored
|
||||
Return type: void
|
||||
*/
|
||||
static void restoreInventory(ServiceBooking* booking)
|
||||
{
|
||||
const int INCREMENT_VALUE = 1;
|
||||
if (!booking)
|
||||
{
|
||||
return;
|
||||
}
|
||||
const auto& services = booking->getServices();
|
||||
for (int serviceIterator = 0; serviceIterator < services.getSize(); ++serviceIterator)
|
||||
{
|
||||
Service* service = services.getValueAt(serviceIterator);
|
||||
if (!service)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const auto& items = service->getRequiredInventoryItems();
|
||||
for (int InventoryIterator = 0; InventoryIterator < items.getSize(); ++InventoryIterator)
|
||||
{
|
||||
InventoryItem* item = items.getValueAt(InventoryIterator);
|
||||
if (item)
|
||||
{
|
||||
item->setQuantity(item->getQuantity() + INCREMENT_VALUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Function: processBookingCancellation
|
||||
Description: Cancels jobs and updates the status of a given booking. Sends notifications to the
|
||||
specified user, resets technician assignment if needed, and restores inventory items.
|
||||
Parameter: ServiceBooking* booking - Pointer to the booking being cancelled
|
||||
util::ServiceJobStatus newServiceBookingStatus - New status to assign to the booking
|
||||
const std::string& notificationTitle - Title of the booking cancellation notification
|
||||
const std::string& notificationMessage - Message body of the booking cancellation notification
|
||||
User* notifyUser - User to notify about the cancellation
|
||||
util::ServiceJobStatus jobCardStatus - New status to assign to associated job cards
|
||||
const std::string& jobNotificationTitle - Title of the job cancellation notification
|
||||
const std::string& jobNotificationMessage - Message body of the job cancellation notification
|
||||
util::Map<std::string, JobCard*>& jobs - Collection of job cards to update
|
||||
ServiceManagementService& currentService - Reference to the service for sending notifications
|
||||
Return type: void
|
||||
*/
|
||||
static void processBookingCancellation(ServiceBooking* booking,
|
||||
util::ServiceJobStatus newServiceBookingStatus,
|
||||
const std::string& notificationTitle,
|
||||
const std::string& notificationMessage,
|
||||
User* notifyUser,
|
||||
util::ServiceJobStatus jobCardStatus,
|
||||
const std::string& jobNotificationTitle,
|
||||
const std::string& jobNotificationMessage,
|
||||
util::Map<std::string, JobCard*>& jobs, ServiceManagementService& currentService)
|
||||
{
|
||||
if (!booking || !notifyUser)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int jobIterator = 0; jobIterator < jobs.getSize(); ++jobIterator)
|
||||
{
|
||||
JobCard* jobCard = jobs.getValueAt(jobIterator);
|
||||
if (jobCard && jobCard->getBookingId() == booking->getId())
|
||||
{
|
||||
jobCard->setStatus(jobCardStatus);
|
||||
currentService.sendNotification(notifyUser, jobNotificationTitle, jobNotificationMessage);
|
||||
}
|
||||
}
|
||||
booking->setStatus(newServiceBookingStatus);
|
||||
currentService.sendNotification(notifyUser, notificationTitle, notificationMessage);
|
||||
if (newServiceBookingStatus == util::ServiceJobStatus::PENDING)
|
||||
{
|
||||
booking->setAssignedTechnician(nullptr);
|
||||
booking->setAssignedTechnicianId("");
|
||||
}
|
||||
restoreInventory(booking);
|
||||
}
|
||||
|
||||
/*
|
||||
Function: cancelCustomerServiceBookings
|
||||
Description: Cancels all service bookings associated with a given customer or technician.
|
||||
@@ -516,69 +598,47 @@ Description: Cancels all service bookings associated with a given customer or te
|
||||
Parameter: const std::string& userID - ID of the customer or technician
|
||||
Return type: void
|
||||
*/
|
||||
void ServiceManagementService::cancelCustomerServiceBookings(const std::string& userID)
|
||||
void ServiceManagementService::cancelCustomerServiceBookings(const std::string& customerID)
|
||||
{
|
||||
const int INCREMENT_VALUE = 1;
|
||||
auto& users = m_dataStore.getUsers();
|
||||
int userIndex = users.find(userID);
|
||||
int userIndex = users.find(customerID);
|
||||
if (userIndex == -1)
|
||||
{
|
||||
throw std::runtime_error("User not found: " + userID);
|
||||
throw std::runtime_error("User not found: " + customerID);
|
||||
}
|
||||
User* user = users.getValueAt(userIndex);
|
||||
if (user == nullptr)
|
||||
User* customer = users.getValueAt(userIndex);
|
||||
if (!customer)
|
||||
{
|
||||
throw std::runtime_error("User not found: " + userID);
|
||||
throw std::runtime_error("User not found: " + customerID);
|
||||
}
|
||||
util::UserType type = user->getUserType();
|
||||
auto& bookings = DataStore::getInstance().getServiceBookings();
|
||||
for (int bookingIterator = 0; bookingIterator < bookings.getSize(); bookingIterator++)
|
||||
auto& bookings = m_dataStore.getServiceBookings();
|
||||
auto& jobs = m_dataStore.getJobCards();
|
||||
for (int iteratorOne = 0; iteratorOne < bookings.getSize(); iteratorOne++)
|
||||
{
|
||||
ServiceBooking* booking = bookings.getValueAt(bookingIterator);
|
||||
if (booking != nullptr &&
|
||||
(booking->getCustomerId() == userID || booking->getAssignedTechnicianId() == userID))
|
||||
ServiceBooking* booking = bookings.getValueAt(iteratorOne);
|
||||
if (!booking)
|
||||
{
|
||||
if (booking->getStatus() == util::ServiceJobStatus::PENDING ||
|
||||
booking->getStatus() == util::ServiceJobStatus::STARTED)
|
||||
{
|
||||
if (type == util::UserType::CUSTOMER)
|
||||
{
|
||||
booking->setStatus(util::ServiceJobStatus::CANCELLED);
|
||||
booking->setCustomer(nullptr);
|
||||
booking->setCustomerId("");
|
||||
User* assignedTechnician = booking->getAssignedTechnician();
|
||||
std::string title = "Customer Service Cancelled";
|
||||
std::string message = "The customer has cancelled their service booking. Your assigned job card has been cancelled and the inventory has been restocked.";
|
||||
sendNotification(assignedTechnician, title, message);
|
||||
}
|
||||
else if (type == util::UserType::TECHNICIAN)
|
||||
{
|
||||
booking->setStatus(util::ServiceJobStatus::PENDING);
|
||||
std::string title = "Technician Unavailable";
|
||||
std::string message = "Your assigned technician is no longer available. Your booking has been reset to pending, and we will reassign a new technician shortly.";
|
||||
sendNotification(booking->getCustomer(), title, message);
|
||||
}
|
||||
booking->setAssignedTechnician(nullptr);
|
||||
booking->setAssignedTechnicianId("");
|
||||
const auto& ListOfServices = booking->getServices();
|
||||
for (int serviceIterator = 0; serviceIterator < ListOfServices.getSize(); serviceIterator++)
|
||||
{
|
||||
Service* service = ListOfServices.getValueAt(serviceIterator);
|
||||
if (service != nullptr)
|
||||
{
|
||||
const auto& items = service->getRequiredInventoryItems();
|
||||
for (int itemIterator = 0; itemIterator < items.getSize(); itemIterator++)
|
||||
{
|
||||
InventoryItem* item = items.getValueAt(itemIterator);
|
||||
if (item != nullptr)
|
||||
{
|
||||
item->setQuantity(item->getQuantity() + INCREMENT_VALUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (booking->getCustomerId() != customerID)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (booking->getStatus() != util::ServiceJobStatus::PENDING && booking->getStatus() != util::ServiceJobStatus::STARTED)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
User* assignedTechnician = booking->getAssignedTechnician();
|
||||
std::string titleToTechnician = "Customer Service Cancelled";
|
||||
std::string messageToTechnician = "The customer has cancelled their service booking. Your assigned job card has been cancelled and the inventory has been restocked.";
|
||||
std::string jobTitle = "Job Cancelled";
|
||||
std::string jobMessage = "The job has been cancelled. Your job card has been cancelled and the inventory has been restocked.";
|
||||
processBookingCancellation(booking,
|
||||
util::ServiceJobStatus::CANCELLED,
|
||||
titleToTechnician, messageToTechnician, assignedTechnician,
|
||||
util::ServiceJobStatus::CANCELLED,
|
||||
jobTitle, jobMessage, jobs, *this
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -591,34 +651,48 @@ Return type: void
|
||||
*/
|
||||
void ServiceManagementService::cancelTechnicianJobs(const std::string& technicianID)
|
||||
{
|
||||
const int INCREMENT_VALUE = 1;
|
||||
auto& jobs = m_dataStore.getJobCards();
|
||||
for (int jobIterator = 0; jobIterator < jobs.getSize(); jobIterator++)
|
||||
auto& users = m_dataStore.getUsers();
|
||||
int userIndex = users.find(technicianID);
|
||||
if (userIndex == -1)
|
||||
{
|
||||
JobCard* job = jobs.getValueAt(jobIterator);
|
||||
if (job != nullptr && job->getTechnicianId() == technicianID)
|
||||
throw std::runtime_error("User not found: " + technicianID);
|
||||
}
|
||||
User* technician = users.getValueAt(userIndex);
|
||||
if (!technician)
|
||||
{
|
||||
throw std::runtime_error("User not found: " + technicianID);
|
||||
}
|
||||
auto& bookings = m_dataStore.getServiceBookings();
|
||||
auto& jobs = m_dataStore.getJobCards();
|
||||
for (int iteratorOne = 0; iteratorOne < bookings.getSize(); iteratorOne++)
|
||||
{
|
||||
ServiceBooking* booking = bookings.getValueAt(iteratorOne);
|
||||
if (!booking)
|
||||
{
|
||||
if (job->getStatus() == util::ServiceJobStatus::PENDING || job->getStatus() == util::ServiceJobStatus::STARTED)
|
||||
{
|
||||
job->setStatus(util::ServiceJobStatus::CANCELLED);
|
||||
std::string title = "Job Cancelled";
|
||||
std::string message = "The Job has cancelled. Your job card has been cancelled and the inventory has been restocked.";
|
||||
sendNotification(job->getTechnician(), title, message);
|
||||
Service* service = job->getService();
|
||||
if (service != nullptr)
|
||||
{
|
||||
const auto& items = service->getRequiredInventoryItems();
|
||||
for (int itemIterator = 0; itemIterator < items.getSize(); itemIterator++)
|
||||
{
|
||||
InventoryItem* item = items.getValueAt(itemIterator);
|
||||
if (item != nullptr)
|
||||
{
|
||||
item->setQuantity(item->getQuantity() + INCREMENT_VALUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
std::string technicianId = booking->getAssignedTechnicianId();
|
||||
if (technicianId != technicianID)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (booking->getStatus() != util::ServiceJobStatus::PENDING && booking->getStatus() != util::ServiceJobStatus::STARTED)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
User* customer = booking->getCustomer();
|
||||
if (!customer)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
std::string title = "Technician Unavailable";
|
||||
std::string message = "Your assigned technician is no longer available. Your booking has been reset to pending, and we will reassign a new technician shortly.";
|
||||
processBookingCancellation(booking,
|
||||
util::ServiceJobStatus::PENDING,
|
||||
title, message, customer,
|
||||
util::ServiceJobStatus::CANCELLED,
|
||||
title, message, jobs, *this
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -833,6 +907,9 @@ void ServiceManagementService::createJobCard(const std::string& bookingID, const
|
||||
{
|
||||
throw std::runtime_error("Failed to create job card.");
|
||||
}
|
||||
title = "Technician assigned";
|
||||
message = "A technician has been assigned to your Service Booking with ID " + bookingID;
|
||||
sendNotification(currentBooking->getCustomer(), title, message);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1055,11 +1132,11 @@ void ServiceManagementService::completeJob(const std::string& jobID)
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("Failed to complete the job, some error occured or job already completed.");
|
||||
throw std::runtime_error("Failed to complete the job, some error occurred or job already completed.");
|
||||
}
|
||||
if (!jobStatusUpdated)
|
||||
{
|
||||
throw std::runtime_error("Failed to complete the job, some error occured or job already completed.");
|
||||
throw std::runtime_error("Failed to complete the job, some error occurred or job already completed.");
|
||||
}
|
||||
|
||||
serviceBookingCompleted = hasCompletedAllJobs(currentJob->getBookingId(), currentAssignedJobs);
|
||||
@@ -1067,8 +1144,8 @@ void ServiceManagementService::completeJob(const std::string& jobID)
|
||||
{
|
||||
currentJob->getBooking()->setStatus(util::ServiceJobStatus::COMPLETED);
|
||||
paymentManagementService.generateInvoice(currentJob->getBooking());
|
||||
std::string title = "Service Booking completed,Invoice Generated.\n";
|
||||
std::string message = "Services completed for the booking and invoice generated.\n";
|
||||
std::string title = "Service Booking completed,Invoice Generated.";
|
||||
std::string message = "Services completed for the booking and invoice generated.";
|
||||
sendNotification(currentJob->getBooking()->getCustomer(), title, message);
|
||||
}
|
||||
}
|
||||
+8
@@ -306,6 +306,14 @@ void UserManagementService::removeUser(const std::string& userID)
|
||||
User* user = m_dataStore.getUsers().getValueAt(index);
|
||||
if (user != nullptr)
|
||||
{
|
||||
if (user->getUserType() == util::UserType::CUSTOMER)
|
||||
{
|
||||
serviceManagementService.cancelCustomerServiceBookings(userID);
|
||||
}
|
||||
if (user->getUserType() == util::UserType::TECHNICIAN)
|
||||
{
|
||||
serviceManagementService.cancelTechnicianJobs(userID);
|
||||
}
|
||||
user->setState(util::State::INACTIVE);
|
||||
inventoryManagementService.detach(user);
|
||||
paymentManagementService.detach(user);
|
||||
|
||||
@@ -263,6 +263,7 @@ Return type: void
|
||||
void AdminMenu::removeInventoryItem()
|
||||
{
|
||||
util::clear();
|
||||
std::cout << "Remove Inventory Item\n";
|
||||
auto inventoryItems = m_controller.getInventoryItems();
|
||||
auto activeItems = filterActiveItems(inventoryItems);
|
||||
int activeItemsSize = activeItems.getSize();
|
||||
@@ -402,6 +403,11 @@ void AdminMenu::createService()
|
||||
util::Map<std::string, const InventoryItem*> activeInventoryItems = filterActiveItems(currentInventoryItems);
|
||||
util::Vector<std::string> selectedInventoryItems;
|
||||
selectInventoryItems(activeInventoryItems,selectedInventoryItems);
|
||||
if (selectedInventoryItems.isEmpty())
|
||||
{
|
||||
util::pressEnter();
|
||||
return;
|
||||
}
|
||||
std::cout << "\nEnter the labour cost: ";
|
||||
util::read(labourCost);
|
||||
m_controller.createService(serviceName, selectedInventoryItems, labourCost);
|
||||
@@ -541,7 +547,7 @@ void AdminMenu::createComboPackages()
|
||||
while (true)
|
||||
{
|
||||
chosenService = selectServiceFromServices(activeServices);
|
||||
if (chosenService == nullptr)
|
||||
if (!chosenService)
|
||||
{
|
||||
std::cout << "Failed to create combo package!\n\n";
|
||||
util::pressEnter();
|
||||
|
||||
@@ -220,20 +220,24 @@ void CustomerMenu::selectComboPackage()
|
||||
util::clear();
|
||||
std::cout << "Select a Combo Package\n";
|
||||
auto comboPackages = m_controller.getComboPackages();
|
||||
if (comboPackages.isEmpty())
|
||||
util::Map<std::string, const ComboPackage*> activeComboPackages = filterComboPackages(comboPackages);
|
||||
if (activeComboPackages.isEmpty())
|
||||
{
|
||||
std::cout << "No combo packages available!";
|
||||
std::cout << "No combo packages available!\n\n";
|
||||
util::pressEnter();
|
||||
return;
|
||||
}
|
||||
const ComboPackage* selectedComboPackage = selectComboPackageFromPackages(comboPackages);
|
||||
const ComboPackage* selectedComboPackage = selectComboPackageFromPackages(activeComboPackages);
|
||||
if (selectedComboPackage == nullptr)
|
||||
{
|
||||
std::cout << "Failed to book combo package!";
|
||||
std::cout << "Failed to book combo package!\n\n";
|
||||
util::pressEnter();
|
||||
return;
|
||||
}
|
||||
std::cout << "Combo Package selected\n";
|
||||
util::pressEnter();
|
||||
util::clear();
|
||||
std::cout << "Enter the vehicle details\n";
|
||||
std::cout << "Enter vehicle number: ";
|
||||
util::read(vehicleNumber);
|
||||
std::cout << "Enter vehicle brand: ";
|
||||
@@ -241,7 +245,7 @@ void CustomerMenu::selectComboPackage()
|
||||
std::cout << "Enter vehicle model: ";
|
||||
util::read(vehicleModel);
|
||||
m_controller.purchaseComboPackage(selectedComboPackage->getId(), vehicleNumber, vehicleBrand, vehicleModel);
|
||||
std::cout << "Combo Package has been booked successfully";
|
||||
std::cout << "Combo Package has been booked successfully\n\n";
|
||||
util::pressEnter();
|
||||
}
|
||||
|
||||
|
||||
@@ -94,13 +94,15 @@ inline void selectInventoryItems(util::Map<std::string, const InventoryItem*>& c
|
||||
bool doRun = true;
|
||||
util::Map<int, const InventoryItem*> currentInventoryMap;
|
||||
int choice;
|
||||
if (currentInventoryItems.getSize() == 0)
|
||||
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;
|
||||
@@ -119,6 +121,19 @@ inline void selectInventoryItems(util::Map<std::string, const InventoryItem*>& c
|
||||
{
|
||||
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()
|
||||
@@ -133,10 +148,9 @@ inline void selectInventoryItems(util::Map<std::string, const InventoryItem*>& c
|
||||
{
|
||||
break;
|
||||
}
|
||||
std::cout << "Select the item (Index) or enter -1 to exit: ";
|
||||
std::cout << "Select the item (Index) or enter 0 to exit: ";
|
||||
util::read(choice);
|
||||
|
||||
if (choice == -1)
|
||||
if (choice == 0)
|
||||
{
|
||||
doRun = false;
|
||||
}
|
||||
@@ -144,6 +158,7 @@ inline void selectInventoryItems(util::Map<std::string, const InventoryItem*>& c
|
||||
{
|
||||
selectedInventoryItems.push_back(currentInventoryMap.getValueAt(currentInventoryMap.find(choice))->getId());
|
||||
std::cout << "Item added successfully.\n" << std::endl;
|
||||
util::pressEnter();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -160,7 +175,7 @@ Parameters:
|
||||
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)
|
||||
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++)
|
||||
@@ -201,8 +216,6 @@ inline bool listServiceBookings(util::Map<std::string, const ServiceBooking*>& c
|
||||
<< 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++)
|
||||
{
|
||||
@@ -219,8 +232,6 @@ inline bool listServiceBookings(util::Map<std::string, const ServiceBooking*>& c
|
||||
<< 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);
|
||||
}
|
||||
@@ -239,7 +250,7 @@ Returns:
|
||||
inline const ServiceBooking* selectPendingServiceBookings(util::Map<int, const ServiceBooking*>& serviceBookingsMap)
|
||||
{
|
||||
int userInputIndex;
|
||||
std::cout << "\nEnter a valid service index: ";
|
||||
std::cout << "\nEnter a service index: ";
|
||||
util::read(userInputIndex);
|
||||
if (serviceBookingsMap.find(userInputIndex) != -1)
|
||||
{
|
||||
@@ -304,7 +315,7 @@ Returns:
|
||||
inline const User* selectTechnician(util::Map<int, const User*>& currentAvailableTechniciansMap)
|
||||
{
|
||||
int userInputIndex;
|
||||
std::cout << "\nEnter valid technician index: ";
|
||||
std::cout << "\nEnter technician index: ";
|
||||
util::read(userInputIndex);
|
||||
if (currentAvailableTechniciansMap.find(userInputIndex) != -1)
|
||||
{
|
||||
@@ -416,6 +427,73 @@ inline util::PaymentMode selectPaymentMode()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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(15) << "VehicleNumber"
|
||||
<< std::setw(20) << "TechnicianName"
|
||||
<< std::setw(15) << "TotalAmount"
|
||||
<< std::setw(25) << "InvoiceDate"
|
||||
<< std::setw(15) << "PaymentStatus"
|
||||
<< std::setw(15) << "PaymentMode"
|
||||
<< 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(15) << 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(15) << 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,
|
||||
@@ -429,34 +507,48 @@ Throws:
|
||||
*/
|
||||
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." << std::endl << std::endl;
|
||||
std::cout << "No invoices found for this account.\n\n";
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int index = 0; index < currentUserInvoices.getSize(); index++)
|
||||
bool doRun = true;
|
||||
do
|
||||
{
|
||||
const Invoice* currentInvoice = currentUserInvoices.getValueAt(index);
|
||||
if (currentInvoice)
|
||||
const Invoice* selectedInvoice;
|
||||
int choice;
|
||||
selectedInvoice = selectInvoiceToDisplay(currentUserInvoices);
|
||||
if (selectedInvoice)
|
||||
{
|
||||
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();
|
||||
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";
|
||||
@@ -478,14 +570,53 @@ inline void displayInvoices(util::Map<std::string, const Invoice*> currentUserIn
|
||||
<< 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
|
||||
{
|
||||
throw std::runtime_error("Null invoice encountered while displaying invoices.");
|
||||
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)
|
||||
{
|
||||
startedJobCards.insert(currentJobCard->getId(), currentJobCard);
|
||||
}
|
||||
}
|
||||
util::pressEnter();
|
||||
return startedJobCards;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -497,49 +628,50 @@ Parameters:
|
||||
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)
|
||||
inline std::string selectJobCardToComplete(util::Map<std::string, const JobCard*>& assignedJobCards)
|
||||
{
|
||||
util::Map<int, const JobCard* > incompleteJobCards;
|
||||
if (assignedJobCards.getSize() == 0)
|
||||
{
|
||||
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++)
|
||||
std::cout << "No started jobs available to complete.\n";
|
||||
return "";
|
||||
}
|
||||
int currentIndex = 1;
|
||||
int choice;
|
||||
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::endl;
|
||||
for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++)
|
||||
{
|
||||
const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator);
|
||||
if (currentJobCard && (currentJobCard->getStatus() == util::ServiceJobStatus::STARTED))
|
||||
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);
|
||||
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;
|
||||
incompleteJobCards.insert(currentIndex++, currentJobCard);
|
||||
}
|
||||
}
|
||||
if (!hasIncompleteJobCard)
|
||||
{
|
||||
std::cout << "No pending jobs are present.\n";
|
||||
return "";
|
||||
}
|
||||
std::cout << "Select the Job Card to complete (Index): ";
|
||||
std::cout << "Select the Job Card to complete (Index): ";
|
||||
util::read(choice);
|
||||
int selectedJobCardIndex = incompleteJobCards.find(choice);
|
||||
if (selectedJobCardIndex != -1)
|
||||
int selectedJobCardIndex = incompleteJobCards.find(choice);
|
||||
if (selectedJobCardIndex != -1)
|
||||
{
|
||||
const JobCard* selectedJobCard = incompleteJobCards.getValueAt(selectedJobCardIndex);
|
||||
return selectedJobCard->getId();
|
||||
const JobCard* selectedJobCard = incompleteJobCards.getValueAt(selectedJobCardIndex);
|
||||
return selectedJobCard->getId();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Invalid index.\n";
|
||||
std::cout << "Invalid index.\n";
|
||||
std::cout << "Failed to complete jobs.\n\n";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -723,6 +855,7 @@ inline void displayAllActiveUsers(util::Map<std::string, const User*>& activeUse
|
||||
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++)
|
||||
@@ -733,6 +866,7 @@ inline void displayAllActiveUsers(util::Map<std::string, const User*>& activeUse
|
||||
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;
|
||||
}
|
||||
@@ -753,7 +887,7 @@ Parameters:
|
||||
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)
|
||||
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++)
|
||||
@@ -780,6 +914,7 @@ inline const Service* selectServiceFromServices(const util::Map<std::string, con
|
||||
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;
|
||||
@@ -826,6 +961,31 @@ inline const Service* selectServiceFromServices(const util::Map<std::string, con
|
||||
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: selectComboPackageFromPackages
|
||||
Description: Displays active combo packages and allows the customer to select one by index.
|
||||
@@ -837,10 +997,11 @@ inline const ComboPackage* selectComboPackageFromPackages(const util::Map<std::s
|
||||
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(15) << "Combo Name"
|
||||
<< std::setw(35) << "Combo Name"
|
||||
<< std::setw(15) << "Estimate Cost"
|
||||
<< std::endl;
|
||||
for (int index = 0; index < comboPackages.getSize(); index++)
|
||||
@@ -854,7 +1015,7 @@ inline const ComboPackage* selectComboPackageFromPackages(const util::Map<std::s
|
||||
std::cout << std::left
|
||||
<< std::setw(10) << currentIndex
|
||||
<< std::setw(15) << currentComboPackage->getId()
|
||||
<< std::setw(25) << currentComboPackage->getPackageName()
|
||||
<< std::setw(35) << util::truncateString(currentComboPackage->getPackageName(), 30)
|
||||
<< std::setw(15) << util::calculateComboServiceEstimatedCost(currentComboPackage)
|
||||
<< std::endl;
|
||||
currentIndex++;
|
||||
@@ -922,7 +1083,7 @@ inline util::Map<std::string, const InventoryItem*> filterActiveItems(const util
|
||||
for (int index = 0; index < inventorySize; index++)
|
||||
{
|
||||
const InventoryItem* item = inventoryItems.getValueAt(index);
|
||||
if (item != nullptr && item->getState() != util::State::INACTIVE)
|
||||
if (item && item->getState() != util::State::INACTIVE)
|
||||
{
|
||||
activeItems.insert(item->getId(), item);
|
||||
}
|
||||
|
||||
@@ -93,18 +93,15 @@ Returns:
|
||||
*/
|
||||
void TechnicianMenu::completeJob()
|
||||
{
|
||||
util::clear();
|
||||
std::cout << "Complete Job\n";
|
||||
util::Map<std::string, const JobCard*> assignedJobCards = m_controller.getJobCardsByUser();
|
||||
util::Map<int, const JobCard*> incompleteJobCards;
|
||||
std::cout << "Jobs to be completed.\n";
|
||||
std::string selectedJobID = selectJobCardToComplete(assignedJobCards, incompleteJobCards);
|
||||
if (selectedJobID == "")
|
||||
{
|
||||
std::cout << "Failed to complete the job.\n";
|
||||
}
|
||||
else
|
||||
util::Map<std::string, const JobCard*> startedJobCards = filterStartedJobCards(assignedJobCards);
|
||||
std::string selectedJobID = selectJobCardToComplete(startedJobCards);
|
||||
if (!selectedJobID.empty())
|
||||
{
|
||||
m_controller.completeJob(selectedJobID);
|
||||
std::cout << "Job marked as completed.\n";
|
||||
std::cout << "\nJob marked as completed.\n\n";
|
||||
}
|
||||
util::pressEnter();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user