Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b5c8b1ee9b |
+2
-2
@@ -427,5 +427,5 @@ FodyWeavers.xsd
|
|||||||
*.msm
|
*.msm
|
||||||
*.msp
|
*.msp
|
||||||
|
|
||||||
# DAT Files
|
# CSV Files
|
||||||
*.dat
|
*.csv
|
||||||
|
|||||||
+2
@@ -140,6 +140,7 @@
|
|||||||
<ClCompile Include="models\User.cpp" />
|
<ClCompile Include="models\User.cpp" />
|
||||||
<ClCompile Include="services\AuthenticationManagementService.cpp" />
|
<ClCompile Include="services\AuthenticationManagementService.cpp" />
|
||||||
<ClCompile Include="services\InventoryManagementService.cpp" />
|
<ClCompile Include="services\InventoryManagementService.cpp" />
|
||||||
|
<ClCompile Include="services\NotificationManagementService.cpp" />
|
||||||
<ClCompile Include="services\PaymentManagementService.cpp" />
|
<ClCompile Include="services\PaymentManagementService.cpp" />
|
||||||
<ClCompile Include="services\ServiceManagementService.cpp" />
|
<ClCompile Include="services\ServiceManagementService.cpp" />
|
||||||
<ClCompile Include="services\UserManagementService.cpp" />
|
<ClCompile Include="services\UserManagementService.cpp" />
|
||||||
@@ -181,6 +182,7 @@
|
|||||||
<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\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" />
|
||||||
|
|||||||
+6
-3
@@ -114,6 +114,9 @@
|
|||||||
<ClCompile Include="datastores\DataStore.cpp">
|
<ClCompile Include="datastores\DataStore.cpp">
|
||||||
<Filter>Source Files\DataStores</Filter>
|
<Filter>Source Files\DataStores</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="services\NotificationManagementService.cpp">
|
||||||
|
<Filter>Source Files\Services</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="core\patterns\Observer.cpp">
|
<ClCompile Include="core\patterns\Observer.cpp">
|
||||||
<Filter>Source Files\Core\Patterns</Filter>
|
<Filter>Source Files\Core\Patterns</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@@ -242,6 +245,9 @@
|
|||||||
<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">
|
<ClInclude Include="utilities\StringHelper.h">
|
||||||
<Filter>Header Files\Utilities</Filter>
|
<Filter>Header Files\Utilities</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -272,8 +278,5 @@
|
|||||||
<ClInclude Include="datastores\sharedmemory\SharedMemory.h">
|
<ClInclude Include="datastores\sharedmemory\SharedMemory.h">
|
||||||
<Filter>Header Files\DataStores\SharedMemory</Filter>
|
<Filter>Header Files\DataStores\SharedMemory</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="datastores\DataStoreLockGuard.h">
|
|
||||||
<Filter>Header Files\DataStores</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -7,8 +7,11 @@ Date: 19-May-2026
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
class Notification;
|
||||||
|
|
||||||
class Observer
|
class Observer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Observer() = default;
|
virtual ~Observer() = default;
|
||||||
|
virtual void addNotification(Notification* notification) = 0;
|
||||||
};
|
};
|
||||||
+51
-70
@@ -144,6 +144,11 @@ bool DataStore::initialize()
|
|||||||
success = false;
|
success = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!SharedMemory::createOrOpenMapping(m_payments))
|
||||||
|
{
|
||||||
|
success = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (!SharedMemory::createOrOpenMapping(m_serviceManagementObservers))
|
if (!SharedMemory::createOrOpenMapping(m_serviceManagementObservers))
|
||||||
{
|
{
|
||||||
success = false;
|
success = false;
|
||||||
@@ -188,6 +193,7 @@ void DataStore::shutdown()
|
|||||||
SharedMemory::closeMapping(m_serviceBookings);
|
SharedMemory::closeMapping(m_serviceBookings);
|
||||||
SharedMemory::closeMapping(m_jobCards);
|
SharedMemory::closeMapping(m_jobCards);
|
||||||
SharedMemory::closeMapping(m_invoices);
|
SharedMemory::closeMapping(m_invoices);
|
||||||
|
SharedMemory::closeMapping(m_payments);
|
||||||
SharedMemory::closeMapping(m_serviceManagementObservers);
|
SharedMemory::closeMapping(m_serviceManagementObservers);
|
||||||
SharedMemory::closeMapping(m_paymentManagementObservers);
|
SharedMemory::closeMapping(m_paymentManagementObservers);
|
||||||
SharedMemory::closeMapping(m_inventoryManagementObservers);
|
SharedMemory::closeMapping(m_inventoryManagementObservers);
|
||||||
@@ -224,6 +230,20 @@ util::Map<std::string, TrackedRecord<User>>& DataStore::getUsers()
|
|||||||
{
|
{
|
||||||
auto users = loadRecords<User, SerializedUser>(m_users);
|
auto users = loadRecords<User, SerializedUser>(m_users);
|
||||||
refreshCache(m_userCache, users);
|
refreshCache(m_userCache, users);
|
||||||
|
auto& notifications = getNotifications();
|
||||||
|
int numberOfNotifications = m_notificationCache.getSize();
|
||||||
|
for (int index = 0; index < numberOfNotifications; index++)
|
||||||
|
{
|
||||||
|
Notification* notification = notifications.getValueAt(index).data;
|
||||||
|
const std::string& recipientUserId = notification->getRecipientUserId();
|
||||||
|
int userIndex = m_userCache.find(recipientUserId);
|
||||||
|
if (userIndex == -1)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Invalid recipient user ID");
|
||||||
|
}
|
||||||
|
User* user = m_userCache.getValueAt(userIndex).data;
|
||||||
|
user->addNotification(notification);
|
||||||
|
}
|
||||||
return m_userCache;
|
return m_userCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,37 +340,6 @@ util::Map<std::string, TrackedRecord<Invoice>>& DataStore::getInvoices()
|
|||||||
return m_invoiceCache;
|
return m_invoiceCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Function: getObservers
|
|
||||||
Description: Retrieves observer records from the specified observer mapping
|
|
||||||
and resolves them to User objects.
|
|
||||||
Parameters:
|
|
||||||
- mapping: Observer mapping to read from
|
|
||||||
Returns:
|
|
||||||
- util::Map<std::string, User*>: Collection of observer records
|
|
||||||
Throws:
|
|
||||||
- std::runtime_error if an observer references an invalid user ID
|
|
||||||
*/
|
|
||||||
util::Map<std::string, User*> DataStore::getObservers(MappingInfo& mapping)
|
|
||||||
{
|
|
||||||
auto& users = getUsers();
|
|
||||||
util::Map<std::string, User*> observers;
|
|
||||||
SharedMemory::ensureLatestMapping(mapping);
|
|
||||||
size_t recordCount = SharedMemory::getRecordCount(mapping);
|
|
||||||
for (size_t index = 0; index < recordCount; index++)
|
|
||||||
{
|
|
||||||
const SerializedObserver* observer = static_cast<SerializedObserver*>(SharedMemory::getRecordAddress(mapping, index));
|
|
||||||
int userIndex = users.find(observer->id);
|
|
||||||
if (userIndex == -1)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("Invalid observer user ID");
|
|
||||||
}
|
|
||||||
User* user = users.getValueAt(userIndex).data;
|
|
||||||
observers.insert(user->getId(), user);
|
|
||||||
}
|
|
||||||
return observers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: getServiceManagementObservers
|
Function: getServiceManagementObservers
|
||||||
Description: Retrieves all service management observer records from the datastore.
|
Description: Retrieves all service management observer records from the datastore.
|
||||||
@@ -361,7 +350,7 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
util::Map<std::string, User*> DataStore::getServiceManagementObservers()
|
util::Map<std::string, User*> DataStore::getServiceManagementObservers()
|
||||||
{
|
{
|
||||||
return getObservers(m_serviceManagementObservers);
|
return util::Map<std::string, User*>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -374,7 +363,7 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
util::Map<std::string, User*> DataStore::getPaymentManagementObservers()
|
util::Map<std::string, User*> DataStore::getPaymentManagementObservers()
|
||||||
{
|
{
|
||||||
return getObservers(m_paymentManagementObservers);
|
return util::Map<std::string, User*>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -387,7 +376,7 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
util::Map<std::string, User*> DataStore::getInventoryManagementObservers()
|
util::Map<std::string, User*> DataStore::getInventoryManagementObservers()
|
||||||
{
|
{
|
||||||
return getObservers(m_inventoryManagementObservers);
|
return util::Map<std::string, User*>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -401,6 +390,7 @@ Returns:
|
|||||||
void DataStore::saveUsers()
|
void DataStore::saveUsers()
|
||||||
{
|
{
|
||||||
saveRecords<User, SerializedUser>(m_users, m_userCache);
|
saveRecords<User, SerializedUser>(m_users, m_userCache);
|
||||||
|
saveNotifications();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -488,49 +478,16 @@ void DataStore::saveInvoices()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Function: saveObservers
|
|
||||||
Description: Persists observer records to the specified observer mapping.
|
|
||||||
Parameters:
|
|
||||||
- mapping: MappingInfo&, observer mapping to save to
|
|
||||||
- observers: util::Map<std::string, User*>&, collection of observer records
|
|
||||||
Returns:
|
|
||||||
- None
|
|
||||||
*/
|
|
||||||
void DataStore::saveObservers(MappingInfo& mapping, util::Map<std::string, User*>& observers)
|
|
||||||
{
|
|
||||||
size_t observerCount = static_cast<size_t>(observers.getSize());
|
|
||||||
size_t capacity = config::file::INITIAL_CAPACITY;
|
|
||||||
while (capacity < observerCount)
|
|
||||||
{
|
|
||||||
capacity *= config::file::GROWTH_FACTOR;
|
|
||||||
}
|
|
||||||
if (!SharedMemory::resizeMapping(mapping, capacity))
|
|
||||||
{
|
|
||||||
throw std::runtime_error("Failed to resize observer mapping");
|
|
||||||
}
|
|
||||||
SharedMemory::setRecordCount(mapping, observerCount);
|
|
||||||
for (size_t index = 0; index < observerCount; index++)
|
|
||||||
{
|
|
||||||
SerializedObserver serializedObserver;
|
|
||||||
User* user = observers.getValueAt(static_cast<int>(index));
|
|
||||||
strcpy_s(serializedObserver.id, sizeof(serializedObserver.id), user->getId().c_str());
|
|
||||||
SerializedObserver* destination = static_cast<SerializedObserver*>(SharedMemory::getRecordAddress(mapping, index));
|
|
||||||
*destination = serializedObserver;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: saveServiceManagementObservers
|
Function: saveServiceManagementObservers
|
||||||
Description: Persists all service management observer records to the datastore.
|
Description: Persists all service management observer records to the datastore.
|
||||||
Parameters:
|
Parameters:
|
||||||
- observers: util::Map<std::string, User*>&, collection of observer records
|
- observers: util::Map<std::string, TrackedRecord<std::string>>&, collection of observer records
|
||||||
Returns:
|
Returns:
|
||||||
- None
|
- None
|
||||||
*/
|
*/
|
||||||
void DataStore::saveServiceManagementObservers(util::Map<std::string, User*>& observers)
|
void DataStore::saveServiceManagementObservers(util::Map<std::string, User*>& observers)
|
||||||
{
|
{
|
||||||
saveObservers(m_serviceManagementObservers, observers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -543,7 +500,6 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
void DataStore::savePaymentManagementObservers(util::Map<std::string, User*>& observers)
|
void DataStore::savePaymentManagementObservers(util::Map<std::string, User*>& observers)
|
||||||
{
|
{
|
||||||
saveObservers(m_paymentManagementObservers, observers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -556,7 +512,32 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
void DataStore::saveInventoryManagementObservers(util::Map<std::string, User*>& observers)
|
void DataStore::saveInventoryManagementObservers(util::Map<std::string, User*>& observers)
|
||||||
{
|
{
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -12,14 +12,14 @@ Date: 19-May-2026
|
|||||||
#include "MappingInfo.h"
|
#include "MappingInfo.h"
|
||||||
#include "TrackedRecord.h"
|
#include "TrackedRecord.h"
|
||||||
#include "SharedMemory.h"
|
#include "SharedMemory.h"
|
||||||
#include "User.h"
|
class User;
|
||||||
#include "Notification.h"
|
class Notification;
|
||||||
#include "Service.h"
|
class Service;
|
||||||
#include "ComboPackage.h"
|
class ComboPackage;
|
||||||
#include "InventoryItem.h"
|
class InventoryItem;
|
||||||
#include "ServiceBooking.h"
|
class ServiceBooking;
|
||||||
#include "JobCard.h"
|
class JobCard;
|
||||||
#include "Invoice.h"
|
class Invoice;
|
||||||
|
|
||||||
class DataStore
|
class DataStore
|
||||||
{
|
{
|
||||||
@@ -39,6 +39,7 @@ private:
|
|||||||
MappingInfo m_serviceBookings;
|
MappingInfo m_serviceBookings;
|
||||||
MappingInfo m_jobCards;
|
MappingInfo m_jobCards;
|
||||||
MappingInfo m_invoices;
|
MappingInfo m_invoices;
|
||||||
|
MappingInfo m_payments;
|
||||||
MappingInfo m_serviceManagementObservers;
|
MappingInfo m_serviceManagementObservers;
|
||||||
MappingInfo m_paymentManagementObservers;
|
MappingInfo m_paymentManagementObservers;
|
||||||
MappingInfo m_inventoryManagementObservers;
|
MappingInfo m_inventoryManagementObservers;
|
||||||
@@ -85,8 +86,6 @@ private:
|
|||||||
void saveRecords(MappingInfo& mapping, util::Map<std::string, TrackedRecord<TObject>>& records);
|
void saveRecords(MappingInfo& mapping, util::Map<std::string, TrackedRecord<TObject>>& records);
|
||||||
template<typename TObject> void clearCache(util::Map<std::string, TrackedRecord<TObject>>&cache);
|
template<typename TObject> void clearCache(util::Map<std::string, TrackedRecord<TObject>>&cache);
|
||||||
template<typename TObject> void refreshCache(util::Map<std::string, TrackedRecord<TObject>>&cache, util::Map<std::string, TrackedRecord<TObject>>&refreshedCache);
|
template<typename TObject> void refreshCache(util::Map<std::string, TrackedRecord<TObject>>&cache, util::Map<std::string, TrackedRecord<TObject>>&refreshedCache);
|
||||||
util::Map<std::string, User*> getObservers(MappingInfo& mapping);
|
|
||||||
void saveObservers(MappingInfo& mapping, util::Map<std::string, User*>& observers);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -230,17 +229,9 @@ void DataStore::refreshCache(util::Map<std::string, TrackedRecord<TObject>>& cac
|
|||||||
for (int index = 0; index < oldCache.getSize(); ++index)
|
for (int index = 0; index < oldCache.getSize(); ++index)
|
||||||
{
|
{
|
||||||
const std::string& id = oldCache.getKeyAt(index);
|
const std::string& id = oldCache.getKeyAt(index);
|
||||||
const TrackedRecord<TObject>& localTrackedRecord = oldCache.getValueAt(index);
|
|
||||||
if (cache.find(id) == -1)
|
if (cache.find(id) == -1)
|
||||||
{
|
{
|
||||||
if (localTrackedRecord.state == RecordState::NEW_RECORD)
|
delete oldCache.getValueAt(index).data;
|
||||||
{
|
|
||||||
cache.insert(id, localTrackedRecord);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
delete localTrackedRecord.data;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -320,7 +320,7 @@ bool SharedMemory::ensureCapacityForInsert(MappingInfo& mapping)
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return resizeMapping(mapping, capacity * config::file::GROWTH_FACTOR);
|
return resizeMapping(mapping, capacity * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ Date: 19-May-2026
|
|||||||
#include "Enums.h"
|
#include "Enums.h"
|
||||||
|
|
||||||
class Service;
|
class Service;
|
||||||
struct SerializedComboPackage;
|
|
||||||
|
|
||||||
class ComboPackage
|
class ComboPackage
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
File: Notification.cpp
|
File: Notification.cpp
|
||||||
Description: Implements the Notification class which represents system notifications in the Vehicle Service Management System.
|
Description: Implements the Notification class which represents system notifications in the Vehicle Service Management System.
|
||||||
Provides constructors, accessors, and mutators for notification details such as ID, recipientID, title, message, and timestamp.
|
Provides constructors, accessors, and mutators for notification details such as ID, recipient, title, message, and timestamp.
|
||||||
Author: Trenser
|
Author: Trenser
|
||||||
Date: 19-May-2026
|
Date: 19-May-2026
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "SerializedRecords.h"
|
|
||||||
#include "Notification.h"
|
#include "Notification.h"
|
||||||
#include "StringHelper.h"
|
#include "StringHelper.h"
|
||||||
#include "Factory.h"
|
#include "Factory.h"
|
||||||
@@ -24,7 +23,7 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
Notification::Notification()
|
Notification::Notification()
|
||||||
: m_id("NOT" + std::to_string(++m_uid)),
|
: m_id("NOT" + std::to_string(++m_uid)),
|
||||||
m_state(util::State::ACTIVE) {}
|
m_recipient(nullptr) {}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: Notification
|
Function: Notification
|
||||||
@@ -38,14 +37,13 @@ Parameters:
|
|||||||
Returns:
|
Returns:
|
||||||
- A new Notification object.
|
- A new Notification object.
|
||||||
*/
|
*/
|
||||||
Notification::Notification(const std::string& recipientUserId, const std::string& title, const std::string& message, const util::Timestamp& createdAt)
|
Notification::Notification(const std::string& recipientUserId, User* recipient, const std::string& title, const std::string& message, const util::Timestamp& createdAt)
|
||||||
: m_id("NOT" + std::to_string(++m_uid)),
|
: m_id("NOT" + std::to_string(++m_uid)),
|
||||||
m_recipientUserId(recipientUserId),
|
m_recipientUserId(recipientUserId),
|
||||||
|
m_recipient(recipient),
|
||||||
m_title(title),
|
m_title(title),
|
||||||
m_message(message),
|
m_message(message),
|
||||||
m_state(util::State::ACTIVE),
|
m_createdAt(createdAt) {}
|
||||||
m_createdAt(createdAt) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: Notification (parameterized constructor with ID)
|
Function: Notification (parameterized constructor with ID)
|
||||||
@@ -60,13 +58,13 @@ Parameters:
|
|||||||
Returns:
|
Returns:
|
||||||
- A new Notification object
|
- A new Notification object
|
||||||
*/
|
*/
|
||||||
Notification::Notification(const std::string& id, const std::string& recipientUserId, const std::string& title, const std::string& message, const util::Timestamp& createdAt, const util::State& state)
|
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_id(id),
|
||||||
m_recipientUserId(recipientUserId),
|
m_recipientUserId(recipientUserId),
|
||||||
|
m_recipient(nullptr),
|
||||||
m_title(title),
|
m_title(title),
|
||||||
m_message(message),
|
m_message(message),
|
||||||
m_createdAt(createdAt),
|
m_createdAt(createdAt)
|
||||||
m_state(state)
|
|
||||||
{
|
{
|
||||||
int idNumber = util::extractNumber(m_id);
|
int idNumber = util::extractNumber(m_id);
|
||||||
if (idNumber > m_uid)
|
if (idNumber > m_uid)
|
||||||
@@ -97,6 +95,17 @@ const std::string& Notification::getRecipientUserId() const
|
|||||||
return m_recipientUserId;
|
return m_recipientUserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: getRecipient
|
||||||
|
Description: Retrieves the pointer to the recipient user.
|
||||||
|
Returns:
|
||||||
|
- User* representing the recipient.
|
||||||
|
*/
|
||||||
|
User* Notification::getRecipient() const
|
||||||
|
{
|
||||||
|
return m_recipient;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: getTitle
|
Function: getTitle
|
||||||
Description: Retrieves the title of the notification.
|
Description: Retrieves the title of the notification.
|
||||||
@@ -130,17 +139,6 @@ const util::Timestamp& Notification::getCreatedAt() const
|
|||||||
return m_createdAt;
|
return m_createdAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Function: getState
|
|
||||||
Description: Retrieves the Notification state
|
|
||||||
Returns:
|
|
||||||
- const util::Timestamp& representing the creation timestamp.
|
|
||||||
*/
|
|
||||||
util::State Notification::getState() const
|
|
||||||
{
|
|
||||||
return m_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: setId
|
Function: setId
|
||||||
Description: Sets the unique ID of the notification.
|
Description: Sets the unique ID of the notification.
|
||||||
@@ -167,6 +165,19 @@ void Notification::setRecipientUserId(const std::string& recipientUserId)
|
|||||||
m_recipientUserId = recipientUserId;
|
m_recipientUserId = recipientUserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: setRecipient
|
||||||
|
Description: Sets the recipient user pointer for the notification.
|
||||||
|
Parameters:
|
||||||
|
- recipient: Pointer to the User object.
|
||||||
|
Returns:
|
||||||
|
- void
|
||||||
|
*/
|
||||||
|
void Notification::setRecipient(User* recipient)
|
||||||
|
{
|
||||||
|
m_recipient = recipient;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: setTitle
|
Function: setTitle
|
||||||
Description: Sets the title of the notification.
|
Description: Sets the title of the notification.
|
||||||
@@ -206,54 +217,71 @@ void Notification::setCreatedAt(const util::Timestamp& createdAt)
|
|||||||
m_createdAt = createdAt;
|
m_createdAt = createdAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Function: setState
|
|
||||||
Description: Sets the Notification state.
|
|
||||||
Parameters:
|
|
||||||
- state: Notification state value.
|
|
||||||
Returns:
|
|
||||||
- void
|
|
||||||
*/
|
|
||||||
void Notification::setState(util::State state)
|
|
||||||
{
|
|
||||||
m_state = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: serialize
|
Function: serialize
|
||||||
Description: Serializes the Notification object into a SerializedNotification record.
|
Description: Serializes the notification into a CSV-formatted string.
|
||||||
Parameters:
|
Parameters:
|
||||||
- None
|
- None
|
||||||
Returns:
|
Returns:
|
||||||
- SerializedNotification: Serialized representation of the notification
|
- std::string: Serialized notification record
|
||||||
*/
|
*/
|
||||||
SerializedNotification Notification::serialize() const
|
std::string Notification::serialize() const
|
||||||
{
|
{
|
||||||
SerializedNotification serialized = {};
|
std::ostringstream serializedNotification;
|
||||||
strcpy_s(serialized.id, sizeof(serialized.id), m_id.c_str());
|
serializedNotification << m_id << ','
|
||||||
strcpy_s(serialized.recipientUserId, sizeof(serialized.recipientUserId), m_recipientUserId.c_str());
|
<< m_recipientUserId << ','
|
||||||
strcpy_s(serialized.title, sizeof(serialized.title), m_title.c_str());
|
<< m_title << ','
|
||||||
strcpy_s(serialized.message, sizeof(serialized.message), m_message.c_str());
|
<< m_message << ','
|
||||||
serialized.createdAt = m_createdAt;
|
<< m_createdAt.toString();
|
||||||
serialized.state = m_state;
|
return serializedNotification.str();
|
||||||
return serialized;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: deserialize
|
Function: deserialize
|
||||||
Description: Deserializes a SerializedNotification record into a Notification object.
|
Description: Deserializes a CSV-formatted string into a Notification object.
|
||||||
Parameters:
|
Parameters:
|
||||||
- serializedNotification: const SerializedNotification&, serialized notification record
|
- record: const std::string&, serialized notification record
|
||||||
Returns:
|
Returns:
|
||||||
- Notification*: Pointer to the deserialized Notification object
|
- Notification*: Pointer to the deserialized Notification object
|
||||||
|
Throws:
|
||||||
|
- std::runtime_error if timestamp parsing fails
|
||||||
*/
|
*/
|
||||||
Notification* Notification::deserialize(const SerializedNotification& serializedNotification)
|
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>(
|
return Factory::getObject<Notification>(
|
||||||
serializedNotification.id,
|
id,
|
||||||
serializedNotification.recipientUserId,
|
recipientUserId,
|
||||||
serializedNotification.title,
|
title,
|
||||||
serializedNotification.message,
|
message,
|
||||||
serializedNotification.createdAt,
|
createdAtTimestamp
|
||||||
serializedNotification.state);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: getHeaders
|
||||||
|
Description: Retrieves the CSV headers for notification serialization.
|
||||||
|
Parameters:
|
||||||
|
- None
|
||||||
|
Returns:
|
||||||
|
- std::string: Header string ("ID,RecipientID,Title,Message,Timestamp")
|
||||||
|
*/
|
||||||
|
std::string Notification::getHeaders()
|
||||||
|
{
|
||||||
|
return "ID,RecipientID,Title,Message,Timestamp";
|
||||||
}
|
}
|
||||||
@@ -9,10 +9,8 @@ Date: 19-May-2026
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "Timestamp.h"
|
#include "Timestamp.h"
|
||||||
#include "Enums.h"
|
|
||||||
|
|
||||||
class User;
|
class User;
|
||||||
struct SerializedNotification;
|
|
||||||
|
|
||||||
class Notification
|
class Notification
|
||||||
{
|
{
|
||||||
@@ -20,26 +18,27 @@ private:
|
|||||||
static int m_uid;
|
static int m_uid;
|
||||||
std::string m_id;
|
std::string m_id;
|
||||||
std::string m_recipientUserId;
|
std::string m_recipientUserId;
|
||||||
|
User* m_recipient;
|
||||||
std::string m_title;
|
std::string m_title;
|
||||||
std::string m_message;
|
std::string m_message;
|
||||||
util::Timestamp m_createdAt;
|
util::Timestamp m_createdAt;
|
||||||
util::State m_state;
|
|
||||||
public:
|
public:
|
||||||
Notification();
|
Notification();
|
||||||
Notification(const std::string& recipientUserId, 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 util::State& state);
|
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;
|
||||||
const std::string& getTitle() const;
|
const std::string& getTitle() const;
|
||||||
const std::string& getMessage() const;
|
const std::string& getMessage() const;
|
||||||
const util::Timestamp& getCreatedAt() const;
|
const util::Timestamp& getCreatedAt() const;
|
||||||
void setId(const std::string& id);
|
void setId(const std::string& id);
|
||||||
void setRecipientUserId(const std::string& recipientUserId);
|
void setRecipientUserId(const std::string& recipientUserId);
|
||||||
|
void setRecipient(User* recipient);
|
||||||
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);
|
||||||
util::State getState() const;
|
std::string serialize() const;
|
||||||
void setState(util::State state);
|
static Notification* deserialize(const std::string&);
|
||||||
SerializedNotification serialize() const;
|
static std::string getHeaders();
|
||||||
static Notification* deserialize(const SerializedNotification&);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -89,6 +89,23 @@ User::User(const std::string& userId, const std::string& userName, const std::st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: ~User
|
||||||
|
Description: Destructor that cleans up dynamically allocated notifications associated with the user.
|
||||||
|
Parameters:
|
||||||
|
- None
|
||||||
|
Returns:
|
||||||
|
- void
|
||||||
|
*/
|
||||||
|
User::~User()
|
||||||
|
{
|
||||||
|
auto values = m_notifications.getValues();
|
||||||
|
for (int index = 0; index < values.getSize(); index++)
|
||||||
|
{
|
||||||
|
delete values[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: getId
|
Function: getId
|
||||||
Description: Retrieves the unique ID of the user.
|
Description: Retrieves the unique ID of the user.
|
||||||
@@ -155,6 +172,17 @@ const std::string& User::getEmail() const
|
|||||||
return m_email;
|
return m_email;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: getNotifications
|
||||||
|
Description: Retrieves the map of notifications associated with the user.
|
||||||
|
Returns:
|
||||||
|
- util::Map<std::string, Notification*>& representing the notifications.
|
||||||
|
*/
|
||||||
|
util::Map<std::string, Notification*>& User::getNotifications()
|
||||||
|
{
|
||||||
|
return m_notifications;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: getUserType
|
Function: getUserType
|
||||||
Description: Retrieves the role of the user.
|
Description: Retrieves the role of the user.
|
||||||
@@ -255,6 +283,22 @@ void User::setEmail(const std::string& email)
|
|||||||
m_email = email;
|
m_email = email;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: addNotification
|
||||||
|
Description: Adds a new notification to the user’s notification map.
|
||||||
|
Parameters:
|
||||||
|
- notification: Pointer to the Notification object.
|
||||||
|
Returns:
|
||||||
|
- void
|
||||||
|
*/
|
||||||
|
void User::addNotification(Notification* notification)
|
||||||
|
{
|
||||||
|
if (notification)
|
||||||
|
{
|
||||||
|
m_notifications.insert(notification->getId(), notification);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: setRole
|
Function: setRole
|
||||||
Description: Sets the role of the user.
|
Description: Sets the role of the user.
|
||||||
|
|||||||
@@ -26,19 +26,21 @@ private:
|
|||||||
std::string m_name;
|
std::string m_name;
|
||||||
std::string m_phone;
|
std::string m_phone;
|
||||||
std::string m_email;
|
std::string m_email;
|
||||||
|
util::Map<std::string, Notification*> m_notifications;
|
||||||
util::UserType m_type;
|
util::UserType m_type;
|
||||||
util::State m_status;
|
util::State m_status;
|
||||||
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(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() = default;
|
~User();
|
||||||
const std::string& getId() const;
|
const std::string& getId() const;
|
||||||
const std::string& getUserName() const;
|
const std::string& getUserName() const;
|
||||||
const std::string& getPassword() const;
|
const std::string& getPassword() const;
|
||||||
const std::string& getName() const;
|
const std::string& getName() const;
|
||||||
const std::string& getPhone() const;
|
const std::string& getPhone() const;
|
||||||
const std::string& getEmail() const;
|
const std::string& getEmail() const;
|
||||||
|
util::Map<std::string, Notification*>& getNotifications();
|
||||||
util::UserType getUserType() const;
|
util::UserType getUserType() const;
|
||||||
util::State getState() const;
|
util::State getState() const;
|
||||||
void setId(const std::string& id);
|
void setId(const std::string& id);
|
||||||
@@ -47,6 +49,7 @@ public:
|
|||||||
void setName(const std::string& name);
|
void setName(const std::string& name);
|
||||||
void setPhone(const std::string& phone);
|
void setPhone(const std::string& phone);
|
||||||
void setEmail(const std::string& email);
|
void setEmail(const std::string& email);
|
||||||
|
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);
|
||||||
SerializedUser serialize() const;
|
SerializedUser serialize() const;
|
||||||
|
|||||||
+105
-23
@@ -12,13 +12,14 @@ Date: 22-May-2026
|
|||||||
#include "Config.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 "InventoryManagementService.h"
|
#include "InventoryManagementService.h"
|
||||||
#include "Timestamp.h"
|
#include "Timestamp.h"
|
||||||
#include "User.h"
|
#include "User.h"
|
||||||
#include "Utility.h"
|
#include "Utility.h"
|
||||||
#include "Vector.h"
|
#include "Vector.h"
|
||||||
#include "DataStoreLockGuard.h"
|
|
||||||
|
|
||||||
util::Map<std::string, User*> InventoryManagementService::m_observers{};
|
util::Map<std::string, User*> InventoryManagementService::m_observers{};
|
||||||
|
|
||||||
@@ -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
|
Function: addInventoryItem
|
||||||
Description: Creates a new inventory item using the Factory and inserts it
|
Description: Creates a new inventory item using the Factory and inserts it
|
||||||
@@ -181,9 +271,6 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
void InventoryManagementService::attach(User* user)
|
void InventoryManagementService::attach(User* user)
|
||||||
{
|
{
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
|
||||||
m_observers.clear();
|
|
||||||
m_observers = m_dataStore.getInventoryManagementObservers();
|
|
||||||
if (user)
|
if (user)
|
||||||
{
|
{
|
||||||
const std::string& userID = user->getId();
|
const std::string& userID = user->getId();
|
||||||
@@ -192,7 +279,6 @@ void InventoryManagementService::attach(User* user)
|
|||||||
m_observers[userID] = user;
|
m_observers[userID] = user;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_dataStore.saveInventoryManagementObservers(m_observers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -205,9 +291,6 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
void InventoryManagementService::detach(User* user)
|
void InventoryManagementService::detach(User* user)
|
||||||
{
|
{
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
|
||||||
m_observers.clear();
|
|
||||||
m_observers = m_dataStore.getInventoryManagementObservers();
|
|
||||||
if (user)
|
if (user)
|
||||||
{
|
{
|
||||||
const std::string& userID = user->getId();
|
const std::string& userID = user->getId();
|
||||||
@@ -216,7 +299,6 @@ void InventoryManagementService::detach(User* user)
|
|||||||
m_observers.remove(userID);
|
m_observers.remove(userID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_dataStore.saveInventoryManagementObservers(m_observers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -233,27 +315,27 @@ Throws:
|
|||||||
*/
|
*/
|
||||||
void InventoryManagementService::sendNotification(User* user, const std::string& title, const std::string& message)
|
void InventoryManagementService::sendNotification(User* user, const std::string& title, const std::string& message)
|
||||||
{
|
{
|
||||||
if (!user)
|
if (user)
|
||||||
{
|
{
|
||||||
return;
|
if (m_observers.find(user->getId()) != -1)
|
||||||
}
|
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
|
||||||
m_observers = m_dataStore.getInventoryManagementObservers();
|
|
||||||
if (m_observers.find(user->getId()) == -1)
|
|
||||||
{
|
{
|
||||||
return;
|
Notification* notification =
|
||||||
}
|
Factory::getObject<Notification>(
|
||||||
Notification* notification = Factory::getObject<Notification>(
|
|
||||||
user->getId(),
|
user->getId(),
|
||||||
|
user,
|
||||||
title,
|
title,
|
||||||
message,
|
message,
|
||||||
util::Timestamp());
|
util::Timestamp()
|
||||||
if (!notification)
|
);
|
||||||
|
if (notification)
|
||||||
|
{
|
||||||
|
user->addNotification(notification);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Failed to create notification");
|
throw std::runtime_error("Failed to create notification");
|
||||||
}
|
}
|
||||||
auto& trackedNotificationsMap = m_dataStore.getNotifications();
|
}
|
||||||
trackedNotificationsMap.insert(notification->getId(), util::createNewRecord(notification));
|
}
|
||||||
m_dataStore.saveNotifications();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
@@ -21,6 +21,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();
|
||||||
@@ -32,4 +33,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();
|
||||||
};
|
};
|
||||||
|
|||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
#include "NotificationManagementService.h"
|
||||||
+1
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
+132
-23
@@ -11,6 +11,7 @@ Date: 20-May-2026
|
|||||||
#include "Config.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 "Invoice.h"
|
||||||
#include "JobCard.h"
|
#include "JobCard.h"
|
||||||
@@ -20,7 +21,6 @@ Date: 20-May-2026
|
|||||||
#include "Timestamp.h"
|
#include "Timestamp.h"
|
||||||
#include "User.h"
|
#include "User.h"
|
||||||
#include "Utility.h"
|
#include "Utility.h"
|
||||||
#include "DataStoreLockGuard.h"
|
|
||||||
|
|
||||||
util::Map<std::string, User*> PaymentManagementService::m_observers{};
|
util::Map<std::string, User*> PaymentManagementService::m_observers{};
|
||||||
|
|
||||||
@@ -34,9 +34,6 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
void PaymentManagementService::attach(User* user)
|
void PaymentManagementService::attach(User* user)
|
||||||
{
|
{
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
|
||||||
m_observers.clear();
|
|
||||||
m_observers = m_dataStore.getPaymentManagementObservers();
|
|
||||||
if (user)
|
if (user)
|
||||||
{
|
{
|
||||||
const std::string& userID = user->getId();
|
const std::string& userID = user->getId();
|
||||||
@@ -45,7 +42,6 @@ void PaymentManagementService::attach(User* user)
|
|||||||
m_observers[userID] = user;
|
m_observers[userID] = user;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_dataStore.savePaymentManagementObservers(m_observers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -58,9 +54,6 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
void PaymentManagementService::detach(User* user)
|
void PaymentManagementService::detach(User* user)
|
||||||
{
|
{
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
|
||||||
m_observers.clear();
|
|
||||||
m_observers = m_dataStore.getPaymentManagementObservers();
|
|
||||||
if (user)
|
if (user)
|
||||||
{
|
{
|
||||||
const std::string& userID = user->getId();
|
const std::string& userID = user->getId();
|
||||||
@@ -69,7 +62,6 @@ void PaymentManagementService::detach(User* user)
|
|||||||
m_observers.remove(userID);
|
m_observers.remove(userID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_dataStore.savePaymentManagementObservers(m_observers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -86,28 +78,28 @@ Throws:
|
|||||||
*/
|
*/
|
||||||
void PaymentManagementService::sendNotification(User* user, const std::string& title, const std::string& message)
|
void PaymentManagementService::sendNotification(User* user, const std::string& title, const std::string& message)
|
||||||
{
|
{
|
||||||
if (!user)
|
if (user)
|
||||||
{
|
{
|
||||||
return;
|
if (m_observers.find(user->getId()) != -1)
|
||||||
}
|
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
|
||||||
m_observers = m_dataStore.getPaymentManagementObservers();
|
|
||||||
if (m_observers.find(user->getId()) == -1)
|
|
||||||
{
|
{
|
||||||
return;
|
Notification* notification =
|
||||||
}
|
Factory::getObject<Notification>(
|
||||||
Notification* notification = Factory::getObject<Notification>(
|
|
||||||
user->getId(),
|
user->getId(),
|
||||||
|
user,
|
||||||
title,
|
title,
|
||||||
message,
|
message,
|
||||||
util::Timestamp());
|
util::Timestamp()
|
||||||
if (!notification)
|
);
|
||||||
|
if (notification)
|
||||||
|
{
|
||||||
|
user->addNotification(notification);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Failed to create notification");
|
throw std::runtime_error("Failed to create notification");
|
||||||
}
|
}
|
||||||
auto& trackedNotificationsMap = m_dataStore.getNotifications();
|
}
|
||||||
trackedNotificationsMap.insert(notification->getId(), util::createNewRecord(notification));
|
}
|
||||||
m_dataStore.saveNotifications();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -148,6 +140,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)
|
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.
|
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:
|
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);
|
||||||
@@ -33,4 +34,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();
|
||||||
};
|
};
|
||||||
|
|||||||
+332
-23
@@ -14,6 +14,7 @@ Date:19-May-2026
|
|||||||
#include "DataStore.h"
|
#include "DataStore.h"
|
||||||
#include "Enums.h"
|
#include "Enums.h"
|
||||||
#include "Factory.h"
|
#include "Factory.h"
|
||||||
|
#include "FileManager.h"
|
||||||
#include "InventoryItem.h"
|
#include "InventoryItem.h"
|
||||||
#include "JobCard.h"
|
#include "JobCard.h"
|
||||||
#include "NotificationManagementService.h"
|
#include "NotificationManagementService.h"
|
||||||
@@ -25,7 +26,6 @@ Date:19-May-2026
|
|||||||
#include "User.h"
|
#include "User.h"
|
||||||
#include "UserManagementService.h"
|
#include "UserManagementService.h"
|
||||||
#include "Utility.h"
|
#include "Utility.h"
|
||||||
#include "DataStoreLockGuard.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: purchaseService
|
Function: purchaseService
|
||||||
@@ -122,9 +122,6 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
void ServiceManagementService::attach(User* user)
|
void ServiceManagementService::attach(User* user)
|
||||||
{
|
{
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
|
||||||
m_observers.clear();
|
|
||||||
m_observers = m_dataStore.getServiceManagementObservers();
|
|
||||||
if (user)
|
if (user)
|
||||||
{
|
{
|
||||||
const std::string& userID = user->getId();
|
const std::string& userID = user->getId();
|
||||||
@@ -133,7 +130,6 @@ void ServiceManagementService::attach(User* user)
|
|||||||
m_observers[userID] = user;
|
m_observers[userID] = user;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_dataStore.saveServiceManagementObservers(m_observers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -146,9 +142,6 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
void ServiceManagementService::detach(User* user)
|
void ServiceManagementService::detach(User* user)
|
||||||
{
|
{
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
|
||||||
m_observers.clear();
|
|
||||||
m_observers = m_dataStore.getServiceManagementObservers();
|
|
||||||
if (user)
|
if (user)
|
||||||
{
|
{
|
||||||
const std::string& userID = user->getId();
|
const std::string& userID = user->getId();
|
||||||
@@ -157,7 +150,6 @@ void ServiceManagementService::detach(User* user)
|
|||||||
m_observers.remove(userID);
|
m_observers.remove(userID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_dataStore.saveServiceManagementObservers(m_observers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -174,28 +166,345 @@ Throws:
|
|||||||
*/
|
*/
|
||||||
void ServiceManagementService::sendNotification(User* user, const std::string& title, const std::string& message)
|
void ServiceManagementService::sendNotification(User* user, const std::string& title, const std::string& message)
|
||||||
{
|
{
|
||||||
if (!user)
|
if (user)
|
||||||
{
|
{
|
||||||
return;
|
if (m_observers.find(user->getId()) != -1)
|
||||||
}
|
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
|
||||||
m_observers = m_dataStore.getServiceManagementObservers();
|
|
||||||
if (m_observers.find(user->getId()) == -1)
|
|
||||||
{
|
{
|
||||||
return;
|
Notification* notification =
|
||||||
}
|
Factory::getObject<Notification>(
|
||||||
Notification* notification = Factory::getObject<Notification>(
|
|
||||||
user->getId(),
|
user->getId(),
|
||||||
|
user,
|
||||||
title,
|
title,
|
||||||
message,
|
message,
|
||||||
util::Timestamp());
|
util::Timestamp()
|
||||||
if (!notification)
|
);
|
||||||
|
if (notification)
|
||||||
|
{
|
||||||
|
user->addNotification(notification);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Failed to create notification");
|
throw std::runtime_error("Failed to create notification");
|
||||||
}
|
}
|
||||||
auto& trackedNotificationsMap = m_dataStore.getNotifications();
|
}
|
||||||
trackedNotificationsMap.insert(notification->getId(), util::createNewRecord(notification));
|
}
|
||||||
m_dataStore.saveNotifications();
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: getObserverIDs
|
||||||
|
Description: Retrieves the IDs of all observers currently attached to the
|
||||||
|
ServiceManagementService.
|
||||||
|
Parameters:
|
||||||
|
- None
|
||||||
|
Returns:
|
||||||
|
- util::Vector<std::string>: Vector of observer user IDs
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
+11
@@ -23,6 +23,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();
|
||||||
@@ -44,4 +45,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();
|
||||||
};
|
};
|
||||||
|
|||||||
+11
-13
@@ -11,6 +11,7 @@ Date:19-May-2026
|
|||||||
#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 "Notification.h"
|
#include "Notification.h"
|
||||||
#include "PaymentManagementService.h"
|
#include "PaymentManagementService.h"
|
||||||
@@ -169,18 +170,13 @@ util::Vector<Notification*> UserManagementService::getUserNotifications(const st
|
|||||||
User* user = trackedUsersMap[userID].data;
|
User* user = trackedUsersMap[userID].data;
|
||||||
if (user)
|
if (user)
|
||||||
{
|
{
|
||||||
auto& trackedNotificationMap = m_dataStore.getNotifications();
|
auto& notifications = user->getNotifications();
|
||||||
int numberOfNotifications = trackedNotificationMap.getSize();
|
int numberOfNotifications = notifications.getSize();
|
||||||
util::Vector<Notification*> notificationsVector;
|
util::Vector<Notification*> notificationsVector;
|
||||||
for (int index = 0; index < numberOfNotifications; index++)
|
for (int index = 0; index < numberOfNotifications; index++)
|
||||||
{
|
{
|
||||||
Notification* notification = trackedNotificationMap.getValueAt(index).data;
|
notificationsVector.push_back(notifications.getValueAt(index));
|
||||||
if (notification->getRecipientUserId() == userID && notification->getState() == util::State::ACTIVE)
|
|
||||||
{
|
|
||||||
notificationsVector.push_back(notification);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
m_dataStore.unlockDataStore();
|
|
||||||
return notificationsVector;
|
return notificationsVector;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -212,18 +208,20 @@ void UserManagementService::deleteNotification(const std::string& notificationID
|
|||||||
{
|
{
|
||||||
throw std::runtime_error("No user found with given UserID");
|
throw std::runtime_error("No user found with given UserID");
|
||||||
}
|
}
|
||||||
|
User* user = trackedUsersMap.getValueAt(userIndex).data;
|
||||||
|
auto& notifications = user->getNotifications();
|
||||||
|
if (notifications.find(notificationID) == -1)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("No notification found with given NotificationID");
|
||||||
|
}
|
||||||
int notificationIndex = trackedNotificationsMap.find(notificationID);
|
int notificationIndex = trackedNotificationsMap.find(notificationID);
|
||||||
if (notificationIndex == -1)
|
if (notificationIndex == -1)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("No notification found with given NotificationID");
|
throw std::runtime_error("No notification found with given NotificationID");
|
||||||
}
|
}
|
||||||
Notification* notification = trackedNotificationsMap.getValueAt(notificationIndex).data;
|
notifications[notificationID]->setState(util::State::INACTIVE);
|
||||||
if (notification->getRecipientUserId() == userID)
|
|
||||||
{
|
|
||||||
notification->setState(util::State::INACTIVE);
|
|
||||||
trackedNotificationsMap.getValueAt(notificationIndex).state = RecordState::MODIFIED;
|
trackedNotificationsMap.getValueAt(notificationIndex).state = RecordState::MODIFIED;
|
||||||
m_dataStore.saveNotifications();
|
m_dataStore.saveNotifications();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ namespace config
|
|||||||
namespace file
|
namespace file
|
||||||
{
|
{
|
||||||
const size_t INITIAL_CAPACITY = 100;
|
const size_t INITIAL_CAPACITY = 100;
|
||||||
const size_t GROWTH_FACTOR = 2;
|
|
||||||
constexpr const char* DIRECTORY = "files/";
|
constexpr const char* DIRECTORY = "files/";
|
||||||
constexpr const char* INVENTORYITEM_FILE = "files/InventoryItem.dat";
|
constexpr const char* INVENTORYITEM_FILE = "files/InventoryItem.dat";
|
||||||
constexpr const char* USER_FILE = "files/User.dat";
|
constexpr const char* USER_FILE = "files/User.dat";
|
||||||
|
|||||||
@@ -43,4 +43,67 @@ namespace util
|
|||||||
position++;
|
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))
|
if (!(std::cin >> value))
|
||||||
{
|
{
|
||||||
std::cin.clear();
|
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");
|
throw std::runtime_error("Invalid console input");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,52 @@ namespace util
|
|||||||
return cost;
|
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>
|
template<typename TObject>
|
||||||
Map<std::string, TObject*> getObjects(const Map<std::string, TrackedRecord<TObject>>& trackedRecords);
|
Map<std::string, TObject*> getObjects(const Map<std::string, TrackedRecord<TObject>>& trackedRecords);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user