Compare commits

..

8 Commits

Author SHA1 Message Date
Avinash Rajesh 6ca659c573 Add standardized documentation headers 2026-05-22 11:27:49 +05:30
Avinash Rajesh 7e9cc27f1c Merge branch 'feature-inventory-management-inv004' into feature-inventory-management 2026-05-21 20:14:03 +05:30
Avinash Rajesh 1377d5fb39 Merge branch 'feature-inventory-management-inv003' into feature-inventory-management 2026-05-21 20:11:55 +05:30
Avinash Rajesh d33f0aa8dc Merge branch 'feature-inventory-management-inv002' into feature-inventory-management 2026-05-21 20:09:53 +05:30
Avinash Rajesh ef41fec208 Implement Check Availability Status Functionality
<UserStory> INV004: Check Availability Status </UserStory>

<Changes>
    1. Updated Controller to delegate getInventoryItem calls to InventoryManagementService.
    2. Implemented InventoryManagementService::getInventoryItem to fetch items from datastore by ID.
    3. Enhanced AdminMenu with checkStockAvailability function:
       - Accepts part ID as input.
       - Retrieves item details from Controller.
       - Displays item information (ID, part name, quantity) if found and active.
       - Handles inactive or missing items gracefully.
</Changes>

<Test>

  Precondition:
  1. Admin user is logged into the system.
  2. Inventory contains multiple items with unique IDs.
  3. DataStore is initialized and accessible.

  Steps:
  1. Navigate to Admin Menu and select "Check Stock Availability".
    - Verify that the system prompts for an Item ID.
  2. Enter a valid Item ID for an active item.
    - Verify that the system displays the item’s details including current quantity.
  3. Enter an Item ID that does not exist.
    - Verify that the system displays “Item not found”.
  4. Enter an Item ID for an inactive item.
    - Verify that the system does not display details and indicates the item is inactive.
</Test>

<Review>
Sreeja Reghukumar
</Review>
2026-05-21 15:04:37 +05:30
Avinash Rajesh 3594fa4f26 Implement Remove Stock Functionality
<UserStory> INV003: Remove Stock </UserStory>

<Changes>
    1. Integrated InventoryManagementService into Controller to handle removal of inventory items.
    2. Implemented InventoryManagementService::removeInventoryItem to mark items as INACTIVE in the datastore.
    3. Enhanced AdminMenu with removeInventoryItem workflow:
       - Displays inventory list with index, ID, part name, quantity, and price.
       - Allows admin to select item by index for removal.
       - Provides confirmation message after successful deletion.
    4. Added static helper function displayInventoryWithItems in AdminMenu for modularized inventory display.
</Changes>

<Test>

  Precondition:
  1. Admin user is logged into the system.
  2. Inventory contains multiple items with unique IDs.
  3. DataStore is initialized and accessible.

  Steps:
  1. Navigate to Admin Menu and select "Remove Inventory Item".
    - Verify that the system displays all inventory items with ID, part name, quantity, and price.
  2. Select an item by entering its index.
    - Verify that the system removes the item and displays a confirmation message.
  3. Attempt to remove an item with an invalid index.
    - Verify that the system rejects the input and shows an error message.
  4. Navigate to "View Stock Levels".
    - Verify that the removed item no longer appears in the inventory list.
</Test>

<Review>
Sreeja Reghukumar
</Review>
2026-05-21 15:03:03 +05:30
Avinash Rajesh 6a8b845efa Implement Add Stock functionality
<UserStory> INV002: Add Stock </UserStory>

<Changes>
    1. Added Controller integration with InventoryManagementService to support adding new inventory items and updating existing stock quantities.
    2. Implemented InventoryManagementService::addInventoryItem to create new items via Factory and insert them into the DataStore.
    3. Implemented InventoryManagementService::addInventoryItemStock to update stock quantities for existing items.
    4. Enhanced AdminMenu with options to add new items or update stock quantities, including input validation and confirmation messages.
    5. Added helper functions in AdminMenu to display inventory items and handle quantity updates interactively.
    6. Included necessary headers (InventoryItem, Factory, iomanip) for new functionality.
</Changes>

<Test>

  Precondition:
  1. Admin user is logged into the system.
  2. Inventory contains existing items with unique IDs.
  3. DataStore is accessible and initialized.

  Steps:
  1. Navigate to Admin Menu and select "Add Inventory Item".
    - Verify that the system prompts for part name, quantity, and price.
  2. Enter details for a new item with a unique part name and ID.
    - Verify that the item is successfully added and a confirmation message is displayed.
  3. Attempt to add an item with a duplicate ID.
    - Verify that the system rejects the duplicate and displays an error message.
  4. Select "Add Quantity" option for an existing item.
    - Verify that the system updates the stock quantity and displays the new total in the confirmation message.
  5. Navigate to "View Stock Levels".
    - Verify that the updated stock quantity is reflected in the inventory list.
</Test>

<Review>
Sreeja Reghukumar
</Review>
2026-05-21 15:00:59 +05:30
Avinash Rajesh 9f882610b3 Implement View Stock Level Functionality
<UserStory> INV001: View Stock Level </UserStory>

<Changes>
    1. Integrated InventoryManagementService into Controller to provide read-only access to inventory items.
    2. Added implementation for InventoryManagementService::getInventoryItems to fetch data from DataStore.
    3. Enhanced AdminMenu with viewStockLevels functionality to display inventory details (ID, part name, quantity, price).
    4. Updated NotificationManagementService interface to provide concrete implementations for sendNotification, attach, detach, and notify methods.
    5. Included necessary headers (InventoryItem, InventoryManagementService, iomanip) for new functionality.
</Changes>

<Test>

  Precondition:
  1. Admin user is logged into the system.
  2. Inventory contains multiple items with varying stock levels.
  3. Notification service is active and users are registered.

  Steps:
  1. Navigate to Admin Menu and select "View Stock Levels".
    - Verify that the system displays all inventory items with ID, part name, quantity, and price.
  2. Check items with sufficient stock.
    - Verify that they are displayed normally without highlighting.
  3. Check items with low stock threshold.
    - Verify that these items are highlighted to indicate low availability.
  4. Trigger a notification for a low-stock item.
    - Verify that the notification is sent to registered users successfully.
</Test>

<Review>
Sreeja Reghukumar
</Review>
2026-05-21 14:57:16 +05:30
16 changed files with 447 additions and 985 deletions
@@ -1,9 +1,20 @@
/*
File: Controller.cpp
Description: Implementation file containing the method definitions
of the Controller class, which manages user authentication,
inventory, services, bookings, and notifications.
Author: Trenser
Date:19-May-2026
*/
#include "Controller.h" #include "Controller.h"
#include "InventoryItem.h"
#include "Service.h"
#include "ServiceBooking.h"
#include "JobCard.h"
/*
Function: login
Description: Authenticates a user based on provided credentials.
Parameter: const std::string& username - the username of the user
const std::string& password - the password of the user
Return type: bool
*/
bool Controller::login(const std::string& username, const std::string& password) bool Controller::login(const std::string& username, const std::string& password)
{ {
return false; return false;
@@ -34,23 +45,9 @@ void Controller::updateUserDetails(const std::string& email, const std::string&
{ {
} }
/*
Function: getServices
Description: Retrieves all available services in read-only form.
Parameters:
- None
Returns:
- util::Map<std::string, const Service*> containing all services
*/
util::Map<std::string, const Service*> Controller::getServices() util::Map<std::string, const Service*> Controller::getServices()
{ {
util::Map<std::string, Service*> currentServices = m_serviceManagementService.getServices(); return util::Map<std::string, const Service*>();
util::Map<std::string, const Service*> readOnlyServices;
for (int iterator = 0; iterator < currentServices.getSize(); iterator++)
{
readOnlyServices.insert(currentServices.getValueAt(iterator)->getId(), currentServices.getValueAt(iterator));
}
return readOnlyServices;
} }
util::Map<std::string, const ComboPackage*> Controller::getComboPackages() util::Map<std::string, const ComboPackage*> Controller::getComboPackages()
@@ -66,61 +63,80 @@ void Controller::purchaseComboPackage(const std::string& comboPackageID, const s
{ {
} }
/*
Function: getInventoryItems
Description: Retrieves all inventory items from the inventory management service
and constructs a read-only map for external use.
Parameter: None
Return type: util::Map<std::string, const InventoryItem*>
*/
util::Map<std::string, const InventoryItem*> Controller::getInventoryItems() util::Map<std::string, const InventoryItem*> Controller::getInventoryItems()
{ {
util::Map<std::string, const InventoryItem*> dummyMap; auto inventoryIems = m_inventoryManagementService.getInventoryItems();
return dummyMap; util::Map<std::string, const InventoryItem*> readOnlyInventoryItems;
int inventoryItemsMapSize = inventoryIems.getSize();
for (int index = 0; index < inventoryItemsMapSize; index++)
{
readOnlyInventoryItems.insert(inventoryIems.getKeyAt(index), inventoryIems.getValueAt(index));
}
return readOnlyInventoryItems;
} }
/*
Function: getInventoryItem
Description: Retrieves a specific inventory item by its ID from the inventory management service.
Parameter: const std::string& inventoryItemID - ID of the inventory item
Return type: const InventoryItem*
*/
const InventoryItem* Controller::getInventoryItem(const std::string& inventoryItemID) const InventoryItem* Controller::getInventoryItem(const std::string& inventoryItemID)
{ {
return nullptr; return m_inventoryManagementService.getInventoryItem(inventoryItemID);
} }
/*
Function: addInventoryItem
Description: Adds a new inventory item with specified details to the inventory management service.
Parameter: const std::string& partName - name of the part
int quantity - quantity of the part
double price - price of the part
Return type: void
*/
void Controller::addInventoryItem(const std::string& partName, int quantity, double price) void Controller::addInventoryItem(const std::string& partName, int quantity, double price)
{ {
m_inventoryManagementService.addInventoryItem(partName, quantity, price);
} }
/*
Function: removeInventoryItem
Description: Removes an inventory item from the inventory management service by its ID.
Parameter: const std::string& inventoryItemID - ID of the inventory item
Return type: void
*/
void Controller::removeInventoryItem(const std::string& inventoryItemID) void Controller::removeInventoryItem(const std::string& inventoryItemID)
{ {
m_inventoryManagementService.removeInventoryItem(inventoryItemID);
} }
/* /*
Function: getServiceBookings Function: addInventoryItemStock
Description: Retrieves all service bookings in read-only form. Description: Adds stock to an existing inventory item in the inventory management service.
Parameters: Parameter: const std::string& selectedItemId - ID of the inventory item
- None int quantity - quantity to add
Returns: Return type: void
- util::Map<std::string, const ServiceBooking*> containing service bookings
*/ */
void Controller::addInventoryItemStock(const std::string& selectedItemId, int quantity)
{
m_inventoryManagementService.addInventoryItemStock(selectedItemId, quantity);
}
util::Map<std::string, const ServiceBooking*> Controller::getServiceBookings() util::Map<std::string, const ServiceBooking*> Controller::getServiceBookings()
{ {
auto serviceBookings = m_serviceManagementService.getServiceBookings(); return util::Map<std::string, const ServiceBooking*>();
util::Map<std::string, const ServiceBooking*> readOnlyServiceBookings;
for (int iterator = 0; iterator < serviceBookings.getSize(); iterator++)
{
readOnlyServiceBookings.insert(serviceBookings.getKeyAt(iterator), serviceBookings.getValueAt(iterator));
}
return readOnlyServiceBookings;
} }
/*
Function: getServiceBookingsByUser
Description: Retrieves all service bookings for a specific user.
Parameters:
- userID: std::string, the user ID
Returns:
- util::Map<std::string, const ServiceBooking*> containing bookings for the user
*/
util::Map<std::string, const ServiceBooking*> Controller::getServiceBookingsByUser(const std::string userID) util::Map<std::string, const ServiceBooking*> Controller::getServiceBookingsByUser(const std::string userID)
{ {
util::Map<std::string, const ServiceBooking*> readOnlyServiceBookingsByUserMap; return util::Map<std::string, const ServiceBooking*>();
util::Map<std::string, ServiceBooking*> currentServiceBookingsByUser = m_serviceManagementService.getServiceBookings(userID);
for (int iterator = 0; iterator < currentServiceBookingsByUser.getSize(); iterator++)
{
readOnlyServiceBookingsByUserMap.insert(currentServiceBookingsByUser.getValueAt(iterator)->getId(), currentServiceBookingsByUser.getValueAt(iterator));
}
return readOnlyServiceBookingsByUserMap;
} }
util::Map<std::string, const User*> Controller::getUsers() util::Map<std::string, const User*> Controller::getUsers()
@@ -128,100 +144,30 @@ util::Map<std::string, const User*> Controller::getUsers()
return util::Map<std::string, const User*>(); return util::Map<std::string, const User*>();
} }
/*
Function: getUsers
Description: Retrieves users filtered by user type.
Parameters:
- userType: util::UserType, type of user (CUSTOMER, TECHNICIAN, ADMIN)
Returns:
- util::Map<std::string, const User*> containing users of the specified type
*/
util::Map<std::string, const User*> Controller::getUsers(util::UserType userType) util::Map<std::string, const User*> Controller::getUsers(util::UserType userType)
{ {
auto userMap = m_userManagementService.getUsers(userType); return util::Map<std::string, const User*>();
util::Map<std::string, const User*> readOnlyUserMap;
for (int iterator = 0; iterator < userMap.getSize(); iterator++)
{
readOnlyUserMap.insert(userMap.getKeyAt(iterator), userMap.getValueAt(iterator));
}
return readOnlyUserMap;
} }
/*
Function: createJobCard
Description: Creates a job card for a service booking assigned to a technician.
Parameters:
- bookingID: std::string, ID of the service booking
- technicianID: std::string, ID of the technician
- serviceID: std::string, ID of the service
Returns:
- void
*/
void Controller::createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID) void Controller::createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID)
{ {
m_serviceManagementService.createJobCard(bookingID, technicianID, serviceID);
} }
/*
Function: createService
Description: Creates a new service with associated inventory items and labor cost.
Parameters:
- name: std::string, name of the service
- inventoryItemIDs: Vector of inventory item IDs
- laborCost: double, labor cost
Returns:
- void
*/
void Controller::createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost) void Controller::createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost)
{ {
m_serviceManagementService.createService(name, inventoryItemIDs, laborCost);
} }
/*
Function: removeService
Description: Removes a service from the system by ID.
Parameters:
- serviceID: std::string, ID of the service
Returns:
- void
*/
void Controller::removeService(const std::string& serviceID) void Controller::removeService(const std::string& serviceID)
{ {
m_serviceManagementService.removeService(serviceID);
} }
/*
Function: getJobCardsByUser
Description: Retrieves job cards assigned to the authenticated technician.
Parameters:
- None
Returns:
- util::Map<std::string, const JobCard*> containing job cards
*/
util::Map<std::string, const JobCard*> Controller::getJobCardsByUser() util::Map<std::string, const JobCard*> Controller::getJobCardsByUser()
{ {
const User* currentUser = getAuthenticatedUser(); return util::Map<std::string, const JobCard*>();
auto jobCardsAssignedToTechnician = m_serviceManagementService.getJobCards(currentUser->getId());
util::Map<std::string, const JobCard*> readOnlyJobCardMap;
for (int iterator = 0; iterator < jobCardsAssignedToTechnician.getSize(); iterator++)
{
JobCard* currentJobCard = jobCardsAssignedToTechnician.getValueAt(iterator);
readOnlyJobCardMap.insert(currentJobCard->getId(), currentJobCard);
}
return readOnlyJobCardMap;
} }
/*
Function: completeJob
Description: Marks a job card as completed.
Parameters:
- jobID: std::string, ID of the job card
Returns:
- void
*/
void Controller::completeJob(const std::string& jobID) void Controller::completeJob(const std::string& jobID)
{ {
m_serviceManagementService.completeJob(jobID);
} }
void Controller::removeUser(const std::string& userID) void Controller::removeUser(const std::string& userID)
@@ -1,10 +1,16 @@
/*
File: Controller.h
Description: Header file declaring the Controller class, which manages
user authentication, inventory, services, bookings, job cards,
invoices, and notifications in the system.
Author: Trenser
Date:19-May-2026
*/
#pragma once #pragma once
#include "Map.h" #include "Map.h"
#include <string> #include <string>
#include "Enums.h" #include "Enums.h"
#include "ServiceManagementService.h" #include "InventoryManagementService.h";
#include "UserManagementService.h"
#include "InventoryManagementService.h"
class Service; class Service;
class ComboPackage; class ComboPackage;
@@ -18,8 +24,7 @@ class Notification;
class Controller class Controller
{ {
private: private:
ServiceManagementService m_serviceManagementService; InventoryManagementService m_inventoryManagementService;
UserManagementService m_userManagementService;
public: public:
bool login(const std::string& username, const std::string& password); bool login(const std::string& username, const std::string& password);
void logout(); void logout();
@@ -53,5 +58,6 @@ public:
util::Vector<const Notification*> getNotifications(); util::Vector<const Notification*> getNotifications();
void deleteNotification(const std::string& notificationID); void deleteNotification(const std::string& notificationID);
void configureNotifications(const std::string& userID, bool paymentNotifications, bool serviceNotifications); void configureNotifications(const std::string& userID, bool paymentNotifications, bool serviceNotifications);
void addInventoryItemStock(const std::string& selectedItemId, int quantity);
void runSystemChecks(); void runSystemChecks();
}; };
@@ -7,7 +7,7 @@ JobCard::JobCard()
m_booking(nullptr), m_booking(nullptr),
m_service(nullptr), m_service(nullptr),
m_technician(nullptr), m_technician(nullptr),
m_status(util::ServiceJobStatus()) {} m_status(ServiceJobStatus()) {}
JobCard::JobCard(const std::string& bookingId, JobCard::JobCard(const std::string& bookingId,
ServiceBooking* booking, ServiceBooking* booking,
@@ -16,7 +16,7 @@ JobCard::JobCard(const std::string& bookingId,
const std::string& technicianId, const std::string& technicianId,
User* technician, User* technician,
const util::Timestamp& assignedDate, const util::Timestamp& assignedDate,
util::ServiceJobStatus status, ServiceJobStatus status,
const util::Timestamp& completionDate const util::Timestamp& completionDate
) )
: m_id("JC" + std::to_string(++m_uid)), : m_id("JC" + std::to_string(++m_uid)),
@@ -70,7 +70,7 @@ const util::Timestamp& JobCard::getAssignedDate() const
return m_assignedDate; return m_assignedDate;
} }
util::ServiceJobStatus JobCard::getStatus() const ServiceJobStatus JobCard::getStatus() const
{ {
return m_status; return m_status;
} }
@@ -120,7 +120,7 @@ void JobCard::setAssignedDate(const util::Timestamp& assignedDate)
m_assignedDate = assignedDate; m_assignedDate = assignedDate;
} }
void JobCard::setStatus(util::ServiceJobStatus status) void JobCard::setStatus(ServiceJobStatus status)
{ {
m_status = status; m_status = status;
} }
@@ -1,12 +1,13 @@
#pragma once #pragma once
#include <string> #include <string>
#include "Timestamp.h" #include "Timestamp.h"
#include "Enums.h"
class ServiceBooking; class ServiceBooking;
class Service; class Service;
class User; class User;
enum class ServiceJobStatus : int;
class JobCard class JobCard
{ {
private: private:
@@ -19,7 +20,7 @@ private:
std::string m_technicianId; std::string m_technicianId;
User* m_technician; User* m_technician;
util::Timestamp m_assignedDate; util::Timestamp m_assignedDate;
util::ServiceJobStatus m_status; ServiceJobStatus m_status;
util::Timestamp m_completionDate; util::Timestamp m_completionDate;
public: public:
@@ -31,7 +32,7 @@ public:
const std::string& technicianId, const std::string& technicianId,
User* technician, User* technician,
const util::Timestamp& assignedDate, const util::Timestamp& assignedDate,
util::ServiceJobStatus status, ServiceJobStatus status,
const util::Timestamp& completionDate const util::Timestamp& completionDate
); );
const std::string& getId() const; const std::string& getId() const;
@@ -42,7 +43,7 @@ public:
const std::string& getTechnicianId() const; const std::string& getTechnicianId() const;
User* getTechnician() const; User* getTechnician() const;
const util::Timestamp& getAssignedDate() const; const util::Timestamp& getAssignedDate() const;
util::ServiceJobStatus getStatus() const; ServiceJobStatus getStatus() const;
const util::Timestamp& getCompletionDate() const; const util::Timestamp& getCompletionDate() const;
void setId(const std::string& id); void setId(const std::string& id);
void setBookingId(const std::string& bookingId); void setBookingId(const std::string& bookingId);
@@ -52,6 +53,6 @@ public:
void setTechnicianId(const std::string& technicianId); void setTechnicianId(const std::string& technicianId);
void setTechnician(User* technician); void setTechnician(User* technician);
void setAssignedDate(const util::Timestamp& assignedDate); void setAssignedDate(const util::Timestamp& assignedDate);
void setStatus(util::ServiceJobStatus status); void setStatus(ServiceJobStatus status);
void setCompletionDate(const util::Timestamp& completionDate); void setCompletionDate(const util::Timestamp& completionDate);
}; };
@@ -18,7 +18,7 @@ ServiceBooking::ServiceBooking(
const std::string& vehicleBrand, const std::string& vehicleBrand,
const std::string& vehicleModel, const std::string& vehicleModel,
const std::string& assignedTechnicianId, const std::string& assignedTechnicianId,
const User* assignedTechnician, const std::string& assignedTechnician,
double discountPercentage double discountPercentage
) )
: m_id("SRV" + std::to_string(++m_uid)), : m_id("SRV" + std::to_string(++m_uid)),
@@ -80,7 +80,7 @@ const std::string& ServiceBooking::getAssignedTechnicianId() const
return m_assignedTechnicianId; return m_assignedTechnicianId;
} }
const User* ServiceBooking::getAssignedTechnician() const const std::string& ServiceBooking::getAssignedTechnician() const
{ {
return m_assignedTechnician; return m_assignedTechnician;
} }
@@ -135,7 +135,7 @@ void ServiceBooking::setAssignedTechnicianId(const std::string& assignedTechnici
m_assignedTechnicianId = assignedTechnicianId; m_assignedTechnicianId = assignedTechnicianId;
} }
void ServiceBooking::setAssignedTechnician(const User* assignedTechnician) void ServiceBooking::setAssignedTechnician(const std::string& assignedTechnician)
{ {
m_assignedTechnician = assignedTechnician; m_assignedTechnician = assignedTechnician;
} }
@@ -19,7 +19,7 @@ private:
std::string m_vehicleBrand; std::string m_vehicleBrand;
std::string m_vehicleModel; std::string m_vehicleModel;
std::string m_assignedTechnicianId; std::string m_assignedTechnicianId;
const User* m_assignedTechnician; std::string m_assignedTechnician;
double m_discountPercentage; double m_discountPercentage;
public: public:
ServiceBooking(); ServiceBooking();
@@ -34,7 +34,7 @@ public:
const std::string& vehicleBrand, const std::string& vehicleBrand,
const std::string& vehicleModel, const std::string& vehicleModel,
const std::string& assignedTechnicianId, const std::string& assignedTechnicianId,
const User* assignedTechnician, const std::string& assignedTechnician,
double discountPercentage double discountPercentage
); );
const std::string& getId() const; const std::string& getId() const;
@@ -46,7 +46,7 @@ public:
const std::string& getVehicleBrand() const; const std::string& getVehicleBrand() const;
const std::string& getVehicleModel() const; const std::string& getVehicleModel() const;
const std::string& getAssignedTechnicianId() const; const std::string& getAssignedTechnicianId() const;
const User* getAssignedTechnician() const; const std::string& getAssignedTechnician() const;
double getDiscountPercentage() const; double getDiscountPercentage() const;
void setId(const std::string& id); void setId(const std::string& id);
void setStatus(const util::ServiceJobStatus& status); void setStatus(const util::ServiceJobStatus& status);
@@ -57,6 +57,6 @@ public:
void setVehicleBrand(const std::string& vehicleBrand); void setVehicleBrand(const std::string& vehicleBrand);
void setVehicleModel(const std::string& vehicleModel); void setVehicleModel(const std::string& vehicleModel);
void setAssignedTechnicianId(const std::string& assignedTechnicianId); void setAssignedTechnicianId(const std::string& assignedTechnicianId);
void setAssignedTechnician(const User* assignedTechnician); void setAssignedTechnician(const std::string& assignedTechnician);
void setDiscountPercentage(double discountPercentage); void setDiscountPercentage(double discountPercentage);
}; };
@@ -1 +1,93 @@
/*
File: InventoryManagementService.cpp
Description: Implementation file containing the method definitions of the
InventoryManagementService class, including inventory operations
and notification handling.
Author: Trenser
Date:19-May-2026
*/
#include "InventoryManagementService.h" #include "InventoryManagementService.h"
#include "InventoryItem.h"
#include "Factory.h"
/*
Function: addInventoryItem
Description: Creates a new inventory item using the Factory and inserts it
into the DataStore.
Parameter: const std::string& partName - name of the part
int quantity - initial quantity of the part
double price - price of the part
Return type: void
*/
void InventoryManagementService::addInventoryItem(const std::string& partName, int quantity, double price)
{
InventoryItem* newItem = Factory::getObject<InventoryItem>(partName, quantity, price);
m_dataStore.getInventoryItems().insert(newItem->getId(), newItem);
}
/*
Function: addInventoryItemStock
Description: Increases the stock quantity of an existing inventory item.
Parameter: const std::string& selectedItemId - ID of the inventory item
int quantity - quantity to add
Return type: void
*/
void InventoryManagementService::addInventoryItemStock(const std::string& selectedItemId, int quantity)
{
int index = m_dataStore.getInventoryItems().find(selectedItemId);
if (index != -1)
{
InventoryItem* item = m_dataStore.getInventoryItems().getValueAt(index);
if (item != nullptr)
{
int totalQuantity = item->getQuantity() + quantity;
item->setQuantity(totalQuantity);
}
}
}
/*
Function: getInventoryItems
Description: Retrieves all inventory items stored in the DataStore.
Parameter: None
Return type: util::Map<std::string, InventoryItem*>
*/
util::Map<std::string, InventoryItem*> InventoryManagementService::getInventoryItems()
{
return m_dataStore.getInventoryItems();
}
/*
Function: removeInventoryItem
Description: Marks an inventory item as inactive instead of deleting it.
Parameter: const std::string& inventoryItemID - ID of the inventory item
Return type: void
*/
void InventoryManagementService::removeInventoryItem(const std::string& inventoryItemID)
{
int index = m_dataStore.getInventoryItems().find(inventoryItemID);
if (index != -1)
{
InventoryItem* item = m_dataStore.getInventoryItems().getValueAt(index);
if (item != nullptr)
{
item->setState(util::State::INACTIVE);
}
}
}
/*
Function: getInventoryItem
Description: Retrieves a specific inventory item by its ID from the DataStore.
Parameter: const std::string& inventoryItemID - ID of the inventory item
Return type: InventoryItem*
*/
InventoryItem* InventoryManagementService::getInventoryItem(const std::string& inventoryItemID)
{
int index = m_dataStore.getInventoryItems().find(inventoryItemID);
if (index != -1)
{
return m_dataStore.getInventoryItems().getValueAt(index);
}
return nullptr;
}
@@ -1,3 +1,11 @@
/*
File: InventoryManagementService.h
Description: Header file declaring the InventoryManagementService class,
which manages inventory items, stock updates, and notifications
related to low stock alerts. Inherits from NotificationManagementService.
Author: Trenser
Date:19-May-2026
*/
#pragma once #pragma once
#include <string> #include <string>
#include "Map.h" #include "Map.h"
@@ -17,6 +25,7 @@ public:
InventoryItem* getInventoryItem(const std::string& inventoryItemID); InventoryItem* getInventoryItem(const std::string& inventoryItemID);
void addInventoryItem(const std::string& partName, int quantity, double price); void addInventoryItem(const std::string& partName, int quantity, double price);
void removeInventoryItem(const std::string& inventoryItemID); void removeInventoryItem(const std::string& inventoryItemID);
void addInventoryItemStock(const std::string& selectedItemId, int quantity);
void sendLowStockAlerts(); void sendLowStockAlerts();
void sendNotification(User* user, const std::string& title, const std::string& message) override; void sendNotification(User* user, const std::string& title, const std::string& message) override;
void attach(User* user) override; void attach(User* user) override;
@@ -1,324 +1 @@
#include "ServiceManagementService.h" #include "ServiceManagementService.h"
#include "UserManagementService.h"
#include "ServiceBooking.h"
#include "Factory.h"
#include "JobCard.h"
#include "Timestamp.h"
#include "Service.h"
#include "Enums.h"
#include "InventoryItem.h"
#include "AuthenticationManagementService.h"
#include "PaymentManagementService.h"
#include "NotificationManagementService.h"
#include "User.h"
/*
Function: getServiceBookings
Description: Retrieves all service bookings from the datastore.
Parameters:
- None
Returns:
- util::Map<std::string, ServiceBooking*> containing all service bookings
*/
util::Map<std::string, ServiceBooking*> ServiceManagementService::getServiceBookings()
{
return m_dataStore.getServiceBookings();
}
/*
Function: getServiceBooking
Description: Retrieves a specific service booking by its ID.
Parameters:
- serviceID: std::string, ID of the service booking
Returns:
- ServiceBooking*: Pointer to the service booking, or nullptr if not found
*/
ServiceBooking* ServiceManagementService::getServiceBooking(const std::string& serviceID)
{
auto currentServiceBookings = getServiceBookings();
for (int iterator = 0; iterator < currentServiceBookings.getSize(); iterator++)
{
if (currentServiceBookings.getValueAt(iterator)->getId() == serviceID)
{
return currentServiceBookings.getValueAt(iterator);
}
}
return nullptr;
}
/*
Function: createJobCard
Description: Creates a job card for a given service booking, service, and technician.
Validates booking, service, technician, and inventory availability before creation.
Parameters:
- bookingID: std::string, ID of the service booking
- technicianID: std::string, ID of the technician
- serviceID: std::string, ID of the service
Returns:
- void
Throws:
- std::runtime_error if booking, service, technician, or inventory validation fails
*/
void ServiceManagementService::createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID)
{
UserManagementService m_userManagementService;
ServiceBooking* currentBooking = getServiceBooking(bookingID);
auto& currentJobCards = m_dataStore.getJobCards();
if (currentBooking == nullptr)
{
throw std::runtime_error("Service Booking not available");
}
auto& currentServices = currentBooking->getServices();
if (currentServices.find(serviceID) == -1)
{
throw std::runtime_error("Invalid service Id");
}
Service* currentService = currentServices.getValueAt(currentServices.find(serviceID));
User* selectedTechnician = m_userManagementService.getUser(technicianID);
if (selectedTechnician == nullptr)
{
throw std::runtime_error("Technician not available");
}
auto& inventoryItems = currentService->getRequiredInventoryItems();
for (int iterator = 0; iterator < inventoryItems.getSize(); iterator++)
{
InventoryItem* currentInventoryItem = inventoryItems.getValueAt(iterator);
if (currentInventoryItem->getQuantity() == 0)
{
std::string errorMessage = "Failed to create job card, " + currentInventoryItem->getPartName() + " is out of stock.";
throw std::runtime_error(errorMessage);
}
else
{
int currentStockQuantity = currentInventoryItem->getQuantity();
currentInventoryItem->setQuantity(currentStockQuantity - 1);
}
}
currentBooking->setAssignedTechnician(selectedTechnician);
currentBooking->setAssignedTechnicianId(selectedTechnician->getId());
std::string title = "Job card created";
std::string message = "Job card created for the service and you are assigned for that.";
JobCard* jobCard = Factory::getObject<JobCard>(bookingID, currentBooking, currentService, serviceID, technicianID, selectedTechnician, util::Timestamp(), util::ServiceJobStatus::STARTED, util::Timestamp());
currentJobCards.insert(jobCard->getId(), jobCard);
sendNotification(selectedTechnician,title, message);
}
/*
Function: createService
Description: Creates a new service with associated inventory items and labor cost.
Validates inventory items before creation.
Parameters:
- name: std::string, name of the service
- inventoryItemIDs: util::Vector<std::string>, IDs of required inventory items
- laborCost: double, labor cost for the service
Returns:
- void
Throws:
- std::runtime_error if inventory items are not found or service creation fails
*/
void ServiceManagementService::createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost)
{
util::Map<std::string, InventoryItem*> currentServiceInventoryItems;
auto inventoryItems = m_dataStore.getInventoryItems();
for (int iteratorOne =0; iteratorOne < inventoryItemIDs.getSize(); iteratorOne++)
{
std::string currentItemID = inventoryItemIDs[iteratorOne];
bool itemFound = false;
for (int iteratorTwo = 0; iteratorTwo < inventoryItems.getSize(); iteratorTwo++)
{
InventoryItem* currentInventoryItem = inventoryItems.getValueAt(iteratorTwo);
if (currentInventoryItem && currentInventoryItem->getId() == currentItemID)
{
itemFound = true;
currentServiceInventoryItems.insert(currentInventoryItem->getId(), currentInventoryItem);
break;
}
}
if (!itemFound)
{
throw std::runtime_error("Inventory item with ID '" + currentItemID + "' not found.");
}
}
Service* newService = Factory::getObject<Service>(name, currentServiceInventoryItems, laborCost);
if (newService == nullptr)
{
throw std::runtime_error("Unable to create new service.");
}
util::Map<std::string, Service*>& currentServices = m_dataStore.getServices();
if (currentServices.find(newService->getId()) != -1)
{
throw std::runtime_error("Service with this ID Already exists.");
}
currentServices.insert(newService->getId(), newService);
}
/*
Function: getServices
Description: Retrieves all services from the datastore.
Parameters:
- None
Returns:
- util::Map<std::string, Service*> containing all services
*/
util::Map<std::string, Service*> ServiceManagementService::getServices()
{
return m_dataStore.getServices();
}
/*
Function: removeService
Description: Marks a service as inactive by its ID.
Parameters:
- serviceID: std::string, ID of the service
Returns:
- void
Throws:
- std::runtime_error if the service is not found
*/
void ServiceManagementService::removeService(const std::string& serviceID)
{
util::Map<std::string, Service*> currentServices = getServices();
if (currentServices.find(serviceID) != -1)
{
currentServices.getValueAt(currentServices.find(serviceID))->setState(util::State::INACTIVE);
}
else
{
throw std::runtime_error("Service not found.");
}
}
/*
Function: getServiceBookings (overloaded)
Description: Retrieves all service bookings for a specific customer.
Parameters:
- customerID: std::string, ID of the customer
Returns:
- util::Map<std::string, ServiceBooking*> containing bookings for the customer
*/
util::Map<std::string, ServiceBooking*> ServiceManagementService::getServiceBookings(const std::string& customerID)
{
util::Map<std::string, ServiceBooking*> currentServiceBookings = getServiceBookings();
util::Map<std::string, ServiceBooking*> currentUserServiceBookings;
if (currentServiceBookings.getSize() != 0)
{
for (int iterator = 0; iterator < currentServiceBookings.getSize(); iterator++)
{
auto currentServiceBooking = currentServiceBookings.getValueAt(iterator);
if (currentServiceBooking->getCustomerId() == customerID)
{
currentUserServiceBookings.insert(currentServiceBooking->getId(), currentServiceBooking);
}
}
}
return currentUserServiceBookings;
}
/*
Function: getJobCards
Description: Retrieves all job cards assigned to a specific technician.
Parameters:
- technicianID: std::string, ID of the technician
Returns:
- util::Map<std::string, JobCard*> containing job cards assigned to the technician
*/
util::Map<std::string, JobCard*> ServiceManagementService::getJobCards(const std::string& technicianID)
{
util::Map<std::string, JobCard*> jobCards = m_dataStore.getJobCards();
util::Map<std::string, JobCard*> technicianJobCards;
for (int iterator = 0; iterator < jobCards.getSize(); iterator++)
{
JobCard* currentJobCard = jobCards.getValueAt(iterator);
if (currentJobCard->getTechnicianId() == technicianID)
{
technicianJobCards.insert(currentJobCard->getId(), currentJobCard);
}
}
return technicianJobCards;
}
/*
Function: hasAllJobCardsinServiceBookingCompleted (static helper)
Description: Checks if all job cards for a given service booking are completed.
Parameters:
- bookingId: std::string, ID of the service booking
- currentAssignedJobs: util::Map<std::string, JobCard*>&, map of assigned job cards
Returns:
- bool: True if all job cards are completed, False otherwise
*/
static bool hasAllJobCardsinServiceBookingCompleted(std::string bookingId, util::Map<std::string, JobCard*>& currentAssignedJobs)
{
for (int iterator = 0; iterator < currentAssignedJobs.getSize(); iterator++)
{
JobCard* currentJob = currentAssignedJobs.getValueAt(iterator);
if (currentJob->getBookingId() == bookingId)
{
if (currentJob->getStatus() == util::ServiceJobStatus::STARTED)
{
return false;
}
}
}
return true;
}
/*
Function: completeJob
Description: Marks a job card as completed for the authenticated technician.
If all job cards in the booking are completed, marks the booking as completed
and generates an invoice.
Parameters:
- jobID: std::string, ID of the job card
Returns:
- void
Throws:
- std::runtime_error if technician is not authenticated, job card not found, or job already completed
*/
void ServiceManagementService::completeJob(const std::string& jobID)
{
AuthenticationManagementService authenticationManagementService;
PaymentManagementService paymentManagementService;
bool jobStatusUpdated = false, serviceBookingCompleted;
JobCard* currentJob;
User* currentTechnician = authenticationManagementService.getAuthenticatedUser();
if (currentTechnician == nullptr)
{
throw std::runtime_error("Unable to fetch current technician.");
}
util::Map<std::string, JobCard*> currentAssignedJobs = getJobCards(currentTechnician->getId());
if (currentAssignedJobs.getSize() == 0)
{
throw std::runtime_error("No job cards assigned to the technician.");
}
if (currentAssignedJobs.find(jobID) != -1)
{
currentJob = currentAssignedJobs.getValueAt(currentAssignedJobs.find(jobID));
if (currentJob == nullptr)
{
throw std::runtime_error("Unable to fetch current job.");
}
if (currentJob->getStatus() == util::ServiceJobStatus::STARTED)
{
currentJob->setStatus(util::ServiceJobStatus::COMPLETED);
jobStatusUpdated = true;
}
}
else
{
throw std::runtime_error("Failed to complete the job, some error occured or job already completed.");
}
if (!jobStatusUpdated)
{
throw std::runtime_error("Failed to complete the job, some error occured or job already completed.");
}
serviceBookingCompleted = hasAllJobCardsinServiceBookingCompleted(currentJob->getBookingId(), currentAssignedJobs);
if (serviceBookingCompleted)
{
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";
sendNotification(currentJob->getBooking()->getCustomer(), title, message);
}
}
@@ -22,7 +22,6 @@ public:
void purchaseComboPackage(const std::string& comboPackageID, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel); void purchaseComboPackage(const std::string& comboPackageID, const std::string& vehicleNumber, const std::string& vehicleBrand, const std::string& vehicleModel);
util::Map<std::string, ServiceBooking*> getServiceBookings(); util::Map<std::string, ServiceBooking*> getServiceBookings();
util::Map<std::string, ServiceBooking*> getServiceBookings(const std::string& customerID); util::Map<std::string, ServiceBooking*> getServiceBookings(const std::string& customerID);
ServiceBooking* getServiceBooking(const std::string& serviceID);
void createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID); void createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID);
void createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost); void createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost);
void removeService(const std::string& serviceID); void removeService(const std::string& serviceID);
@@ -1,31 +1 @@
#include "UserManagementService.h" #include "UserManagementService.h"
#include "User.h"
util::Map<std::string, User*> UserManagementService::getUsers(util::UserType type)
{
util::Map<std::string, User*>& currentUsers = m_dataStore.getUsers();
util::Map<std::string, User*> filteredUsersMap;
for (int iterator = 0; iterator < currentUsers.getSize(); iterator++)
{
User* currentUser = currentUsers.getValueAt(iterator);
if (currentUser->getUserType() == type)
{
filteredUsersMap.insert(currentUser->getId(), currentUser);
}
}
return filteredUsersMap;
}
User* UserManagementService::getUser(const std::string& userID)
{
util::Map<std::string, User*>& currentUsers = m_dataStore.getUsers();
for (int iterator = 0; iterator < currentUsers.getSize(); iterator++)
{
User* currentUser = currentUsers.getValueAt(iterator);
if (currentUser->getId() == userID)
{
return currentUser;
}
}
return nullptr;
}
@@ -24,7 +24,6 @@ namespace util
enum class ServiceJobStatus enum class ServiceJobStatus
{ {
PENDING,
STARTED, STARTED,
COMPLETED COMPLETED
}; };
@@ -126,8 +125,6 @@ namespace util
return "STARTED"; return "STARTED";
case ServiceJobStatus::COMPLETED: case ServiceJobStatus::COMPLETED:
return "COMPLETED"; return "COMPLETED";
case ServiceJobStatus::PENDING:
return "STARTED";
} }
throw std::invalid_argument("Invalid ServiceJobStatus"); throw std::invalid_argument("Invalid ServiceJobStatus");
} }
@@ -1,13 +1,23 @@
/*
File: AdminMenu.cpp
Description: Implementation file containing the method definitions of the
AdminMenu class, including menu handling, inventory operations,
and stock management functions.
Author: Trenser
Date:19-May-2026
*/
#include <iomanip> #include <iomanip>
#include "AdminMenu.h" #include "AdminMenu.h"
#include "Service.h" #include "InventoryItem.h"
#include "InputHelper.h" #include "InputHelper.h"
#include "OutputHelper.h" #include "OutputHelper.h"
#include "ServiceBooking.h"
#include "Enums.h"
#include "Service.h"
#include "InventoryItem.h"
/*
Function: showMenu
Description: Displays the admin menu and handles user input until the menu is exited.
Parameter: None
Return type: void
*/
void AdminMenu::showMenu() void AdminMenu::showMenu()
{ {
bool isMenuActive = true; bool isMenuActive = true;
@@ -46,384 +56,264 @@ void AdminMenu::changePassword()
{ {
} }
/*
Function: viewStockLevels
Description: Displays all active inventory items with their details
including ID, part name, quantity, and price.
Parameter: None
Return type: void
*/
void AdminMenu::viewStockLevels() void AdminMenu::viewStockLevels()
{ {
auto inventoryItems = m_controller.getInventoryItems();
std::cout << std::left << 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 < inventoryItems.getSize(); ++iterator)
{
const InventoryItem* item = inventoryItems.getValueAt(iterator);
if (item != nullptr)
{
if (item->getState() != util::State::INACTIVE)
{
std::cout << std::left << std::setw(15) << item->getId()
<< std::setw(25) << item->getPartName()
<< std::setw(10) << item->getQuantity()
<< std::setw(10) << item->getPrice()
<< std::endl;
}
}
}
} }
/*
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*>
*/
static util::Map<std::string, const InventoryItem*>
filterActiveItems(const util::Map<std::string, const InventoryItem*>& inventoryItems)
{
util::Map<std::string, const InventoryItem*> activeItems;
int inventorySize = inventoryItems.getSize();
for (int index = 0; index < inventorySize; index++)
{
const InventoryItem* item = inventoryItems.getValueAt(index);
if (item != nullptr && item->getState() != util::State::INACTIVE)
{
activeItems.insert(item->getId(), item);
}
}
return activeItems;
}
/*
Function: displayInventoryWithItems
Description: Displays inventory items in a tabular format with index, ID,
part name, quantity, and price.
Parameter: util::Map<std::string, const InventoryItem*>& inventoryItems -
map of inventory items to display
Return type: void
*/
static void displayInventoryWithItems(util::Map<std::string, const InventoryItem*>& inventoryItems)
{
int inventorySize = inventoryItems.getSize();
std::cout << std::left << std::setw(10) << "Index"
<< std::setw(15) << "Item ID"
<< std::setw(25) << "Part Name"
<< std::setw(10) << "Quantity"
<< std::setw(10) << "Price"
<< std::endl;
for (int iterator = 0; iterator < inventorySize; iterator++)
{
const InventoryItem* item = inventoryItems.getValueAt(iterator);
if (item != nullptr)
{
std::cout << std::left << std::setw(10) << (iterator + 1)
<< std::setw(15) << item->getId()
<< std::setw(25) << item->getPartName()
<< std::setw(10) << item->getQuantity()
<< std::setw(10) << item->getPrice()
<< std::endl;
}
}
}
/*
Function: addQuantityToItem
Description: Allows the admin to select an active inventory item and
increase its stock quantity.
Parameter: util::Map<std::string, const InventoryItem*>& inventoryItems -
map of inventory items
Controller& m_controller - controller instance to update stock
Return type: void
*/
static void addQuantityToItem(util::Map<std::string, const InventoryItem*>& inventoryItems, Controller& m_controller)
{
int itemIndex;
int quantity;
auto activeItems = filterActiveItems(inventoryItems);
int activeSize = activeItems.getSize();
if (activeSize == 0)
{
std::cout << "No active items available in Inventory" << std::endl;
return;
}
displayInventoryWithItems(activeItems);
std::cout << "Enter the index of the item to update: ";
util::read(itemIndex);
if (itemIndex < 1 || itemIndex > activeSize)
{
std::cout << "Invalid index selected." << std::endl;
return;
}
std::cout << "Enter quantity to add: ";
util::read(quantity);
if (quantity < 0)
{
std::cout << "The quantity should be Greater than 0." << std::endl;
return;
}
const InventoryItem* selectedItem = activeItems.getValueAt(itemIndex - 1);
if (selectedItem != nullptr)
{
std::string selectedItemId = selectedItem->getId();
m_controller.addInventoryItemStock(selectedItemId, quantity);
std::cout << "Updated " << selectedItem->getPartName()
<< " stock. New quantity: " << selectedItem->getQuantity()
<< std::endl;
}
else
{
std::cout << "Error: Selected item could not be found." << std::endl;
}
}
/*
Function: addInventoryItem
Description: Allows the admin to either add a new inventory item
or increase the quantity of an existing item.
Parameter: None
Return type: void
*/
void AdminMenu::addInventoryItem() void AdminMenu::addInventoryItem()
{
}
void AdminMenu::removeInventoryItem()
{
}
void AdminMenu::checkStockAvailability()
{
}
/*
Function: listServiceBookings (static helper)
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
*/
static bool listServiceBookings(util::Map<std::string, const ServiceBooking*>& currentBookings, int& bookingsSize, util::Map<int, const ServiceBooking*>& serviceBookingsMap)
{
int currentIndex = 1;
bool hasPendingService = false;
std::cout << std::left
<< std::setw(10) << "Index"
<< std::setw(10) << "ID"
<< std::setw(12) << "Status"
<< std::setw(12) << "CustID"
<< std::setw(20) << "Customer"
<< std::setw(15) << "VehicleNo"
<< std::setw(15) << "Brand"
<< std::setw(15) << "Model"
<< std::setw(20) << "Technician"
<< std::setw(15) << "TechID"
<< std::endl;
for (int iterator = 0; iterator < bookingsSize; iterator++)
{
const ServiceBooking* currentBooking = currentBookings.getValueAt(iterator);
if (currentBooking && currentBooking->getStatus() == util::ServiceJobStatus::PENDING)
{
hasPendingService = true;
std::cout << std::left
<< std::setw(10) << currentIndex
<< std::setw(10) << currentBooking->getId()
<< std::setw(12) << util::getServiceJobStatusString(currentBooking->getStatus())
<< std::setw(12) << currentBooking->getCustomerId()
<< std::setw(20) << currentBooking->getCustomer()->getName()
<< std::setw(15) << currentBooking->getVehicleNumber()
<< std::setw(15) << currentBooking->getVehicleBrand()
<< std::setw(15) << currentBooking->getVehicleModel()
<< std::setw(20) << (currentBooking->getAssignedTechnician() == nullptr ? "Null" : currentBooking->getAssignedTechnician()->getName())
<< std::setw(15) << (currentBooking->getAssignedTechnicianId().empty() ? "Null" : currentBooking->getAssignedTechnicianId())
<< std::endl;
serviceBookingsMap.insert(currentIndex++, currentBooking);
}
}
if (!hasPendingService)
{
std::cout << "No pending service available." << std::endl;
return false;
}
return true;
}
/*
Function: selectPendingServiceBookings (static helper)
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
*/
static const ServiceBooking* selectPendingServiceBookings(util::Map<int, const ServiceBooking*>& serviceBookingsMap)
{
int userInputIndex;
std::cout << "Enter a valid service index: ";
util::read(userInputIndex);
if (serviceBookingsMap.find(userInputIndex) != -1)
{
return serviceBookingsMap.getValueAt(userInputIndex);
}
else
{
std::cout << "Enter a valid index.";
return nullptr;
}
}
/*
Function: listAvailableTechnicians (static helper)
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
*/
static void listAvailableTechnicians( util::Map<std::string, const User*> currentAvailableTechnicians, int numberOfTechnicians, util::Map<int, const User*>& currentAvailableTechniciansMap)
{
bool hasTechnicians = false;
int currentIndex = 1;
std::cout << std::left
<< std::setw(6) << "Index"
<< std::setw(15) << "Technician ID"
<< std::setw(20) << "Name"
<< std::endl;
for (int iterator = 0; iterator < numberOfTechnicians; iterator++)
{
const User* currentTechnician = currentAvailableTechnicians.getValueAt(iterator);
if (currentTechnician->getState() == util::State::INACTIVE)
{
continue;
}
hasTechnicians = true;
std::cout << std::left
<< std::setw(6) << currentIndex
<< std::setw(15) << currentTechnician->getId()
<< std::setw(20) << currentTechnician->getName()
<< std::endl;
currentAvailableTechniciansMap.insert(currentIndex++, currentTechnician);
}
if (!hasTechnicians)
{
std::cout << "No technicians currently available.";
}
}
/*
Function: selectTechnician (static helper)
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
*/
static const User* selectTechnician(util::Map<int, const User*>& currentAvailableTechniciansMap)
{
int userInputIndex;
util::read(userInputIndex);
if (currentAvailableTechniciansMap.find(userInputIndex) != -1)
{
return currentAvailableTechniciansMap.getValueAt(userInputIndex);
}
else
{
std::cout << "Enter a valid index.";
return nullptr;
}
}
/*
Function: assignJob
Description: Allows the admin to assign pending service bookings to available technicians.
Creates job cards for selected services.
Parameters:
- None
Returns:
- void
*/
void AdminMenu::assignJob()
{ {
util::clear(); util::clear();
std::string selectedService; int choice, quantity;
bool hasPendingService = false; double price;
auto currentBookings = m_controller.getServiceBookings(); std::string partName;
auto availableTechnicians = m_controller.getUsers(util::UserType::TECHNICIAN); std::cout << "1. Add new item \n2. Add Quantity\nEnter your choice : ";
int bookingsSize = currentBookings.getSize(); util::read(choice);
util::Map<int, const ServiceBooking*> serviceBookingsMap; switch (choice)
util::Map<int, const User*> currentAvailableTechniciansMap;
if (listServiceBookings(currentBookings, bookingsSize, serviceBookingsMap))
{ {
const ServiceBooking* selectedService = selectPendingServiceBookings(serviceBookingsMap); case 1:
if (selectedService)
{ {
if (availableTechnicians.getSize() != 0) std::cout << "--------Enter Item Details----------\n";
{ std::cout << "Part Name : ";
listAvailableTechnicians(availableTechnicians, availableTechnicians.getSize(), currentAvailableTechniciansMap); util::read(partName);
const User* selectedTechnician = selectTechnician(currentAvailableTechniciansMap); std::cout << "Quantity : ";
if (selectedTechnician) util::read(quantity);
{ std::cout << "Price : ";
auto& servicesInBooking = selectedService->getServices(); util::read(price);
for (int iterator = 0; iterator < servicesInBooking.getSize(); iterator++) m_controller.addInventoryItem(partName, quantity, price);
{ std::cout << "New Item " << partName << " added to the Inventory.\n";
m_controller.createJobCard(selectedService->getId(), selectedTechnician->getId(), servicesInBooking.getValueAt(iterator)->getId());
}
}
}
else
{
std::cout << "No technicians are currently available.";
}
}
}
}
/*
Function: selectInventoryItems (static helper)
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
*/
static void selectInventoryItems(util::Map<std::string, const InventoryItem*>& currentInventoryItems, util::Vector<std::string>& selectedInventoryItems)
{
bool doRun = true, hasInventoryItems = false;
util::Map<int, const InventoryItem*> currentInventoryMap;
int currentIndex = 1;
int choice;
if (currentInventoryItems.getSize() == 0)
{
std::cout << "Inventory empty.";
}
while (doRun)
{
bool hasInventoryItems = false;
int currentIndex = 1;
currentInventoryMap.clear();
std::cout << std::left
<< std::setw(6) << "Index"
<< std::setw(12) << "Item ID"
<< std::setw(20) << "Part Name"
<< std::setw(10) << "Price"
<< std::setw(10) << "Quantity"
<< std::endl;
for (int iterator = 0; iterator < currentInventoryItems.getSize(); iterator++)
{
const InventoryItem* currentInventoryItem = currentInventoryItems.getValueAt(iterator);
if (currentInventoryItem->getState() == util::State::INACTIVE)
{
continue;
}
std::cout << std::left
<< std::setw(6) << currentIndex
<< std::setw(12) << currentInventoryItem->getId()
<< std::setw(20) << currentInventoryItem->getPartName()
<< std::setw(10) << currentInventoryItem->getPrice()
<< std::setw(10) << currentInventoryItem->getQuantity()
<< std::endl;
hasInventoryItems = true;
currentInventoryMap.insert(currentIndex++, currentInventoryItem);
}
if (!hasInventoryItems)
{
std::cout << "No items present in the inventory." << std::endl;
doRun = false;
break; break;
} }
std::cout << "Select the item (Index) or enter -1 to exit: "; case 2:
util::read(choice);
if (choice == -1)
{ {
doRun = false; auto inventoryItems = m_controller.getInventoryItems();
} addQuantityToItem(inventoryItems, m_controller);
else if (currentInventoryMap.find(choice) != -1) break;
{
selectedInventoryItems.push_back(currentInventoryMap.getValueAt(choice)->getId());
std::cout << "Item added successfully." << std::endl;
}
else
{
std::cout << "Enter a valid integer." << std::endl;
} }
} }
util::pressEnter();
} }
/* /*
Function: createService Function: removeInventoryItem
Description: Allows the admin to create a new service by selecting inventory items and specifying labor cost. Description: Removes an active inventory item by marking it inactive
Parameters: after user selection.
- None Parameter: None
Returns: Return type: void
- void
*/ */
void AdminMenu::removeInventoryItem()
{
util::clear();
auto inventoryItems = m_controller.getInventoryItems();
auto activeItems = filterActiveItems(inventoryItems);
int activeItemsSize = activeItems.getSize();
if (activeItemsSize == 0)
{
std::cout << "No items available in Inventory." << std::endl;
util::pressEnter();
return;
}
displayInventoryWithItems(activeItems);
int itemIndex;
std::cout << "Enter the index of the item to remove: ";
util::read(itemIndex);
if (itemIndex < 1 || itemIndex > activeItemsSize)
{
std::cout << "Invalid index selected." << std::endl;
util::pressEnter();
return;
}
const InventoryItem* selectedItem = inventoryItems.getValueAt(itemIndex - 1);
if (selectedItem != nullptr)
{
if(selectedItem->getState() != util::State::INACTIVE)
{
std::string selectedItemId = selectedItem->getId();
m_controller.removeInventoryItem(selectedItemId);
std::cout << "Item " << selectedItem->getPartName() << " removed successfully." << std::endl;
}
}
util::pressEnter();
}
/*
Function: checkStockAvailability
Description: Checks if a specific inventory item is available
and displays its details if active.
Parameter: None
Return type: void
*/
void AdminMenu::checkStockAvailability()
{
util::clear();
std::string itemId;
std::cout << "Enter the Item Id : ";
util::read(itemId);
const InventoryItem* selectedItem = m_controller.getInventoryItem(itemId);
if (selectedItem != nullptr)
{
if (selectedItem->getState() != util::State::INACTIVE)
{
std::cout << "Item Details\n";
std::cout << "---------------------------------------------\n";
std::cout << "Item ID : " << selectedItem->getId() << "\n";
std::cout << "Part Name : " << selectedItem->getPartName() << "\n";
std::cout << "Quantity : " << selectedItem->getQuantity() << "\n";
}
}
util::pressEnter();
}
void AdminMenu::assignJob()
{
}
void AdminMenu::createService() void AdminMenu::createService()
{ {
util::clear();
std::string serviceName;
double labourCost;
std::cout << "Enter the service name: ";
util::read(serviceName);
util::Map<std::string, const InventoryItem*> currentInventoryItems = m_controller.getInventoryItems();
util::Vector<std::string> selectedInventoryItems;
selectInventoryItems(currentInventoryItems,selectedInventoryItems);
std::cout << "Enter the labour cost: ";
util::read(labourCost);
m_controller.createService(serviceName, selectedInventoryItems, labourCost);
std::cout << "Service created sucessfully.\n";
} }
/*
Function: selectServicesToRemove (static helper)
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
*/
static std::string selectServicesToRemove(util::Map<std::string, const Service*> currentServices)
{
util::Map<int, const Service*> currentServicesMap;
bool hasServices = false;
int currentIndex = 1, choice;
std::cout << std::left
<< std::setw(6) << "Index"
<< std::setw(12) << "Service ID"
<< std::setw(20) << "Name"
<< std::setw(10) << "Labor Cost"
<< std::endl;
for (int iterator = 0; iterator < currentServices.getSize(); iterator++)
{
const Service* currentService = currentServices.getValueAt(iterator);
if (currentService->getState() == util::State::INACTIVE)
{
continue;
}
std::cout << std::left
<< std::setw(6) << currentIndex
<< std::setw(12) << currentService->getId()
<< std::setw(20) << currentService->getName()
<< std::setw(10) << currentService->getLaborCost()
<< std::endl;
hasServices = true;
currentServicesMap.insert(currentIndex++, currentService);
}
if (!hasServices)
{
std::cout << "No services currently available." << std::endl;
return "";
}
std::cout << "Enter your choice: ";
util::read(choice);
if (currentServicesMap.find(choice) != -1)
{
return currentServicesMap.getValueAt(currentServicesMap.find(choice))->getId();
}
else
{
std::cout << "Invalid choice." << std::endl;
return "";
}
}
/*
Function: removeService
Description: Allows the admin to remove an existing service by selecting from available services.
Parameters:
- None
Returns:
- void
*/
void AdminMenu::removeService() void AdminMenu::removeService()
{ {
util::clear();
std::string selectedServiceID;
util::Map<std::string, const Service*> currentServices = m_controller.getServices();
selectedServiceID = selectServicesToRemove(currentServices);
if (selectedServiceID != "")
{
m_controller.removeService(selectedServiceID);
std::cout << "Service removed sucessfully.";
}
else
{
std::cout << "Failed to remove service.";
}
} }
void AdminMenu::addTechnician() void AdminMenu::addTechnician()
@@ -1,3 +1,11 @@
/*
File: AdminMenu.h
Description: Header file declaring the AdminMenu class, which provides
administrative operations such as inventory management,
user management, service configuration, and notifications.
Author: Trenser
Date:19-May-2026
*/
#pragma once #pragma once
#include "Controller.h" #include "Controller.h"
@@ -1,10 +1,6 @@
#include <iomanip>
#include "CustomerMenu.h" #include "CustomerMenu.h"
#include "InputHelper.h" #include "InputHelper.h"
#include "OutputHelper.h" #include "OutputHelper.h"
#include "User.h"
#include "ServiceBooking.h"
#include "Enums.h"
void CustomerMenu::showMenu() void CustomerMenu::showMenu()
{ {
@@ -55,55 +51,8 @@ void CustomerMenu::selectComboPackage()
{ {
} }
/*
Function: viewServiceHistory
Description: Displays the customers past service bookings in tabular format,
including booking ID, technician, vehicle details, discount percentage, and status.
Parameters:
- None
Returns:
- void
*/
void CustomerMenu::viewServiceHistory() void CustomerMenu::viewServiceHistory()
{ {
util::clear();
bool hasServiceHistory = false;
const User* currentUser = m_controller.getAuthenticatedUser();
std::string currentUserID = currentUser->getId();
util::Map<std::string, const ServiceBooking*> serviceBookingsByCurrentUser = m_controller.getServiceBookingsByUser(currentUserID);
if (serviceBookingsByCurrentUser.getSize() != 0)
{
std::cout << std::left
<< std::setw(12) << "Booking ID"
<< std::setw(20) << "Technician"
<< std::setw(15) << "Vehicle Brand"
<< std::setw(15) << "Vehicle Number"
<< std::setw(15) << "Vehicle Model"
<< std::setw(10) << "Discount %"
<< std::setw(12) << "Status"
<< std::endl;
for (int iterator = 0; iterator < serviceBookingsByCurrentUser.getSize(); iterator++)
{
const ServiceBooking* currentBooking = serviceBookingsByCurrentUser.getValueAt(iterator);
std::string technicianName = currentBooking->getAssignedTechnician() == nullptr
? "Not Assigned"
: currentBooking->getAssignedTechnician()->getName();
std::cout << std::left
<< std::setw(12) << currentBooking->getId()
<< std::setw(20) << technicianName
<< std::setw(15) << currentBooking->getVehicleBrand()
<< std::setw(15) << currentBooking->getVehicleNumber()
<< std::setw(15) << currentBooking->getVehicleModel()
<< std::setw(10) << currentBooking->getDiscountPercentage()
<< std::setw(12) << util::getServiceJobStatusString(currentBooking->getStatus())
<< std::endl;
hasServiceHistory = true;
}
}
if (!hasServiceHistory)
{
std::cout << "No history available." << std::endl;
}
} }
void CustomerMenu::completePayments() void CustomerMenu::completePayments()
@@ -1,10 +1,6 @@
#include <iomanip>
#include "TechnicianMenu.h" #include "TechnicianMenu.h"
#include "InputHelper.h" #include "InputHelper.h"
#include "OutputHelper.h" #include "OutputHelper.h"
#include "JobCard.h"
#include "Enums.h"
#include "Service.h"
void TechnicianMenu::showMenu() void TechnicianMenu::showMenu()
{ {
@@ -35,86 +31,8 @@ bool TechnicianMenu::handleOperation(int choice)
return false; return false;
} }
/*
Function: selectJobCardToComplete (static helper)
Description: Lists all incomplete job cards assigned to the technician and allows selection by index.
Parameters:
- assignedJobCards: util::Map<std::string, const JobCard*>&, job cards assigned to the technician
- incompleteJobCards: util::Map<int, const JobCard*>&, map of incomplete job cards indexed for selection
Returns:
- std::string: ID of the selected job card, or empty string if none selected
*/
static std::string selectJobCardToComplete(util::Map<std::string, const JobCard*>& assignedJobCards, util::Map<int, const JobCard*>& incompleteJobCards)
{
int currentIndex = 1;
int choice;
bool hasIncompleteJobCard = false;
std::cout << std::left
<< std::setw(6) << "Index"
<< std::setw(12) << "BookingID"
<< std::setw(12) << "JobID"
<< std::setw(20) << "ServiceName"
<< std::setw(12) << "ServiceID"
<< std::endl;
for (int iterator = 0; iterator < assignedJobCards.getSize(); iterator++)
{
const JobCard* currentJobCard = assignedJobCards.getValueAt(iterator);
if (currentJobCard && (currentJobCard->getStatus() == util::ServiceJobStatus::STARTED))
{
std::cout << std::left << std::setw(6) << currentIndex
<< std::setw(12) << currentJobCard->getBookingId()
<< std::setw(12) << currentJobCard->getId()
<< std::setw(20) << currentJobCard->getService()->getName()
<< std::setw(12) << currentJobCard->getServiceId()
<< std::endl;
hasIncompleteJobCard = true;
incompleteJobCards.insert(currentIndex++, currentJobCard);
}
}
if (!hasIncompleteJobCard)
{
std::cout << "No pending jobs are present.\n";
return "";
}
std::cout << "Select the Job Card to complete (Index): ";
util::read(choice);
int selectedJobCardIndex = incompleteJobCards.find(choice);
if (selectedJobCardIndex != -1)
{
const JobCard* selectedJobCard = incompleteJobCards.getValueAt(selectedJobCardIndex);
return selectedJobCard->getId();
}
else
{
std::cout << "Invalid choice.\n";
return "";
}
}
/*
Function: completeJob
Description: Allows the technician to mark a selected job card as completed.
Validates selection and updates job status through the controller.
Parameters:
- None
Returns:
- void
*/
void TechnicianMenu::completeJob() void TechnicianMenu::completeJob()
{ {
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
{
m_controller.completeJob(selectedJobID);
std::cout << "Job marked as completed.\n";
}
} }
void TechnicianMenu::viewNotifications() void TechnicianMenu::viewNotifications()