Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| febfa45e4a | |||
| 33cbb1dac3 | |||
| 80b91f3f1b | |||
| a87af89a8a | |||
| f1ca8c2a58 | |||
| d55bbb6349 | |||
| ae488f5670 | |||
| d8f7e46180 | |||
| 3d7944f77d | |||
| 9439202c5a | |||
| e6faa63b88 | |||
| 31e660bc9e | |||
| 5fd0a47459 | |||
| fb509ccb3f | |||
| 8d07b11eae | |||
| 1e11903cca | |||
| 089fe496b2 |
+2
-2
@@ -80,7 +80,7 @@ void InventoryManagementService::sendLowStockAlerts()
|
|||||||
{
|
{
|
||||||
throw std::runtime_error("The system has no admins present!");
|
throw std::runtime_error("The system has no admins present!");
|
||||||
}
|
}
|
||||||
for (int index = 0; index <= inventoryItemsSize; index++)
|
for (int index = 0; index < inventoryItemsSize; index++)
|
||||||
{
|
{
|
||||||
InventoryItem* inventoryItem = inventoryItems.getValueAt(index);
|
InventoryItem* inventoryItem = inventoryItems.getValueAt(index);
|
||||||
if (inventoryItem && inventoryItem->getQuantity() < config::threshold::INVENTORY_LOW_STOCK_THRESHOLD)
|
if (inventoryItem && inventoryItem->getQuantity() < config::threshold::INVENTORY_LOW_STOCK_THRESHOLD)
|
||||||
@@ -323,7 +323,7 @@ void InventoryManagementService::sendNotification(User* user, const std::string&
|
|||||||
Factory::getObject<Notification>(
|
Factory::getObject<Notification>(
|
||||||
user->getId(),
|
user->getId(),
|
||||||
user,
|
user,
|
||||||
"InventoryManagementService: " + title,
|
title,
|
||||||
message,
|
message,
|
||||||
util::Timestamp()
|
util::Timestamp()
|
||||||
);
|
);
|
||||||
|
|||||||
+1
-1
@@ -86,7 +86,7 @@ void PaymentManagementService::sendNotification(User* user, const std::string& t
|
|||||||
Factory::getObject<Notification>(
|
Factory::getObject<Notification>(
|
||||||
user->getId(),
|
user->getId(),
|
||||||
user,
|
user,
|
||||||
"PaymentManagementService: " + title,
|
title,
|
||||||
message,
|
message,
|
||||||
util::Timestamp()
|
util::Timestamp()
|
||||||
);
|
);
|
||||||
|
|||||||
+2
-2
@@ -61,7 +61,7 @@ void ServiceManagementService::purchaseService(const util::Vector<std::string>&
|
|||||||
Service* service = servicesMap.getValueAt(serviceIndex);
|
Service* service = servicesMap.getValueAt(serviceIndex);
|
||||||
selectedServices[service->getId()] = service;
|
selectedServices[service->getId()] = service;
|
||||||
}
|
}
|
||||||
ServiceBooking* serviceBooking = Factory::getObject<ServiceBooking>(util::ServiceJobStatus::STARTED, selectedServices, authenticatedUser->getId(), authenticatedUser, vehicleNumber, vehicleBrand, vehicleModel, 0);
|
ServiceBooking* serviceBooking = Factory::getObject<ServiceBooking>(util::ServiceJobStatus::PENDING, selectedServices, authenticatedUser->getId(), authenticatedUser, vehicleNumber, vehicleBrand, vehicleModel, 0);
|
||||||
if (serviceBooking == nullptr)
|
if (serviceBooking == nullptr)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Failed to create service booking");
|
throw std::runtime_error("Failed to create service booking");
|
||||||
@@ -175,7 +175,7 @@ void ServiceManagementService::sendNotification(User* user, const std::string& t
|
|||||||
Factory::getObject<Notification>(
|
Factory::getObject<Notification>(
|
||||||
user->getId(),
|
user->getId(),
|
||||||
user,
|
user,
|
||||||
"ServiceManagementService: " + title,
|
title,
|
||||||
message,
|
message,
|
||||||
util::Timestamp()
|
util::Timestamp()
|
||||||
);
|
);
|
||||||
|
|||||||
+25
-9
@@ -19,7 +19,7 @@ Date:19-May-2026
|
|||||||
#include "User.h"
|
#include "User.h"
|
||||||
#include "UserManagementService.h"
|
#include "UserManagementService.h"
|
||||||
#include "Vector.h"
|
#include "Vector.h"
|
||||||
|
#include "Validator.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: ensureAdminExists
|
Function: ensureAdminExists
|
||||||
@@ -74,16 +74,18 @@ void UserManagementService::createUser(const std::string& username, const std::s
|
|||||||
PaymentManagementService paymentManagementService;
|
PaymentManagementService paymentManagementService;
|
||||||
ServiceManagementService serviceManagementService;
|
ServiceManagementService serviceManagementService;
|
||||||
auto& usersMap = m_dataStore.getUsers();
|
auto& usersMap = m_dataStore.getUsers();
|
||||||
int index = usersMap.findIf(
|
if (util::isUsernameDuplicate(username, usersMap))
|
||||||
[&](const std::string&, User* user)
|
|
||||||
{
|
|
||||||
return user->getUserName() == username;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (index != -1)
|
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Username already exists");
|
throw std::runtime_error("Username already exists");
|
||||||
}
|
}
|
||||||
|
if (util::isEmailDuplicate(email, usersMap))
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Email already exists");
|
||||||
|
}
|
||||||
|
if (util::isPhoneDuplicate(phone, usersMap))
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Phone already exists");
|
||||||
|
}
|
||||||
User* newUser = Factory::getObject<User>(username, password, name, phone, email, type);
|
User* newUser = Factory::getObject<User>(username, password, name, phone, email, type);
|
||||||
usersMap.insert(newUser->getId(), newUser);
|
usersMap.insert(newUser->getId(), newUser);
|
||||||
paymentManagementService.attach(newUser);
|
paymentManagementService.attach(newUser);
|
||||||
@@ -109,9 +111,23 @@ void UserManagementService::updateUserDetails(const std::string& userID, const s
|
|||||||
int index = usersMap.find(userID);
|
int index = usersMap.find(userID);
|
||||||
if (index == -1)
|
if (index == -1)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("User does not exist!");
|
throw std::runtime_error("User does not exist!\n");
|
||||||
}
|
}
|
||||||
User* user = usersMap.getValueAt(index);
|
User* user = usersMap.getValueAt(index);
|
||||||
|
if (email != user->getEmail())
|
||||||
|
{
|
||||||
|
if (util::isEmailDuplicate(email, usersMap))
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Email already exists!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (phone != user->getPhone())
|
||||||
|
{
|
||||||
|
if (util::isPhoneDuplicate(phone, usersMap))
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Phone number already exists!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
user->setEmail(email);
|
user->setEmail(email);
|
||||||
user->setPhone(phone);
|
user->setPhone(phone);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ namespace util
|
|||||||
*/
|
*/
|
||||||
inline void pressEnter()
|
inline void pressEnter()
|
||||||
{
|
{
|
||||||
|
std::cout << std::endl;
|
||||||
system("pause");
|
system("pause");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,4 +106,70 @@ bool util::isPasswordValid(const std::string& password)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return hasUpper && hasLower && hasDigit && hasSpecial;
|
return hasUpper && hasLower && hasDigit && hasSpecial;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function: isUsernameDuplicate
|
||||||
|
* Description: Checks if the given username already exists among active users.
|
||||||
|
* Parameters:
|
||||||
|
* username - string containing the username to validate
|
||||||
|
* usersMap - map of user objects keyed by identifier
|
||||||
|
* Returns:
|
||||||
|
* bool - true if the username is already in use by an active user, false otherwise
|
||||||
|
* Notes:
|
||||||
|
* - Only considers users with state util::State::ACTIVE
|
||||||
|
*/
|
||||||
|
bool util::isUsernameDuplicate(const std::string& username, const util::Map<std::string, User*>& usersMap)
|
||||||
|
{
|
||||||
|
int index = usersMap.findIf(
|
||||||
|
[&](const std::string&, User* user)
|
||||||
|
{
|
||||||
|
return (user->getUserName() == username && user->getState() == util::State::ACTIVE);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return index != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function: isPhoneDuplicate
|
||||||
|
* Description: Checks if the given phone number already exists among active users.
|
||||||
|
* Parameters:
|
||||||
|
* phone - string containing the phone number to validate
|
||||||
|
* usersMap - map of user objects keyed by identifier
|
||||||
|
* Returns:
|
||||||
|
* bool - true if the phone number is already in use by an active user, false otherwise
|
||||||
|
* Notes:
|
||||||
|
* - Only considers users with state util::State::ACTIVE
|
||||||
|
*/
|
||||||
|
bool util::isPhoneDuplicate(const std::string& phone, const util::Map<std::string, User*>& usersMap)
|
||||||
|
{
|
||||||
|
int index = usersMap.findIf(
|
||||||
|
[&](const std::string&, User* user)
|
||||||
|
{
|
||||||
|
return (user->getPhone() == phone && user->getState() == util::State::ACTIVE);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return index != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function: isEmailDuplicate
|
||||||
|
* Description: Checks if the given email address already exists among active users.
|
||||||
|
* Parameters:
|
||||||
|
* email - string containing the email address to validate
|
||||||
|
* usersMap - map of user objects keyed by identifier
|
||||||
|
* Returns:
|
||||||
|
* bool - true if the email address is already in use by an active user, false otherwise
|
||||||
|
* Notes:
|
||||||
|
* - Only considers users with state util::State::ACTIVE
|
||||||
|
*/
|
||||||
|
bool util::isEmailDuplicate(const std::string& email, const util::Map<std::string, User*>& usersMap)
|
||||||
|
{
|
||||||
|
int index = usersMap.findIf(
|
||||||
|
[&](const std::string&, User* user)
|
||||||
|
{
|
||||||
|
return (user->getEmail() == email && user->getState() == util::State::ACTIVE);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return index != -1;
|
||||||
}
|
}
|
||||||
@@ -9,10 +9,15 @@
|
|||||||
#include<string>
|
#include<string>
|
||||||
#include<algorithm>
|
#include<algorithm>
|
||||||
#include<cctype>
|
#include<cctype>
|
||||||
|
#include "Map.h"
|
||||||
|
#include "User.h"
|
||||||
|
|
||||||
namespace util
|
namespace util
|
||||||
{
|
{
|
||||||
bool isPhoneNumberValid(const std::string&);
|
bool isPhoneNumberValid(const std::string&);
|
||||||
bool isEmailValid(const std::string&);
|
bool isEmailValid(const std::string&);
|
||||||
bool isPasswordValid(const std::string&);
|
bool isPasswordValid(const std::string&);
|
||||||
|
bool isUsernameDuplicate(const std::string&, const util::Map<std::string, User*>&);
|
||||||
|
bool isPhoneDuplicate(const std::string&, const util::Map<std::string, User*>&);
|
||||||
|
bool isEmailDuplicate(const std::string&, const util::Map<std::string, User*>&);
|
||||||
}
|
}
|
||||||
@@ -158,10 +158,33 @@ void AdminMenu::viewStockLevels()
|
|||||||
{
|
{
|
||||||
util::clear();
|
util::clear();
|
||||||
auto inventoryItems = m_controller.getInventoryItems();
|
auto inventoryItems = m_controller.getInventoryItems();
|
||||||
|
bool hasActiveItems = false;
|
||||||
|
std::cout << "View Stock Levels" << std::endl;
|
||||||
|
if (inventoryItems.isEmpty())
|
||||||
|
{
|
||||||
|
std::cout << "No items found in Inventory.\n";
|
||||||
|
util::pressEnter();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int index = 0; index < inventoryItems.getSize(); index++)
|
||||||
|
{
|
||||||
|
const InventoryItem* item = inventoryItems.getValueAt(index);
|
||||||
|
if (item->getState() == util::State::ACTIVE)
|
||||||
|
{
|
||||||
|
hasActiveItems = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasActiveItems)
|
||||||
|
{
|
||||||
|
std::cout << "No active Inventory Item found.\n";
|
||||||
|
util::pressEnter();
|
||||||
|
return;
|
||||||
|
}
|
||||||
std::cout << std::left << std::setw(15) << "Item ID"
|
std::cout << std::left << std::setw(15) << "Item ID"
|
||||||
<< std::setw(25) << "Part Name"
|
<< std::setw(25) << "Part Name"
|
||||||
<< std::setw(10) << "Quantity"
|
<< std::setw(15) << "Quantity"
|
||||||
<< std::setw(10) << "Price"
|
<< std::setw(15) << "Price"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
for (int iterator = 0; iterator < inventoryItems.getSize(); ++iterator)
|
for (int iterator = 0; iterator < inventoryItems.getSize(); ++iterator)
|
||||||
{
|
{
|
||||||
@@ -172,12 +195,14 @@ void AdminMenu::viewStockLevels()
|
|||||||
{
|
{
|
||||||
std::cout << std::left << std::setw(15) << item->getId()
|
std::cout << std::left << std::setw(15) << item->getId()
|
||||||
<< std::setw(25) << item->getPartName()
|
<< std::setw(25) << item->getPartName()
|
||||||
<< std::setw(10) << item->getQuantity()
|
<< std::setw(15) << item->getQuantity()
|
||||||
<< std::setw(10) << item->getPrice()
|
<< std::setw(15) << item->getPrice()
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::cout << "\n";
|
||||||
|
util::pressEnter();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -273,8 +298,10 @@ void AdminMenu::checkStockAvailability()
|
|||||||
{
|
{
|
||||||
util::clear();
|
util::clear();
|
||||||
std::string itemId;
|
std::string itemId;
|
||||||
std::cout << "Enter the Item Id : ";
|
std::cout << "Check Stock Availability \n";
|
||||||
|
std::cout << "Enter the Item ID : ";
|
||||||
util::read(itemId);
|
util::read(itemId);
|
||||||
|
util::clear();
|
||||||
const InventoryItem* selectedItem = m_controller.getInventoryItem(itemId);
|
const InventoryItem* selectedItem = m_controller.getInventoryItem(itemId);
|
||||||
if (selectedItem != nullptr)
|
if (selectedItem != nullptr)
|
||||||
{
|
{
|
||||||
@@ -287,6 +314,10 @@ void AdminMenu::checkStockAvailability()
|
|||||||
std::cout << "Quantity : " << selectedItem->getQuantity() << "\n";
|
std::cout << "Quantity : " << selectedItem->getQuantity() << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Item not Found" << std::endl;
|
||||||
|
}
|
||||||
util::pressEnter();
|
util::pressEnter();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -443,6 +474,7 @@ void AdminMenu::removeUser()
|
|||||||
auto listOfUsers = m_controller.getUsers();
|
auto listOfUsers = m_controller.getUsers();
|
||||||
auto listOfActiveUsers = filterActiveUsers(listOfUsers);
|
auto listOfActiveUsers = filterActiveUsers(listOfUsers);
|
||||||
int activeUserCount = listOfActiveUsers.getSize();
|
int activeUserCount = listOfActiveUsers.getSize();
|
||||||
|
std::cout << "Remove User \n";
|
||||||
if (activeUserCount < 1)
|
if (activeUserCount < 1)
|
||||||
{
|
{
|
||||||
std::cout << "No Active users." << std::endl;
|
std::cout << "No Active users." << std::endl;
|
||||||
|
|||||||
@@ -144,11 +144,12 @@ void CustomerMenu::updateDetails()
|
|||||||
{
|
{
|
||||||
std::string email, phone;
|
std::string email, phone;
|
||||||
util::clear();
|
util::clear();
|
||||||
|
std::cout << "Update Details\n";
|
||||||
std::cout << "Enter new email: ";
|
std::cout << "Enter new email: ";
|
||||||
util::read(email);
|
util::read(email);
|
||||||
if (!util::isEmailValid(email))
|
if (!util::isEmailValid(email))
|
||||||
{
|
{
|
||||||
std::cout << "Error: Email is invalid!";
|
std::cout << "Error: Email is invalid!\n";
|
||||||
util::pressEnter();
|
util::pressEnter();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -156,12 +157,12 @@ void CustomerMenu::updateDetails()
|
|||||||
util::read(phone);
|
util::read(phone);
|
||||||
if (!util::isPhoneNumberValid(phone))
|
if (!util::isPhoneNumberValid(phone))
|
||||||
{
|
{
|
||||||
std::cout << "Error: Phone number is invalid!";
|
std::cout << "Error: Phone number is invalid!\n";
|
||||||
util::pressEnter();
|
util::pressEnter();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_controller.updateUserDetails(email, phone);
|
m_controller.updateUserDetails(email, phone);
|
||||||
std::cout << "Profile details updated successfully";
|
std::cout << "Profile details updated successfully\n";
|
||||||
util::pressEnter();
|
util::pressEnter();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,9 +176,16 @@ Return type: void
|
|||||||
void CustomerMenu::selectService()
|
void CustomerMenu::selectService()
|
||||||
{
|
{
|
||||||
std::string vehicleNumber, vehicleBrand, vehicleModel;
|
std::string vehicleNumber, vehicleBrand, vehicleModel;
|
||||||
auto services = m_controller.getServices();
|
|
||||||
util::Vector<std::string> selectedServices;
|
|
||||||
util::clear();
|
util::clear();
|
||||||
|
std::cout << "Select a Service\n";
|
||||||
|
auto services = m_controller.getServices();
|
||||||
|
if (services.isEmpty())
|
||||||
|
{
|
||||||
|
std::cout << "No services available!";
|
||||||
|
util::pressEnter();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
util::Vector<std::string> selectedServices;
|
||||||
const Service* selectedService = selectServiceFromServices(services);
|
const Service* selectedService = selectServiceFromServices(services);
|
||||||
if (selectedService == nullptr)
|
if (selectedService == nullptr)
|
||||||
{
|
{
|
||||||
@@ -187,6 +195,7 @@ void CustomerMenu::selectService()
|
|||||||
}
|
}
|
||||||
selectedServices.push_back(selectedService->getId());
|
selectedServices.push_back(selectedService->getId());
|
||||||
util::clear();
|
util::clear();
|
||||||
|
std::cout << "Enter Vehicle Details\n";
|
||||||
std::cout << "Enter vehicle number: ";
|
std::cout << "Enter vehicle number: ";
|
||||||
util::read(vehicleNumber);
|
util::read(vehicleNumber);
|
||||||
std::cout << "Enter vehicle brand: ";
|
std::cout << "Enter vehicle brand: ";
|
||||||
@@ -208,8 +217,15 @@ Return type: void
|
|||||||
void CustomerMenu::selectComboPackage()
|
void CustomerMenu::selectComboPackage()
|
||||||
{
|
{
|
||||||
std::string vehicleNumber, vehicleBrand, vehicleModel;
|
std::string vehicleNumber, vehicleBrand, vehicleModel;
|
||||||
auto comboPackages = m_controller.getComboPackages();
|
|
||||||
util::clear();
|
util::clear();
|
||||||
|
std::cout << "Select a Combo Package\n";
|
||||||
|
auto comboPackages = m_controller.getComboPackages();
|
||||||
|
if (comboPackages.isEmpty())
|
||||||
|
{
|
||||||
|
std::cout << "No combo packages available!";
|
||||||
|
util::pressEnter();
|
||||||
|
return;
|
||||||
|
}
|
||||||
const ComboPackage* selectedComboPackage = selectComboPackageFromPackages(comboPackages);
|
const ComboPackage* selectedComboPackage = selectComboPackageFromPackages(comboPackages);
|
||||||
if (selectedComboPackage == nullptr)
|
if (selectedComboPackage == nullptr)
|
||||||
{
|
{
|
||||||
@@ -245,16 +261,17 @@ void CustomerMenu::viewServiceHistory()
|
|||||||
const User* currentUser = m_controller.getAuthenticatedUser();
|
const User* currentUser = m_controller.getAuthenticatedUser();
|
||||||
std::string currentUserID = currentUser->getId();
|
std::string currentUserID = currentUser->getId();
|
||||||
util::Map<std::string, const ServiceBooking*> serviceBookingsByCurrentUser = m_controller.getServiceBookingsByUser(currentUserID);
|
util::Map<std::string, const ServiceBooking*> serviceBookingsByCurrentUser = m_controller.getServiceBookingsByUser(currentUserID);
|
||||||
|
std::cout << "View Service History" << std::endl;
|
||||||
if (serviceBookingsByCurrentUser.getSize() != 0)
|
if (serviceBookingsByCurrentUser.getSize() != 0)
|
||||||
{
|
{
|
||||||
std::cout << std::left
|
std::cout << std::left
|
||||||
<< std::setw(12) << "Booking ID"
|
<< std::setw(15) << "Booking ID"
|
||||||
<< std::setw(20) << "Technician"
|
<< std::setw(20) << "Technician"
|
||||||
<< std::setw(15) << "Vehicle Brand"
|
<< std::setw(20) << "Vehicle Brand"
|
||||||
<< std::setw(15) << "Vehicle Number"
|
<< std::setw(20) << "Vehicle Number"
|
||||||
<< std::setw(15) << "Vehicle Model"
|
<< std::setw(20) << "Vehicle Model"
|
||||||
<< std::setw(10) << "Discount %"
|
<< std::setw(20) << "Discount %"
|
||||||
<< std::setw(12) << "Status"
|
<< std::setw(20) << "Status"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
for (int iterator = 0; iterator < serviceBookingsByCurrentUser.getSize(); iterator++)
|
for (int iterator = 0; iterator < serviceBookingsByCurrentUser.getSize(); iterator++)
|
||||||
{
|
{
|
||||||
@@ -263,13 +280,13 @@ void CustomerMenu::viewServiceHistory()
|
|||||||
? "Not Assigned"
|
? "Not Assigned"
|
||||||
: currentBooking->getAssignedTechnician()->getName();
|
: currentBooking->getAssignedTechnician()->getName();
|
||||||
std::cout << std::left
|
std::cout << std::left
|
||||||
<< std::setw(12) << currentBooking->getId()
|
<< std::setw(15) << currentBooking->getId()
|
||||||
<< std::setw(20) << technicianName
|
<< std::setw(20) << technicianName
|
||||||
<< std::setw(15) << currentBooking->getVehicleBrand()
|
<< std::setw(20) << currentBooking->getVehicleBrand()
|
||||||
<< std::setw(15) << currentBooking->getVehicleNumber()
|
<< std::setw(20) << currentBooking->getVehicleNumber()
|
||||||
<< std::setw(15) << currentBooking->getVehicleModel()
|
<< std::setw(20) << currentBooking->getVehicleModel()
|
||||||
<< std::setw(10) << currentBooking->getDiscountPercentage()
|
<< std::setw(20) << currentBooking->getDiscountPercentage()
|
||||||
<< std::setw(12) << util::getServiceJobStatusString(currentBooking->getStatus())
|
<< std::setw(20) << util::getServiceJobStatusString(currentBooking->getStatus())
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
hasServiceHistory = true;
|
hasServiceHistory = true;
|
||||||
}
|
}
|
||||||
@@ -293,11 +310,35 @@ Returns:
|
|||||||
void CustomerMenu::completePayments()
|
void CustomerMenu::completePayments()
|
||||||
{
|
{
|
||||||
util::clear();
|
util::clear();
|
||||||
|
std::cout << "Complete Payments\n";
|
||||||
util::Map<std::string, const Invoice*> currentInvoices = m_controller.getInvoicesByUser();
|
util::Map<std::string, const Invoice*> currentInvoices = m_controller.getInvoicesByUser();
|
||||||
|
if (currentInvoices.isEmpty())
|
||||||
|
{
|
||||||
|
std::cout << "No pending invoices available for payment.\n";
|
||||||
|
util::pressEnter();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bool hasPending = false;
|
||||||
|
for (int index = 0; index < currentInvoices.getSize(); ++index)
|
||||||
|
{
|
||||||
|
const Invoice* invoice = currentInvoices.getValueAt(index);
|
||||||
|
if (invoice && invoice->getStatus() == util::PaymentStatus::PENDING)
|
||||||
|
{
|
||||||
|
hasPending = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasPending)
|
||||||
|
{
|
||||||
|
std::cout << "No pending invoices available for payment.\n";
|
||||||
|
util::pressEnter();
|
||||||
|
return;
|
||||||
|
}
|
||||||
std::string selectedID = selectInvoiceFromUserForPayment(currentInvoices);
|
std::string selectedID = selectInvoiceFromUserForPayment(currentInvoices);
|
||||||
if (selectedID == "")
|
if (selectedID == "")
|
||||||
{
|
{
|
||||||
std::cout << "Payment failed.\n";
|
std::cout << "Payment failed.\n";
|
||||||
|
util::pressEnter();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
util::PaymentMode paymentMode = selectPaymentMode();
|
util::PaymentMode paymentMode = selectPaymentMode();
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ inline std::string selectServicesToRemove(util::Map<std::string, const Service*>
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cout << "Invalid choice." << std::endl;
|
std::cout << "Invalid index." << std::endl;
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,7 +91,7 @@ Parameters:
|
|||||||
Returns:
|
Returns:
|
||||||
- void
|
- void
|
||||||
*/
|
*/
|
||||||
static void selectInventoryItems(util::Map<std::string, const InventoryItem*>& currentInventoryItems, util::Vector<std::string>& selectedInventoryItems)
|
inline void selectInventoryItems(util::Map<std::string, const InventoryItem*>& currentInventoryItems, util::Vector<std::string>& selectedInventoryItems)
|
||||||
{
|
{
|
||||||
bool doRun = true, hasInventoryItems = false;
|
bool doRun = true, hasInventoryItems = false;
|
||||||
util::Map<int, const InventoryItem*> currentInventoryMap;
|
util::Map<int, const InventoryItem*> currentInventoryMap;
|
||||||
@@ -166,7 +166,7 @@ Parameters:
|
|||||||
Returns:
|
Returns:
|
||||||
- bool: True if pending services exist, False otherwise
|
- bool: True if pending services exist, False otherwise
|
||||||
*/
|
*/
|
||||||
static bool listServiceBookings(util::Map<std::string, const ServiceBooking*>& currentBookings, int& bookingsSize, util::Map<int, const ServiceBooking*>& serviceBookingsMap)
|
inline bool listServiceBookings(util::Map<std::string, const ServiceBooking*>& currentBookings, int& bookingsSize, util::Map<int, const ServiceBooking*>& serviceBookingsMap)
|
||||||
{
|
{
|
||||||
int currentIndex = 1;
|
int currentIndex = 1;
|
||||||
bool hasPendingService = false;
|
bool hasPendingService = false;
|
||||||
@@ -220,7 +220,7 @@ Parameters:
|
|||||||
Returns:
|
Returns:
|
||||||
- const ServiceBooking*: Pointer to the selected booking, or nullptr if invalid
|
- const ServiceBooking*: Pointer to the selected booking, or nullptr if invalid
|
||||||
*/
|
*/
|
||||||
static const ServiceBooking* selectPendingServiceBookings(util::Map<int, const ServiceBooking*>& serviceBookingsMap)
|
inline const ServiceBooking* selectPendingServiceBookings(util::Map<int, const ServiceBooking*>& serviceBookingsMap)
|
||||||
{
|
{
|
||||||
int userInputIndex;
|
int userInputIndex;
|
||||||
std::cout << "Enter a valid service index: ";
|
std::cout << "Enter a valid service index: ";
|
||||||
@@ -246,7 +246,7 @@ Parameters:
|
|||||||
Returns:
|
Returns:
|
||||||
- void
|
- void
|
||||||
*/
|
*/
|
||||||
static void listAvailableTechnicians(util::Map<std::string, const User*> currentAvailableTechnicians, int numberOfTechnicians, util::Map<int, const User*>& currentAvailableTechniciansMap)
|
inline void listAvailableTechnicians(util::Map<std::string, const User*> currentAvailableTechnicians, int numberOfTechnicians, util::Map<int, const User*>& currentAvailableTechniciansMap)
|
||||||
{
|
{
|
||||||
bool hasTechnicians = false;
|
bool hasTechnicians = false;
|
||||||
int currentIndex = 1;
|
int currentIndex = 1;
|
||||||
@@ -284,7 +284,7 @@ Parameters:
|
|||||||
Returns:
|
Returns:
|
||||||
- const User*: Pointer to the selected technician, or nullptr if invalid
|
- const User*: Pointer to the selected technician, or nullptr if invalid
|
||||||
*/
|
*/
|
||||||
static const User* selectTechnician(util::Map<int, const User*>& currentAvailableTechniciansMap)
|
inline const User* selectTechnician(util::Map<int, const User*>& currentAvailableTechniciansMap)
|
||||||
{
|
{
|
||||||
int userInputIndex;
|
int userInputIndex;
|
||||||
util::read(userInputIndex);
|
util::read(userInputIndex);
|
||||||
@@ -307,8 +307,9 @@ Parameters:
|
|||||||
Returns:
|
Returns:
|
||||||
- std::string: ID of the selected invoice, or empty string if none selected
|
- std::string: ID of the selected invoice, or empty string if none selected
|
||||||
*/
|
*/
|
||||||
static std::string selectInvoiceFromUserForPayment(const util::Map<std::string, const Invoice*>& currentInvoices)
|
inline std::string selectInvoiceFromUserForPayment(const util::Map<std::string, const Invoice*>& currentInvoices)
|
||||||
{
|
{
|
||||||
|
util::clear();
|
||||||
int currentIndex = 1, choice;
|
int currentIndex = 1, choice;
|
||||||
util::Map<int, const Invoice*> pendingInvoicesForPayment;
|
util::Map<int, const Invoice*> pendingInvoicesForPayment;
|
||||||
std::cout << std::left
|
std::cout << std::left
|
||||||
@@ -316,8 +317,8 @@ static std::string selectInvoiceFromUserForPayment(const util::Map<std::string,
|
|||||||
<< std::setw(12) << "BookingID"
|
<< std::setw(12) << "BookingID"
|
||||||
<< std::setw(15) << "VehicleBrand"
|
<< std::setw(15) << "VehicleBrand"
|
||||||
<< std::setw(15) << "VehicleNumber"
|
<< std::setw(15) << "VehicleNumber"
|
||||||
<< std::setw(12) << "TechID"
|
<< std::setw(12) << "Technician ID"
|
||||||
<< std::setw(20) << "TechnicianName"
|
<< std::setw(20) << "Technician Name"
|
||||||
<< std::setw(10) << "Discount(%)"
|
<< std::setw(10) << "Discount(%)"
|
||||||
<< std::setw(12) << "TotalAmount"
|
<< std::setw(12) << "TotalAmount"
|
||||||
<< std::setw(20) << "InvoiceDate"
|
<< std::setw(20) << "InvoiceDate"
|
||||||
@@ -359,7 +360,7 @@ static std::string selectInvoiceFromUserForPayment(const util::Map<std::string,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cout << "Invalid choice.\n";
|
std::cout << "Invalid index.\n";
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -372,7 +373,7 @@ Parameters:
|
|||||||
Returns:
|
Returns:
|
||||||
- util::PaymentMode: Selected payment mode
|
- util::PaymentMode: Selected payment mode
|
||||||
*/
|
*/
|
||||||
static util::PaymentMode selectPaymentMode()
|
inline util::PaymentMode selectPaymentMode()
|
||||||
{
|
{
|
||||||
int choice;
|
int choice;
|
||||||
std::cout << "Enter the payment Mode\n1.OFFLINE\n2.ONLINE\nChoice: ";
|
std::cout << "Enter the payment Mode\n1.OFFLINE\n2.ONLINE\nChoice: ";
|
||||||
@@ -389,7 +390,7 @@ static util::PaymentMode selectPaymentMode()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cout << "Invalid choice, Offline mode selected.\n";
|
std::cout << "Invalid choice. Offline mode selected.\n";
|
||||||
return util::PaymentMode::OFFLINE;
|
return util::PaymentMode::OFFLINE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -405,7 +406,7 @@ Returns:
|
|||||||
Throws:
|
Throws:
|
||||||
- std::runtime_error if a null invoice is encountered
|
- std::runtime_error if a null invoice is encountered
|
||||||
*/
|
*/
|
||||||
static void displayInvoices(util::Map<std::string, const Invoice*> currentUserInvoices)
|
inline void displayInvoices(util::Map<std::string, const Invoice*> currentUserInvoices)
|
||||||
{
|
{
|
||||||
if (currentUserInvoices.getSize() == 0)
|
if (currentUserInvoices.getSize() == 0)
|
||||||
{
|
{
|
||||||
@@ -471,7 +472,7 @@ Parameters:
|
|||||||
Returns:
|
Returns:
|
||||||
- std::string: ID of the selected job card, or empty string if none selected
|
- std::string: ID of the selected job card, or empty string if none selected
|
||||||
*/
|
*/
|
||||||
static 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)
|
||||||
{
|
{
|
||||||
int currentIndex = 1;
|
int currentIndex = 1;
|
||||||
int choice;
|
int choice;
|
||||||
@@ -513,7 +514,7 @@ static std::string selectJobCardToComplete(util::Map<std::string, const JobCard*
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cout << "Invalid choice.\n";
|
std::cout << "Invalid index.\n";
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -528,11 +529,6 @@ Return type: const Notification* - pointer to the selected notification
|
|||||||
*/
|
*/
|
||||||
inline const Notification* selectNotification(const util::Vector<const Notification*>& notifications)
|
inline const Notification* selectNotification(const util::Vector<const Notification*>& notifications)
|
||||||
{
|
{
|
||||||
if (notifications.getSize() == 0)
|
|
||||||
{
|
|
||||||
std::cout << "No notifications available." << std::endl;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
util::Map<int, const Notification*> indexedNotifications;
|
util::Map<int, const Notification*> indexedNotifications;
|
||||||
std::cout << std::left
|
std::cout << std::left
|
||||||
<< std::setw(6) << "Index"
|
<< std::setw(6) << "Index"
|
||||||
@@ -549,7 +545,7 @@ inline const Notification* selectNotification(const util::Vector<const Notificat
|
|||||||
std::cout << std::left
|
std::cout << std::left
|
||||||
<< std::setw(6) << currentIndex
|
<< std::setw(6) << currentIndex
|
||||||
<< std::setw(15) << currentNotification->getId()
|
<< std::setw(15) << currentNotification->getId()
|
||||||
<< std::setw(30) << currentNotification->getTitle()
|
<< std::setw(35) << currentNotification->getTitle()
|
||||||
<< std::setw(25) << currentNotification->getCreatedAt().toString()
|
<< std::setw(25) << currentNotification->getCreatedAt().toString()
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
indexedNotifications.insert(currentIndex, currentNotification);
|
indexedNotifications.insert(currentIndex, currentNotification);
|
||||||
@@ -561,7 +557,7 @@ inline const Notification* selectNotification(const util::Vector<const Notificat
|
|||||||
util::read(selectedIndex);
|
util::read(selectedIndex);
|
||||||
if (!indexedNotifications.containsKey(selectedIndex))
|
if (!indexedNotifications.containsKey(selectedIndex))
|
||||||
{
|
{
|
||||||
std::cout << "Invalid selection." << std::endl;
|
std::cout << "Invalid index." << std::endl;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return indexedNotifications[selectedIndex];
|
return indexedNotifications[selectedIndex];
|
||||||
@@ -602,6 +598,13 @@ inline void viewAndDeleteNotification(Controller& controller)
|
|||||||
{
|
{
|
||||||
util::clear();
|
util::clear();
|
||||||
auto notifications = controller.getNotifications();
|
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);
|
const Notification* selectedNotification = selectNotification(notifications);
|
||||||
if (!selectedNotification)
|
if (!selectedNotification)
|
||||||
{
|
{
|
||||||
@@ -623,10 +626,16 @@ Return type: void
|
|||||||
inline void changePasswordHelper(Controller& controller)
|
inline void changePasswordHelper(Controller& controller)
|
||||||
{
|
{
|
||||||
util::clear();
|
util::clear();
|
||||||
std::string newPassword;
|
const User* authenticatedUser = controller.getAuthenticatedUser();
|
||||||
|
if (!authenticatedUser)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("No user is currently logged in!");
|
||||||
|
}
|
||||||
|
std::string newPassword, confirmedPassword;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
util::clear();
|
util::clear();
|
||||||
|
std::cout << "Change Password\n";
|
||||||
std::cout << "Enter new password: ";
|
std::cout << "Enter new password: ";
|
||||||
util::read(newPassword);
|
util::read(newPassword);
|
||||||
if (!util::isPasswordValid(newPassword))
|
if (!util::isPasswordValid(newPassword))
|
||||||
@@ -635,6 +644,20 @@ inline void changePasswordHelper(Controller& controller)
|
|||||||
util::pressEnter();
|
util::pressEnter();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (newPassword == authenticatedUser->getPassword())
|
||||||
|
{
|
||||||
|
std::cout << "New password cannot be same as old password. Try again\n";
|
||||||
|
util::pressEnter();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::cout << "Confirm new password: ";
|
||||||
|
util::read(confirmedPassword);
|
||||||
|
if (confirmedPassword != newPassword)
|
||||||
|
{
|
||||||
|
std::cout << "Passwords are different. Try again\n";
|
||||||
|
util::pressEnter();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
controller.changePassword(newPassword);
|
controller.changePassword(newPassword);
|
||||||
std::cout << "Password changed successfully\n";
|
std::cout << "Password changed successfully\n";
|
||||||
util::pressEnter();
|
util::pressEnter();
|
||||||
@@ -655,7 +678,7 @@ inline util::Map<std::string, const User*> filterActiveUsers(const util::Map<std
|
|||||||
for (int index = 0; index < inventorySize; index++)
|
for (int index = 0; index < inventorySize; index++)
|
||||||
{
|
{
|
||||||
const User* user = listOfUsers.getValueAt(index);
|
const User* user = listOfUsers.getValueAt(index);
|
||||||
if (user != nullptr && user->getState() != util::State::INACTIVE)
|
if (user != nullptr && user->getState() != util::State::INACTIVE && user->getUserType() != util::UserType::ADMIN)
|
||||||
{
|
{
|
||||||
activeUsers.insert(user->getId(), user);
|
activeUsers.insert(user->getId(), user);
|
||||||
}
|
}
|
||||||
@@ -764,8 +787,8 @@ inline const ComboPackage* selectComboPackageFromPackages(const util::Map<std::s
|
|||||||
int userInputIndex;
|
int userInputIndex;
|
||||||
std::cout << std::left
|
std::cout << std::left
|
||||||
<< std::setw(10) << "Index"
|
<< std::setw(10) << "Index"
|
||||||
<< std::setw(15) << "Combo Package ID"
|
<< std::setw(15) << "Combo ID"
|
||||||
<< std::setw(15) << "Combo Package Name"
|
<< std::setw(15) << "Combo Name"
|
||||||
<< std::setw(15) << "Estimate Cost"
|
<< std::setw(15) << "Estimate Cost"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
for (int index = 0; index < comboPackages.getSize(); index++)
|
for (int index = 0; index < comboPackages.getSize(); index++)
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ void UserInterface::login()
|
|||||||
{
|
{
|
||||||
std::string username, password;
|
std::string username, password;
|
||||||
util::clear();
|
util::clear();
|
||||||
|
std::cout << "Login\n";
|
||||||
std::cout << "Enter username: ";
|
std::cout << "Enter username: ";
|
||||||
util::read(username);
|
util::read(username);
|
||||||
std::cout << "Enter password: ";
|
std::cout << "Enter password: ";
|
||||||
@@ -92,7 +93,7 @@ void UserInterface::login()
|
|||||||
if (m_controller.login(username, password))
|
if (m_controller.login(username, password))
|
||||||
{
|
{
|
||||||
const User* authenticatedUser = m_controller.getAuthenticatedUser();
|
const User* authenticatedUser = m_controller.getAuthenticatedUser();
|
||||||
if (authenticatedUser != nullptr)
|
if (authenticatedUser && authenticatedUser->getState() != util::State::INACTIVE)
|
||||||
{
|
{
|
||||||
switch (authenticatedUser->getUserType())
|
switch (authenticatedUser->getUserType())
|
||||||
{
|
{
|
||||||
@@ -110,10 +111,16 @@ void UserInterface::login()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (authenticatedUser && authenticatedUser->getState() == util::State::INACTIVE)
|
||||||
|
{
|
||||||
|
std::cout << "\nError: Your account has been disabled. Please contact your Administrator.";
|
||||||
|
util::pressEnter();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cout << "\nError: Invalid Username or Password";
|
std::cout << "\nError: Invalid Username or Password";
|
||||||
|
util::pressEnter();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,6 +136,7 @@ void UserInterface::registerCustomer()
|
|||||||
{
|
{
|
||||||
std::string username, name, email, phone, password;
|
std::string username, name, email, phone, password;
|
||||||
util::clear();
|
util::clear();
|
||||||
|
std::cout << "Register Customer\n";
|
||||||
std::cout << "Enter username: ";
|
std::cout << "Enter username: ";
|
||||||
util::read(username);
|
util::read(username);
|
||||||
std::cout << "Enter name: ";
|
std::cout << "Enter name: ";
|
||||||
|
|||||||
Reference in New Issue
Block a user