Merge branch 'feature-file-management' into feature

This commit is contained in:
2026-05-22 16:25:59 +05:30
41 changed files with 1566 additions and 70 deletions
@@ -173,9 +173,12 @@
<ClInclude Include="services\UserManagementService.h" /> <ClInclude Include="services\UserManagementService.h" />
<ClInclude Include="utilities\Config.h" /> <ClInclude Include="utilities\Config.h" />
<ClInclude Include="utilities\Enums.h" /> <ClInclude Include="utilities\Enums.h" />
<ClInclude Include="utilities\FileHelper.h" />
<ClInclude Include="utilities\FileManager.h" />
<ClInclude Include="utilities\InputHelper.h" /> <ClInclude Include="utilities\InputHelper.h" />
<ClInclude Include="utilities\Map.h" /> <ClInclude Include="utilities\Map.h" />
<ClInclude Include="utilities\OutputHelper.h" /> <ClInclude Include="utilities\OutputHelper.h" />
<ClInclude Include="utilities\StringHelper.h" />
<ClInclude Include="utilities\Timestamp.h" /> <ClInclude Include="utilities\Timestamp.h" />
<ClInclude Include="utilities\Utility.h" /> <ClInclude Include="utilities\Utility.h" />
<ClInclude Include="utilities\Validator.h" /> <ClInclude Include="utilities\Validator.h" />
@@ -242,5 +242,14 @@
<ClInclude Include="utilities\Config.h"> <ClInclude Include="utilities\Config.h">
<Filter>Header Files\Utilities</Filter> <Filter>Header Files\Utilities</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="utilities\FileManager.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
<ClInclude Include="utilities\StringHelper.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
<ClInclude Include="utilities\FileHelper.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>
@@ -423,6 +423,34 @@ void Controller::configureNotifications(bool paymentNotifications, bool serviceN
} }
} }
void Controller::loadSystemData()
{
m_userManagementService.loadUsers();
m_inventoryManagementService.loadInventoryItems();
m_serviceManagementService.loadServices();
m_serviceManagementService.loadComboPackages();
m_serviceManagementService.loadServiceBookings();
m_serviceManagementService.loadJobCards();
m_paymentManagementService.loadInvoices();
m_serviceManagementService.loadObservers();
m_paymentManagementService.loadObservers();
m_inventoryManagementService.loadObservers();
}
void Controller::saveSystemData()
{
m_userManagementService.saveUsers();
m_inventoryManagementService.saveInventoryItems();
m_serviceManagementService.saveServices();
m_serviceManagementService.saveComboPackages();
m_serviceManagementService.saveServiceBookings();
m_serviceManagementService.saveJobCards();
m_paymentManagementService.saveInvoices();
m_serviceManagementService.saveObservers();
m_paymentManagementService.saveObservers();
m_inventoryManagementService.saveObservers();
}
/* /*
Function: runSystemChecks Function: runSystemChecks
Description: Executes system checks including sending low stock alerts Description: Executes system checks including sending low stock alerts
@@ -67,5 +67,7 @@ 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(bool paymentNotifications, bool serviceNotifications); void configureNotifications(bool paymentNotifications, bool serviceNotifications);
void loadSystemData();
void saveSystemData();
void runSystemChecks(); void runSystemChecks();
}; };
@@ -8,6 +8,7 @@ Date: 19-May-2026
#pragma once #pragma once
#include <string> #include <string>
#include "Map.h" #include "Map.h"
#include "Vector.h"
class User; class User;
class Notification; class Notification;
@@ -0,0 +1 @@
Place files here.
@@ -7,7 +7,12 @@ Author: Trenser
Date: 19-May-2026 Date: 19-May-2026
*/ */
#include <sstream>
#include <stdexcept>
#include "ComboPackage.h" #include "ComboPackage.h"
#include "Service.h"
#include "Factory.h"
#include "StringHelper.h"
int ComboPackage::m_uid = 0; int ComboPackage::m_uid = 0;
@@ -41,7 +46,29 @@ ComboPackage::ComboPackage(const std::string& packageName, double discountPercen
m_packageName(packageName), m_packageName(packageName),
m_discountPercentage(discountPercentage), m_discountPercentage(discountPercentage),
m_status(util::State::ACTIVE), m_status(util::State::ACTIVE),
m_services(services) {} m_services(services)
{
int numberOfServices = m_services.getSize();
auto servicePointers = m_services.getValues();
for (int index = 0; index < numberOfServices; index++)
{
m_serviceIDs.push_back(servicePointers[index]->getId());
}
}
ComboPackage::ComboPackage(const std::string& id, const std::string& packageName, double discountPercentage, const util::Vector<std::string>& serviceIDs, util::State status)
: m_id(id),
m_packageName(packageName),
m_discountPercentage(discountPercentage),
m_serviceIDs(serviceIDs),
m_status(status)
{
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
{
m_uid = idNumber;
}
}
/* /*
Function: getId Function: getId
@@ -95,6 +122,11 @@ util::State ComboPackage::getState() const
return m_status; return m_status;
} }
const util::Vector<std::string>& ComboPackage::getServiceIDs() const
{
return m_serviceIDs;
}
/* /*
Function: getServices Function: getServices
Description: Retrieves the map of services included in the combo package. Description: Retrieves the map of services included in the combo package.
@@ -158,6 +190,13 @@ Returns:
void ComboPackage::setServices(const util::Map<std::string, Service*>& services) void ComboPackage::setServices(const util::Map<std::string, Service*>& services)
{ {
m_services = services; m_services = services;
m_serviceIDs.clear();
int numberOfServices = m_services.getSize();
auto servicePointers = m_services.getValues();
for (int index = 0; index < numberOfServices; index++)
{
m_serviceIDs.push_back(servicePointers[index]->getId());
}
} }
/* /*
@@ -172,3 +211,76 @@ void ComboPackage::setState(util::State status)
{ {
m_status = status; m_status = status;
} }
static std::string getServiceIDsAsString(const util::Vector<std::string>& serviceIDs)
{
int numberOfServices = serviceIDs.getSize();
std::string serviceIDsString;
for (int index = 0; index < numberOfServices; index++)
{
serviceIDsString += serviceIDs[index];
if (index < numberOfServices - 1)
{
serviceIDsString += '|';
}
}
return serviceIDsString;
}
static util::Vector<std::string> getServiceIDsAsVector(const std::string& serviceIDsString)
{
util::Vector<std::string> serviceIDs;
std::string serviceID;
std::istringstream serializedServiceIDs(serviceIDsString);
while (getline(serializedServiceIDs, serviceID, '|'))
{
serviceIDs.push_back(serviceID);
}
return serviceIDs;
}
std::string ComboPackage::serialize() const
{
std::ostringstream serializedComboPackage;
serializedComboPackage << m_id << ','
<< m_packageName << ','
<< m_discountPercentage << ','
<< getServiceIDsAsString(m_serviceIDs) << ','
<< util::getStateString(m_status);
return serializedComboPackage.str();
}
ComboPackage* ComboPackage::deserialize(const std::string& record)
{
std::string id, packageName;
std::string discountPercentageString, serviceIDsString, statusString;
double discountPercentage;
std::istringstream serializedComboPackage(record);
getline(serializedComboPackage, id, ',');
getline(serializedComboPackage, packageName, ',');
getline(serializedComboPackage, discountPercentageString, ',');
getline(serializedComboPackage, serviceIDsString, ',');
getline(serializedComboPackage, statusString, ',');
try
{
discountPercentage = std::stod(discountPercentageString);
}
catch (...)
{
throw std::runtime_error("Invalid combo package data");
}
util::Vector<std::string> serviceIDs = getServiceIDsAsVector(serviceIDsString);
util::State status = util::getState(statusString);
return Factory::getObject<ComboPackage>(
id,
packageName,
discountPercentage,
serviceIDs,
status
);
}
std::string ComboPackage::getHeaders()
{
return "ID,PackageName,DiscountPercentage,ServiceIDs,Status";
}
@@ -8,6 +8,7 @@ Date: 19-May-2026
#pragma once #pragma once
#include <string> #include <string>
#include "Map.h" #include "Map.h"
#include "Vector.h"
#include "Enums.h" #include "Enums.h"
class Service; class Service;
@@ -19,14 +20,17 @@ private:
std::string m_id; std::string m_id;
std::string m_packageName; std::string m_packageName;
double m_discountPercentage; double m_discountPercentage;
util::Vector<std::string> m_serviceIDs;
util::Map<std::string, Service*> m_services; util::Map<std::string, Service*> m_services;
util::State m_status; util::State m_status;
public: public:
ComboPackage(); ComboPackage();
ComboPackage(const std::string& packageName, double discountPercentage, const util::Map<std::string, Service*>& services); ComboPackage(const std::string& packageName, double discountPercentage, const util::Map<std::string, Service*>& services);
ComboPackage(const std::string& id, const std::string& packageName, double discountPercentage, const util::Vector<std::string>& serviceIDs, util::State status);
const std::string& getId() const; const std::string& getId() const;
const std::string& getPackageName() const; const std::string& getPackageName() const;
double getDiscountPercentage() const; double getDiscountPercentage() const;
const util::Vector<std::string>& getServiceIDs() const;
const util::Map<std::string, Service*>& getServices() const; const util::Map<std::string, Service*>& getServices() const;
util::State getState() const; util::State getState() const;
void setId(const std::string& id); void setId(const std::string& id);
@@ -34,4 +38,7 @@ public:
void setDiscountPercentage(double discountPercentage); void setDiscountPercentage(double discountPercentage);
void setServices(const util::Map<std::string, Service*>& services); void setServices(const util::Map<std::string, Service*>& services);
void setState(util::State status); void setState(util::State status);
std::string serialize() const;
static ComboPackage* deserialize(const std::string&);
static std::string getHeaders();
}; };
@@ -6,7 +6,11 @@ Author: Trenser
Date: 19-May-2026 Date: 19-May-2026
*/ */
#include <sstream>
#include <stdexcept>
#include "InventoryItem.h" #include "InventoryItem.h"
#include "Factory.h"
#include "StringHelper.h"
int InventoryItem::m_uid = 0; int InventoryItem::m_uid = 0;
@@ -43,6 +47,20 @@ InventoryItem::InventoryItem(const std::string& partName, int quantity, double p
m_status(util::State::ACTIVE), m_status(util::State::ACTIVE),
m_price(price) {} m_price(price) {}
InventoryItem::InventoryItem(const std::string& id, const std::string& partName, int quantity, double price, util::State status)
: m_id(id),
m_partName(partName),
m_quantity(quantity),
m_status(status),
m_price(price)
{
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
{
m_uid = idNumber;
}
}
/* /*
Function: getId Function: getId
Description: Retrieves the unique ID of the inventory item. Description: Retrieves the unique ID of the inventory item.
@@ -171,4 +189,51 @@ Returns:
void InventoryItem::setState(util::State status) void InventoryItem::setState(util::State status)
{ {
m_status = status; m_status = status;
} }
std::string InventoryItem::serialize() const
{
std::ostringstream serializedInventoryItem;
serializedInventoryItem << m_id << ','
<< m_partName << ','
<< m_quantity << ','
<< m_price << ','
<< util::getStateString(m_status);
return serializedInventoryItem.str();
}
InventoryItem* InventoryItem::deserialize(const std::string& record)
{
std::string id, partName;
std::string quantityString, priceString, statusString;
int quantity;
double price;
std::istringstream serializedInventoryItem(record);
getline(serializedInventoryItem, id, ',');
getline(serializedInventoryItem, partName, ',');
getline(serializedInventoryItem, quantityString, ',');
getline(serializedInventoryItem, priceString, ',');
getline(serializedInventoryItem, statusString, ',');
try
{
quantity = std::stoi(quantityString);
price = std::stod(priceString);
}
catch (...)
{
throw std::runtime_error("Invalid inventory item data");
}
util::State status = util::getState(statusString);
return Factory::getObject<InventoryItem>(
id,
partName,
quantity,
price,
status
);
}
std::string InventoryItem::getHeaders()
{
return "ID,PartName,Quantity,Price,Status";
}
@@ -23,6 +23,7 @@ private:
public: public:
InventoryItem(); InventoryItem();
InventoryItem(const std::string& partName, int quantity, double price); InventoryItem(const std::string& partName, int quantity, double price);
InventoryItem(const std::string& id, const std::string& partName, int quantity, double price, util::State status);
const std::string& getId() const; const std::string& getId() const;
const std::string& getPartName() const; const std::string& getPartName() const;
int getQuantity() const; int getQuantity() const;
@@ -33,4 +34,7 @@ public:
void setQuantity(int quantity); void setQuantity(int quantity);
void setPrice(double price); void setPrice(double price);
void setState(util::State status); void setState(util::State status);
std::string serialize() const;
static InventoryItem* deserialize(const std::string&);
static std::string getHeaders();
}; };
@@ -7,7 +7,12 @@ Author: Trenser
Date: 19-May-2026 Date: 19-May-2026
*/ */
#include <sstream>
#include <stdexcept>
#include "Invoice.h" #include "Invoice.h"
#include "Factory.h"
#include "InventoryItem.h"
#include "StringHelper.h"
int Invoice::m_uid = 0; int Invoice::m_uid = 0;
@@ -74,14 +79,49 @@ Invoice::Invoice(
m_totalAmount(totalAmount), m_totalAmount(totalAmount),
m_paymentDate(paymentDate), m_paymentDate(paymentDate),
m_paymentMethod(paymentMethod), m_paymentMethod(paymentMethod),
m_status(status) {} m_status(status)
{
int numberOfParts = m_parts.getSize();
auto partPointers = m_parts.getValues();
for (int index = 0; index < numberOfParts; index++)
{
m_partIDs.push_back(partPointers[index]->getId());
}
}
Invoice::Invoice(
const std::string& id,
const std::string& bookingId,
const util::Timestamp& invoiceDate,
const util::Vector<std::string>& partIDs,
double laborCost,
double partsCost,
double discountPercentage,
double totalAmount,
const util::Timestamp& paymentDate,
util::PaymentMode paymentMethod,
util::PaymentStatus status
)
: m_id(id),
m_bookingId(bookingId),
m_booking(nullptr),
m_invoiceDate(invoiceDate),
m_partIDs(partIDs),
m_laborCost(laborCost),
m_partsCost(partsCost),
m_discountPercentage(discountPercentage),
m_totalAmount(totalAmount),
m_paymentDate(paymentDate),
m_paymentMethod(paymentMethod),
m_status(status)
{
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
{
m_uid = idNumber;
}
}
/*
Function: getId
Description: Retrieves the unique ID of the invoice.
Returns:
- const std::string& representing the invoice ID.
*/
const std::string& Invoice::getId() const const std::string& Invoice::getId() const
{ {
return m_id; return m_id;
@@ -131,6 +171,11 @@ double Invoice::getLaborCost() const
return m_laborCost; return m_laborCost;
} }
const util::Vector<std::string>& Invoice::getPartIDs() const
{
return m_partIDs;
}
/* /*
Function: getParts Function: getParts
Description: Retrieves the map of inventory items used in the service. Description: Retrieves the map of inventory items used in the service.
@@ -284,6 +329,13 @@ Returns:
void Invoice::setParts(const util::Map<std::string, InventoryItem*>& parts) void Invoice::setParts(const util::Map<std::string, InventoryItem*>& parts)
{ {
m_parts = parts; m_parts = parts;
m_partIDs.clear();
int numberOfParts = m_parts.getSize();
auto partPointers = m_parts.getValues();
for (int index = 0; index < numberOfParts; index++)
{
m_partIDs.push_back(partPointers[index]->getId());
}
} }
/* /*
@@ -362,4 +414,105 @@ Returns:
void Invoice::setStatus(util::PaymentStatus status) void Invoice::setStatus(util::PaymentStatus status)
{ {
m_status = status; m_status = status;
} }
static std::string getPartIDsAsString(const util::Vector<std::string>& partIDs)
{
int numberOfParts = partIDs.getSize();
std::string partIDsString;
for (int index = 0; index < numberOfParts; index++)
{
partIDsString += partIDs[index];
if (index < numberOfParts - 1)
{
partIDsString += '|';
}
}
return partIDsString;
}
static util::Vector<std::string> getPartIDsAsVector(const std::string& partIDsString)
{
util::Vector<std::string> partIDs;
std::string partID;
std::istringstream serializedPartIDs(partIDsString);
while (getline(serializedPartIDs, partID, '|'))
{
partIDs.push_back(partID);
}
return partIDs;
}
std::string Invoice::serialize() const
{
std::ostringstream serializedInvoice;
serializedInvoice << m_id << ','
<< m_bookingId << ','
<< m_invoiceDate.toString() << ','
<< m_laborCost << ','
<< getPartIDsAsString(m_partIDs) << ','
<< m_partsCost << ','
<< m_discountPercentage << ','
<< m_totalAmount << ','
<< m_paymentDate.toString() << ','
<< util::getPaymentModeString(m_paymentMethod) << ','
<< util::getPaymentStatusString(m_status);
return serializedInvoice.str();
}
Invoice* Invoice::deserialize(const std::string& record)
{
std::string id, bookingId;
std::string invoiceDateString, laborCostString, partIDsString;
std::string partsCostString, discountPercentageString, totalAmountString;
std::string paymentDateString, paymentMethodString, statusString;
double laborCost, partsCost, discountPercentage, totalAmount;
std::istringstream serializedInvoice(record);
getline(serializedInvoice, id, ',');
getline(serializedInvoice, bookingId, ',');
getline(serializedInvoice, invoiceDateString, ',');
getline(serializedInvoice, laborCostString, ',');
getline(serializedInvoice, partIDsString, ',');
getline(serializedInvoice, partsCostString, ',');
getline(serializedInvoice, discountPercentageString, ',');
getline(serializedInvoice, totalAmountString, ',');
getline(serializedInvoice, paymentDateString, ',');
getline(serializedInvoice, paymentMethodString, ',');
getline(serializedInvoice, statusString, ',');
util::Timestamp invoiceDate;
util::Timestamp paymentDate;
try
{
invoiceDate = util::Timestamp::fromString(invoiceDateString);
paymentDate = util::Timestamp::fromString(paymentDateString);
laborCost = std::stod(laborCostString);
partsCost = std::stod(partsCostString);
discountPercentage = std::stod(discountPercentageString);
totalAmount = std::stod(totalAmountString);
}
catch (...)
{
throw std::runtime_error("Invalid invoice data");
}
util::Vector<std::string> partIDs = getPartIDsAsVector(partIDsString);
util::PaymentMode paymentMethod = util::getPaymentMode(paymentMethodString);
util::PaymentStatus status = util::getPaymentStatus(statusString);
return Factory::getObject<Invoice>(
id,
bookingId,
invoiceDate,
partIDs,
laborCost,
partsCost,
discountPercentage,
totalAmount,
paymentDate,
paymentMethod,
status
);
}
std::string Invoice::getHeaders()
{
return "ID,BookingID,InvoiceDate,LaborCost,PartIDs,PartsCost,DiscountPercentage,TotalAmount,PaymentDate,PaymentMethod,Status";
}
@@ -10,6 +10,7 @@ Date: 19-May-2026
#pragma once #pragma once
#include <string> #include <string>
#include "Map.h" #include "Map.h"
#include "Vector.h"
#include "Timestamp.h" #include "Timestamp.h"
#include "Enums.h" #include "Enums.h"
@@ -25,6 +26,7 @@ private:
ServiceBooking* m_booking; ServiceBooking* m_booking;
util::Timestamp m_invoiceDate; util::Timestamp m_invoiceDate;
double m_laborCost; double m_laborCost;
util::Vector<std::string> m_partIDs;
util::Map<std::string, InventoryItem*> m_parts; util::Map<std::string, InventoryItem*> m_parts;
double m_partsCost; double m_partsCost;
double m_discountPercentage; double m_discountPercentage;
@@ -32,7 +34,6 @@ private:
util::Timestamp m_paymentDate; util::Timestamp m_paymentDate;
util::PaymentMode m_paymentMethod; util::PaymentMode m_paymentMethod;
util::PaymentStatus m_status; util::PaymentStatus m_status;
public: public:
Invoice(); Invoice();
Invoice( Invoice(
@@ -48,11 +49,25 @@ public:
util::PaymentMode paymentMethod, util::PaymentMode paymentMethod,
util::PaymentStatus status util::PaymentStatus status
); );
Invoice(
const std::string& id,
const std::string& bookingId,
const util::Timestamp& invoiceDate,
const util::Vector<std::string>& partIDs,
double laborCost,
double partsCost,
double discountPercentage,
double totalAmount,
const util::Timestamp& paymentDate,
util::PaymentMode paymentMethod,
util::PaymentStatus status
);
const std::string& getId() const; const std::string& getId() const;
const std::string& getBookingId() const; const std::string& getBookingId() const;
ServiceBooking* getBooking() const; ServiceBooking* getBooking() const;
const util::Timestamp& getInvoiceDate() const; const util::Timestamp& getInvoiceDate() const;
double getLaborCost() const; double getLaborCost() const;
const util::Vector<std::string>& getPartIDs() const;
const util::Map<std::string, InventoryItem*>& getParts() const; const util::Map<std::string, InventoryItem*>& getParts() const;
double getPartsCost() const; double getPartsCost() const;
double getDiscountPercentage() const; double getDiscountPercentage() const;
@@ -72,4 +87,7 @@ public:
void setPaymentDate(const util::Timestamp& paymentDate); void setPaymentDate(const util::Timestamp& paymentDate);
void setPaymentMethod(util::PaymentMode paymentMethod); void setPaymentMethod(util::PaymentMode paymentMethod);
void setStatus(util::PaymentStatus status); void setStatus(util::PaymentStatus status);
std::string serialize() const;
static Invoice* deserialize(const std::string&);
static std::string getHeaders();
}; };
@@ -6,7 +6,12 @@ Description: Implementation file containing the method definitions of the
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#include <sstream>
#include <stdexcept>
#include "JobCard.h" #include "JobCard.h"
#include "Factory.h"
#include "StringHelper.h"
#include "Enums.h"
int JobCard::m_uid = 0; int JobCard::m_uid = 0;
@@ -62,6 +67,32 @@ JobCard::JobCard(const std::string& bookingId,
m_status(status), m_status(status),
m_completionDate(completionDate) {} m_completionDate(completionDate) {}
JobCard::JobCard(const std::string& id,
const std::string& bookingId,
const std::string& serviceId,
const std::string& technicianId,
const util::Timestamp& assignedDate,
util::ServiceJobStatus status,
const util::Timestamp& completionDate
)
: m_id(id),
m_bookingId(bookingId),
m_booking(nullptr),
m_service(nullptr),
m_serviceId(serviceId),
m_technicianId(technicianId),
m_technician(nullptr),
m_assignedDate(assignedDate),
m_status(status),
m_completionDate(completionDate)
{
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
{
m_uid = idNumber;
}
}
/* /*
Function: getId Function: getId
Description: Retrieves the unique ID of the job card. Description: Retrieves the unique ID of the job card.
@@ -298,4 +329,57 @@ Returns:
void JobCard::setCompletionDate(const util::Timestamp& completionDate) void JobCard::setCompletionDate(const util::Timestamp& completionDate)
{ {
m_completionDate = completionDate; m_completionDate = completionDate;
}
std::string JobCard::serialize() const
{
std::ostringstream serializedJobCard;
serializedJobCard << m_id << ','
<< m_bookingId << ','
<< m_serviceId << ','
<< m_technicianId << ','
<< m_assignedDate.toString() << ','
<< util::getServiceJobStatusString(m_status) << ','
<< m_completionDate.toString();
return serializedJobCard.str();
}
JobCard* JobCard::deserialize(const std::string& record)
{
std::string id, bookingId, serviceId, technicianId;
std::string assignedDateString, statusString, completionDateString;
std::istringstream serializedJobCard(record);
getline(serializedJobCard, id, ',');
getline(serializedJobCard, bookingId, ',');
getline(serializedJobCard, serviceId, ',');
getline(serializedJobCard, technicianId, ',');
getline(serializedJobCard, assignedDateString, ',');
getline(serializedJobCard, statusString, ',');
getline(serializedJobCard, completionDateString, ',');
util::Timestamp assignedDate;
util::Timestamp completionDate;
try
{
assignedDate = util::Timestamp::fromString(assignedDateString);
completionDate = util::Timestamp::fromString(completionDateString);
}
catch (...)
{
throw std::runtime_error("Invalid timestamp");
}
util::ServiceJobStatus status = util::getServiceJobStatus(statusString);
return Factory::getObject<JobCard>(
id,
bookingId,
serviceId,
technicianId,
assignedDate,
status,
completionDate
);
}
std::string JobCard::getHeaders()
{
return "ID,BookingID,ServiceID,TechnicianID,AssignedDate,Status,CompletionDate";
} }
@@ -42,6 +42,14 @@ public:
util::ServiceJobStatus status, util::ServiceJobStatus status,
const util::Timestamp& completionDate const util::Timestamp& completionDate
); );
JobCard(const std::string& id,
const std::string& bookingId,
const std::string& serviceId,
const std::string& technicianId,
const util::Timestamp& assignedDate,
util::ServiceJobStatus status,
const util::Timestamp& completionDate
);
const std::string& getId() const; const std::string& getId() const;
const std::string& getBookingId() const; const std::string& getBookingId() const;
ServiceBooking* getBooking() const; ServiceBooking* getBooking() const;
@@ -62,4 +70,7 @@ public:
void setAssignedDate(const util::Timestamp& assignedDate); void setAssignedDate(const util::Timestamp& assignedDate);
void setStatus(util::ServiceJobStatus status); void setStatus(util::ServiceJobStatus status);
void setCompletionDate(const util::Timestamp& completionDate); void setCompletionDate(const util::Timestamp& completionDate);
std::string serialize() const;
static JobCard* deserialize(const std::string&);
static std::string getHeaders();
}; };
@@ -6,7 +6,10 @@ Author: Trenser
Date: 19-May-2026 Date: 19-May-2026
*/ */
#include <sstream>
#include "Notification.h" #include "Notification.h"
#include "StringHelper.h"
#include "Factory.h"
int Notification::m_uid = 0; int Notification::m_uid = 0;
@@ -42,6 +45,21 @@ Notification::Notification(const std::string& recipientUserId, User* recipient,
m_message(message), m_message(message),
m_createdAt(createdAt) {} m_createdAt(createdAt) {}
Notification::Notification(const std::string& id, const std::string& recipientUserId, const std::string& title, const std::string& message, const util::Timestamp& createdAt)
: m_id(id),
m_recipientUserId(recipientUserId),
m_recipient(nullptr),
m_title(title),
m_message(message),
m_createdAt(createdAt)
{
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
{
m_uid = idNumber;
}
}
/* /*
Function: getId Function: getId
Description: Retrieves the unique ID of the notification. Description: Retrieves the unique ID of the notification.
@@ -184,4 +202,47 @@ Returns:
void Notification::setCreatedAt(const util::Timestamp& createdAt) void Notification::setCreatedAt(const util::Timestamp& createdAt)
{ {
m_createdAt = createdAt; m_createdAt = createdAt;
}
std::string Notification::serialize() const
{
std::ostringstream serializedNotification;
serializedNotification << m_id << ','
<< m_recipientUserId << ','
<< m_title << ','
<< m_message << ','
<< m_createdAt.toString();
return serializedNotification.str();
}
Notification* Notification::deserialize(const std::string& record)
{
std::string id, recipientUserId, title, message, createdAtTimestampString;
std::istringstream serializedNotification(record);
getline(serializedNotification, id, ',');
getline(serializedNotification, recipientUserId, ',');
getline(serializedNotification, title, ',');
getline(serializedNotification, message, ',');
getline(serializedNotification, createdAtTimestampString, ',');
util::Timestamp createdAtTimestamp;
try
{
createdAtTimestamp = util::Timestamp::fromString(createdAtTimestampString);
}
catch (...)
{
throw std::runtime_error("Invalid createdAt timestamp");
}
return Factory::getObject<Notification>(
id,
recipientUserId,
title,
message,
createdAtTimestamp
);
}
std::string Notification::getHeaders()
{
return "ID,RecipientID,Title,Message,Timestamp";
} }
@@ -25,6 +25,7 @@ private:
public: public:
Notification(); Notification();
Notification(const std::string& recipientUserId, User* recipient, const std::string& title, const std::string& message, const util::Timestamp& createdAt); Notification(const std::string& recipientUserId, User* recipient, const std::string& title, const std::string& message, const util::Timestamp& createdAt);
Notification(const std::string& id, const std::string& recipientUserId, const std::string& title, const std::string& message, const util::Timestamp& createdAt);
const std::string& getId() const; const std::string& getId() const;
const std::string& getRecipientUserId() const; const std::string& getRecipientUserId() const;
User* getRecipient() const; User* getRecipient() const;
@@ -37,4 +38,7 @@ public:
void setTitle(const std::string& title); void setTitle(const std::string& title);
void setMessage(const std::string& message); void setMessage(const std::string& message);
void setCreatedAt(const util::Timestamp& createdAt); void setCreatedAt(const util::Timestamp& createdAt);
std::string serialize() const;
static Notification* deserialize(const std::string&);
static std::string getHeaders();
}; };
@@ -7,7 +7,11 @@ Author: Trenser
Date: 19-May-2026 Date: 19-May-2026
*/ */
#include <sstream>
#include "Service.h" #include "Service.h"
#include "InventoryItem.h"
#include "StringHelper.h"
#include "Factory.h"
int Service::m_uid = 0; int Service::m_uid = 0;
@@ -40,7 +44,29 @@ Service::Service(const std::string& name, const util::Map<std::string, Inventory
m_name(name), m_name(name),
m_requiredInventoryItems(requiredInventoryItems), m_requiredInventoryItems(requiredInventoryItems),
m_status(util::State::ACTIVE), m_status(util::State::ACTIVE),
m_laborCost(laborCost) {} m_laborCost(laborCost)
{
int numberOfInventoryItems = m_requiredInventoryItems.getSize();
auto inventoryItemPointers = m_requiredInventoryItems.getValues();
for (int index = 0; index < numberOfInventoryItems; index++)
{
m_requiredInventoryItemIDs.push_back(inventoryItemPointers[index]->getId());
}
}
Service::Service(const std::string& id, const std::string& name, const util::Vector<std::string>& requiredInventoryItemIDs, double laborCost, util::State status)
: m_id(id),
m_name(name),
m_requiredInventoryItemIDs(requiredInventoryItemIDs),
m_status(status),
m_laborCost(laborCost)
{
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
{
m_uid = idNumber;
}
}
/* /*
Function: getId Function: getId
@@ -64,6 +90,11 @@ const std::string& Service::getName() const
return m_name; return m_name;
} }
const util::Vector<std::string>& Service::getRequiredInventoryItemIDs() const
{
return m_requiredInventoryItemIDs;
}
/* /*
Function: getRequiredInventoryItems Function: getRequiredInventoryItems
Description: Retrieves the map of inventory items required for the service. Description: Retrieves the map of inventory items required for the service.
@@ -134,6 +165,13 @@ Returns:
void Service::setRequiredInventoryItems(const util::Map<std::string, InventoryItem*>& requiredInventoryItems) void Service::setRequiredInventoryItems(const util::Map<std::string, InventoryItem*>& requiredInventoryItems)
{ {
m_requiredInventoryItems = requiredInventoryItems; m_requiredInventoryItems = requiredInventoryItems;
m_requiredInventoryItemIDs.clear();
int numberOfRequiredInventoryItems = m_requiredInventoryItems.getSize();
auto inventoryItemPointers = m_requiredInventoryItems.getValues();
for (int index = 0; index < numberOfRequiredInventoryItems; index++)
{
m_requiredInventoryItemIDs.push_back(inventoryItemPointers[index]->getId());
}
} }
/* /*
@@ -160,4 +198,77 @@ Returns:
void Service::setState(util::State status) void Service::setState(util::State status)
{ {
m_status = status; m_status = status;
}
static std::string getInventoryItemIDsAsString(const util::Vector<std::string>& inventoryItemIds)
{
int numberOfInventoryItems = inventoryItemIds.getSize();
std::string inventoryItemIDs;
for (int index = 0; index < numberOfInventoryItems; index++)
{
inventoryItemIDs += inventoryItemIds[index];
if (index < numberOfInventoryItems - 1)
{
inventoryItemIDs += '|';
}
}
return inventoryItemIDs;
}
static util::Vector<std::string> getInventoryItemIDsAsVector(const std::string& inventoryItemIDsString)
{
util::Vector<std::string> inventoryItemIDs;
std::string inventoryItemID;
std::istringstream serializedInventoryItemIDs(inventoryItemIDsString);
while (getline(serializedInventoryItemIDs, inventoryItemID, '|'))
{
inventoryItemIDs.push_back(inventoryItemID);
}
return inventoryItemIDs;
}
std::string Service::serialize() const
{
std::ostringstream serializedService;
serializedService << m_id << ','
<< m_name << ','
<< getInventoryItemIDsAsString(m_requiredInventoryItemIDs) << ','
<< m_laborCost << ','
<< util::getStateString(m_status);
return serializedService.str();
}
Service* Service::deserialize(const std::string& record)
{
std::string id, name;
std::string inventoryItemIDsString, laborCostString, statusString;
double laborCost;
std::istringstream serializedService(record);
getline(serializedService, id, ',');
getline(serializedService, name, ',');
getline(serializedService, inventoryItemIDsString, ',');
getline(serializedService, laborCostString, ',');
getline(serializedService, statusString, ',');
util::Vector<std::string> inventoryItemIDs = getInventoryItemIDsAsVector(inventoryItemIDsString);
try
{
laborCost = std::stod(laborCostString);
}
catch (...)
{
throw std::runtime_error("Invalid labor cost");
}
util::State status = util::getState(statusString);
return Factory::getObject<Service>(
id,
name,
inventoryItemIDs,
laborCost,
status
);
}
std::string Service::getHeaders()
{
return "ID,Name,InventoryIDs,LaborCost,Status";
} }
@@ -10,6 +10,7 @@ Date: 19-May-2026
#pragma once #pragma once
#include <string> #include <string>
#include "Map.h" #include "Map.h"
#include "Vector.h"
#include "Enums.h" #include "Enums.h"
class InventoryItem; class InventoryItem;
@@ -20,14 +21,17 @@ private:
static int m_uid; static int m_uid;
std::string m_id; std::string m_id;
std::string m_name; std::string m_name;
util::Vector<std::string> m_requiredInventoryItemIDs;
util::Map<std::string, InventoryItem*> m_requiredInventoryItems; util::Map<std::string, InventoryItem*> m_requiredInventoryItems;
double m_laborCost; double m_laborCost;
util::State m_status; util::State m_status;
public: public:
Service(); Service();
Service(const std::string& name, const util::Map<std::string, InventoryItem*>& requiredInventoryItems, double laborCost); Service(const std::string& name, const util::Map<std::string, InventoryItem*>& requiredInventoryItems, double laborCost);
Service(const std::string& id, const std::string& name, const util::Vector<std::string>& requiredInventoryItemIDs, double laborCost, util::State state);
const std::string& getId() const; const std::string& getId() const;
const std::string& getName() const; const std::string& getName() const;
const util::Vector<std::string>& getRequiredInventoryItemIDs() const;
const util::Map<std::string, InventoryItem*>& getRequiredInventoryItems() const; const util::Map<std::string, InventoryItem*>& getRequiredInventoryItems() const;
double getLaborCost() const; double getLaborCost() const;
util::State getState() const; util::State getState() const;
@@ -36,4 +40,7 @@ public:
void setRequiredInventoryItems(const util::Map<std::string, InventoryItem*>& requiredInventoryItems); void setRequiredInventoryItems(const util::Map<std::string, InventoryItem*>& requiredInventoryItems);
void setLaborCost(double laborCost); void setLaborCost(double laborCost);
void setState(util::State status); void setState(util::State status);
std::string serialize() const;
static Service* deserialize(const std::string&);
static std::string getHeaders();
}; };
@@ -6,7 +6,13 @@ Description: Implementation file containing the method definitions of the
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#include <stdexcept>
#include <sstream>
#include "ServiceBooking.h" #include "ServiceBooking.h"
#include "Service.h"
#include "Enums.h"
#include "Factory.h"
#include "StringHelper.h"
int ServiceBooking::m_uid = 0; int ServiceBooking::m_uid = 0;
@@ -37,8 +43,6 @@ Parameter: const std::string& id - booking ID
const std::string& vehicleNumber - vehicle registration number const std::string& vehicleNumber - vehicle registration number
const std::string& vehicleBrand - brand of the vehicle const std::string& vehicleBrand - brand of the vehicle
const std::string& vehicleModel - model of the vehicle const std::string& vehicleModel - model of the vehicle
const std::string& assignedTechnicianId - ID of the assigned technician
User* assignedTechnician - pointer to the technician object
double discountPercentage - discount applied to the booking double discountPercentage - discount applied to the booking
Return type: Constructor Return type: Constructor
*/ */
@@ -65,14 +69,44 @@ ServiceBooking::ServiceBooking(
m_assignedTechnician(nullptr), m_assignedTechnician(nullptr),
m_discountPercentage(discountPercentage) m_discountPercentage(discountPercentage)
{ {
int numberOfServices = m_services.getSize();
auto servicePointers = m_services.getValues();
for (int index = 0; index < numberOfServices; index++)
{
m_serviceIDs.push_back(servicePointers[index]->getId());
}
}
ServiceBooking::ServiceBooking(
const std::string& id,
util::ServiceJobStatus status,
const util::Vector<std::string>& serviceIDs,
const std::string& customerId,
const std::string& vehicleNumber,
const std::string& vehicleBrand,
const std::string& vehicleModel,
const std::string& assignedTechnicianId,
double discountPercentage
)
: m_id(id),
m_status(status),
m_serviceIDs(serviceIDs),
m_customerId(customerId),
m_customer(nullptr),
m_vehicleNumber(vehicleNumber),
m_vehicleBrand(vehicleBrand),
m_vehicleModel(vehicleModel),
m_assignedTechnicianId(assignedTechnicianId),
m_assignedTechnician(nullptr),
m_discountPercentage(discountPercentage)
{
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
{
m_uid = idNumber;
}
} }
/*
Function: getId
Description: Retrieves the unique ID of the service booking.
Returns:
- const std::string& representing the booking ID.
*/
const std::string& ServiceBooking::getId() const const std::string& ServiceBooking::getId() const
{ {
return m_id; return m_id;
@@ -89,6 +123,11 @@ util::ServiceJobStatus ServiceBooking::getStatus() const
return m_status; return m_status;
} }
const util::Vector<std::string>& ServiceBooking::getServiceIDs() const
{
return m_serviceIDs;
}
/* /*
Function: getServices Function: getServices
Description: Retrieves the map of services included in the booking. Description: Retrieves the map of services included in the booking.
@@ -225,6 +264,13 @@ Returns:
void ServiceBooking::setServices(const util::Map<std::string, Service*>& services) void ServiceBooking::setServices(const util::Map<std::string, Service*>& services)
{ {
m_services = services; m_services = services;
m_serviceIDs.clear();
int numberOfServices = m_services.getSize();
auto servicePointers = m_services.getValues();
for (int index = 0; index < numberOfServices; index++)
{
m_serviceIDs.push_back(servicePointers[index]->getId());
}
} }
/* /*
@@ -327,4 +373,89 @@ Returns:
void ServiceBooking::setDiscountPercentage(double discountPercentage) void ServiceBooking::setDiscountPercentage(double discountPercentage)
{ {
m_discountPercentage = discountPercentage; m_discountPercentage = discountPercentage;
} }
static std::string getServiceIDsAsString(const util::Vector<std::string>& serviceIDs)
{
int numberOfServices = serviceIDs.getSize();
std::string serviceIDsString;
for (int index = 0; index < numberOfServices; index++)
{
serviceIDsString += serviceIDs[index];
if (index < numberOfServices - 1)
{
serviceIDsString += '|';
}
}
return serviceIDsString;
}
static util::Vector<std::string> getServiceIDsAsVector(const std::string& serviceIDsString)
{
util::Vector<std::string> serviceIDs;
std::string serviceID;
std::istringstream serializedServiceIDs(serviceIDsString);
while (getline(serializedServiceIDs, serviceID, '|'))
{
serviceIDs.push_back(serviceID);
}
return serviceIDs;
}
std::string ServiceBooking::serialize() const
{
std::ostringstream serializedBooking;
serializedBooking << m_id << ','
<< util::getServiceJobStatusString(m_status) << ','
<< getServiceIDsAsString(m_serviceIDs) << ','
<< m_customerId << ','
<< m_vehicleNumber << ','
<< m_vehicleBrand << ','
<< m_vehicleModel << ','
<< m_assignedTechnicianId << ','
<< m_discountPercentage << ',';
return serializedBooking.str();
}
ServiceBooking* ServiceBooking::deserialize(const std::string& record)
{
std::string id, customerId, vehicleNumber, vehicleBrand, vehicleModel, assignedTechnicianId;
std::string serviceJobStatusString, serviceIDsString, discountPercentageString;
double discountPercentage;
std::istringstream serializedBooking(record);
getline(serializedBooking, id, ',');
getline(serializedBooking, serviceJobStatusString, ',');
getline(serializedBooking, serviceIDsString, ',');
getline(serializedBooking, customerId, ',');
getline(serializedBooking, vehicleNumber, ',');
getline(serializedBooking, vehicleBrand, ',');
getline(serializedBooking, vehicleModel, ',');
getline(serializedBooking, assignedTechnicianId, ',');
getline(serializedBooking, discountPercentageString, ',');
util::Vector<std::string> serviceIDs = getServiceIDsAsVector(serviceIDsString);
try
{
discountPercentage = std::stod(discountPercentageString);
}
catch (...)
{
throw std::runtime_error("Invalid discount percentage");
}
util::ServiceJobStatus status = util::getServiceJobStatus(serviceJobStatusString);
return Factory::getObject<ServiceBooking>(
id,
status,
serviceIDs,
customerId,
vehicleNumber,
vehicleBrand,
vehicleModel,
assignedTechnicianId,
discountPercentage
);
}
std::string ServiceBooking::getHeaders()
{
return "ID,Status,ServiceIDs,CustomerID,VehicleNumber,VehicleBrand,VehicleModel,AssignedTechnicianID,DiscountPercentage";
}
@@ -9,6 +9,7 @@ Date:19-May-2026
#pragma once #pragma once
#include <string> #include <string>
#include "Map.h" #include "Map.h"
#include "Vector.h"
#include "Enums.h" #include "Enums.h"
class Service; class Service;
@@ -20,6 +21,7 @@ private:
static int m_uid; static int m_uid;
std::string m_id; std::string m_id;
util::ServiceJobStatus m_status; util::ServiceJobStatus m_status;
util::Vector<std::string> m_serviceIDs;
util::Map<std::string, Service*> m_services; util::Map<std::string, Service*> m_services;
std::string m_customerId; std::string m_customerId;
User* m_customer; User* m_customer;
@@ -42,8 +44,20 @@ public:
const std::string& vehicleModel, const std::string& vehicleModel,
double discountPercentage double discountPercentage
); );
ServiceBooking(
const std::string& id,
util::ServiceJobStatus status,
const util::Vector<std::string>& serviceIDs,
const std::string& customerId,
const std::string& vehicleNumber,
const std::string& vehicleBrand,
const std::string& vehicleModel,
const std::string& assignedTechnicianId,
double discountPercentage
);
const std::string& getId() const; const std::string& getId() const;
util::ServiceJobStatus getStatus() const; util::ServiceJobStatus getStatus() const;
const util::Vector<std::string>& getServiceIDs() const;
const util::Map<std::string, Service*>& getServices() const; const util::Map<std::string, Service*>& getServices() const;
const std::string& getCustomerId() const; const std::string& getCustomerId() const;
User* getCustomer() const; User* getCustomer() const;
@@ -64,4 +78,7 @@ public:
void setAssignedTechnicianId(const std::string& assignedTechnicianId); void setAssignedTechnicianId(const std::string& assignedTechnicianId);
void setAssignedTechnician(User* assignedTechnician); void setAssignedTechnician(User* assignedTechnician);
void setDiscountPercentage(double discountPercentage); void setDiscountPercentage(double discountPercentage);
std::string serialize() const;
static ServiceBooking* deserialize(const std::string&);
static std::string getHeaders();
}; };
@@ -7,9 +7,12 @@ Author: Trenser
Date: 19-May-2026 Date: 19-May-2026
*/ */
#include <sstream>
#include "User.h" #include "User.h"
#include "Notification.h" #include "Notification.h"
#include "Enums.h" #include "Enums.h"
#include "Factory.h"
#include "StringHelper.h"
int User::m_uid = 0; int User::m_uid = 0;
@@ -50,6 +53,23 @@ User::User(const std::string& userName, const std::string& password, const std::
m_type(role), m_type(role),
m_status(util::State::ACTIVE) {} m_status(util::State::ACTIVE) {}
User::User(const std::string& userId, const std::string& userName, const std::string& password, const std::string& name, const std::string& phone, const std::string& email, util::UserType role, util::State status)
: m_id(userId),
m_userName(userName),
m_password(password),
m_name(name),
m_phone(phone),
m_email(email),
m_type(role),
m_status(status)
{
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
{
m_uid = idNumber;
}
}
/* /*
Function: ~User Function: ~User
Description: Destructor that cleans up dynamically allocated notifications associated with the user. Description: Destructor that cleans up dynamically allocated notifications associated with the user.
@@ -60,9 +80,10 @@ Returns:
*/ */
User::~User() User::~User()
{ {
for (int index = 0; index < m_notifications.getSize(); index++) auto values = m_notifications.getValues();
for (int index = 0; index < values.getSize(); index++)
{ {
delete m_notifications.getValues()[index]; delete values[index];
} }
} }
@@ -284,3 +305,48 @@ void User::setState(util::State status)
{ {
m_status = status; m_status = status;
} }
std::string User::serialize() const
{
std::ostringstream serializedUser;
serializedUser << m_id << ','
<< m_userName << ','
<< m_password << ','
<< m_name << ','
<< m_phone << ','
<< m_email << ','
<< util::getUserTypeString(m_type) << ','
<< util::getStateString(m_status);
return serializedUser.str();
}
User* User::deserialize(const std::string& record)
{
std::string id, name, username, phone, password, email;
std::string userTypeString, stateString;
std::istringstream serializedUser(record);
getline(serializedUser, id, ',');
getline(serializedUser, username, ',');
getline(serializedUser, password, ',');
getline(serializedUser, name, ',');
getline(serializedUser, phone, ',');
getline(serializedUser, email, ',');
getline(serializedUser, userTypeString, ',');
getline(serializedUser, stateString);
util::UserType userType = util::getUserType(userTypeString);
util::State status = util::getState(stateString);
return Factory::getObject<User>(id,
username,
password,
name,
phone,
email,
userType,
status);
}
std::string User::getHeaders()
{
return "ID,Username,Password,Name,Phone,Email,UserType,UserStatus";
}
@@ -31,6 +31,7 @@ private:
public: public:
User(); User();
User(const std::string& userName, const std::string& password, const std::string& name, const std::string& phone, const std::string& email, util::UserType role); User(const std::string& userName, const std::string& password, const std::string& name, const std::string& phone, const std::string& email, util::UserType role);
User(const std::string& userId, const std::string& userName, const std::string& password, const std::string& name, const std::string& phone, const std::string& email, util::UserType role, util::State status);
~User(); ~User();
const std::string& getId() const; const std::string& getId() const;
const std::string& getUserName() const; const std::string& getUserName() const;
@@ -50,4 +51,7 @@ public:
void addNotification(Notification* notification) override; void addNotification(Notification* notification) override;
void setRole(util::UserType role); void setRole(util::UserType role);
void setState(util::State status); void setState(util::State status);
std::string serialize() const;
static User* deserialize(const std::string&);
static std::string getHeaders();
}; };
@@ -7,6 +7,7 @@ Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#include "InventoryManagementService.h" #include "InventoryManagementService.h"
#include "Config.h"
#include "Vector.h" #include "Vector.h"
#include "Enums.h" #include "Enums.h"
#include "InventoryItem.h" #include "InventoryItem.h"
@@ -14,6 +15,8 @@ Date:19-May-2026
#include "User.h" #include "User.h"
#include "Factory.h" #include "Factory.h"
#include "Timestamp.h" #include "Timestamp.h"
#include "FileManager.h"
#include "Utility.h"
util::Map<std::string, User*> InventoryManagementService::m_observers{}; util::Map<std::string, User*> InventoryManagementService::m_observers{};
@@ -196,3 +199,47 @@ void InventoryManagementService::sendLowStockAlerts()
} }
} }
} }
util::Vector<std::string> InventoryManagementService::getObserverIDs()
{
util::Vector<std::string> observerIDs;
int numberOfObservers = m_observers.getSize();
for (int index = 0; index < numberOfObservers; index++)
{
User* observer = m_observers.getValueAt(index);
if (observer)
{
observerIDs.push_back(observer->getId());
}
}
return observerIDs;
}
void InventoryManagementService::loadInventoryItems()
{
util::FileManager<InventoryItem> inventoryItemFileManager(config::file::INVENTORYITEM_FILE);
auto& inventoryItems = m_dataStore.getInventoryItems();
auto inventoryItemsMap = inventoryItemFileManager.load();
int numberOfInventoryItems = inventoryItemsMap.getSize();
for (int index = 0; index < numberOfInventoryItems; index++)
{
inventoryItems[inventoryItemsMap.getKeyAt(index)] = inventoryItemsMap.getValueAt(index);
}
}
void InventoryManagementService::saveInventoryItems()
{
util::FileManager<InventoryItem> inventoryItemFileManager(config::file::INVENTORYITEM_FILE);
auto& inventoryItems = m_dataStore.getInventoryItems();
inventoryItemFileManager.save(inventoryItems);
}
void InventoryManagementService::loadObservers()
{
util::loadObservers(config::file::INVENTORYMANAGEMENTOBSERVERS, this, m_dataStore);
}
void InventoryManagementService::saveObservers()
{
util::saveObservers(config::file::INVENTORYMANAGEMENTOBSERVERS, this);
}
@@ -9,6 +9,7 @@ Date:19-May-2026
#pragma once #pragma once
#include <string> #include <string>
#include "Map.h" #include "Map.h"
#include "Vector.h"
#include "NotificationManagementService.h" #include "NotificationManagementService.h"
#include "DataStore.h" #include "DataStore.h"
@@ -19,6 +20,7 @@ class InventoryManagementService : public NotificationManagementService
private: private:
DataStore& m_dataStore; DataStore& m_dataStore;
static util::Map<std::string, User*> m_observers; static util::Map<std::string, User*> m_observers;
util::Vector<std::string> getObserverIDs() override;
public: public:
InventoryManagementService() : m_dataStore(DataStore::getInstance()) {} InventoryManagementService() : m_dataStore(DataStore::getInstance()) {}
util::Map<std::string, InventoryItem*> getInventoryItems(); util::Map<std::string, InventoryItem*> getInventoryItems();
@@ -30,4 +32,8 @@ public:
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;
void detach(User* user) override; void detach(User* user) override;
void loadInventoryItems();
void saveInventoryItems();
void loadObservers();
void saveObservers();
}; };
@@ -19,4 +19,5 @@ public:
virtual void sendNotification(User* recipient, const std::string& title, const std::string& message) = 0; virtual void sendNotification(User* recipient, const std::string& title, const std::string& message) = 0;
virtual void attach(User* user) = 0; virtual void attach(User* user) = 0;
virtual void detach(User* user) = 0; virtual void detach(User* user) = 0;
virtual util::Vector<std::string> getObserverIDs() = 0;
}; };
@@ -7,15 +7,15 @@ Author: Trenser
Date: 20-May-2026 Date: 20-May-2026
*/ */
#include <stdexcept>
#include "PaymentManagementService.h"
#include "Config.h" #include "Config.h"
#include "Enums.h" #include "Enums.h"
#include <stdexcept>
#include "Enums.h"
#include "Factory.h" #include "Factory.h"
#include "FileManager.h"
#include "InventoryItem.h" #include "InventoryItem.h"
#include "Invoice.h" #include "Invoice.h"
#include "JobCard.h" #include "JobCard.h"
#include "PaymentManagementService.h"
#include "Service.h" #include "Service.h"
#include "ServiceBooking.h" #include "ServiceBooking.h"
#include "Timestamp.h" #include "Timestamp.h"
@@ -61,7 +61,7 @@ void PaymentManagementService::generateInvoice(ServiceBooking* booking)
{ {
createInventoryItemsMap(completeInventoryItemMapOfBooking, currentService); createInventoryItemsMap(completeInventoryItemMapOfBooking, currentService);
totalLabourCost += currentService->getLaborCost(); totalLabourCost += currentService->getLaborCost();
totalPartsCost += calculatePartsCost(currentService); totalPartsCost += util::calculatePartsCost(currentService);
} }
} }
totalServiceCost = totalLabourCost + totalPartsCost; totalServiceCost = totalLabourCost + totalPartsCost;
@@ -222,4 +222,69 @@ void PaymentManagementService::sendPaymentReminders()
} }
} }
} }
} }
util::Vector<std::string> PaymentManagementService::getObserverIDs()
{
util::Vector<std::string> observerIDs;
int numberOfObservers = m_observers.getSize();
for (int index = 0; index < numberOfObservers; index++)
{
User* observer = m_observers.getValueAt(index);
if (observer)
{
observerIDs.push_back(observer->getId());
}
}
return observerIDs;
}
void PaymentManagementService::loadInvoices()
{
util::FileManager<Invoice> invoiceFileManager(config::file::INVOICE_FILE);
auto& invoices = m_dataStore.getInvoices();
auto& serviceBookings = m_dataStore.getServiceBookings();
auto& inventoryItems = m_dataStore.getInventoryItems();
auto invoicesMap = invoiceFileManager.load();
for (int invoiceIndex = 0; invoiceIndex < invoicesMap.getSize(); invoiceIndex++)
{
Invoice* invoice = invoicesMap.getValueAt(invoiceIndex);
int bookingIndex = serviceBookings.find(invoice->getBookingId());
if (bookingIndex == -1)
{
throw std::runtime_error("Invalid Booking ID");
}
ServiceBooking* booking = serviceBookings.getValueAt(bookingIndex);
invoice->setBooking(booking);
util::Map<std::string, InventoryItem*> invoiceParts;
auto& partIDs = invoice->getPartIDs();
for (int partIndex = 0; partIndex < partIDs.getSize(); partIndex++)
{
const std::string& partID = partIDs[partIndex];
int inventoryIndex = inventoryItems.find(partID);
if (inventoryIndex == -1)
{
throw std::runtime_error("Invalid Part ID");
}
invoiceParts[partID] = inventoryItems.getValueAt(inventoryIndex);
}
invoice->setParts(invoiceParts);
invoices[invoice->getId()] = invoice;
}
}
void PaymentManagementService::saveInvoices()
{
util::FileManager<Invoice> invoiceFileManager(config::file::INVOICE_FILE);
auto& invoices = m_dataStore.getInvoices();
invoiceFileManager.save(invoices);
}
void PaymentManagementService::loadObservers()
{
util::loadObservers(config::file::PAYMENTMANAGEMENTOBSERVERS, this, m_dataStore);
}
void PaymentManagementService::saveObservers()
{
util::saveObservers(config::file::PAYMENTMANAGEMENTOBSERVERS, this);
}
@@ -22,6 +22,7 @@ class PaymentManagementService : public NotificationManagementService
private: private:
DataStore& m_dataStore; DataStore& m_dataStore;
static util::Map<std::string, User*> m_observers; static util::Map<std::string, User*> m_observers;
util::Vector<std::string> getObserverIDs() override;
public: public:
PaymentManagementService() : m_dataStore(DataStore::getInstance()) {} PaymentManagementService() : m_dataStore(DataStore::getInstance()) {}
void generateInvoice(ServiceBooking* booking); void generateInvoice(ServiceBooking* booking);
@@ -31,4 +32,8 @@ public:
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;
void detach(User* user) override; void detach(User* user) override;
void loadInvoices();
void saveInvoices();
void loadObservers();
void saveObservers();
}; };
@@ -6,12 +6,16 @@ Description: Implementation file containing the method definitions of the
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#include <stdexcept> #include <stdexcept>
#include "AuthenticationManagementService.h" #include "AuthenticationManagementService.h"
#include "ComboPackage.h" #include "ComboPackage.h"
#include "Config.h"
#include "Enums.h" #include "Enums.h"
#include "Factory.h" #include "Factory.h"
#include "FileManager.h"
#include "InventoryItem.h" #include "InventoryItem.h"
#include "Invoice.h"
#include "JobCard.h" #include "JobCard.h"
#include "NotificationManagementService.h" #include "NotificationManagementService.h"
#include "PaymentManagementService.h" #include "PaymentManagementService.h"
@@ -21,6 +25,7 @@ Date:19-May-2026
#include "Timestamp.h" #include "Timestamp.h"
#include "User.h" #include "User.h"
#include "UserManagementService.h" #include "UserManagementService.h"
#include "Utility.h"
util::Map<std::string, User*> ServiceManagementService::m_observers{}; util::Map<std::string, User*> ServiceManagementService::m_observers{};
@@ -590,3 +595,205 @@ void ServiceManagementService::sendNotification(User* user, const std::string& t
} }
} }
} }
util::Vector<std::string> ServiceManagementService::getObserverIDs()
{
util::Vector<std::string> observerIDs;
int numberOfObservers = m_observers.getSize();
for (int index = 0; index < numberOfObservers; index++)
{
User* observer = m_observers.getValueAt(index);
if (observer)
{
observerIDs.push_back(observer->getId());
}
}
return observerIDs;
}
void ServiceManagementService::loadServices()
{
util::FileManager<Service> serviceFileManager(config::file::SERVICE_FILE);
auto& services = m_dataStore.getServices();
auto& inventoryItems = m_dataStore.getInventoryItems();
auto servicesMap = serviceFileManager.load();
for (int serviceIndex = 0; serviceIndex < servicesMap.getSize(); serviceIndex++)
{
Service* service = servicesMap.getValueAt(serviceIndex);
services[service->getId()] = service;
util::Map<std::string, InventoryItem*> inventoryItemsMap;
auto& inventoryItemIDs = service->getRequiredInventoryItemIDs();
for (int inventoryItemIndex = 0; inventoryItemIndex < inventoryItemIDs.getSize(); inventoryItemIndex++)
{
const std::string& inventoryItemID = inventoryItemIDs[inventoryItemIndex];
int index = inventoryItems.find(inventoryItemID);
if (index == -1)
{
throw std::runtime_error("Invalid Inventory Item ID");
}
inventoryItemsMap[inventoryItemID] = inventoryItems.getValueAt(index);
}
service->setRequiredInventoryItems(inventoryItemsMap);
}
}
void ServiceManagementService::saveServices()
{
util::FileManager<Service> serviceFileManager(config::file::SERVICE_FILE);
auto& services = m_dataStore.getServices();
serviceFileManager.save(services);
}
void ServiceManagementService::loadComboPackages()
{
util::FileManager<ComboPackage> comboPackageFileManager(config::file::COMBOPACKAGE_FILE);
auto& comboPackages = m_dataStore.getComboPackages();
auto& services = m_dataStore.getServices();
auto comboPackagesMap = comboPackageFileManager.load();
for (int packageIndex = 0; packageIndex < comboPackagesMap.getSize(); packageIndex++)
{
ComboPackage* comboPackage = comboPackagesMap.getValueAt(packageIndex);
util::Map<std::string, Service*> packageServices;
auto& serviceIDs = comboPackage->getServiceIDs();
for (int serviceIndex = 0; serviceIndex < serviceIDs.getSize(); serviceIndex++)
{
const std::string& serviceID = serviceIDs[serviceIndex];
int serviceMapIndex = services.find(serviceID);
if (serviceMapIndex == -1)
{
throw std::runtime_error("Invalid Service ID");
}
packageServices[serviceID] = services.getValueAt(serviceMapIndex);
}
comboPackage->setServices(packageServices);
comboPackages[comboPackage->getId()] = comboPackage;
}
}
void ServiceManagementService::saveComboPackages()
{
util::FileManager<ComboPackage> comboPackageFileManager(config::file::COMBOPACKAGE_FILE);
auto& comboPackages = m_dataStore.getComboPackages();
comboPackageFileManager.save(comboPackages);
}
void ServiceManagementService::loadServiceBookings()
{
util::FileManager<ServiceBooking> bookingFileManager(config::file::SERVICEBOOKING_FILE);
auto& serviceBookings = m_dataStore.getServiceBookings();
auto& services = m_dataStore.getServices();
auto& users = m_dataStore.getUsers();
auto bookingsMap = bookingFileManager.load();
for (int bookingIndex = 0; bookingIndex < bookingsMap.getSize(); bookingIndex++)
{
ServiceBooking* booking = bookingsMap.getValueAt(bookingIndex);
util::Map<std::string, Service*> bookingServices;
auto& serviceIDs = booking->getServiceIDs();
for (int serviceIndex = 0; serviceIndex < serviceIDs.getSize(); serviceIndex++)
{
const std::string& serviceID = serviceIDs[serviceIndex];
int serviceMapIndex = services.find(serviceID);
if (serviceMapIndex == -1)
{
throw std::runtime_error("Invalid Service ID");
}
bookingServices[serviceID] = services.getValueAt(serviceMapIndex);
}
booking->setServices(bookingServices);
int customerIndex = users.find(booking->getCustomerId());
if (customerIndex == -1)
{
throw std::runtime_error("Invalid Customer ID");
}
User* customer = users.getValueAt(customerIndex);
if (customer->getUserType() != util::UserType::CUSTOMER)
{
throw std::runtime_error("User is not a customer");
}
booking->setCustomer(customer);
const std::string& technicianId = booking->getAssignedTechnicianId();
if (!technicianId.empty())
{
int technicianIndex = users.find(technicianId);
if (technicianIndex == -1)
{
throw std::runtime_error("Invalid Technician ID");
}
User* technician = users.getValueAt(technicianIndex);
if (technician->getUserType() != util::UserType::TECHNICIAN)
{
throw std::runtime_error("User is not a technician");
}
booking->setAssignedTechnician(technician);
}
serviceBookings[booking->getId()] = booking;
}
}
void ServiceManagementService::saveServiceBookings()
{
util::FileManager<ServiceBooking> bookingFileManager(config::file::SERVICEBOOKING_FILE);
auto& serviceBookings = m_dataStore.getServiceBookings();
bookingFileManager.save(serviceBookings);
}
void ServiceManagementService::loadJobCards()
{
util::FileManager<JobCard> jobCardFileManager(config::file::JOBCARD_FILE);
auto& jobCards = m_dataStore.getJobCards();
auto& serviceBookings = m_dataStore.getServiceBookings();
auto& services = m_dataStore.getServices();
auto& users = m_dataStore.getUsers();
auto jobCardsMap = jobCardFileManager.load();
for (int jobCardIndex = 0; jobCardIndex < jobCardsMap.getSize(); jobCardIndex++)
{
JobCard* jobCard = jobCardsMap.getValueAt(jobCardIndex);
int bookingIndex = serviceBookings.find(jobCard->getBookingId());
if (bookingIndex == -1)
{
throw std::runtime_error("Invalid Booking ID");
}
ServiceBooking* booking = serviceBookings.getValueAt(bookingIndex);
jobCard->setBooking(booking);
int serviceIndex = services.find(jobCard->getServiceId());
if (serviceIndex == -1)
{
throw std::runtime_error("Invalid Service ID");
}
Service* service = services.getValueAt(serviceIndex);
if (booking->getServices().find(jobCard->getServiceId()) == -1)
{
throw std::runtime_error("Service does not belong to booking");
}
jobCard->setService(service);
int technicianIndex = users.find(jobCard->getTechnicianId());
if (technicianIndex == -1)
{
throw std::runtime_error("Invalid Technician ID");
}
User* technician = users.getValueAt(technicianIndex);
if (technician->getUserType() != util::UserType::TECHNICIAN)
{
throw std::runtime_error("User is not a technician");
}
jobCard->setTechnician(technician);
jobCards[jobCard->getId()] = jobCard;
}
}
void ServiceManagementService::saveJobCards()
{
util::FileManager<JobCard> jobCardFileManager(config::file::JOBCARD_FILE);
auto& jobCards = m_dataStore.getJobCards();
jobCardFileManager.save(jobCards);
}
void ServiceManagementService::loadObservers()
{
util::loadObservers(config::file::SERVICEMANAGEMENTOBSERVERS, this, m_dataStore);
}
void ServiceManagementService::saveObservers()
{
util::saveObservers(config::file::SERVICEMANAGEMENTOBSERVERS, this);
}
@@ -22,6 +22,7 @@ class ServiceManagementService : public NotificationManagementService
private: private:
DataStore& m_dataStore; DataStore& m_dataStore;
static util::Map<std::string, User*> m_observers; static util::Map<std::string, User*> m_observers;
util::Vector<std::string> getObserverIDs() override;
public: public:
ServiceManagementService() : m_dataStore(DataStore::getInstance()) {} ServiceManagementService() : m_dataStore(DataStore::getInstance()) {}
util::Map<std::string, Service*> getServices(); util::Map<std::string, Service*> getServices();
@@ -43,4 +44,14 @@ public:
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;
void detach(User* user) override; void detach(User* user) override;
void loadServices();
void saveServices();
void loadComboPackages();
void saveComboPackages();
void loadServiceBookings();
void saveServiceBookings();
void loadJobCards();
void saveJobCards();
void loadObservers();
void saveObservers();
}; };
@@ -5,16 +5,20 @@ Description: Implementation file containing the method definitions of the
Author: Trenser Author: Trenser
Date:19-May-2026 Date:19-May-2026
*/ */
#include "UserManagementService.h"
#include <stdexcept>
#include "Config.h" #include "Config.h"
#include "Enums.h" #include "Enums.h"
#include "Factory.h" #include "Factory.h"
#include "FileManager.h"
#include "InventoryManagementService.h" #include "InventoryManagementService.h"
#include "Invoice.h"
#include "PaymentManagementService.h" #include "PaymentManagementService.h"
#include "ServiceManagementService.h" #include "ServiceManagementService.h"
#include "User.h" #include "User.h"
#include "UserManagementService.h"
#include "Utility.h"
#include "Vector.h" #include "Vector.h"
#include <stdexcept>
void UserManagementService::ensureAdminExists() void UserManagementService::ensureAdminExists()
{ {
@@ -203,3 +207,50 @@ void UserManagementService::deleteNotification(const std::string& notificationID
} }
notifications.remove(notificationID); notifications.remove(notificationID);
} }
void UserManagementService::loadUsers()
{
util::FileManager<User> userFileManager(config::file::USER_FILE);
util::FileManager<Notification> notificationFileManager(config::file::NOTIFICATION_FILE);
auto& users = m_dataStore.getUsers();
auto usersMap = userFileManager.load();
auto notificationsMap = notificationFileManager.load();
int numberOfUsers = usersMap.getSize();
int numberOfNotifications = notificationsMap.getSize();
for (int index = 0; index < numberOfUsers; index++)
{
users[usersMap.getKeyAt(index)] = usersMap.getValueAt(index);
}
for (int index = 0; index < numberOfNotifications; index++)
{
Notification* notification = notificationsMap.getValueAt(index);
const std::string& recipientUserId = notification->getRecipientUserId();
int userIndex = users.find(recipientUserId);
if (userIndex == -1)
{
throw std::runtime_error("Invalid recipient user ID");
}
User* user = users.getValueAt(userIndex);
user->addNotification(notification);
}
}
void UserManagementService::saveUsers()
{
util::FileManager<User> userFileManager(config::file::USER_FILE);
util::FileManager<Notification> notificationFileManager(config::file::NOTIFICATION_FILE);
auto& users = m_dataStore.getUsers();
util::Map<std::string, Notification*> notifications;
for (int userIndex = 0; userIndex < users.getSize(); userIndex++)
{
User* user = users.getValueAt(userIndex);
auto& userNotifications = user->getNotifications();
for (int notificationIndex = 0; notificationIndex < userNotifications.getSize(); notificationIndex++)
{
notifications[userNotifications.getKeyAt(notificationIndex)] =
userNotifications.getValueAt(notificationIndex);
}
}
userFileManager.save(users);
notificationFileManager.save(notifications);
}
@@ -29,4 +29,6 @@ public:
util::Vector<Notification*> getUserNotifications(const std::string& userID); util::Vector<Notification*> getUserNotifications(const std::string& userID);
void deleteNotification(const std::string& notificationID, const std::string& userID); void deleteNotification(const std::string& notificationID, const std::string& userID);
void ensureAdminExists(); void ensureAdminExists();
void loadUsers();
void saveUsers();
}; };
@@ -24,4 +24,19 @@ namespace config
constexpr int INVENTORY_LOW_STOCK_THRESHOLD = 5; constexpr int INVENTORY_LOW_STOCK_THRESHOLD = 5;
constexpr int PAYMENT_REMINDER_THRESHOLD_HOURS = 168; constexpr int PAYMENT_REMINDER_THRESHOLD_HOURS = 168;
} }
namespace file
{
constexpr const char* INVENTORYITEM_FILE = "files/InventoryItem.csv";
constexpr const char* USER_FILE = "files/User.csv";
constexpr const char* NOTIFICATION_FILE = "files/Notification.csv";
constexpr const char* SERVICE_FILE = "files/Service.csv";
constexpr const char* COMBOPACKAGE_FILE = "files/ComboPackage.csv";
constexpr const char* SERVICEBOOKING_FILE = "files/ServiceBooking.csv";
constexpr const char* JOBCARD_FILE = "files/JobCard.csv";
constexpr const char* INVOICE_FILE = "files/Invoice.csv";
constexpr const char* SERVICEMANAGEMENTOBSERVERS = "files/ServiceManagementObservers.csv";
constexpr const char* PAYMENTMANAGEMENTOBSERVERS = "files/PaymentManagementObservers.csv";
constexpr const char* INVENTORYMANAGEMENTOBSERVERS = "files/InventoryManagementObservers.csv";
}
} }
@@ -253,9 +253,9 @@ namespace util
switch (status) switch (status)
{ {
case State::ACTIVE: case State::ACTIVE:
return "STARTED"; return "ACTIVE";
case State::INACTIVE: case State::INACTIVE:
return "COMPLETED"; return "INACTIVE";
} }
throw std::invalid_argument("Invalid State"); throw std::invalid_argument("Invalid State");
} }
@@ -276,7 +276,7 @@ namespace util
{ {
return State::ACTIVE; return State::ACTIVE;
} }
if (value == "COMPLETED") if (value == "INACTIVE")
{ {
return State::INACTIVE; return State::INACTIVE;
} }
@@ -0,0 +1,47 @@
#pragma once
#include <fstream>
#include <string>
#include <stdexcept>
#include "Vector.h"
namespace util
{
inline util::Vector<std::string> loadRecords(const std::string& filePath)
{
util::Vector<std::string> records;
std::ifstream file(filePath);
if (!file.is_open())
{
std::ofstream newFile(filePath);
newFile.close();
file.open(filePath);
}
std::string line;
bool isHeader = true;
while (std::getline(file, line))
{
if (isHeader)
{
isHeader = false;
continue;
}
records.push_back(line);
}
return records;
}
inline void saveRecords(const std::string& filePath, const util::Vector<std::string>& records)
{
std::ofstream file(filePath, std::ios::trunc);
if (!file.is_open())
{
throw std::runtime_error("Failed to open file " + filePath);
}
file << "Values" << '\n';
int numberOfRecords = records.getSize();
for (int index = 0; index < numberOfRecords; index++)
{
file << records[index] << '\n';
}
}
}
@@ -0,0 +1,83 @@
#pragma once
#include <string>
#include <stdexcept>
#include <fstream>
#include "Vector.h"
#include "Map.h"
namespace util
{
template <typename T> using objects = util::Map<std::string, T*>;
template <typename T>
class FileManager
{
private:
std::string m_filePath;
public:
FileManager() : m_filePath("") {}
FileManager(const std::string& filePath) : m_filePath(filePath) {}
objects<T> load();
void save(const objects<T>&);
};
template <typename T>
objects<T> FileManager<T>::load()
{
objects<T> records;
std::ifstream file(m_filePath);
if (!file.is_open())
{
std::ofstream newFile(m_filePath);
newFile.close();
file.open(m_filePath);
}
util::Vector<std::string> lines;
std::string line;
while (std::getline(file, line))
{
lines.push_back(line);
}
int numberOfLines = lines.getSize();
bool isHeader = true;
for (int lineIndex = 0; lineIndex < numberOfLines; lineIndex++)
{
const auto& record = lines[lineIndex];
if (isHeader)
{
isHeader = false;
continue;
}
auto object = T::deserialize(record);
if (!object)
{
throw std::runtime_error("Failed to deserialize record");
}
records[object->getId()] = object;
}
return records;
}
template <typename T>
void FileManager<T>::save(const objects<T>& records)
{
util::Vector<std::string> lines;
lines.push_back(T::getHeaders());
int numberOfRecords = records.getSize();
for (int recordIndex = 0; recordIndex < numberOfRecords; recordIndex++)
{
const auto& record = records.getValueAt(recordIndex);
lines.push_back(record->serialize());
}
std::ofstream file(m_filePath, std::ios::trunc);
if (!file.is_open())
{
throw std::runtime_error("Failed to open file " + m_filePath);
}
int numberOfLines = lines.getSize();
for (int lineIndex = 0; lineIndex < numberOfLines; lineIndex++)
{
file << lines[lineIndex] << '\n';
}
}
}
@@ -34,7 +34,7 @@ namespace util
/* /*
* Function: read * Function: read
* Description: Reads a line of text input from console into a string. * Description: Reads a line of text input from console into a string and cleans it up.
* Parameters: * Parameters:
* value - reference to a string where the input will be stored * value - reference to a string where the input will be stored
* Returns: * Returns:
@@ -43,6 +43,15 @@ namespace util
inline void read(std::string& value) inline void read(std::string& value)
{ {
std::getline(std::cin >> std::ws, value); std::getline(std::cin >> std::ws, value);
std::string cleanedValue;
for (int index = 0; index < value.length(); index++)
{
if (value[index] != ',')
{
cleanedValue += value[index];
}
}
value = cleanedValue;
} }
/* /*
@@ -0,0 +1,18 @@
#include <cctype>
#include <string>
namespace util
{
inline int extractNumber(const std::string& input)
{
int result = 0;
for (char character : input)
{
if (std::isdigit(static_cast<unsigned char>(character)))
{
result = result * 10 + (character - '0');
}
}
return result;
}
}
@@ -9,44 +9,72 @@ Date:19-May-2026
#include "Service.h" #include "Service.h"
#include "ComboPackage.h" #include "ComboPackage.h"
#include "InventoryItem.h" #include "InventoryItem.h"
#include "NotificationManagementService.h"
#include "FileHelper.h"
#include "DataStore.h"
/* namespace util
Function: calculatePartsCost
Description: Calculates the total cost of parts required for a given service
by summing the prices of all associated inventory items.
Parameter: const Service* service - pointer to the service object
Return type: double - total cost of required parts
*/
inline double calculatePartsCost(const Service* service)
{ {
double cost = 0; /*
auto& requiredInventoryItems = service->getRequiredInventoryItems(); Function: calculatePartsCost
int requiredInventoryItemsSize = requiredInventoryItems.getSize(); Description: Calculates the total cost of parts required for a given service
for (int index = 0; index < requiredInventoryItemsSize; index++) by summing the prices of all associated inventory items.
Parameter: const Service* service - pointer to the service object
Return type: double - total cost of required parts
*/
inline double calculatePartsCost(const Service* service)
{ {
cost += requiredInventoryItems.getValueAt(index)->getPrice(); double cost = 0;
auto& requiredInventoryItems = service->getRequiredInventoryItems();
int requiredInventoryItemsSize = requiredInventoryItems.getSize();
for (int index = 0; index < requiredInventoryItemsSize; index++)
{
cost += requiredInventoryItems.getValueAt(index)->getPrice();
}
return cost;
} }
return cost;
}
/* /*
Function: calculateComboServiceEstimatedCost Function: calculateComboServiceEstimatedCost
Description: Calculates the estimated total cost of a combo package by summing Description: Calculates the estimated total cost of a combo package by summing
the labor cost and parts cost of all services included in the package. the labor cost and parts cost of all services included in the package.
Parameters: Parameters:
- comboPackage: const ComboPackage*, pointer to the combo package whose cost is to be estimated - comboPackage: const ComboPackage*, pointer to the combo package whose cost is to be estimated
Returns: Returns:
- double: The estimated total cost of the combo package - double: The estimated total cost of the combo package
*/ */
inline double calculateComboServiceEstimatedCost(const ComboPackage* comboPackage) inline double calculateComboServiceEstimatedCost(const ComboPackage* comboPackage)
{
double cost = 0;
auto& services = comboPackage->getServices();
int servicesSize = services.getSize();
for (int index = 0; index < servicesSize; index++)
{ {
const Service* service = services.getValueAt(index); double cost = 0;
cost += calculatePartsCost(service) + service->getLaborCost(); auto& services = comboPackage->getServices();
int servicesSize = services.getSize();
for (int index = 0; index < servicesSize; index++)
{
const Service* service = services.getValueAt(index);
cost += calculatePartsCost(service) + service->getLaborCost();
}
return cost;
}
inline void loadObservers(const std::string& filePath, NotificationManagementService* service, DataStore& dataStore)
{
auto observerIDs = util::loadRecords(filePath);
auto& users = dataStore.getUsers();
for (int index = 0; index < observerIDs.getSize(); index++)
{
const std::string& observerID = observerIDs[index];
int userIndex = users.find(observerID);
if (userIndex == -1)
{
throw std::runtime_error("Invalid Observer ID");
}
service->attach(users.getValueAt(userIndex));
}
}
inline void saveObservers(const std::string& filePath, NotificationManagementService* service)
{
auto observerIDs = service->getObserverIDs();
util::saveRecords(filePath, observerIDs);
} }
return cost;
} }
@@ -858,7 +858,7 @@ static const Service* selectServiceFromServices(const util::Map<std::string, con
continue; continue;
} }
activeServicesMap.insert(currentIndex, currentService); activeServicesMap.insert(currentIndex, currentService);
double partsCost = calculatePartsCost(currentService); double partsCost = util::calculatePartsCost(currentService);
std::cout << std::left std::cout << std::left
<< std::setw(10) << currentIndex << std::setw(10) << currentIndex
<< std::setw(15) << currentService->getId() << std::setw(15) << currentService->getId()
@@ -177,7 +177,7 @@ static const Service* selectServiceFromServices(const util::Map<std::string, con
continue; continue;
} }
activeServicesMap.insert(currentIndex, currentService); activeServicesMap.insert(currentIndex, currentService);
double partsCost = calculatePartsCost(currentService); double partsCost = util::calculatePartsCost(currentService);
std::cout << std::left std::cout << std::left
<< std::setw(10) << currentIndex << std::setw(10) << currentIndex
<< std::setw(15) << currentService->getId() << std::setw(15) << currentService->getId()
@@ -250,7 +250,7 @@ static const ComboPackage* selectComboPackageFromPackages(const util::Map<std::s
<< std::setw(10) << currentIndex << std::setw(10) << currentIndex
<< std::setw(15) << currentComboPackage->getId() << std::setw(15) << currentComboPackage->getId()
<< std::setw(25) << currentComboPackage->getPackageName() << std::setw(25) << currentComboPackage->getPackageName()
<< std::setw(15) << calculateComboServiceEstimatedCost(currentComboPackage) << std::setw(15) << util::calculateComboServiceEstimatedCost(currentComboPackage)
<< std::endl; << std::endl;
currentIndex++; currentIndex++;
} }
@@ -22,6 +22,7 @@ Return type: void
*/ */
void UserInterface::run() void UserInterface::run()
{ {
m_controller.loadSystemData();
m_controller.runSystemChecks(); m_controller.runSystemChecks();
bool isMenuActive = true; bool isMenuActive = true;
while (isMenuActive) while (isMenuActive)
@@ -43,6 +44,7 @@ void UserInterface::run()
util::pressEnter(); util::pressEnter();
} }
} }
m_controller.saveSystemData();
} }
/* /*