Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 623cff9cfd | |||
| 3d884c8329 | |||
| 79d6b47aa8 |
+2
-2
@@ -427,5 +427,5 @@ FodyWeavers.xsd
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# DAT Files
|
||||
*.dat
|
||||
# CSV Files
|
||||
*.csv
|
||||
|
||||
+1
@@ -181,6 +181,7 @@
|
||||
<ClInclude Include="utilities\Config.h" />
|
||||
<ClInclude Include="utilities\Enums.h" />
|
||||
<ClInclude Include="utilities\FileHelper.h" />
|
||||
<ClInclude Include="utilities\FileManager.h" />
|
||||
<ClInclude Include="utilities\InputHelper.h" />
|
||||
<ClInclude Include="utilities\Map.h" />
|
||||
<ClInclude Include="utilities\OutputHelper.h" />
|
||||
|
||||
+4
-1
@@ -242,6 +242,9 @@
|
||||
<ClInclude Include="utilities\Config.h">
|
||||
<Filter>Header Files\Utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="utilities\FileManager.h">
|
||||
<Filter>Header Files\Utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="utilities\StringHelper.h">
|
||||
<Filter>Header Files\Utilities</Filter>
|
||||
</ClInclude>
|
||||
@@ -273,7 +276,7 @@
|
||||
<Filter>Header Files\DataStores\SharedMemory</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="datastores\DataStoreLockGuard.h">
|
||||
<Filter>Header Files\DataStores</Filter>
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -7,6 +7,8 @@ Date: 19-May-2026
|
||||
|
||||
#pragma once
|
||||
|
||||
class Notification;
|
||||
|
||||
class Observer
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -144,6 +144,11 @@ bool DataStore::initialize()
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
if (!SharedMemory::createOrOpenMapping(m_payments))
|
||||
{
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
if (!SharedMemory::createOrOpenMapping(m_serviceManagementObservers))
|
||||
{
|
||||
success = false;
|
||||
@@ -188,6 +193,7 @@ void DataStore::shutdown()
|
||||
SharedMemory::closeMapping(m_serviceBookings);
|
||||
SharedMemory::closeMapping(m_jobCards);
|
||||
SharedMemory::closeMapping(m_invoices);
|
||||
SharedMemory::closeMapping(m_payments);
|
||||
SharedMemory::closeMapping(m_serviceManagementObservers);
|
||||
SharedMemory::closeMapping(m_paymentManagementObservers);
|
||||
SharedMemory::closeMapping(m_inventoryManagementObservers);
|
||||
@@ -514,7 +520,7 @@ void DataStore::saveObservers(MappingInfo& mapping, util::Map<std::string, User*
|
||||
{
|
||||
SerializedObserver serializedObserver;
|
||||
User* user = observers.getValueAt(static_cast<int>(index));
|
||||
strcpy_s(serializedObserver.id, sizeof(serializedObserver.id), user->getId().c_str());
|
||||
strcpy_s(serializedObserver.id, user->getId().c_str());
|
||||
SerializedObserver* destination = static_cast<SerializedObserver*>(SharedMemory::getRecordAddress(mapping, index));
|
||||
*destination = serializedObserver;
|
||||
}
|
||||
@@ -559,6 +565,32 @@ void DataStore::saveInventoryManagementObservers(util::Map<std::string, User*>&
|
||||
saveObservers(m_inventoryManagementObservers, observers);
|
||||
}
|
||||
|
||||
/*
|
||||
Function: lockDataStore
|
||||
Description: Acquires exclusive access to the datastore.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- bool: True if the datastore was successfully locked, otherwise false
|
||||
*/
|
||||
bool DataStore::lockDataStore()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
Function: unlockDataStore
|
||||
Description: Releases exclusive access to the datastore.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- bool: True if the datastore was successfully unlocked, otherwise false
|
||||
*/
|
||||
bool DataStore::unlockDataStore()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
Function: lockDataStore
|
||||
Description: Acquires the datastore mutex, providing
|
||||
|
||||
@@ -12,14 +12,14 @@ Date: 19-May-2026
|
||||
#include "MappingInfo.h"
|
||||
#include "TrackedRecord.h"
|
||||
#include "SharedMemory.h"
|
||||
#include "User.h"
|
||||
#include "Notification.h"
|
||||
#include "Service.h"
|
||||
#include "ComboPackage.h"
|
||||
#include "InventoryItem.h"
|
||||
#include "ServiceBooking.h"
|
||||
#include "JobCard.h"
|
||||
#include "Invoice.h"
|
||||
class User;
|
||||
class Notification;
|
||||
class Service;
|
||||
class ComboPackage;
|
||||
class InventoryItem;
|
||||
class ServiceBooking;
|
||||
class JobCard;
|
||||
class Invoice;
|
||||
|
||||
class DataStore
|
||||
{
|
||||
@@ -39,6 +39,7 @@ private:
|
||||
MappingInfo m_serviceBookings;
|
||||
MappingInfo m_jobCards;
|
||||
MappingInfo m_invoices;
|
||||
MappingInfo m_payments;
|
||||
MappingInfo m_serviceManagementObservers;
|
||||
MappingInfo m_paymentManagementObservers;
|
||||
MappingInfo m_inventoryManagementObservers;
|
||||
@@ -230,17 +231,9 @@ void DataStore::refreshCache(util::Map<std::string, TrackedRecord<TObject>>& cac
|
||||
for (int index = 0; index < oldCache.getSize(); ++index)
|
||||
{
|
||||
const std::string& id = oldCache.getKeyAt(index);
|
||||
const TrackedRecord<TObject>& localTrackedRecord = oldCache.getValueAt(index);
|
||||
if (cache.find(id) == -1)
|
||||
{
|
||||
if (localTrackedRecord.state == RecordState::NEW_RECORD)
|
||||
{
|
||||
cache.insert(id, localTrackedRecord);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete localTrackedRecord.data;
|
||||
}
|
||||
delete oldCache.getValueAt(index).data;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,6 @@ Date: 19-May-2026
|
||||
#include "Enums.h"
|
||||
|
||||
class Service;
|
||||
struct SerializedComboPackage;
|
||||
|
||||
class ComboPackage
|
||||
{
|
||||
|
||||
+4
-16
@@ -10,8 +10,6 @@ Date:19-May-2026
|
||||
#include <stdexcept>
|
||||
#include "AuthenticationManagementService.h"
|
||||
#include "User.h"
|
||||
#include "Utility.h"
|
||||
#include "DataStoreLockGuard.h"
|
||||
|
||||
User* AuthenticationManagementService::m_authenticatedUser = nullptr;
|
||||
|
||||
@@ -26,12 +24,11 @@ Return type: bool - true if login successful, false otherwise
|
||||
*/
|
||||
bool AuthenticationManagementService::login(const std::string& username, const std::string& password)
|
||||
{
|
||||
DataStoreLockGuard lock(m_dataStore);
|
||||
auto& trackedUserMap = m_dataStore.getUsers();
|
||||
int trackedUserMapSize = trackedUserMap.getSize();
|
||||
for (int index = 0; index < trackedUserMapSize; index++)
|
||||
util::Map<std::string, User*> users = m_dataStore.getUsers();
|
||||
int usersMapSize = users.getSize();
|
||||
for (int index = 0; index < usersMapSize; index++)
|
||||
{
|
||||
User* user = trackedUserMap.getValueAt(index).data;
|
||||
User* user = users.getValueAt(index);
|
||||
if (username == user->getUserName())
|
||||
{
|
||||
if (password == user->getPassword())
|
||||
@@ -77,18 +74,9 @@ Return type: void
|
||||
*/
|
||||
void AuthenticationManagementService::changePassword(const std::string& newPassword)
|
||||
{
|
||||
DataStoreLockGuard lock(m_dataStore);
|
||||
auto& trackedUsersMap = m_dataStore.getUsers();
|
||||
if (m_authenticatedUser == nullptr)
|
||||
{
|
||||
throw std::runtime_error("There is no user currently logged in!");
|
||||
}
|
||||
int index = trackedUsersMap.find(m_authenticatedUser->getId());
|
||||
if (index == -1)
|
||||
{
|
||||
throw std::runtime_error("User does not exist!\n");
|
||||
}
|
||||
m_authenticatedUser->setPassword(newPassword);
|
||||
trackedUsersMap.getValueAt(index).state = RecordState::MODIFIED;
|
||||
m_dataStore.saveUsers();
|
||||
}
|
||||
|
||||
+90
@@ -12,6 +12,7 @@ Date: 22-May-2026
|
||||
#include "Config.h"
|
||||
#include "Enums.h"
|
||||
#include "Factory.h"
|
||||
#include "FileManager.h"
|
||||
#include "InventoryItem.h"
|
||||
#include "InventoryManagementService.h"
|
||||
#include "Timestamp.h"
|
||||
@@ -89,6 +90,95 @@ void InventoryManagementService::sendLowStockAlerts()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Function: getObserverIDs
|
||||
Description: Retrieves the IDs of all observers currently attached to the
|
||||
InventoryManagementService.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- util::Vector<std::string>: Vector of observer user IDs
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
Function: loadInventoryItems
|
||||
Description: Loads inventory items from persistent storage into the datastore.
|
||||
Uses FileManager to deserialize inventory items from the configured file.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Function: saveInventoryItems
|
||||
Description: Saves inventory items from the datastore to persistent storage.
|
||||
Uses FileManager to serialize inventory items into the configured file.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
*/
|
||||
void InventoryManagementService::saveInventoryItems()
|
||||
{
|
||||
util::FileManager<InventoryItem> inventoryItemFileManager(config::file::INVENTORYITEM_FILE);
|
||||
auto& inventoryItems = m_dataStore.getInventoryItems();
|
||||
inventoryItemFileManager.save(inventoryItems);
|
||||
}
|
||||
|
||||
/*
|
||||
Function: loadObservers
|
||||
Description: Loads observer IDs from persistent storage and attaches corresponding
|
||||
users as observers to the InventoryManagementService.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
*/
|
||||
void InventoryManagementService::loadObservers()
|
||||
{
|
||||
util::loadObservers(config::file::INVENTORYMANAGEMENTOBSERVERS, this, m_dataStore);
|
||||
}
|
||||
|
||||
/*
|
||||
Function: saveObservers
|
||||
Description: Saves the current observer IDs of the InventoryManagementService
|
||||
to persistent storage for future retrieval.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
*/
|
||||
void InventoryManagementService::saveObservers()
|
||||
{
|
||||
util::saveObservers(config::file::INVENTORYMANAGEMENTOBSERVERS, this);
|
||||
}
|
||||
|
||||
/*
|
||||
Function: addInventoryItem
|
||||
Description: Creates a new inventory item using the Factory and inserts it
|
||||
|
||||
+5
@@ -21,6 +21,7 @@ class InventoryManagementService : public NotificationManagementService
|
||||
private:
|
||||
DataStore& m_dataStore;
|
||||
static util::Map<std::string, User*> m_observers;
|
||||
util::Vector<std::string> getObserverIDs() override;
|
||||
public:
|
||||
InventoryManagementService() : m_dataStore(DataStore::getInstance()) {}
|
||||
util::Map<std::string, InventoryItem*> getInventoryItems();
|
||||
@@ -32,4 +33,8 @@ public:
|
||||
void sendNotification(User* user, const std::string& title, const std::string& message) override;
|
||||
void attach(User* user) override;
|
||||
void detach(User* user) override;
|
||||
void loadInventoryItems();
|
||||
void saveInventoryItems();
|
||||
void loadObservers();
|
||||
void saveObservers();
|
||||
};
|
||||
|
||||
+1
@@ -19,4 +19,5 @@ public:
|
||||
virtual void sendNotification(User* recipient, const std::string& title, const std::string& message) = 0;
|
||||
virtual void attach(User* user) = 0;
|
||||
virtual void detach(User* user) = 0;
|
||||
virtual util::Vector<std::string> getObserverIDs() = 0;
|
||||
};
|
||||
|
||||
+118
@@ -11,6 +11,7 @@ Date: 20-May-2026
|
||||
#include "Config.h"
|
||||
#include "Enums.h"
|
||||
#include "Factory.h"
|
||||
#include "FileManager.h"
|
||||
#include "InventoryItem.h"
|
||||
#include "Invoice.h"
|
||||
#include "JobCard.h"
|
||||
@@ -148,6 +149,123 @@ void PaymentManagementService::sendPaymentReminders()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Function: getObserverIDs
|
||||
Description: Retrieves the IDs of all observers currently attached to the
|
||||
PaymentManagementService.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- util::Vector<std::string>: Vector of observer user IDs
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
Function: loadInvoices
|
||||
Description: Loads invoices from persistent storage into the datastore.
|
||||
Validates associated service bookings and inventory parts before
|
||||
attaching them to each invoice. Throws exceptions if invalid IDs
|
||||
are encountered.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
Throws:
|
||||
- std::runtime_error if a booking ID or part ID is invalid
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Function: saveInvoices
|
||||
Description: Saves invoices from the datastore to persistent storage.
|
||||
Uses FileManager to serialize invoices into the configured file.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
*/
|
||||
void PaymentManagementService::saveInvoices()
|
||||
{
|
||||
util::FileManager<Invoice> invoiceFileManager(config::file::INVOICE_FILE);
|
||||
auto& invoices = m_dataStore.getInvoices();
|
||||
invoiceFileManager.save(invoices);
|
||||
}
|
||||
|
||||
/*
|
||||
Function: loadObservers
|
||||
Description: Loads observer IDs from persistent storage and attaches corresponding
|
||||
users as observers to the PaymentManagementService.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
Throws:
|
||||
- std::runtime_error if an observer ID is invalid (not found in datastore)
|
||||
*/
|
||||
void PaymentManagementService::loadObservers()
|
||||
{
|
||||
util::loadObservers(config::file::PAYMENTMANAGEMENTOBSERVERS, this, m_dataStore);
|
||||
}
|
||||
|
||||
/*
|
||||
Function: saveObservers
|
||||
Description: Saves the current observer IDs of the PaymentManagementService
|
||||
to persistent storage for future retrieval.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
*/
|
||||
void PaymentManagementService::saveObservers()
|
||||
{
|
||||
util::saveObservers(config::file::PAYMENTMANAGEMENTOBSERVERS, this);
|
||||
}
|
||||
|
||||
/*
|
||||
Function: createInventoryItemsMap (static helper)
|
||||
Description: Builds a map of inventory items required for a given service and adds them to the booking’s inventory map.
|
||||
|
||||
+5
@@ -22,6 +22,7 @@ class PaymentManagementService : public NotificationManagementService
|
||||
private:
|
||||
DataStore& m_dataStore;
|
||||
static util::Map<std::string, User*> m_observers;
|
||||
util::Vector<std::string> getObserverIDs() override;
|
||||
public:
|
||||
PaymentManagementService() : m_dataStore(DataStore::getInstance()) {}
|
||||
void generateInvoice(ServiceBooking* booking);
|
||||
@@ -33,4 +34,8 @@ public:
|
||||
void sendNotification(User* user, const std::string& title, const std::string& message) override;
|
||||
void attach(User* user) override;
|
||||
void detach(User* user) override;
|
||||
void loadInvoices();
|
||||
void saveInvoices();
|
||||
void loadObservers();
|
||||
void saveObservers();
|
||||
};
|
||||
|
||||
+294
@@ -14,6 +14,7 @@ Date:19-May-2026
|
||||
#include "DataStore.h"
|
||||
#include "Enums.h"
|
||||
#include "Factory.h"
|
||||
#include "FileManager.h"
|
||||
#include "InventoryItem.h"
|
||||
#include "JobCard.h"
|
||||
#include "NotificationManagementService.h"
|
||||
@@ -198,6 +199,299 @@ void ServiceManagementService::sendNotification(User* user, const std::string& t
|
||||
m_dataStore.saveNotifications();
|
||||
}
|
||||
|
||||
/*
|
||||
Function: loadServices
|
||||
Description: Loads services from persistent storage into the datastore.
|
||||
Validates required inventory items and attaches them to each service.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
Throws:
|
||||
- std::runtime_error if an inventory item ID is invalid
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Function: saveServices
|
||||
Description: Saves services from the datastore to persistent storage.
|
||||
Uses FileManager to serialize services into the configured file.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
*/
|
||||
void ServiceManagementService::saveServices()
|
||||
{
|
||||
util::FileManager<Service> serviceFileManager(config::file::SERVICE_FILE);
|
||||
auto& services = m_dataStore.getServices();
|
||||
serviceFileManager.save(services);
|
||||
}
|
||||
|
||||
/*
|
||||
Function: loadComboPackages
|
||||
Description: Loads combo packages from persistent storage into the datastore.
|
||||
Validates associated services and attaches them to each package.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
Throws:
|
||||
- std::runtime_error if a service ID is invalid
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Function: saveComboPackages
|
||||
Description: Saves combo packages from the datastore to persistent storage.
|
||||
Uses FileManager to serialize combo packages into the configured file.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
*/
|
||||
void ServiceManagementService::saveComboPackages()
|
||||
{
|
||||
util::FileManager<ComboPackage> comboPackageFileManager(config::file::COMBOPACKAGE_FILE);
|
||||
auto& comboPackages = m_dataStore.getComboPackages();
|
||||
comboPackageFileManager.save(comboPackages);
|
||||
}
|
||||
|
||||
/*
|
||||
Function: loadServiceBookings
|
||||
Description: Loads service bookings from persistent storage into the datastore.
|
||||
Validates associated services, customers, and technicians before
|
||||
attaching them to each booking.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
Throws:
|
||||
- std::runtime_error if a service ID, customer ID, or technician ID is invalid
|
||||
- std::runtime_error if a user is not of the expected type (customer/technician)
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Function: saveServiceBookings
|
||||
Description: Saves service bookings from the datastore to persistent storage.
|
||||
Uses FileManager to serialize bookings into the configured file.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
*/
|
||||
void ServiceManagementService::saveServiceBookings()
|
||||
{
|
||||
util::FileManager<ServiceBooking> bookingFileManager(config::file::SERVICEBOOKING_FILE);
|
||||
auto& serviceBookings = m_dataStore.getServiceBookings();
|
||||
bookingFileManager.save(serviceBookings);
|
||||
}
|
||||
|
||||
/*
|
||||
Function: loadJobCards
|
||||
Description: Loads job cards from persistent storage into the datastore.
|
||||
Validates associated bookings, services, and technicians before
|
||||
attaching them to each job card.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
Throws:
|
||||
- std::runtime_error if a booking ID, service ID, or technician ID is invalid
|
||||
- std::runtime_error if a service does not belong to the booking
|
||||
- std::runtime_error if a user is not a technician
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Function: saveJobCards
|
||||
Description: Saves job cards from the datastore to persistent storage.
|
||||
Uses FileManager to serialize job cards into the configured file.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
*/
|
||||
void ServiceManagementService::saveJobCards()
|
||||
{
|
||||
util::FileManager<JobCard> jobCardFileManager(config::file::JOBCARD_FILE);
|
||||
auto& jobCards = m_dataStore.getJobCards();
|
||||
jobCardFileManager.save(jobCards);
|
||||
}
|
||||
|
||||
/*
|
||||
Function: loadObservers
|
||||
Description: Loads observer IDs from persistent storage and attaches corresponding
|
||||
users as observers to the ServiceManagementService.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
Throws:
|
||||
- std::runtime_error if an observer ID is invalid (not found in datastore)
|
||||
*/
|
||||
void ServiceManagementService::loadObservers()
|
||||
{
|
||||
util::loadObservers(config::file::SERVICEMANAGEMENTOBSERVERS, this, m_dataStore);
|
||||
}
|
||||
|
||||
/*
|
||||
Function: saveObservers
|
||||
Description: Saves the current observer IDs of the ServiceManagementService
|
||||
to persistent storage for future retrieval.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- void
|
||||
*/
|
||||
void ServiceManagementService::saveObservers()
|
||||
{
|
||||
util::saveObservers(config::file::SERVICEMANAGEMENTOBSERVERS, this);
|
||||
}
|
||||
|
||||
/*
|
||||
Function: restoreInventory
|
||||
Description: Restores inventory quantities for all required items in the services associated
|
||||
|
||||
+9
@@ -23,6 +23,7 @@ class ServiceManagementService : public NotificationManagementService
|
||||
private:
|
||||
DataStore& m_dataStore;
|
||||
static util::Map<std::string, User*> m_observers;
|
||||
util::Vector<std::string> getObserverIDs() override;
|
||||
public:
|
||||
ServiceManagementService() : m_dataStore(DataStore::getInstance()) {}
|
||||
util::Map<std::string, Service*> getServices();
|
||||
@@ -44,4 +45,12 @@ public:
|
||||
void sendNotification(User* user, const std::string& title, const std::string& message) override;
|
||||
void attach(User* user) override;
|
||||
void detach(User* user) override;
|
||||
void loadServices();
|
||||
void saveServices();
|
||||
void loadComboPackages();
|
||||
void saveComboPackages();
|
||||
void loadServiceBookings();
|
||||
void saveServiceBookings();
|
||||
void loadJobCards();
|
||||
void saveJobCards();
|
||||
};
|
||||
|
||||
+4
-5
@@ -11,6 +11,7 @@ Date:19-May-2026
|
||||
#include "Config.h"
|
||||
#include "Enums.h"
|
||||
#include "Factory.h"
|
||||
#include "FileManager.h"
|
||||
#include "InventoryManagementService.h"
|
||||
#include "Notification.h"
|
||||
#include "PaymentManagementService.h"
|
||||
@@ -180,6 +181,7 @@ util::Vector<Notification*> UserManagementService::getUserNotifications(const st
|
||||
notificationsVector.push_back(notification);
|
||||
}
|
||||
}
|
||||
m_dataStore.unlockDataStore();
|
||||
return notificationsVector;
|
||||
}
|
||||
else
|
||||
@@ -211,19 +213,16 @@ void UserManagementService::deleteNotification(const std::string& notificationID
|
||||
{
|
||||
throw std::runtime_error("No user found with given UserID");
|
||||
}
|
||||
User* user = trackedUsersMap.getValueAt(userIndex).data;
|
||||
int notificationIndex = trackedNotificationsMap.find(notificationID);
|
||||
if (notificationIndex == -1)
|
||||
{
|
||||
throw std::runtime_error("No notification found with given NotificationID");
|
||||
}
|
||||
Notification* notification = trackedNotificationsMap.getValueAt(notificationIndex).data;
|
||||
if (notification->getRecipientUserId() == userID)
|
||||
{
|
||||
notification->setState(util::State::INACTIVE);
|
||||
trackedNotificationsMap.getValueAt(notificationIndex).data->setState(util::State::INACTIVE);
|
||||
trackedNotificationsMap.getValueAt(notificationIndex).state = RecordState::MODIFIED;
|
||||
m_dataStore.saveNotifications();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Function: getUsers
|
||||
|
||||
@@ -43,4 +43,67 @@ namespace util
|
||||
position++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Function: loadRecords
|
||||
Description: Loads records from a given file path into a vector of strings.
|
||||
Skips the header line if present. Creates the file if it does not exist.
|
||||
Parameters:
|
||||
- filePath: const std::string&, path to the file
|
||||
Returns:
|
||||
- util::Vector<std::string>: Vector containing all records (excluding header)
|
||||
Throws:
|
||||
- None (creates file if missing)
|
||||
*/
|
||||
inline util::Vector<std::string> loadRecords(const std::string& filePath)
|
||||
{
|
||||
util::Vector<std::string> records;
|
||||
std::ifstream file(filePath);
|
||||
if (!file.is_open())
|
||||
{
|
||||
ensureDirectoryExists(filePath);
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
Function: saveRecords
|
||||
Description: Saves records to a given file path. Overwrites existing content
|
||||
and writes a header line followed by all records.
|
||||
Parameters:
|
||||
- filePath: const std::string&, path to the file
|
||||
- records: const util::Vector<std::string>&, vector of records to save
|
||||
Returns:
|
||||
- void
|
||||
Throws:
|
||||
- std::runtime_error if the file cannot be opened for writing
|
||||
*/
|
||||
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,119 @@
|
||||
/*
|
||||
File: FileManager.h
|
||||
Description: Declares and implements a generic FileManager template class for
|
||||
loading and saving objects to and from files. Uses serialization
|
||||
and deserialization methods defined in the object type T.
|
||||
Provides persistence support for system entities such as Users,
|
||||
Services, InventoryItems, etc.
|
||||
Author: Trenser
|
||||
Date: 22-May-2026
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include "Vector.h"
|
||||
#include "Map.h"
|
||||
#include "FileHelper.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>&);
|
||||
};
|
||||
|
||||
/*
|
||||
Function: load
|
||||
Description: Loads records from the file into a map of objects.
|
||||
Skips the header line, deserializes each record into an object of type T,
|
||||
and stores them in a map keyed by object ID.
|
||||
Parameters:
|
||||
- None
|
||||
Returns:
|
||||
- util::Map<std::string, T*> containing deserialized objects
|
||||
Throws:
|
||||
- std::runtime_error if deserialization fails for any record
|
||||
*/
|
||||
template <typename T>
|
||||
objects<T> FileManager<T>::load()
|
||||
{
|
||||
objects<T> records;
|
||||
std::ifstream file(m_filePath);
|
||||
if (!file.is_open())
|
||||
{
|
||||
ensureDirectoryExists(m_filePath);
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
Function: save
|
||||
Description: Saves records to the file. Serializes each object of type T into a string,
|
||||
writes a header line, and then writes all serialized records to the file.
|
||||
Parameters:
|
||||
- records: const util::Map<std::string, T*>&, map of objects to save
|
||||
Returns:
|
||||
- void
|
||||
Throws:
|
||||
- std::runtime_error if the file cannot be opened for writing
|
||||
*/
|
||||
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';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ namespace util
|
||||
if (!(std::cin >> value))
|
||||
{
|
||||
std::cin.clear();
|
||||
std::cin.ignore((std::numeric_limits<std::streamsize>::max)(), '\n');
|
||||
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||
throw std::runtime_error("Invalid console input");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,52 @@ namespace util
|
||||
return cost;
|
||||
}
|
||||
|
||||
/*
|
||||
Function: loadObservers
|
||||
Description: Loads observer IDs from a file and attaches the corresponding users
|
||||
to the notification management service. Validates that each observer ID
|
||||
exists in the datastore before attaching.
|
||||
Parameters:
|
||||
- filePath: const std::string&, path to the file containing observer IDs
|
||||
- service: NotificationManagementService*, pointer to the notification service
|
||||
- dataStore: DataStore&, reference to the datastore containing users
|
||||
Returns:
|
||||
- void
|
||||
Throws:
|
||||
- std::runtime_error if an observer ID is invalid (not found in datastore)
|
||||
*/
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Function: saveObservers
|
||||
Description: Saves the current observer IDs from the notification management service
|
||||
to a file for persistence.
|
||||
Parameters:
|
||||
- filePath: const std::string&, path to the file where observer IDs will be saved
|
||||
- service: NotificationManagementService*, pointer to the notification service
|
||||
Returns:
|
||||
- void
|
||||
*/
|
||||
inline void saveObservers(const std::string& filePath, NotificationManagementService* service)
|
||||
{
|
||||
auto observerIDs = service->getObserverIDs();
|
||||
util::saveRecords(filePath, observerIDs);
|
||||
}
|
||||
|
||||
template<typename TObject>
|
||||
Map<std::string, TObject*> getObjects(const Map<std::string, TrackedRecord<TObject>>& trackedRecords);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user