diff --git a/.gitignore b/.gitignore
index fe37065..37b6ea3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -427,5 +427,5 @@ FodyWeavers.xsd
*.msm
*.msp
-# CSV Files
-*.csv
+# DAT Files
+*.dat
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj
index 7c4bfd3..34bfc34 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj
@@ -140,7 +140,6 @@
-
@@ -182,7 +181,6 @@
-
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters
index 7e74b19..c13b320 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters
@@ -114,9 +114,6 @@
Source Files\DataStores
-
- Source Files\Services
-
Source Files\Core\Patterns
@@ -245,9 +242,6 @@
Header Files\Utilities
-
- Header Files\Utilities
-
Header Files\Utilities
@@ -278,5 +272,8 @@
Header Files\DataStores\SharedMemory
+
+ Header Files\DataStores
+
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp
index 9bc1d86..487ecd5 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp
@@ -588,63 +588,37 @@ void Controller::configureNotifications(bool paymentNotifications, bool serviceN
}
/*
-Function: loadSystemData
-Description: Loads all system data from persistent storage into memory.
- Invokes the respective management services to load users, inventory items, services,
- combo packages, service bookings, job cards, invoices, and observers.
+Function: initialize
+Description: Initializes the system and run system checks to ensure critical configurations, such as verifying admin existence.
Parameters:
- None
Returns:
- - void
+ - bool
*/
-void Controller::loadSystemData()
+bool Controller::initialize()
{
- m_userManagementService.loadUsers();
- m_inventoryManagementService.loadInventoryItems();
- m_serviceManagementService.loadServices();
- m_serviceManagementService.loadComboPackages();
- m_serviceManagementService.loadServiceBookings();
- m_serviceManagementService.loadJobCards();
- m_paymentManagementService.loadInvoices();
- m_serviceManagementService.loadObservers();
- m_paymentManagementService.loadObservers();
- m_inventoryManagementService.loadObservers();
-}
+ auto& dataStore = DataStore::getInstance();
-/*
-Function: saveSystemData
-Description: Saves all system data from memory back to persistent storage.
- Invokes the respective management services to save users, inventory items, services,
- combo packages, service bookings, job cards, invoices, and observers.
-Parameters:
- - None
-Returns:
- - void
-*/
-void Controller::saveSystemData()
-{
- m_userManagementService.saveUsers();
- m_inventoryManagementService.saveInventoryItems();
- m_serviceManagementService.saveServices();
- m_serviceManagementService.saveComboPackages();
- m_serviceManagementService.saveServiceBookings();
- m_serviceManagementService.saveJobCards();
- m_paymentManagementService.saveInvoices();
- m_serviceManagementService.saveObservers();
- m_paymentManagementService.saveObservers();
- m_inventoryManagementService.saveObservers();
-}
-
-/*
-Function: runSystemChecks
-Description: Runs system checks to ensure critical configurations, such as verifying admin existence.
-Parameter: None
-Return type: void
-*/
-void Controller::runSystemChecks()
-{
+ if (!dataStore.initialize())
+ {
+ return false;
+ }
m_userManagementService.ensureAdminExists();
m_inventoryManagementService.sendLowStockAlerts();
m_paymentManagementService.sendPaymentReminders();
+ return true;
}
+/*
+Function: shutdown
+Description: Shutdown the system, and do necessary cleanups
+Parameters:
+ - None
+Returns:
+ - void
+*/
+void Controller::shutdown()
+{
+ auto& dataStore = DataStore::getInstance();
+ dataStore.shutdown();
+}
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h
index 35241a0..7ec1c30 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h
@@ -70,7 +70,6 @@ public:
util::Vector getNotifications();
void deleteNotification(const std::string& notificationID);
void configureNotifications(bool paymentNotifications, bool serviceNotifications);
- void loadSystemData();
- void saveSystemData();
- void runSystemChecks();
+ bool initialize();
+ void shutdown();
};
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/patterns/Observer.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/patterns/Observer.h
index 7fd7262..98e6f97 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/patterns/Observer.h
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/patterns/Observer.h
@@ -7,11 +7,8 @@ Date: 19-May-2026
#pragma once
-class Notification;
-
class Observer
{
public:
virtual ~Observer() = default;
- virtual void addNotification(Notification* notification) = 0;
};
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp
index 3092551..b77ad3d 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp
@@ -12,6 +12,8 @@ Date: 19-May-2026
#include "Config.h"
#include "SerializedRecords.h"
#include "FileHelper.h"
+#include "ServiceBooking.h"
+#include "JobCard.h"
#include "Invoice.h"
/*
@@ -145,11 +147,6 @@ bool DataStore::initialize()
success = false;
break;
}
- if (!SharedMemory::createOrOpenMapping(m_payments))
- {
- success = false;
- break;
- }
if (!SharedMemory::createOrOpenMapping(m_serviceManagementObservers))
{
success = false;
@@ -194,7 +191,6 @@ 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);
@@ -229,6 +225,8 @@ Returns:
*/
util::Map>& DataStore::getUsers()
{
+ auto users = loadRecords(m_users);
+ refreshCache(m_userCache, users);
return m_userCache;
}
@@ -242,6 +240,8 @@ Returns:
*/
util::Map>& DataStore::getNotifications()
{
+ auto notifications = loadRecords(m_notifications);
+ refreshCache(m_notificationCache, notifications);
return m_notificationCache;
}
@@ -255,6 +255,28 @@ Returns:
*/
util::Map>& DataStore::getServices()
{
+ util::Map> services = loadRecords(m_services);
+ refreshCache(m_serviceCache, services);
+ util::Map>& inventoryItems = getInventoryItems();
+ size_t numberOfServices = m_serviceCache.getSize();
+ for (int iteratorOne =0; iteratorOne < numberOfServices; iteratorOne++)
+ {
+ Service* currentService = m_serviceCache.getValueAt(iteratorOne).data;
+ util::Map inventoryItemMap;
+ util::Vector currentServiceInventoryItem = currentService->getRequiredInventoryItemIDs();
+ for (int iteratorTwo = 0; iteratorTwo < currentServiceInventoryItem.getSize(); iteratorTwo++)
+ {
+ const std::string& currentInventoryItemId = currentServiceInventoryItem[iteratorTwo];
+ int currentInventoryItemIndex = inventoryItems.find(currentInventoryItemId);
+ if (currentInventoryItemIndex == -1)
+ {
+ throw std::runtime_error("Invalid inventory item ID");
+ }
+ InventoryItem* currentItem = inventoryItems.getValueAt(currentInventoryItemIndex).data;
+ inventoryItemMap[currentInventoryItemId] = currentItem;
+ }
+ currentService->setRequiredInventoryItems(inventoryItemMap);
+ }
return m_serviceCache;
}
@@ -268,6 +290,28 @@ Returns:
*/
util::Map>& DataStore::getComboPackages()
{
+ util::Map> comboPackages = loadRecords(m_comboPackages);
+ refreshCache(m_comboPackageCache, comboPackages);
+ util::Map>& services = getServices();
+ size_t numberOfComboPackages = m_comboPackageCache.getSize();
+ for (int iteratorOne = 0; iteratorOne < numberOfComboPackages; iteratorOne++)
+ {
+ ComboPackage* currentComboPackage = m_comboPackageCache.getValueAt(iteratorOne).data;
+ util::Vector currentServiceIds = currentComboPackage->getServiceIDs();
+ util::Map currentComboPackageServices;
+ for (int iteratorTwo = 0; iteratorTwo < currentServiceIds.getSize(); iteratorTwo++)
+ {
+ const std::string& currentServiceId = currentServiceIds[iteratorTwo];
+ int serviceIndex = services.find(currentServiceId);
+ if (serviceIndex == -1)
+ {
+ throw std::runtime_error("Invalid service ID");
+ }
+ Service* currentService = services.getValueAt(serviceIndex).data;
+ currentComboPackageServices[currentServiceId] = currentService;
+ }
+ currentComboPackage->setServices(currentComboPackageServices);
+ }
return m_comboPackageCache;
}
@@ -281,6 +325,8 @@ Returns:
*/
util::Map>& DataStore::getInventoryItems()
{
+ auto inventoryItems = loadRecords(m_inventoryItems);
+ refreshCache(m_inventoryItemCache, inventoryItems);
return m_inventoryItemCache;
}
@@ -294,6 +340,49 @@ Returns:
*/
util::Map>& DataStore::getServiceBookings()
{
+ util::Map> serviceBookings = loadRecords(m_serviceBookings);
+ refreshCache(m_serviceBookingCache, serviceBookings);
+ auto& users = getUsers();
+ auto& services = getServices();
+ size_t numberOfServiceBookings = m_serviceBookingCache.getSize();
+ for (int iteratorOne = 0; iteratorOne < numberOfServiceBookings; iteratorOne++)
+ {
+ ServiceBooking* serviceBooking = m_serviceBookingCache.getValueAt(iteratorOne).data;
+ auto& serviceIds = serviceBooking->getServiceIDs();
+ util::Map servicesInBooking;
+ for (int iteratorTwo = 0; iteratorTwo < serviceIds.getSize(); iteratorTwo++)
+ {
+ const std::string& currentServiceId = serviceIds[iteratorTwo];
+ int serviceIndex = services.find(currentServiceId);
+ if (serviceIndex == -1)
+ {
+ throw std::runtime_error("Invalid service index.");
+ }
+ auto currentService = services.getValueAt(serviceIndex);
+ servicesInBooking[currentServiceId] = currentService.data;
+ }
+ serviceBooking->setServices(servicesInBooking);
+ if (!serviceBooking->getCustomerId().empty())
+ {
+ int userIndex = users.find(serviceBooking->getCustomerId());
+ if (userIndex == -1)
+ {
+ throw std::runtime_error("Invalid user index.");
+ }
+ auto customer = users.getValueAt(userIndex);
+ serviceBooking->setCustomer(customer.data);
+ }
+ if (!serviceBooking->getAssignedTechnicianId().empty())
+ {
+ int technicianIndex = users.find(serviceBooking->getAssignedTechnicianId());
+ if (technicianIndex == -1)
+ {
+ throw std::runtime_error("Invalid technician index.");
+ }
+ auto technician = users.getValueAt(technicianIndex);
+ serviceBooking->setAssignedTechnician(technician.data);
+ }
+ }
return m_serviceBookingCache;
}
@@ -307,9 +396,51 @@ Returns:
*/
util::Map>& DataStore::getJobCards()
{
+ util::Map> jobCards = loadRecords(m_jobCards);
+ refreshCache(m_jobCardCache, jobCards);
+ auto& serviceBookings = getServiceBookings();
+ auto& services = getServices();
+ auto& users = getUsers();
+ int numberOfJobCards = m_jobCardCache.getSize();
+ for (int iterator = 0; iterator < numberOfJobCards; iterator++)
+ {
+ JobCard* jobCard = m_jobCardCache.getValueAt(iterator).data;
+ if (!jobCard)
+ {
+ continue;
+ }
+ const std::string& bookingId = jobCard->getBookingId();
+ int bookingIndex = serviceBookings.find(bookingId);
+ if (bookingIndex == -1)
+ {
+ throw std::runtime_error("Invalid booking ID: " + bookingId);
+ }
+ auto trackedBooking = serviceBookings.getValueAt(bookingIndex);
+ jobCard->setBooking(trackedBooking.data);
+ const std::string& serviceId = jobCard->getServiceId();
+ int serviceIndex = services.find(serviceId);
+ if (serviceIndex == -1)
+ {
+ throw std::runtime_error("Invalid service ID: " + serviceId);
+ }
+ auto trackedService = services.getValueAt(serviceIndex);
+ jobCard->setService(trackedService.data);
+ const std::string& technicianId = jobCard->getTechnicianId();
+ if (!technicianId.empty())
+ {
+ int technicianIndex = users.find(technicianId);
+ if (technicianIndex == -1)
+ {
+ throw std::runtime_error("Invalid technician ID: " + technicianId);
+ }
+ auto trackedTechnician = users.getValueAt(technicianIndex);
+ jobCard->setTechnician(trackedTechnician.data);
+ }
+ }
return m_jobCardCache;
}
+
/*
Function: getInvoices
Description: Retrieves all invoice records from the datastore.
@@ -362,6 +493,37 @@ util::Map>& DataStore::getInvoices()
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: Collection of observer records
+Throws:
+ - std::runtime_error if an observer references an invalid user ID
+*/
+util::Map DataStore::getObservers(MappingInfo& mapping)
+{
+ auto& users = getUsers();
+ util::Map observers;
+ SharedMemory::ensureLatestMapping(mapping);
+ size_t recordCount = SharedMemory::getRecordCount(mapping);
+ for (size_t index = 0; index < recordCount; index++)
+ {
+ const SerializedObserver* observer = static_cast(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
Description: Retrieves all service management observer records from the datastore.
@@ -372,7 +534,7 @@ Returns:
*/
util::Map DataStore::getServiceManagementObservers()
{
- return util::Map();
+ return getObservers(m_serviceManagementObservers);
}
/*
@@ -385,7 +547,7 @@ Returns:
*/
util::Map DataStore::getPaymentManagementObservers()
{
- return util::Map();
+ return getObservers(m_paymentManagementObservers);
}
/*
@@ -398,7 +560,7 @@ Returns:
*/
util::Map DataStore::getInventoryManagementObservers()
{
- return util::Map();
+ return getObservers(m_inventoryManagementObservers);
}
/*
@@ -411,6 +573,7 @@ Returns:
*/
void DataStore::saveUsers()
{
+ saveRecords(m_users, m_userCache);
}
/*
@@ -423,6 +586,7 @@ Returns:
*/
void DataStore::saveNotifications()
{
+ saveRecords(m_notifications, m_notificationCache);
}
/*
@@ -435,6 +599,7 @@ Returns:
*/
void DataStore::saveServices()
{
+ saveRecords(m_services, m_serviceCache);
}
/*
@@ -447,6 +612,7 @@ Returns:
*/
void DataStore::saveComboPackages()
{
+ saveRecords(m_comboPackages, m_comboPackageCache);
}
/*
@@ -459,6 +625,7 @@ Returns:
*/
void DataStore::saveInventoryItems()
{
+ saveRecords(m_inventoryItems, m_inventoryItemCache);
}
/*
@@ -471,6 +638,7 @@ Returns:
*/
void DataStore::saveServiceBookings()
{
+ saveRecords(m_serviceBookings, m_serviceBookingCache);
}
/*
@@ -483,6 +651,7 @@ Returns:
*/
void DataStore::saveJobCards()
{
+ saveRecords(m_jobCards, m_jobCardCache);
}
/*
@@ -498,16 +667,49 @@ void DataStore::saveInvoices()
saveRecords(m_invoices, m_invoiceCache);
}
+/*
+Function: saveObservers
+Description: Persists observer records to the specified observer mapping.
+Parameters:
+ - mapping: MappingInfo&, observer mapping to save to
+ - observers: util::Map&, collection of observer records
+Returns:
+ - None
+*/
+void DataStore::saveObservers(MappingInfo& mapping, util::Map& observers)
+{
+ size_t observerCount = static_cast(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(index));
+ strcpy_s(serializedObserver.id, sizeof(serializedObserver.id), user->getId().c_str());
+ SerializedObserver* destination = static_cast(SharedMemory::getRecordAddress(mapping, index));
+ *destination = serializedObserver;
+ }
+}
+
/*
Function: saveServiceManagementObservers
Description: Persists all service management observer records to the datastore.
Parameters:
- - observers: util::Map>&, collection of observer records
+ - observers: util::Map&, collection of observer records
Returns:
- None
*/
void DataStore::saveServiceManagementObservers(util::Map& observers)
{
+ saveObservers(m_serviceManagementObservers, observers);
}
/*
@@ -520,6 +722,7 @@ Returns:
*/
void DataStore::savePaymentManagementObservers(util::Map& observers)
{
+ saveObservers(m_paymentManagementObservers, observers);
}
/*
@@ -532,32 +735,7 @@ Returns:
*/
void DataStore::saveInventoryManagementObservers(util::Map& 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;
+ saveObservers(m_inventoryManagementObservers, observers);
}
/*
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h
index 3950b11..021d831 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h
@@ -11,15 +11,16 @@ Date: 19-May-2026
#include "Map.h"
#include "MappingInfo.h"
#include "TrackedRecord.h"
+#include "SerializedRecords.h"
#include "SharedMemory.h"
-class User;
-class Notification;
-class Service;
-class ComboPackage;
-class InventoryItem;
-class ServiceBooking;
-class JobCard;
-class Invoice;
+#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 DataStore
{
@@ -39,7 +40,6 @@ private:
MappingInfo m_serviceBookings;
MappingInfo m_jobCards;
MappingInfo m_invoices;
- MappingInfo m_payments;
MappingInfo m_serviceManagementObservers;
MappingInfo m_paymentManagementObservers;
MappingInfo m_inventoryManagementObservers;
@@ -86,6 +86,8 @@ private:
void saveRecords(MappingInfo& mapping, util::Map>& records);
template void clearCache(util::Map>&cache);
template void refreshCache(util::Map>&cache, util::Map>&refreshedCache);
+ util::Map getObservers(MappingInfo& mapping);
+ void saveObservers(MappingInfo& mapping, util::Map& observers);
};
/*
@@ -229,9 +231,17 @@ void DataStore::refreshCache(util::Map>& cac
for (int index = 0; index < oldCache.getSize(); ++index)
{
const std::string& id = oldCache.getKeyAt(index);
+ const TrackedRecord& localTrackedRecord = oldCache.getValueAt(index);
if (cache.find(id) == -1)
{
- delete oldCache.getValueAt(index).data;
+ if (localTrackedRecord.state == RecordState::NEW_RECORD)
+ {
+ cache.insert(id, localTrackedRecord);
+ }
+ else
+ {
+ delete localTrackedRecord.data;
+ }
}
}
}
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/SharedMemory.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/SharedMemory.cpp
index 6a10c9f..0c5c7b1 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/SharedMemory.cpp
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/SharedMemory.cpp
@@ -10,6 +10,7 @@ Created: 11-June-2026
*/
#include "SharedMemory.h"
+#include "Windows.h"
#include "Config.h"
/*
@@ -319,7 +320,7 @@ bool SharedMemory::ensureCapacityForInsert(MappingInfo& mapping)
{
return true;
}
- return resizeMapping(mapping, capacity * 2);
+ return resizeMapping(mapping, capacity * config::file::GROWTH_FACTOR);
}
/*
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.cpp
index 4e69d9f..7e9d1a9 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.cpp
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.cpp
@@ -9,6 +9,7 @@ Date: 19-May-2026
#include
#include
+#include "SerializedRecords.h"
#include "ComboPackage.h"
#include "Service.h"
#include "Factory.h"
@@ -28,7 +29,8 @@ Returns:
ComboPackage::ComboPackage()
: m_id("CMP" + std::to_string(++m_uid)),
m_status(util::State::ACTIVE),
- m_discountPercentage(0.0) {}
+ m_discountPercentage(0.0) {
+}
/*
Function: ComboPackage
@@ -270,72 +272,38 @@ static util::Vector getServiceIDsAsVector(const std::string& servic
/*
Function: serialize
-Description: Serializes the combo package into a CSV-formatted string.
+Description: Serializes the ComboPackage object into a SerializedComboPackage record.
Parameters:
- None
Returns:
- - std::string: Serialized combo package record
+ - SerializedComboPackage: Serialized representation of the combo package
*/
-std::string ComboPackage::serialize() const
+SerializedComboPackage ComboPackage::serialize() const
{
- std::ostringstream serializedComboPackage;
- serializedComboPackage << m_id << ','
- << m_packageName << ','
- << m_discountPercentage << ','
- << getServiceIDsAsString(m_serviceIDs) << ','
- << util::getStateString(m_status);
- return serializedComboPackage.str();
+ SerializedComboPackage serialized = {};
+ strcpy_s(serialized.id, sizeof(serialized.id), m_id.c_str());
+ strcpy_s(serialized.packageName, sizeof(serialized.packageName), m_packageName.c_str());
+ strcpy_s(serialized.serviceIDs, sizeof(serialized.serviceIDs), getServiceIDsAsString(m_serviceIDs).c_str());
+ serialized.discountPercentage = m_discountPercentage;
+ serialized.status = m_status;
+ return serialized;
}
/*
Function: deserialize
-Description: Deserializes a CSV-formatted string into a ComboPackage object.
+Description: Deserializes a SerializedComboPackage record into a ComboPackage object.
Parameters:
- - record: const std::string&, serialized combo package record
+ - serializedComboPackage: const SerializedComboPackage&, serialized combo package record
Returns:
- ComboPackage*: Pointer to the deserialized ComboPackage object
-Throws:
- - std::runtime_error if data is invalid
*/
-ComboPackage* ComboPackage::deserialize(const std::string& record)
+ComboPackage* ComboPackage::deserialize(const SerializedComboPackage& serializedComboPackage)
{
- std::string id, packageName;
- std::string discountPercentageString, serviceIDsString, statusString;
- double discountPercentage;
- std::istringstream serializedComboPackage(record);
- getline(serializedComboPackage, id, ',');
- getline(serializedComboPackage, packageName, ',');
- getline(serializedComboPackage, discountPercentageString, ',');
- getline(serializedComboPackage, serviceIDsString, ',');
- getline(serializedComboPackage, statusString, ',');
- try
- {
- discountPercentage = std::stod(discountPercentageString);
- }
- catch (...)
- {
- throw std::runtime_error("Invalid combo package data");
- }
- util::Vector serviceIDs = getServiceIDsAsVector(serviceIDsString);
- util::State status = util::getState(statusString);
+ util::Vector serviceIDs = getServiceIDsAsVector(serializedComboPackage.serviceIDs);
return Factory::getObject(
- id,
- packageName,
- discountPercentage,
+ serializedComboPackage.id,
+ serializedComboPackage.packageName,
+ serializedComboPackage.discountPercentage,
serviceIDs,
- status
- );
-}
-
-/*
-Function: getHeaders
-Description: Retrieves the CSV headers for combo package serialization.
-Parameters:
- - None
-Returns:
- - std::string: Header string ("ID,PackageName,DiscountPercentage,ServiceIDs,Status")
-*/
-std::string ComboPackage::getHeaders()
-{
- return "ID,PackageName,DiscountPercentage,ServiceIDs,Status";
-}
+ serializedComboPackage.status);
+}
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.h
index 941c2b3..671e346 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.h
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.h
@@ -12,6 +12,7 @@ Date: 19-May-2026
#include "Enums.h"
class Service;
+struct SerializedComboPackage;
class ComboPackage
{
@@ -38,7 +39,6 @@ public:
void setDiscountPercentage(double discountPercentage);
void setServices(const util::Map& services);
void setState(util::State status);
- std::string serialize() const;
- static ComboPackage* deserialize(const std::string&);
- static std::string getHeaders();
+ SerializedComboPackage serialize() const;
+ static ComboPackage* deserialize(const SerializedComboPackage&);
};
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/InventoryItem.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/InventoryItem.cpp
index f34b8a5..67fb7ba 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/InventoryItem.cpp
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/InventoryItem.cpp
@@ -8,6 +8,7 @@ Date: 19-May-2026
#include
#include
+#include "SerializedRecords.h"
#include "Factory.h"
#include "StringHelper.h"
#include "InventoryItem.h"
@@ -27,7 +28,8 @@ InventoryItem::InventoryItem()
: m_id("IIM" + std::to_string(++m_uid)),
m_quantity(0),
m_status(util::State::ACTIVE),
- m_price(0.0) {}
+ m_price(0.0) {
+}
/*
Function: InventoryItem
@@ -45,7 +47,8 @@ InventoryItem::InventoryItem(const std::string& partName, int quantity, double p
m_partName(partName),
m_quantity(quantity),
m_status(util::State::ACTIVE),
- m_price(price) {}
+ m_price(price) {
+}
/*
Function: InventoryItem (parameterized constructor with ID)
@@ -206,73 +209,37 @@ void InventoryItem::setState(util::State status)
/*
Function: serialize
-Description: Serializes the inventory item into a CSV-formatted string.
+Description: Serializes the InventoryItem object into a SerializedInventoryItem record.
Parameters:
- None
Returns:
- - std::string: Serialized inventory item record
+ - SerializedInventoryItem: Serialized representation of the inventory item
*/
-std::string InventoryItem::serialize() const
+SerializedInventoryItem InventoryItem::serialize() const
{
- std::ostringstream serializedInventoryItem;
- serializedInventoryItem << m_id << ','
- << m_partName << ','
- << m_quantity << ','
- << m_price << ','
- << util::getStateString(m_status);
- return serializedInventoryItem.str();
+ SerializedInventoryItem serialized = {};
+ strcpy_s(serialized.id, sizeof(serialized.id), m_id.c_str());
+ strcpy_s(serialized.partName, sizeof(serialized.partName), m_partName.c_str());
+ serialized.quantity = m_quantity;
+ serialized.price = m_price;
+ serialized.status = m_status;
+ return serialized;
}
/*
Function: deserialize
-Description: Deserializes a CSV-formatted string into an InventoryItem object.
+Description: Deserializes a SerializedInventoryItem record into an InventoryItem object.
Parameters:
- - record: const std::string&, serialized inventory item record
+ - serializedInventoryItem: const SerializedInventoryItem&, serialized inventory item record
Returns:
- InventoryItem*: Pointer to the deserialized InventoryItem object
-Throws:
- - std::runtime_error if data is invalid
*/
-InventoryItem* InventoryItem::deserialize(const std::string& record)
+InventoryItem* InventoryItem::deserialize(const SerializedInventoryItem& serializedInventoryItem)
{
- std::string id, partName;
- std::string quantityString, priceString, statusString;
- int quantity;
- double price;
- std::istringstream serializedInventoryItem(record);
- getline(serializedInventoryItem, id, ',');
- getline(serializedInventoryItem, partName, ',');
- getline(serializedInventoryItem, quantityString, ',');
- getline(serializedInventoryItem, priceString, ',');
- getline(serializedInventoryItem, statusString, ',');
- try
- {
- quantity = std::stoi(quantityString);
- price = std::stod(priceString);
- }
- catch (...)
- {
- throw std::runtime_error("Invalid inventory item data");
- }
- util::State status = util::getState(statusString);
return Factory::getObject(
- id,
- partName,
- quantity,
- price,
- status
- );
-}
-
-/*
-Function: getHeaders
-Description: Retrieves the CSV headers for inventory item serialization.
-Parameters:
- - None
-Returns:
- - std::string: Header string ("ID,PartName,Quantity,Price,Status")
-*/
-std::string InventoryItem::getHeaders()
-{
- return "ID,PartName,Quantity,Price,Status";
+ serializedInventoryItem.id,
+ serializedInventoryItem.partName,
+ serializedInventoryItem.quantity,
+ serializedInventoryItem.price,
+ serializedInventoryItem.status);
}
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/InventoryItem.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/InventoryItem.h
index 5808e8f..90b716a 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/InventoryItem.h
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/InventoryItem.h
@@ -6,11 +6,12 @@ Author: Trenser
Date: 19-May-2026
*/
-
#pragma once
#include
#include "Enums.h"
+struct SerializedInventoryItem;
+
class InventoryItem
{
private:
@@ -34,7 +35,6 @@ public:
void setQuantity(int quantity);
void setPrice(double price);
void setState(util::State status);
- std::string serialize() const;
- static InventoryItem* deserialize(const std::string&);
- static std::string getHeaders();
+ SerializedInventoryItem serialize() const;
+ static InventoryItem* deserialize(const SerializedInventoryItem&);
};
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp
index 214a8e0..0bea7c2 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp
@@ -9,6 +9,7 @@ Date:19-May-2026
#include
#include
+#include "SerializedRecords.h"
#include "JobCard.h"
#include "Factory.h"
#include "StringHelper.h"
@@ -28,7 +29,8 @@ JobCard::JobCard()
m_booking(nullptr),
m_service(nullptr),
m_technician(nullptr),
- m_status(util::ServiceJobStatus()) {}
+ m_status(util::ServiceJobStatus()) {
+}
/*
Function: JobCard
@@ -65,7 +67,8 @@ JobCard::JobCard(const std::string& bookingId,
m_technician(technician),
m_assignedDate(assignedDate),
m_status(status),
- m_completionDate(completionDate) {}
+ m_completionDate(completionDate) {
+}
/*
Function: JobCard (parameterized constructor with ID)
@@ -351,79 +354,41 @@ void JobCard::setCompletionDate(const util::Timestamp& completionDate)
/*
Function: serialize
-Description: Serializes the job card into a CSV-formatted string.
+Description: Serializes the JobCard object into a SerializedJobCard record.
Parameters:
- None
Returns:
- - std::string: Serialized job card record
+ - SerializedJobCard: Serialized representation of the job card
*/
-std::string JobCard::serialize() const
+SerializedJobCard JobCard::serialize() const
{
- std::ostringstream serializedJobCard;
- serializedJobCard << m_id << ','
- << m_bookingId << ','
- << m_serviceId << ','
- << m_technicianId << ','
- << m_assignedDate.toString() << ','
- << util::getServiceJobStatusString(m_status) << ','
- << m_completionDate.toString();
- return serializedJobCard.str();
+ SerializedJobCard serialized = {};
+ strcpy_s(serialized.id, sizeof(serialized.id), m_id.c_str());
+ strcpy_s(serialized.bookingId, sizeof(serialized.bookingId), m_bookingId.c_str());
+ strcpy_s(serialized.serviceId, sizeof(serialized.serviceId), m_serviceId.c_str());
+ strcpy_s(serialized.technicianId, sizeof(serialized.technicianId), m_technicianId.c_str());
+ serialized.assignedDate = m_assignedDate;
+ serialized.status = m_status;
+ serialized.completionDate = m_completionDate;
+ return serialized;
}
/*
Function: deserialize
-Description: Deserializes a CSV-formatted string into a JobCard object.
+Description: Deserializes a SerializedJobCard record into a JobCard object.
Parameters:
- - record: const std::string&, serialized job card record
+ - serializedJobCard: const SerializedJobCard&, serialized job card record
Returns:
- JobCard*: Pointer to the deserialized JobCard object
-Throws:
- - std::runtime_error if timestamp parsing fails
*/
-JobCard* JobCard::deserialize(const std::string& record)
+JobCard* JobCard::deserialize(const SerializedJobCard& serializedJobCard)
{
- std::string id, bookingId, serviceId, technicianId;
- std::string assignedDateString, statusString, completionDateString;
- std::istringstream serializedJobCard(record);
- getline(serializedJobCard, id, ',');
- getline(serializedJobCard, bookingId, ',');
- getline(serializedJobCard, serviceId, ',');
- getline(serializedJobCard, technicianId, ',');
- getline(serializedJobCard, assignedDateString, ',');
- getline(serializedJobCard, statusString, ',');
- getline(serializedJobCard, completionDateString, ',');
- util::Timestamp assignedDate;
- util::Timestamp completionDate;
- try
- {
- assignedDate = util::Timestamp::fromString(assignedDateString);
- completionDate = util::Timestamp::fromString(completionDateString);
- }
- catch (...)
- {
- throw std::runtime_error("Invalid timestamp");
- }
- util::ServiceJobStatus status = util::getServiceJobStatus(statusString);
return Factory::getObject(
- id,
- bookingId,
- serviceId,
- technicianId,
- assignedDate,
- status,
- completionDate
- );
-}
-
-/*
-Function: getHeaders
-Description: Retrieves the CSV headers for job card serialization.
-Parameters:
- - None
-Returns:
- - std::string: Header string ("ID,BookingID,ServiceID,TechnicianID,AssignedDate,Status,CompletionDate")
-*/
-std::string JobCard::getHeaders()
-{
- return "ID,BookingID,ServiceID,TechnicianID,AssignedDate,Status,CompletionDate";
+ serializedJobCard.id,
+ serializedJobCard.bookingId,
+ serializedJobCard.serviceId,
+ serializedJobCard.technicianId,
+ serializedJobCard.assignedDate,
+ serializedJobCard.status,
+ serializedJobCard.completionDate);
}
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h
index a845263..ed243e8 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h
@@ -15,6 +15,7 @@ Date:19-May-2026
class ServiceBooking;
class Service;
class User;
+struct SerializedJobCard;
class JobCard
{
@@ -34,11 +35,11 @@ public:
JobCard();
JobCard(const std::string& bookingId,
ServiceBooking* booking,
- Service* service,
- const std::string& serviceId,
- const std::string& technicianId,
- User* technician,
- const util::Timestamp& assignedDate,
+ Service* service,
+ const std::string& serviceId,
+ const std::string& technicianId,
+ User* technician,
+ const util::Timestamp& assignedDate,
util::ServiceJobStatus status,
const util::Timestamp& completionDate
);
@@ -70,7 +71,6 @@ public:
void setAssignedDate(const util::Timestamp& assignedDate);
void setStatus(util::ServiceJobStatus status);
void setCompletionDate(const util::Timestamp& completionDate);
- std::string serialize() const;
- static JobCard* deserialize(const std::string&);
- static std::string getHeaders();
+ SerializedJobCard serialize() const;
+ static JobCard* deserialize(const SerializedJobCard&);
};
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.cpp
index 0bae917..83532ec 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.cpp
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.cpp
@@ -1,12 +1,13 @@
/*
File: Notification.cpp
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, recipient, title, message, and timestamp.
+ Provides constructors, accessors, and mutators for notification details such as ID, recipientID, title, message, and timestamp.
Author: Trenser
Date: 19-May-2026
*/
#include
+#include "SerializedRecords.h"
#include "Notification.h"
#include "StringHelper.h"
#include "Factory.h"
@@ -22,8 +23,8 @@ Returns:
- A new Notification object.
*/
Notification::Notification()
- : m_id("NOT" + std::to_string(++m_uid)),
- m_recipient(nullptr) {}
+ : m_id("NOT" + std::to_string(++m_uid)),
+ m_state(util::State::ACTIVE) {}
/*
Function: Notification
@@ -37,13 +38,14 @@ Parameters:
Returns:
- A new Notification object.
*/
-Notification::Notification(const std::string& recipientUserId, User* recipient, const std::string& title, const std::string& message, const util::Timestamp& createdAt)
+Notification::Notification(const std::string& recipientUserId, const std::string& title, const std::string& message, const util::Timestamp& createdAt)
: m_id("NOT" + std::to_string(++m_uid)),
m_recipientUserId(recipientUserId),
- m_recipient(recipient),
m_title(title),
m_message(message),
- m_createdAt(createdAt) {}
+ m_state(util::State::ACTIVE),
+ m_createdAt(createdAt) {
+}
/*
Function: Notification (parameterized constructor with ID)
@@ -58,13 +60,13 @@ Parameters:
Returns:
- 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)
+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)
: m_id(id),
m_recipientUserId(recipientUserId),
- m_recipient(nullptr),
m_title(title),
m_message(message),
- m_createdAt(createdAt)
+ m_createdAt(createdAt),
+ m_state(state)
{
int idNumber = util::extractNumber(m_id);
if (idNumber > m_uid)
@@ -79,7 +81,7 @@ Description: Retrieves the unique ID of the notification.
Returns:
- const std::string& representing the notification ID.
*/
-const std::string& Notification::getId() const
+const std::string& Notification::getId() const
{
return m_id;
}
@@ -95,17 +97,6 @@ const std::string& Notification::getRecipientUserId() const
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
Description: Retrieves the title of the notification.
@@ -139,6 +130,17 @@ const util::Timestamp& Notification::getCreatedAt() const
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
Description: Sets the unique ID of the notification.
@@ -165,19 +167,6 @@ void Notification::setRecipientUserId(const std::string& 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
Description: Sets the title of the notification.
@@ -217,71 +206,54 @@ void Notification::setCreatedAt(const util::Timestamp& 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
-Description: Serializes the notification into a CSV-formatted string.
+Description: Serializes the Notification object into a SerializedNotification record.
Parameters:
- None
Returns:
- - std::string: Serialized notification record
+ - SerializedNotification: Serialized representation of the notification
*/
-std::string Notification::serialize() const
+SerializedNotification Notification::serialize() const
{
- std::ostringstream serializedNotification;
- serializedNotification << m_id << ','
- << m_recipientUserId << ','
- << m_title << ','
- << m_message << ','
- << m_createdAt.toString();
- return serializedNotification.str();
+ SerializedNotification serialized = {};
+ strcpy_s(serialized.id, sizeof(serialized.id), m_id.c_str());
+ strcpy_s(serialized.recipientUserId, sizeof(serialized.recipientUserId), m_recipientUserId.c_str());
+ strcpy_s(serialized.title, sizeof(serialized.title), m_title.c_str());
+ strcpy_s(serialized.message, sizeof(serialized.message), m_message.c_str());
+ serialized.createdAt = m_createdAt;
+ serialized.state = m_state;
+ return serialized;
}
/*
Function: deserialize
-Description: Deserializes a CSV-formatted string into a Notification object.
+Description: Deserializes a SerializedNotification record into a Notification object.
Parameters:
- - record: const std::string&, serialized notification record
+ - serializedNotification: const SerializedNotification&, serialized notification record
Returns:
- Notification*: Pointer to the deserialized Notification object
-Throws:
- - std::runtime_error if timestamp parsing fails
*/
-Notification* Notification::deserialize(const std::string& record)
+Notification* Notification::deserialize(const SerializedNotification& serializedNotification)
{
- 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(
- id,
- recipientUserId,
- title,
- message,
- createdAtTimestamp
- );
-}
-
-/*
-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";
+ serializedNotification.id,
+ serializedNotification.recipientUserId,
+ serializedNotification.title,
+ serializedNotification.message,
+ serializedNotification.createdAt,
+ serializedNotification.state);
}
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.h
index 57869fa..a102cc6 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.h
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.h
@@ -9,8 +9,10 @@ Date: 19-May-2026
#pragma once
#include
#include "Timestamp.h"
+#include "Enums.h"
class User;
+struct SerializedNotification;
class Notification
{
@@ -18,27 +20,26 @@ private:
static int m_uid;
std::string m_id;
std::string m_recipientUserId;
- User* m_recipient;
std::string m_title;
std::string m_message;
util::Timestamp m_createdAt;
+ util::State m_state;
public:
Notification();
- 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);
+ Notification(const std::string& recipientUserId, 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);
const std::string& getId() const;
const std::string& getRecipientUserId() const;
- User* getRecipient() const;
const std::string& getTitle() const;
const std::string& getMessage() const;
const util::Timestamp& getCreatedAt() const;
void setId(const std::string& id);
void setRecipientUserId(const std::string& recipientUserId);
- void setRecipient(User* recipient);
void setTitle(const std::string& title);
void setMessage(const std::string& message);
void setCreatedAt(const util::Timestamp& createdAt);
- std::string serialize() const;
- static Notification* deserialize(const std::string&);
- static std::string getHeaders();
+ util::State getState() const;
+ void setState(util::State state);
+ SerializedNotification serialize() const;
+ static Notification* deserialize(const SerializedNotification&);
};
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.cpp
index 0717467..fc39531 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.cpp
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.cpp
@@ -8,6 +8,7 @@ Date: 19-May-2026
*/
#include
+#include "SerializedRecords.h"
#include "Service.h"
#include "InventoryItem.h"
#include "StringHelper.h"
@@ -27,7 +28,8 @@ Returns:
Service::Service()
: m_id("SRV" + std::to_string(++m_uid)),
m_status(util::State::ACTIVE),
- m_laborCost(0.0) {}
+ m_laborCost(0.0) {
+}
/*
Function: Service
@@ -44,7 +46,7 @@ Service::Service(const std::string& name, const util::Map getInventoryItemIDsAsVector(const std::string&
/*
Function: serialize
-Description: Serializes the service into a CSV-formatted string.
+Description: Serializes the Service object into a SerializedService record.
Parameters:
- None
Returns:
- - std::string: Serialized service record
+ - SerializedService: Serialized representation of the service
*/
-std::string Service::serialize() const
+SerializedService Service::serialize() const
{
- std::ostringstream serializedService;
- serializedService << m_id << ','
- << m_name << ','
- << getInventoryItemIDsAsString(m_requiredInventoryItemIDs) << ','
- << m_laborCost << ','
- << util::getStateString(m_status);
- return serializedService.str();
+ SerializedService serialized = {};
+ strcpy_s(serialized.id, sizeof(serialized.id), m_id.c_str());
+ strcpy_s(serialized.name, sizeof(serialized.name), m_name.c_str());
+ strcpy_s(serialized.inventoryItemIDs, sizeof(serialized.inventoryItemIDs), getInventoryItemIDsAsString(m_requiredInventoryItemIDs).c_str());
+ serialized.laborCost = m_laborCost;
+ serialized.status = m_status;
+ return serialized;
}
/*
Function: deserialize
-Description: Deserializes a CSV-formatted string into a Service object.
+Description: Deserializes a SerializedService record into a Service object.
Parameters:
- - record: const std::string&, serialized service record
+ - serializedService: const SerializedService&, serialized service record
Returns:
- Service*: Pointer to the deserialized Service object
-Throws:
- - std::runtime_error if labor cost parsing fails
*/
-Service* Service::deserialize(const std::string& record)
+Service* Service::deserialize(const SerializedService& serializedService)
{
- std::string id, name;
- std::string inventoryItemIDsString, laborCostString, statusString;
- double laborCost;
- std::istringstream serializedService(record);
- getline(serializedService, id, ',');
- getline(serializedService, name, ',');
- getline(serializedService, inventoryItemIDsString, ',');
- getline(serializedService, laborCostString, ',');
- getline(serializedService, statusString, ',');
- util::Vector inventoryItemIDs = getInventoryItemIDsAsVector(inventoryItemIDsString);
- try
- {
- laborCost = std::stod(laborCostString);
- }
- catch (...)
- {
- throw std::runtime_error("Invalid labor cost");
- }
- util::State status = util::getState(statusString);
+ util::Vector inventoryItemIDs = getInventoryItemIDsAsVector(serializedService.inventoryItemIDs);
return Factory::getObject(
- id,
- name,
+ serializedService.id,
+ serializedService.name,
inventoryItemIDs,
- laborCost,
- status
- );
-}
-
-/*
-Function: getHeaders
-Description: Retrieves the CSV headers for service serialization.
-Parameters:
- - None
-Returns:
- - std::string: Header string ("ID,Name,InventoryIDs,LaborCost,Status")
-*/
-std::string Service::getHeaders()
-{
- return "ID,Name,InventoryIDs,LaborCost,Status";
+ serializedService.laborCost,
+ serializedService.status);
}
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.h
index b80e674..bff13d6 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.h
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.h
@@ -6,7 +6,6 @@ Author: Trenser
Date: 19-May-2026
*/
-
#pragma once
#include
#include "Map.h"
@@ -14,6 +13,7 @@ Date: 19-May-2026
#include "Enums.h"
class InventoryItem;
+struct SerializedService;
class Service
{
@@ -40,7 +40,6 @@ public:
void setRequiredInventoryItems(const util::Map& requiredInventoryItems);
void setLaborCost(double laborCost);
void setState(util::State status);
- std::string serialize() const;
- static Service* deserialize(const std::string&);
- static std::string getHeaders();
+ SerializedService serialize() const;
+ static Service* deserialize(const SerializedService&);
};
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp
index 31b9d87..bd7d4d1 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp
@@ -6,8 +6,10 @@ Description: Implementation file containing the method definitions of the
Author: Trenser
Date:19-May-2026
*/
+
#include
#include
+#include "SerializedRecords.h"
#include "ServiceBooking.h"
#include "Service.h"
#include "Enums.h"
@@ -28,7 +30,8 @@ ServiceBooking::ServiceBooking()
m_customer(nullptr),
m_assignedTechnician(nullptr),
m_status(util::ServiceJobStatus::PENDING),
- m_discountPercentage(0.0) {}
+ m_discountPercentage(0.0) {
+}
/*
Function: ServiceBooking
@@ -437,84 +440,46 @@ static util::Vector getServiceIDsAsVector(const std::string& servic
/*
Function: serialize
-Description: Serializes the service booking into a CSV-formatted string.
+Description: Serializes the ServiceBooking object into a SerializedServiceBooking record.
Parameters:
- None
Returns:
- - std::string: Serialized booking record
+ - SerializedServiceBooking: Serialized representation of the service booking
*/
-std::string ServiceBooking::serialize() const
+SerializedServiceBooking ServiceBooking::serialize() const
{
- std::ostringstream serializedBooking;
- serializedBooking << m_id << ','
- << util::getServiceJobStatusString(m_status) << ','
- << getServiceIDsAsString(m_serviceIDs) << ','
- << m_customerId << ','
- << m_vehicleNumber << ','
- << m_vehicleBrand << ','
- << m_vehicleModel << ','
- << m_assignedTechnicianId << ','
- << m_discountPercentage << ',';
- return serializedBooking.str();
+ SerializedServiceBooking serialized = {};
+ strcpy_s(serialized.id, sizeof(serialized.id), m_id.c_str());
+ strcpy_s(serialized.serviceIDs, sizeof(serialized.serviceIDs), getServiceIDsAsString(m_serviceIDs).c_str());
+ strcpy_s(serialized.customerId, sizeof(serialized.customerId), m_customerId.c_str());
+ strcpy_s(serialized.vehicleNumber, sizeof(serialized.vehicleNumber), m_vehicleNumber.c_str());
+ strcpy_s(serialized.vehicleBrand, sizeof(serialized.vehicleBrand), m_vehicleBrand.c_str());
+ strcpy_s(serialized.vehicleModel, sizeof(serialized.vehicleModel), m_vehicleModel.c_str());
+ strcpy_s(serialized.assignedTechnicianId, sizeof(serialized.assignedTechnicianId), m_assignedTechnicianId.c_str());
+ serialized.status = m_status;
+ serialized.discountPercentage = m_discountPercentage;
+ return serialized;
}
/*
Function: deserialize
-Description: Deserializes a CSV-formatted string into a ServiceBooking object.
+Description: Deserializes a SerializedServiceBooking record into a ServiceBooking object.
Parameters:
- - record: const std::string&, serialized booking record
+ - serializedServiceBooking: const SerializedServiceBooking&, serialized service booking record
Returns:
- ServiceBooking*: Pointer to the deserialized ServiceBooking object
-Throws:
- - std::runtime_error if discount percentage parsing fails
*/
-ServiceBooking* ServiceBooking::deserialize(const std::string& record)
+ServiceBooking* ServiceBooking::deserialize(const SerializedServiceBooking& serializedServiceBooking)
{
- std::string id, customerId, vehicleNumber, vehicleBrand, vehicleModel, assignedTechnicianId;
- std::string serviceJobStatusString, serviceIDsString, discountPercentageString;
- double discountPercentage;
- std::istringstream serializedBooking(record);
- getline(serializedBooking, id, ',');
- getline(serializedBooking, serviceJobStatusString, ',');
- getline(serializedBooking, serviceIDsString, ',');
- getline(serializedBooking, customerId, ',');
- getline(serializedBooking, vehicleNumber, ',');
- getline(serializedBooking, vehicleBrand, ',');
- getline(serializedBooking, vehicleModel, ',');
- getline(serializedBooking, assignedTechnicianId, ',');
- getline(serializedBooking, discountPercentageString, ',');
- util::Vector serviceIDs = getServiceIDsAsVector(serviceIDsString);
- try
- {
- discountPercentage = std::stod(discountPercentageString);
- }
- catch (...)
- {
- throw std::runtime_error("Invalid discount percentage");
- }
- util::ServiceJobStatus status = util::getServiceJobStatus(serviceJobStatusString);
+ util::Vector serviceIDs = getServiceIDsAsVector(serializedServiceBooking.serviceIDs);
return Factory::getObject(
- id,
- status,
+ serializedServiceBooking.id,
+ serializedServiceBooking.status,
serviceIDs,
- customerId,
- vehicleNumber,
- vehicleBrand,
- vehicleModel,
- assignedTechnicianId,
- discountPercentage
- );
-}
-
-/*
-Function: getHeaders
-Description: Retrieves the CSV headers for service booking serialization.
-Parameters:
- - None
-Returns:
- - std::string: Header string ("ID,Status,ServiceIDs,CustomerID,VehicleNumber,VehicleBrand,VehicleModel,AssignedTechnicianID,DiscountPercentage")
-*/
-std::string ServiceBooking::getHeaders()
-{
- return "ID,Status,ServiceIDs,CustomerID,VehicleNumber,VehicleBrand,VehicleModel,AssignedTechnicianID,DiscountPercentage";
+ serializedServiceBooking.customerId,
+ serializedServiceBooking.vehicleNumber,
+ serializedServiceBooking.vehicleBrand,
+ serializedServiceBooking.vehicleModel,
+ serializedServiceBooking.assignedTechnicianId,
+ serializedServiceBooking.discountPercentage);
}
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h
index 24acb32..433d9d1 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h
@@ -6,6 +6,7 @@ Description: Header file declaring the ServiceBooking class, which represents
Author: Trenser
Date:19-May-2026
*/
+
#pragma once
#include
#include "Map.h"
@@ -14,6 +15,7 @@ Date:19-May-2026
class Service;
class User;
+struct SerializedServiceBooking;
class ServiceBooking
{
@@ -78,7 +80,6 @@ public:
void setAssignedTechnicianId(const std::string& assignedTechnicianId);
void setAssignedTechnician(User* assignedTechnician);
void setDiscountPercentage(double discountPercentage);
- std::string serialize() const;
- static ServiceBooking* deserialize(const std::string&);
- static std::string getHeaders();
+ SerializedServiceBooking serialize() const;
+ static ServiceBooking* deserialize(const SerializedServiceBooking&);
};
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.cpp
index 0b4e86e..5794259 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.cpp
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.cpp
@@ -8,6 +8,7 @@ Date: 19-May-2026
*/
#include
+#include "SerializedRecords.h"
#include "User.h"
#include "Notification.h"
#include "Enums.h"
@@ -28,7 +29,8 @@ Returns:
User::User()
: m_id("USR" + std::to_string(++m_uid)),
m_type(util::UserType::CUSTOMER),
- m_status(util::State::ACTIVE) {}
+ m_status(util::State::ACTIVE) {
+}
/*
Function: User
@@ -51,7 +53,8 @@ User::User(const std::string& userName, const std::string& password, const std::
m_phone(phone),
m_email(email),
m_type(role),
- m_status(util::State::ACTIVE) {}
+ m_status(util::State::ACTIVE) {
+}
/*
Function: User (parameterized constructor with ID)
@@ -86,23 +89,6 @@ 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
Description: Retrieves the unique ID of the user.
@@ -169,17 +155,6 @@ const std::string& User::getEmail() const
return m_email;
}
-/*
-Function: getNotifications
-Description: Retrieves the map of notifications associated with the user.
-Returns:
- - util::Map& representing the notifications.
-*/
-util::Map& User::getNotifications()
-{
- return m_notifications;
-}
-
/*
Function: getUserType
Description: Retrieves the role of the user.
@@ -280,22 +255,6 @@ void User::setEmail(const std::string& 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
Description: Sets the role of the user.
@@ -324,68 +283,43 @@ void User::setState(util::State status)
/*
Function: serialize
-Description: Serializes the user into a CSV-formatted string.
+Description: Serializes the User object into a SerializedUser record.
Parameters:
- None
Returns:
- - std::string: Serialized user record
+ - SerializedUser: Serialized representation of the user
*/
-std::string User::serialize() const
+SerializedUser User::serialize() const
{
- std::ostringstream serializedUser;
- serializedUser << m_id << ','
- << m_userName << ','
- << m_password << ','
- << m_name << ','
- << m_phone << ','
- << m_email << ','
- << util::getUserTypeString(m_type) << ','
- << util::getStateString(m_status);
- return serializedUser.str();
+ SerializedUser serialized = {};
+ strcpy_s(serialized.id, sizeof(serialized.id), m_id.c_str());
+ strcpy_s(serialized.username, sizeof(serialized.username), m_userName.c_str());
+ strcpy_s(serialized.password, sizeof(serialized.password), m_password.c_str());
+ strcpy_s(serialized.name, sizeof(serialized.name), m_name.c_str());
+ strcpy_s(serialized.phone, sizeof(serialized.phone), m_phone.c_str());
+ strcpy_s(serialized.email, sizeof(serialized.email), m_email.c_str());
+ serialized.userType = m_type;
+ serialized.status = m_status;
+ return serialized;
}
/*
Function: deserialize
-Description: Deserializes a CSV-formatted string into a User object.
+Description: Deserializes a SerializedUser record into a User object.
Parameters:
- - record: const std::string&, serialized user record
+ - serializedUser: const SerializedUser&, serialized user record
Returns:
- User*: Pointer to the deserialized User object
*/
-User* User::deserialize(const std::string& record)
+User* User::deserialize(const SerializedUser& serializedUser)
{
- std::string id, name, username, phone, password, email;
- std::string userTypeString, stateString;
- std::istringstream serializedUser(record);
- getline(serializedUser, id, ',');
- getline(serializedUser, username, ',');
- getline(serializedUser, password, ',');
- getline(serializedUser, name, ',');
- getline(serializedUser, phone, ',');
- getline(serializedUser, email, ',');
- getline(serializedUser, userTypeString, ',');
- getline(serializedUser, stateString);
- util::UserType userType = util::getUserType(userTypeString);
- util::State status = util::getState(stateString);
- return Factory::getObject(id,
- username,
- password,
- name,
- phone,
- email,
- userType,
- status);
-}
-
-/*
-Function: getHeaders
-Description: Retrieves the CSV headers for user serialization.
-Parameters:
- - None
-Returns:
- - std::string: Header string ("ID,Username,Password,Name,Phone,Email,UserType,UserStatus")
-*/
-std::string User::getHeaders()
-{
- return "ID,Username,Password,Name,Phone,Email,UserType,UserStatus";
+ return Factory::getObject(
+ serializedUser.id,
+ serializedUser.username,
+ serializedUser.password,
+ serializedUser.name,
+ serializedUser.phone,
+ serializedUser.email,
+ serializedUser.userType,
+ serializedUser.status);
}
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.h
index 12923f6..1a0f93f 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.h
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.h
@@ -14,6 +14,7 @@ Date: 19-May-2026
#include "Enums.h"
class Notification;
+struct SerializedUser;
class User : public Observer
{
@@ -25,21 +26,19 @@ private:
std::string m_name;
std::string m_phone;
std::string m_email;
- util::Map m_notifications;
util::UserType m_type;
util::State m_status;
public:
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& userId, const std::string& userName, const std::string& password, const std::string& name, const std::string& phone, const std::string& email, util::UserType role, util::State status);
- ~User();
+ ~User() = default;
const std::string& getId() const;
const std::string& getUserName() const;
const std::string& getPassword() const;
const std::string& getName() const;
const std::string& getPhone() const;
const std::string& getEmail() const;
- util::Map& getNotifications();
util::UserType getUserType() const;
util::State getState() const;
void setId(const std::string& id);
@@ -48,10 +47,8 @@ public:
void setName(const std::string& name);
void setPhone(const std::string& phone);
void setEmail(const std::string& email);
- void addNotification(Notification* notification) override;
void setRole(util::UserType role);
void setState(util::State status);
- std::string serialize() const;
- static User* deserialize(const std::string&);
- static std::string getHeaders();
+ SerializedUser serialize() const;
+ static User* deserialize(const SerializedUser& serializedUser);
};
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.cpp
index dc3a94c..71d66b6 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.cpp
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.cpp
@@ -10,6 +10,8 @@ Date:19-May-2026
#include
#include "AuthenticationManagementService.h"
#include "User.h"
+#include "Utility.h"
+#include "DataStoreLockGuard.h"
User* AuthenticationManagementService::m_authenticatedUser = nullptr;
@@ -24,11 +26,12 @@ Return type: bool - true if login successful, false otherwise
*/
bool AuthenticationManagementService::login(const std::string& username, const std::string& password)
{
- util::Map users = m_dataStore.getUsers();
- int usersMapSize = users.getSize();
- for (int index = 0; index < usersMapSize; index++)
+ DataStoreLockGuard lock(m_dataStore);
+ auto& trackedUserMap = m_dataStore.getUsers();
+ int trackedUserMapSize = trackedUserMap.getSize();
+ for (int index = 0; index < trackedUserMapSize; index++)
{
- User* user = users.getValueAt(index);
+ User* user = trackedUserMap.getValueAt(index).data;
if (username == user->getUserName())
{
if (password == user->getPassword())
@@ -74,9 +77,18 @@ 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();
}
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp
index d08d957..8e17739 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp
@@ -12,14 +12,13 @@ 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"
#include "User.h"
#include "Utility.h"
#include "Vector.h"
-
+#include "DataStoreLockGuard.h"
util::Map InventoryManagementService::m_observers{};
@@ -58,18 +57,19 @@ Returns:
*/
void InventoryManagementService::sendLowStockAlerts()
{
- auto& inventoryItems = m_dataStore.getInventoryItems();
- if (inventoryItems.isEmpty())
+ DataStoreLockGuard lock(m_dataStore);
+ auto& trackedInventoryItemsMap = m_dataStore.getInventoryItems();
+ auto& trackedUserMap = m_dataStore.getUsers();
+ if (trackedInventoryItemsMap.isEmpty())
{
return;
}
- int inventoryItemsSize = inventoryItems.getSize();
- auto& usersMap = m_dataStore.getUsers();
- int usersMapSize = usersMap.getSize();
+ int inventoryItemsSize = trackedInventoryItemsMap.getSize();
+ int usersMapSize = trackedUserMap.getSize();
util::Vector adminUsers;
for (int index = 0; index < usersMapSize; index++)
{
- User* user = usersMap.getValueAt(index);
+ User* user = trackedUserMap.getValueAt(index).data;
if (user->getUserType() == util::UserType::ADMIN)
{
adminUsers.push_back(user);
@@ -82,7 +82,7 @@ void InventoryManagementService::sendLowStockAlerts()
}
for (int index = 0; index < inventoryItemsSize; index++)
{
- InventoryItem* inventoryItem = inventoryItems.getValueAt(index);
+ InventoryItem* inventoryItem = trackedInventoryItemsMap.getValueAt(index).data;
if (inventoryItem && inventoryItem->getQuantity() < config::threshold::INVENTORY_LOW_STOCK_THRESHOLD)
{
sendLowStockAlertsToAdmins(*this, inventoryItem, adminUsers);
@@ -90,95 +90,6 @@ void InventoryManagementService::sendLowStockAlerts()
}
}
-/*
-Function: getObserverIDs
-Description: Retrieves the IDs of all observers currently attached to the
- InventoryManagementService.
-Parameters:
- - None
-Returns:
- - util::Vector: Vector of observer user IDs
-*/
-util::Vector InventoryManagementService::getObserverIDs()
-{
- util::Vector 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 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 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
@@ -190,8 +101,11 @@ Return type: void
*/
void InventoryManagementService::addInventoryItem(const std::string& partName, int quantity, double price)
{
+ DataStoreLockGuard lock(m_dataStore);
+ auto& trackedInventoryItemMap = m_dataStore.getInventoryItems();
InventoryItem* newItem = Factory::getObject(partName, quantity, price);
- m_dataStore.getInventoryItems().insert(newItem->getId(), newItem);
+ trackedInventoryItemMap.insert(newItem->getId(), util::createNewRecord(newItem));
+ m_dataStore.saveInventoryItems();
}
/*
@@ -203,16 +117,22 @@ Return type: void
*/
void InventoryManagementService::addInventoryItemStock(const std::string& selectedItemId, int quantity)
{
- int index = m_dataStore.getInventoryItems().find(selectedItemId);
- if (index != -1)
- {
- InventoryItem* item = m_dataStore.getInventoryItems().getValueAt(index);
- if (item != nullptr)
- {
- int totalQuantity = item->getQuantity() + quantity;
- item->setQuantity(totalQuantity);
- }
- }
+ DataStoreLockGuard lock(m_dataStore);
+ auto& trackedInventoryItemMap = m_dataStore.getInventoryItems();
+ int index = trackedInventoryItemMap.find(selectedItemId);
+ if (index == -1)
+ {
+ throw std::runtime_error("Inventory update failed: Item ID '" + selectedItemId + "' not found.");
+ }
+ InventoryItem* item = trackedInventoryItemMap.getValueAt(index).data;
+ if (item == nullptr)
+ {
+ throw std::runtime_error("Inventory update failed. Item does not exist.\n");
+ }
+ int totalQuantity = item->getQuantity() + quantity;
+ item->setQuantity(totalQuantity);
+ trackedInventoryItemMap.getValueAt(index).state = RecordState::MODIFIED;
+ m_dataStore.saveInventoryItems();
}
/*
@@ -223,7 +143,10 @@ Return type: util::Map
*/
util::Map InventoryManagementService::getInventoryItems()
{
- return m_dataStore.getInventoryItems();
+ DataStoreLockGuard lock(m_dataStore);
+ auto& trackedInventoryItemMap = m_dataStore.getInventoryItems();
+ auto inventoryMap = util::getObjects(trackedInventoryItemMap);
+ return inventoryMap;
}
/*
@@ -234,15 +157,21 @@ Return type: void
*/
void InventoryManagementService::removeInventoryItem(const std::string& inventoryItemID)
{
- int index = m_dataStore.getInventoryItems().find(inventoryItemID);
- if (index != -1)
- {
- InventoryItem* item = m_dataStore.getInventoryItems().getValueAt(index);
- if (item != nullptr)
- {
- item->setState(util::State::INACTIVE);
- }
- }
+ DataStoreLockGuard lock(m_dataStore);
+ auto& trackedInventoryItemMap = m_dataStore.getInventoryItems();
+ int index = trackedInventoryItemMap.find(inventoryItemID);
+ if (index == -1)
+ {
+ throw std::runtime_error("Inventory removal failed: Item ID '" + inventoryItemID + "' not found.");
+ }
+ InventoryItem* item = trackedInventoryItemMap.getValueAt(index).data;
+ if (item == nullptr)
+ {
+ throw std::runtime_error("Inventory removal failed: Item ID does not exist.");
+ }
+ item->setState(util::State::INACTIVE);
+ trackedInventoryItemMap.getValueAt(index).state = RecordState::MODIFIED;
+ m_dataStore.saveInventoryItems();
}
/*
@@ -253,12 +182,19 @@ Return type: InventoryItem*
*/
InventoryItem* InventoryManagementService::getInventoryItem(const std::string& inventoryItemID)
{
- int index = m_dataStore.getInventoryItems().find(inventoryItemID);
- if (index != -1)
+ DataStoreLockGuard lock(m_dataStore);
+ auto& trackedInventoryItemMap = m_dataStore.getInventoryItems();
+ int index = trackedInventoryItemMap.find(inventoryItemID);
+ if (index == -1)
{
- return m_dataStore.getInventoryItems().getValueAt(index);
+ return nullptr;
}
- return nullptr;
+ InventoryItem* inventoryItem = trackedInventoryItemMap.getValueAt(index).data;
+ if (inventoryItem == nullptr)
+ {
+ throw std::runtime_error("Item ID does not exist.");
+ }
+ return inventoryItem;
}
/*
@@ -271,6 +207,9 @@ Returns:
*/
void InventoryManagementService::attach(User* user)
{
+ DataStoreLockGuard lock(m_dataStore);
+ m_observers.clear();
+ m_observers = m_dataStore.getInventoryManagementObservers();
if (user)
{
const std::string& userID = user->getId();
@@ -279,6 +218,7 @@ void InventoryManagementService::attach(User* user)
m_observers[userID] = user;
}
}
+ m_dataStore.saveInventoryManagementObservers(m_observers);
}
/*
@@ -291,6 +231,9 @@ Returns:
*/
void InventoryManagementService::detach(User* user)
{
+ DataStoreLockGuard lock(m_dataStore);
+ m_observers.clear();
+ m_observers = m_dataStore.getInventoryManagementObservers();
if (user)
{
const std::string& userID = user->getId();
@@ -299,6 +242,7 @@ void InventoryManagementService::detach(User* user)
m_observers.remove(userID);
}
}
+ m_dataStore.saveInventoryManagementObservers(m_observers);
}
/*
@@ -315,27 +259,27 @@ Throws:
*/
void InventoryManagementService::sendNotification(User* user, const std::string& title, const std::string& message)
{
- if (user)
+ if (!user)
{
- if (m_observers.find(user->getId()) != -1)
- {
- Notification* notification =
- Factory::getObject(
- user->getId(),
- user,
- title,
- message,
- util::Timestamp()
- );
- if (notification)
- {
- user->addNotification(notification);
- }
- else
- {
- throw std::runtime_error("Failed to create notification");
- }
- }
+ return;
}
+ DataStoreLockGuard lock(m_dataStore);
+ m_observers = m_dataStore.getInventoryManagementObservers();
+ if (m_observers.find(user->getId()) == -1)
+ {
+ return;
+ }
+ Notification* notification = Factory::getObject(
+ user->getId(),
+ title,
+ message,
+ util::Timestamp());
+ if (!notification)
+ {
+ throw std::runtime_error("Failed to create notification");
+ }
+ auto& trackedNotificationsMap = m_dataStore.getNotifications();
+ trackedNotificationsMap.insert(notification->getId(), util::createNewRecord(notification));
+ m_dataStore.saveNotifications();
}
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.h
index f5db383..2c3736c 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.h
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.h
@@ -21,7 +21,6 @@ class InventoryManagementService : public NotificationManagementService
private:
DataStore& m_dataStore;
static util::Map m_observers;
- util::Vector getObserverIDs() override;
public:
InventoryManagementService() : m_dataStore(DataStore::getInstance()) {}
util::Map getInventoryItems();
@@ -33,8 +32,4 @@ 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();
};
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/NotificationManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/NotificationManagementService.cpp
deleted file mode 100644
index cc23059..0000000
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/NotificationManagementService.cpp
+++ /dev/null
@@ -1 +0,0 @@
-#include "NotificationManagementService.h"
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/NotificationManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/NotificationManagementService.h
index 33d214a..18d0dda 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/NotificationManagementService.h
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/NotificationManagementService.h
@@ -19,5 +19,4 @@ 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 getObserverIDs() = 0;
};
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp
index dfd9aeb..dc42a5b 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp
@@ -11,7 +11,6 @@ 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"
@@ -22,6 +21,7 @@ Date: 20-May-2026
#include "Timestamp.h"
#include "User.h"
#include "Utility.h"
+#include "DataStoreLockGuard.h"
util::Map PaymentManagementService::m_observers{};
@@ -35,6 +35,9 @@ Returns:
*/
void PaymentManagementService::attach(User* user)
{
+ DataStoreLockGuard lock(m_dataStore);
+ m_observers.clear();
+ m_observers = m_dataStore.getPaymentManagementObservers();
if (user)
{
const std::string& userID = user->getId();
@@ -43,6 +46,7 @@ void PaymentManagementService::attach(User* user)
m_observers[userID] = user;
}
}
+ m_dataStore.savePaymentManagementObservers(m_observers);
}
/*
@@ -55,6 +59,9 @@ Returns:
*/
void PaymentManagementService::detach(User* user)
{
+ DataStoreLockGuard lock(m_dataStore);
+ m_observers.clear();
+ m_observers = m_dataStore.getPaymentManagementObservers();
if (user)
{
const std::string& userID = user->getId();
@@ -63,6 +70,7 @@ void PaymentManagementService::detach(User* user)
m_observers.remove(userID);
}
}
+ m_dataStore.savePaymentManagementObservers(m_observers);
}
/*
@@ -79,28 +87,28 @@ Throws:
*/
void PaymentManagementService::sendNotification(User* user, const std::string& title, const std::string& message)
{
- if (user)
+ if (!user)
{
- if (m_observers.find(user->getId()) != -1)
- {
- Notification* notification =
- Factory::getObject(
- user->getId(),
- user,
- title,
- message,
- util::Timestamp()
- );
- if (notification)
- {
- user->addNotification(notification);
- }
- else
- {
- throw std::runtime_error("Failed to create notification");
- }
- }
+ return;
}
+ DataStoreLockGuard lock(m_dataStore);
+ m_observers = m_dataStore.getPaymentManagementObservers();
+ if (m_observers.find(user->getId()) == -1)
+ {
+ return;
+ }
+ Notification* notification = Factory::getObject(
+ user->getId(),
+ title,
+ message,
+ util::Timestamp());
+ if (!notification)
+ {
+ throw std::runtime_error("Failed to create notification");
+ }
+ auto& trackedNotificationsMap = m_dataStore.getNotifications();
+ trackedNotificationsMap.insert(notification->getId(), util::createNewRecord(notification));
+ m_dataStore.saveNotifications();
}
/*
@@ -142,123 +150,6 @@ void PaymentManagementService::sendPaymentReminders()
}
}
-/*
-Function: getObserverIDs
-Description: Retrieves the IDs of all observers currently attached to the
- PaymentManagementService.
-Parameters:
- - None
-Returns:
- - util::Vector: Vector of observer user IDs
-*/
-util::Vector PaymentManagementService::getObserverIDs()
-{
- util::Vector 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 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 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 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.
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.h
index 04c5560..ca5cacf 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.h
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.h
@@ -22,7 +22,6 @@ class PaymentManagementService : public NotificationManagementService
private:
DataStore& m_dataStore;
static util::Map m_observers;
- util::Vector getObserverIDs() override;
public:
PaymentManagementService() : m_dataStore(DataStore::getInstance()) {}
void generateInvoice(ServiceBooking* booking);
@@ -34,8 +33,4 @@ 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();
};
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp
index 1a9f753..ed59380 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp
@@ -14,7 +14,6 @@ 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"
@@ -25,7 +24,9 @@ Date:19-May-2026
#include "Timestamp.h"
#include "User.h"
#include "UserManagementService.h"
+#include "DataStoreLockGuard.h"
#include "Utility.h"
+#include "DataStoreLockGuard.h"
/*
Function: purchaseService
@@ -46,18 +47,19 @@ void ServiceManagementService::purchaseService(const util::Vector&
{
throw std::runtime_error("No user is currently logged in!");
}
- auto& servicesMap = m_dataStore.getServices();
- auto& serviceBookingMap = m_dataStore.getServiceBookings();
+ DataStoreLockGuard lock(m_dataStore);
+ auto& trackedServicesMap = m_dataStore.getServices();
+ auto& trackedServiceBookingMap = m_dataStore.getServiceBookings();
util::Map selectedServices;
int selectedServicesCount = serviceIDs.getSize();
for (int index = 0; index < selectedServicesCount; index++)
{
- int serviceIndex = servicesMap.find(serviceIDs[index]);
+ int serviceIndex = trackedServicesMap.find(serviceIDs[index]);
if (serviceIndex == -1)
{
throw std::runtime_error("Service not found!");
}
- Service* service = servicesMap.getValueAt(serviceIndex);
+ Service* service = trackedServicesMap.getValueAt(serviceIndex).data;
selectedServices[service->getId()] = service;
}
ServiceBooking* serviceBooking = Factory::getObject(util::ServiceJobStatus::PENDING, selectedServices, authenticatedUser->getId(), authenticatedUser, vehicleNumber, vehicleBrand, vehicleModel, 0);
@@ -65,7 +67,7 @@ void ServiceManagementService::purchaseService(const util::Vector&
{
throw std::runtime_error("Failed to create service booking");
}
- serviceBookingMap[serviceBooking->getId()] = serviceBooking;
+ trackedServiceBookingMap[serviceBooking->getId()] = util::createNewRecord(serviceBooking);
std::string title = "Service Booking succeeded";
std::string message = "Your service booking has been successfully placed with ID " + serviceBooking->getId();
sendNotification(authenticatedUser, title, message);
@@ -90,21 +92,22 @@ void ServiceManagementService::purchaseComboPackage(const std::string& comboPack
{
throw std::runtime_error("No user is currently logged in!");
}
- auto& comboPackagesMap = m_dataStore.getComboPackages();
- auto& serviceBookingMap = m_dataStore.getServiceBookings();
- int comboPackageIndex = comboPackagesMap.find(comboPackageID);
+ DataStoreLockGuard lock(m_dataStore);
+ auto& trackedComboPackagesMap = m_dataStore.getComboPackages();
+ auto& trackedServiceBookingMap = m_dataStore.getServiceBookings();
+ int comboPackageIndex = trackedComboPackagesMap.find(comboPackageID);
if (comboPackageIndex == -1)
{
throw std::runtime_error("Combo Package not found!");
}
- const ComboPackage* comboPackage = comboPackagesMap[comboPackageID];
+ const ComboPackage* comboPackage = trackedComboPackagesMap[comboPackageID].data;
util::Map selectedServices = comboPackage->getServices();
ServiceBooking* serviceBooking = Factory::getObject(util::ServiceJobStatus::PENDING, selectedServices, authenticatedUser->getId(), authenticatedUser, vehicleNumber, vehicleBrand, vehicleModel, comboPackage->getDiscountPercentage());
if (serviceBooking == nullptr)
{
throw std::runtime_error("Failed to create combo package service booking");
}
- serviceBookingMap[serviceBooking->getId()] = serviceBooking;
+ trackedServiceBookingMap[serviceBooking->getId()] = util::createNewRecord(serviceBooking);
std::string title = "Combo Package Service Booking succeeded";
std::string message = "Your service booking for the combo package has been successfully placed with ID " + serviceBooking->getId();
sendNotification(authenticatedUser, title, message);
@@ -122,6 +125,9 @@ Returns:
*/
void ServiceManagementService::attach(User* user)
{
+ DataStoreLockGuard lock(m_dataStore);
+ m_observers.clear();
+ m_observers = m_dataStore.getServiceManagementObservers();
if (user)
{
const std::string& userID = user->getId();
@@ -130,6 +136,7 @@ void ServiceManagementService::attach(User* user)
m_observers[userID] = user;
}
}
+ m_dataStore.saveServiceManagementObservers(m_observers);
}
/*
@@ -142,6 +149,9 @@ Returns:
*/
void ServiceManagementService::detach(User* user)
{
+ DataStoreLockGuard lock(m_dataStore);
+ m_observers.clear();
+ m_observers = m_dataStore.getServiceManagementObservers();
if (user)
{
const std::string& userID = user->getId();
@@ -150,6 +160,7 @@ void ServiceManagementService::detach(User* user)
m_observers.remove(userID);
}
}
+ m_dataStore.saveServiceManagementObservers(m_observers);
}
/*
@@ -166,345 +177,28 @@ Throws:
*/
void ServiceManagementService::sendNotification(User* user, const std::string& title, const std::string& message)
{
- if (user)
- {
- if (m_observers.find(user->getId()) != -1)
- {
- Notification* notification =
- Factory::getObject(
- user->getId(),
- user,
- title,
- message,
- util::Timestamp()
- );
- if (notification)
- {
- user->addNotification(notification);
- }
- else
- {
- throw std::runtime_error("Failed to create notification");
- }
- }
- }
-}
-
-/*
-Function: getObserverIDs
-Description: Retrieves the IDs of all observers currently attached to the
- ServiceManagementService.
-Parameters:
- - None
-Returns:
- - util::Vector: Vector of observer user IDs
-*/
-util::Vector ServiceManagementService::getObserverIDs()
-{
- util::Vector 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 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++)
+ if (!user)
{
- Service* service = servicesMap.getValueAt(serviceIndex);
- services[service->getId()] = service;
- util::Map 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);
+ return;
}
-}
-
-/*
-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 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 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++)
+ DataStoreLockGuard lock(m_dataStore);
+ m_observers = m_dataStore.getServiceManagementObservers();
+ if (m_observers.find(user->getId()) == -1)
{
- ComboPackage* comboPackage = comboPackagesMap.getValueAt(packageIndex);
- util::Map 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;
+ return;
}
-}
-
-/*
-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 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 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++)
+ Notification* notification = Factory::getObject(
+ user->getId(),
+ title,
+ message,
+ util::Timestamp());
+ if (!notification)
{
- ServiceBooking* booking = bookingsMap.getValueAt(bookingIndex);
- util::Map 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;
+ throw std::runtime_error("Failed to create notification");
}
-}
-
-/*
-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 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 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 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);
+ auto& trackedNotificationsMap = m_dataStore.getNotifications();
+ trackedNotificationsMap.insert(notification->getId(), util::createNewRecord(notification));
+ m_dataStore.saveNotifications();
}
/*
@@ -514,7 +208,7 @@ Description: Restores inventory quantities for all required items in the service
Parameter: ServiceBooking* booking - Pointer to the booking whose inventory items need to be restored
Return type: void
*/
-static void restoreInventory(ServiceBooking* booking)
+static void restoreInventory(ServiceBooking* booking, util::Map>& trackedInventoryItems)
{
const int INCREMENT_VALUE = 1;
if (!booking)
@@ -533,9 +227,17 @@ static void restoreInventory(ServiceBooking* booking)
for (int InventoryIterator = 0; InventoryIterator < items.getSize(); ++InventoryIterator)
{
InventoryItem* item = items.getValueAt(InventoryIterator);
+ const std::string& currentItemId = item->getId();
+ int itemIndex = trackedInventoryItems.find(currentItemId);
+ if (itemIndex == -1)
+ {
+ continue;
+ }
+ auto& currentTrackedInventoryItem = trackedInventoryItems.getValueAt(itemIndex);
if (item)
{
item->setQuantity(item->getQuantity() + INCREMENT_VALUE);
+ currentTrackedInventoryItem.state = RecordState::MODIFIED;
}
}
}
@@ -553,23 +255,28 @@ Parameters:
util::UserType userType - Type of user initiating cancellation (CUSTOMER or TECHNICIAN)
Return type: void
*/
-static void processBookingCancellation(ServiceBooking* booking,
- util::Map& jobs,
+static void processBookingCancellation(TrackedRecord& trackedBooking,
+ util::Map>& jobs,
ServiceManagementService& currentService,
- util::UserType userType)
+ util::UserType userType,
+ util::Map>& trackedInventoryItems)
{
+ ServiceBooking* booking = trackedBooking.data;
if (!booking)
{
return;
}
+ const std::string& bookingId = booking->getId();
for (int jobIterator = 0; jobIterator < jobs.getSize(); ++jobIterator)
{
- JobCard* jobCard = jobs.getValueAt(jobIterator);
+ auto& trackedJobCard = jobs.getValueAt(jobIterator);
+ JobCard* jobCard = trackedJobCard.data;
if (!jobCard || jobCard->getBookingId() != booking->getId() || jobCard->getStatus() == util::ServiceJobStatus::CANCELLED)
{
continue;
}
jobCard->setStatus(util::ServiceJobStatus::CANCELLED);
+ trackedJobCard.state = RecordState::MODIFIED;
if (userType == util::UserType::CUSTOMER)
{
if (User* technician = booking->getAssignedTechnician())
@@ -602,7 +309,8 @@ static void processBookingCancellation(ServiceBooking* booking,
}
booking->setAssignedTechnician(nullptr);
booking->setAssignedTechnicianId("");
- restoreInventory(booking);
+ trackedBooking.state = RecordState::MODIFIED;
+ restoreInventory(booking, trackedInventoryItems);
}
/*
@@ -615,22 +323,25 @@ Return type: void
*/
void ServiceManagementService::cancelCustomerServiceBookings(const std::string& customerID)
{
- auto& users = m_dataStore.getUsers();
- int userIndex = users.find(customerID);
+ DataStoreLockGuard lock(m_dataStore);
+ auto& trackedUsers = m_dataStore.getUsers();
+ int userIndex = trackedUsers.find(customerID);
if (userIndex == -1)
{
throw std::runtime_error("User not found: " + customerID);
}
- User* customer = users.getValueAt(userIndex);
+ User* customer = trackedUsers.getValueAt(userIndex).data;
if (!customer)
{
throw std::runtime_error("User not found: " + customerID);
}
- auto& bookings = m_dataStore.getServiceBookings();
- auto& jobs = m_dataStore.getJobCards();
- for (int iteratorOne = 0; iteratorOne < bookings.getSize(); iteratorOne++)
+ auto& trackedBookings = m_dataStore.getServiceBookings();
+ auto& trackedJobs = m_dataStore.getJobCards();
+ auto& trackedInventoryItems = m_dataStore.getInventoryItems();
+ for (int iteratorOne = 0; iteratorOne < trackedBookings.getSize(); iteratorOne++)
{
- ServiceBooking* booking = bookings.getValueAt(iteratorOne);
+ auto& trackedBooking = trackedBookings.getValueAt(iteratorOne);
+ ServiceBooking* booking = trackedBooking.data;
if (!booking)
{
continue;
@@ -645,8 +356,12 @@ void ServiceManagementService::cancelCustomerServiceBookings(const std::string&
{
continue;
}
- processBookingCancellation(booking, jobs, *this, util::UserType::CUSTOMER);
+ processBookingCancellation(trackedBooking, trackedJobs, *this, util::UserType::CUSTOMER, trackedInventoryItems);
}
+ m_dataStore.saveUsers();
+ m_dataStore.saveServiceBookings();
+ m_dataStore.saveJobCards();
+ m_dataStore.saveInventoryItems();
}
/*
@@ -658,22 +373,25 @@ Return type: void
*/
void ServiceManagementService::cancelTechnicianJobs(const std::string& technicianID)
{
- auto& users = m_dataStore.getUsers();
- int userIndex = users.find(technicianID);
+ DataStoreLockGuard lock(m_dataStore);
+ auto& trackedUsers = m_dataStore.getUsers();
+ int userIndex = trackedUsers.find(technicianID);
if (userIndex == -1)
{
throw std::runtime_error("User not found: " + technicianID);
}
- User* technician = users.getValueAt(userIndex);
+ User* technician = trackedUsers.getValueAt(userIndex).data;
if (!technician)
{
throw std::runtime_error("User not found: " + technicianID);
}
- auto& bookings = m_dataStore.getServiceBookings();
- auto& jobs = m_dataStore.getJobCards();
- for (int iteratorOne = 0; iteratorOne < bookings.getSize(); iteratorOne++)
+ auto& trackedBookings = m_dataStore.getServiceBookings();
+ auto& trackedJobs = m_dataStore.getJobCards();
+ auto& trackedInventoryItems = m_dataStore.getInventoryItems();
+ for (int iteratorOne = 0; iteratorOne < trackedBookings.getSize(); iteratorOne++)
{
- ServiceBooking* booking = bookings.getValueAt(iteratorOne);
+ auto& trackedBooking = trackedBookings.getValueAt(iteratorOne);
+ ServiceBooking* booking = trackedBooking.data;
if (!booking)
{
continue;
@@ -694,8 +412,12 @@ void ServiceManagementService::cancelTechnicianJobs(const std::string& technicia
{
continue;
}
- processBookingCancellation(booking, jobs, *this, util::UserType::TECHNICIAN);
+ processBookingCancellation(trackedBooking, trackedJobs, *this, util::UserType::TECHNICIAN, trackedInventoryItems);
}
+ m_dataStore.saveUsers();
+ m_dataStore.saveInventoryItems();
+ m_dataStore.saveServiceBookings();
+ m_dataStore.saveJobCards();
}
/*
@@ -709,6 +431,7 @@ Return type: void
*/
void ServiceManagementService::createComboPackage(const std::string& packageName, const util::Vector& serviceIDsInNewCombo, double discountPercentage)
{
+ DataStoreLockGuard lock(m_dataStore);
if (packageName.empty())
{
throw std::invalid_argument("The Combo Package Name cannot be empty.\n");
@@ -721,19 +444,19 @@ void ServiceManagementService::createComboPackage(const std::string& packageName
{
throw std::invalid_argument("Discount percentage must be between 0 and 100.");
}
- auto& servicesMap = m_dataStore.getServices();
+ auto& trackedServicesMap = m_dataStore.getServices();
for (int index = 0; index < serviceIDsInNewCombo.getSize(); index++)
{
- const std::string serviceid = serviceIDsInNewCombo[index];
- if (servicesMap.find(serviceid) == -1)
+ const std::string& serviceid = serviceIDsInNewCombo[index];
+ if (trackedServicesMap.find(serviceid) == -1)
{
throw std::runtime_error("Service ID not found: " + serviceid);
}
}
- auto& comboPackageMap = m_dataStore.getComboPackages();
- for (int iterator = 0; iterator < comboPackageMap.getSize(); iterator++)
+ auto& trackedComboPackageMap = m_dataStore.getComboPackages();
+ for (int iterator = 0; iterator < trackedComboPackageMap.getSize(); iterator++)
{
- ComboPackage* existingCombos = comboPackageMap.getValueAt(iterator);
+ ComboPackage* existingCombos = trackedComboPackageMap.getValueAt(iterator).data;
const util::Map& servicesInsideExistingCombos = existingCombos->getServices();
if (servicesInsideExistingCombos.getSize() == serviceIDsInNewCombo.getSize())
{
@@ -757,15 +480,16 @@ void ServiceManagementService::createComboPackage(const std::string& packageName
for (int iteratorOne = 0; iteratorOne < serviceIDsInNewCombo.getSize(); iteratorOne++)
{
const std::string& serviceId = serviceIDsInNewCombo[iteratorOne];
- int serviceIndex = servicesMap.find(serviceId);
+ int serviceIndex = trackedServicesMap.find(serviceId);
if (serviceIndex == -1)
{
throw std::runtime_error("Service ID not found: " + serviceId);
}
- selectedServices.insert(serviceId, servicesMap.getValueAt(serviceIndex));
+ selectedServices.insert(serviceId, trackedServicesMap.getValueAt(serviceIndex).data);
}
ComboPackage* newComboPackage = Factory::getObject(packageName, discountPercentage, selectedServices);
- comboPackageMap.insert(newComboPackage->getId(), newComboPackage);
+ trackedComboPackageMap.insert(newComboPackage->getId(), util::createNewRecord(newComboPackage));
+ m_dataStore.saveComboPackages();
}
/*
@@ -776,7 +500,10 @@ Return type: util::Map
*/
util::Map ServiceManagementService::getComboPackages()
{
- return m_dataStore.getComboPackages();
+ DataStoreLockGuard lock(m_dataStore);
+ util::Map comboPackages;
+ comboPackages = util::getObjects(m_dataStore.getComboPackages());
+ return comboPackages;
}
/*
@@ -787,14 +514,17 @@ Return type: void
*/
void ServiceManagementService::removeComboPackage(const std::string& comboPackageID)
{
+ DataStoreLockGuard lock(m_dataStore);
bool removed = false;
- util::Map& currentComboPackages = m_dataStore.getComboPackages();
- for (int iterator = 0; iterator < currentComboPackages.getSize(); iterator++)
+ auto& trackedComboPackages = m_dataStore.getComboPackages();
+ for (int iterator = 0; iterator < trackedComboPackages.getSize(); iterator++)
{
- ComboPackage* currentComboPackage = currentComboPackages.getValueAt(iterator);
+ auto& comboPackage = trackedComboPackages.getValueAt(iterator);
+ ComboPackage* currentComboPackage = comboPackage.data;
if (currentComboPackage && currentComboPackage->getId() == comboPackageID)
{
currentComboPackage->setState(util::State::INACTIVE);
+ comboPackage.state = RecordState::MODIFIED;
removed = true;
break;
}
@@ -803,6 +533,7 @@ void ServiceManagementService::removeComboPackage(const std::string& comboPackag
{
throw std::runtime_error("Combo package with ID '" + comboPackageID + "' not found.");
}
+ m_dataStore.saveComboPackages();
}
/*
@@ -815,7 +546,10 @@ Returns:
*/
util::Map ServiceManagementService::getServiceBookings()
{
- return m_dataStore.getServiceBookings();
+ DataStoreLockGuard lock(m_dataStore);
+ util::Map serviceBookings;
+ serviceBookings = util::getObjects(m_dataStore.getServiceBookings());
+ return serviceBookings;
}
/*
@@ -854,9 +588,10 @@ Throws:
*/
void ServiceManagementService::createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID)
{
+ DataStoreLockGuard lock(m_dataStore);
UserManagementService m_userManagementService;
ServiceBooking* currentBooking = getServiceBooking(bookingID);
- auto& currentJobCards = m_dataStore.getJobCards();
+ auto& currentTrackedJobCards = m_dataStore.getJobCards();
if (currentBooking == nullptr)
{
throw std::runtime_error("Service Booking not available");
@@ -902,7 +637,7 @@ void ServiceManagementService::createJobCard(const std::string& bookingID, const
JobCard* jobCard = Factory::getObject(bookingID, currentBooking, currentService, serviceID, technicianID, selectedTechnician, util::Timestamp(), util::ServiceJobStatus::STARTED, util::Timestamp());
if (jobCard)
{
- currentJobCards.insert(jobCard->getId(), jobCard);
+ currentTrackedJobCards.insert(jobCard->getId(), util::createNewRecord(jobCard));
sendNotification(selectedTechnician, title, message);
}
else
@@ -912,6 +647,7 @@ void ServiceManagementService::createJobCard(const std::string& bookingID, const
title = "Technician assigned";
message = "A technician has been assigned to your Service Booking with ID " + bookingID;
sendNotification(currentBooking->getCustomer(), title, message);
+ m_dataStore.saveJobCards();
}
/*
@@ -929,15 +665,17 @@ Throws:
*/
void ServiceManagementService::createService(const std::string& name, const util::Vector& inventoryItemIDs, double laborCost)
{
+ DataStoreLockGuard lock(m_dataStore);
util::Map currentServiceInventoryItems;
- auto inventoryItems = m_dataStore.getInventoryItems();
+ auto& trackedInventoryItems = m_dataStore.getInventoryItems();
+ auto& currentServices = m_dataStore.getServices();
for (int iteratorOne =0; iteratorOne < inventoryItemIDs.getSize(); iteratorOne++)
{
std::string currentItemID = inventoryItemIDs[iteratorOne];
bool itemFound = false;
- for (int iteratorTwo = 0; iteratorTwo < inventoryItems.getSize(); iteratorTwo++)
+ for (int iteratorTwo = 0; iteratorTwo < trackedInventoryItems.getSize(); iteratorTwo++)
{
- InventoryItem* currentInventoryItem = inventoryItems.getValueAt(iteratorTwo);
+ InventoryItem* currentInventoryItem = trackedInventoryItems.getValueAt(iteratorTwo).data;
if (currentInventoryItem && currentInventoryItem->getId() == currentItemID)
{
itemFound = true;
@@ -955,12 +693,12 @@ void ServiceManagementService::createService(const std::string& name, const util
{
throw std::runtime_error("Unable to create new service.");
}
- util::Map& currentServices = m_dataStore.getServices();
if (currentServices.find(newService->getId()) != -1)
{
throw std::runtime_error("Service with this ID Already exists.");
}
- currentServices.insert(newService->getId(), newService);
+ currentServices.insert(newService->getId(), util::createNewRecord(newService));
+ m_dataStore.saveServices();
}
/*
@@ -973,7 +711,10 @@ Returns:
*/
util::Map ServiceManagementService::getServices()
{
- return m_dataStore.getServices();
+ DataStoreLockGuard lock(m_dataStore);
+ util::Map services;
+ services = util::getObjects(m_dataStore.getServices());
+ return services;
}
/*
@@ -988,14 +729,19 @@ Throws:
*/
void ServiceManagementService::removeService(const std::string& serviceID)
{
- util::Map& currentServices = m_dataStore.getServices();
- util::Map& currentComboPackages = m_dataStore.getComboPackages();
- if (currentServices.find(serviceID) != -1)
+ DataStoreLockGuard lock(m_dataStore);
+ auto& currentTrackedServices = m_dataStore.getServices();
+ auto& currentTrackedComboPackages = m_dataStore.getComboPackages();
+ if (currentTrackedServices.find(serviceID) != -1)
{
- currentServices.getValueAt(currentServices.find(serviceID))->setState(util::State::INACTIVE);
- for (int iterator = 0; iterator < currentComboPackages.getSize(); iterator++)
+ int serviceIndex, comboPackageIndex;
+ serviceIndex = currentTrackedServices.find(serviceID);
+ currentTrackedServices.getValueAt(serviceIndex).data->setState(util::State::INACTIVE);
+ currentTrackedServices.getValueAt(serviceIndex).state = RecordState::MODIFIED;
+ for (int iterator = 0; iterator < currentTrackedComboPackages.getSize(); iterator++)
{
- ComboPackage* currentComboPackage = currentComboPackages.getValueAt(iterator);
+ comboPackageIndex = iterator;
+ ComboPackage* currentComboPackage = currentTrackedComboPackages.getValueAt(iterator).data;
if (currentComboPackage && currentComboPackage->getState() == util::State::ACTIVE)
{
util::Map currentServices = currentComboPackage->getServices();
@@ -1005,6 +751,7 @@ void ServiceManagementService::removeService(const std::string& serviceID)
if (currentService->getId() == serviceID)
{
currentComboPackage->setState(util::State::INACTIVE);
+ currentTrackedComboPackages.getValueAt(comboPackageIndex).state = RecordState::MODIFIED;
break;
}
}
@@ -1015,6 +762,8 @@ void ServiceManagementService::removeService(const std::string& serviceID)
{
throw std::runtime_error("Service not found.");
}
+ m_dataStore.saveServices();
+ m_dataStore.saveComboPackages();
}
/*
@@ -1053,11 +802,12 @@ Returns:
*/
util::Map ServiceManagementService::getJobCards(const std::string& technicianID)
{
- util::Map jobCards = m_dataStore.getJobCards();
+ DataStoreLockGuard lock(m_dataStore);
+ auto& trackedJobCards = m_dataStore.getJobCards();
util::Map technicianJobCards;
- for (int iterator = 0; iterator < jobCards.getSize(); iterator++)
+ for (int iterator = 0; iterator < trackedJobCards.getSize(); iterator++)
{
- JobCard* currentJobCard = jobCards.getValueAt(iterator);
+ JobCard* currentJobCard = trackedJobCards.getValueAt(iterator).data;
if (currentJobCard->getTechnicianId() == technicianID)
{
technicianJobCards.insert(currentJobCard->getId(), currentJobCard);
@@ -1106,6 +856,7 @@ Returns:
*/
void ServiceManagementService::updateJobStatus(const std::string& jobID)
{
+ DataStoreLockGuard lock(m_dataStore);
AuthenticationManagementService authenticationManagementService;
PaymentManagementService paymentManagementService;
bool jobStatusUpdated = false, serviceBookingCompleted;
@@ -1120,8 +871,15 @@ void ServiceManagementService::updateJobStatus(const std::string& jobID)
{
throw std::runtime_error("No job cards assigned to the technician.");
}
+ auto& trackedJobCards = m_dataStore.getJobCards();
+ auto& trackedServiceBookings = m_dataStore.getServiceBookings();
if (currentAssignedJobs.find(jobID) != -1)
{
+ int jobIndex = trackedJobCards.find(jobID);
+ if (jobIndex == -1)
+ {
+ throw std::runtime_error("Unable to fetch current job.");
+ }
currentJob = currentAssignedJobs.getValueAt(currentAssignedJobs.find(jobID));
if (currentJob == nullptr)
{
@@ -1130,16 +888,20 @@ void ServiceManagementService::updateJobStatus(const std::string& jobID)
if (currentJob->getStatus() == util::ServiceJobStatus::STARTED)
{
currentJob->setStatus(util::ServiceJobStatus::IN_PROGRESS);
+ trackedJobCards.getValueAt(jobIndex).state = RecordState::MODIFIED;
jobStatusUpdated = true;
}
else if (currentJob->getStatus() == util::ServiceJobStatus::IN_PROGRESS)
{
currentJob->setStatus(util::ServiceJobStatus::COMPLETED);
+ trackedJobCards.getValueAt(jobIndex).state = RecordState::MODIFIED;
jobStatusUpdated = true;
serviceBookingCompleted = hasCompletedAllJobs(currentJob->getBookingId(), currentAssignedJobs);
if (serviceBookingCompleted)
{
+ const std::string& bookingId = currentJob->getBookingId();
currentJob->getBooking()->setStatus(util::ServiceJobStatus::COMPLETED);
+ trackedServiceBookings.getValueAt(trackedServiceBookings.find(bookingId)).state = RecordState::MODIFIED;
paymentManagementService.generateInvoice(currentJob->getBooking());
std::string title = "Service Booking completed. Invoice Generated.";
std::string message = "Services completed for the booking and invoice generated.";
@@ -1155,4 +917,6 @@ void ServiceManagementService::updateJobStatus(const std::string& jobID)
{
throw std::runtime_error("Failed to update job status. Job may already be completed.");
}
+ m_dataStore.saveJobCards();
+ m_dataStore.saveServiceBookings();
}
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h
index b2a4384..2fcfd6d 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h
@@ -23,7 +23,6 @@ class ServiceManagementService : public NotificationManagementService
private:
DataStore& m_dataStore;
static util::Map m_observers;
- util::Vector getObserverIDs() override;
public:
ServiceManagementService() : m_dataStore(DataStore::getInstance()) {}
util::Map getServices();
@@ -45,14 +44,4 @@ 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();
- void loadObservers();
- void saveObservers();
};
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp
index 8ba68d0..e923e1c 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp
@@ -11,7 +11,6 @@ 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"
@@ -20,6 +19,9 @@ Date:19-May-2026
#include "UserManagementService.h"
#include "Vector.h"
#include "Validator.h"
+#include "Utility.h"
+#include "TrackedRecord.h"
+#include "DataStoreLockGuard.h"
/*
Function: ensureAdminExists
@@ -31,12 +33,13 @@ Return type: void
*/
void UserManagementService::ensureAdminExists()
{
+ DataStoreLockGuard lock(m_dataStore);
auto& usersMap = m_dataStore.getUsers();
int usersMapSize = usersMap.getSize();
bool isAdminFound = false;
for (int index = 0; index < usersMapSize; index++)
{
- User* user = usersMap.getValueAt(index);
+ User* user = usersMap.getValueAt(index).data;
if (user && user->getUserType() == util::UserType::ADMIN)
{
isAdminFound = true;
@@ -73,7 +76,9 @@ void UserManagementService::createUser(const std::string& username, const std::s
InventoryManagementService inventoryManagementService;
PaymentManagementService paymentManagementService;
ServiceManagementService serviceManagementService;
- auto& usersMap = m_dataStore.getUsers();
+ DataStoreLockGuard lock(m_dataStore);
+ auto& trackedUsersMap = m_dataStore.getUsers();
+ auto usersMap = util::getObjects(trackedUsersMap);
if (util::isUsernameDuplicate(username, usersMap))
{
throw std::runtime_error("Username already exists");
@@ -87,13 +92,14 @@ void UserManagementService::createUser(const std::string& username, const std::s
throw std::runtime_error("Phone already exists");
}
User* newUser = Factory::getObject(username, password, name, phone, email, type);
- usersMap.insert(newUser->getId(), newUser);
+ trackedUsersMap.insert(newUser->getId(), util::createNewRecord(newUser));
paymentManagementService.attach(newUser);
serviceManagementService.attach(newUser);
if (newUser->getUserType() == util::UserType::ADMIN)
{
inventoryManagementService.attach(newUser);
}
+ m_dataStore.saveUsers();
}
/*
@@ -107,19 +113,24 @@ Return type: void
*/
void UserManagementService::updateUserDetails(const std::string& userID, const std::string& email, const std::string& phone)
{
- auto& usersMap = m_dataStore.getUsers();
- int index = usersMap.find(userID);
+ DataStoreLockGuard lock(m_dataStore);
+ auto& trackedUsersMap = m_dataStore.getUsers();
+ auto usersMap = util::getObjects(trackedUsersMap);
+ int index = trackedUsersMap.find(userID);
if (index == -1)
{
throw std::runtime_error("User does not exist!\n");
}
- User* user = usersMap.getValueAt(index);
+ User* user = trackedUsersMap.getValueAt(index).data;
+ bool isModified = false;
if (email != user->getEmail())
{
if (util::isEmailDuplicate(email, usersMap))
{
throw std::runtime_error("Email already exists!\n");
}
+ user->setEmail(email);
+ isModified = true;
}
if (phone != user->getPhone())
{
@@ -127,9 +138,14 @@ void UserManagementService::updateUserDetails(const std::string& userID, const s
{
throw std::runtime_error("Phone number already exists!\n");
}
+ user->setPhone(phone);
+ isModified = true;
+ }
+ if (isModified)
+ {
+ trackedUsersMap.getValueAt(index).state = RecordState::MODIFIED;
+ m_dataStore.saveUsers();
}
- user->setEmail(email);
- user->setPhone(phone);
}
/*
@@ -144,20 +160,25 @@ Throws:
*/
util::Vector UserManagementService::getUserNotifications(const std::string& userID)
{
- auto& usersMap = m_dataStore.getUsers();
- if (usersMap.find(userID) == -1)
+ DataStoreLockGuard lock(m_dataStore);
+ auto& trackedUsersMap = m_dataStore.getUsers();
+ if (trackedUsersMap.find(userID) == -1)
{
throw std::runtime_error("No user found with given UserID");
}
- User* user = usersMap[userID];
+ User* user = trackedUsersMap[userID].data;
if (user)
{
- auto& notifications = user->getNotifications();
- int numberOfNotifications = notifications.getSize();
+ auto& trackedNotificationMap = m_dataStore.getNotifications();
+ int numberOfNotifications = trackedNotificationMap.getSize();
util::Vector notificationsVector;
for (int index = 0; index < numberOfNotifications; index++)
{
- notificationsVector.push_back(notifications.getValueAt(index));
+ Notification* notification = trackedNotificationMap.getValueAt(index).data;
+ if (notification->getRecipientUserId() == userID && notification->getState() == util::State::ACTIVE)
+ {
+ notificationsVector.push_back(notification);
+ }
}
return notificationsVector;
}
@@ -169,97 +190,39 @@ util::Vector UserManagementService::getUserNotifications(const st
/*
Function: deleteNotification
-Description: Deletes a specific notification associated with a given user ID.
+Description: Marks a specific notification associated with a given user
+ as inactive.
Parameters:
- notificationID: The unique ID of the notification to be deleted.
- userID: The unique ID of the user whose notification is to be deleted.
Returns:
- void
Throws:
- - std::runtime_error if no user is found with the given UserID or if no notification is found with the given NotificationID.
+ - std::runtime_error if no user is found with the given UserID or
+ if no notification is found with the given NotificationID.
*/
void UserManagementService::deleteNotification(const std::string& notificationID, const std::string& userID)
{
- auto& usersMap = m_dataStore.getUsers();
- if (usersMap.find(userID) == -1)
+ DataStoreLockGuard lock(m_dataStore);
+ auto& trackedUsersMap = m_dataStore.getUsers();
+ auto& trackedNotificationsMap = m_dataStore.getNotifications();
+ int userIndex = trackedUsersMap.find(userID);
+ if (userIndex == -1)
{
throw std::runtime_error("No user found with given UserID");
}
- User* user = usersMap[userID];
- auto& notifications = user->getNotifications();
- if (notifications.find(notificationID) == -1)
+ int notificationIndex = trackedNotificationsMap.find(notificationID);
+ if (notificationIndex == -1)
{
throw std::runtime_error("No notification found with given NotificationID");
}
- notifications.remove(notificationID);
-}
-
-/*
-Function: loadUsers
-Description: Loads users and notifications from persistent storage into the datastore.
- Validates that each notification’s recipient exists and attaches the
- notification to the corresponding user.
-Parameters:
- - None
-Returns:
- - void
-Throws:
- - std::runtime_error if a notification recipient user ID is invalid
-*/
-void UserManagementService::loadUsers()
-{
- util::FileManager userFileManager(config::file::USER_FILE);
- util::FileManager notificationFileManager(config::file::NOTIFICATION_FILE);
- auto& users = m_dataStore.getUsers();
- auto usersMap = userFileManager.load();
- auto notificationsMap = notificationFileManager.load();
- int numberOfUsers = usersMap.getSize();
- int numberOfNotifications = notificationsMap.getSize();
- for (int index = 0; index < numberOfUsers; index++)
- {
- users[usersMap.getKeyAt(index)] = usersMap.getValueAt(index);
- }
- for (int index = 0; index < numberOfNotifications; index++)
- {
- Notification* notification = notificationsMap.getValueAt(index);
- const std::string& recipientUserId = notification->getRecipientUserId();
- int userIndex = users.find(recipientUserId);
- if (userIndex == -1)
- {
- throw std::runtime_error("Invalid recipient user ID");
- }
- User* user = users.getValueAt(userIndex);
- user->addNotification(notification);
- }
-}
-
-/*
-Function: saveUsers
-Description: Saves users and their notifications from the datastore to persistent storage.
- Collects notifications from all users into a single map before saving.
-Parameters:
- - None
-Returns:
- - void
-*/
-void UserManagementService::saveUsers()
-{
- util::FileManager userFileManager(config::file::USER_FILE);
- util::FileManager notificationFileManager(config::file::NOTIFICATION_FILE);
- auto& users = m_dataStore.getUsers();
- util::Map notifications;
- for (int userIndex = 0; userIndex < users.getSize(); userIndex++)
- {
- User* user = users.getValueAt(userIndex);
- auto& userNotifications = user->getNotifications();
- for (int notificationIndex = 0; notificationIndex < userNotifications.getSize(); notificationIndex++)
- {
- notifications[userNotifications.getKeyAt(notificationIndex)] =
- userNotifications.getValueAt(notificationIndex);
- }
- }
- userFileManager.save(users);
- notificationFileManager.save(notifications);
+ Notification* notification = trackedNotificationsMap.getValueAt(notificationIndex).data;
+ if (notification->getRecipientUserId() == userID)
+ {
+ notification->setState(util::State::INACTIVE);
+ trackedNotificationsMap.getValueAt(notificationIndex).state = RecordState::MODIFIED;
+ m_dataStore.saveNotifications();
+ }
}
/*
@@ -270,7 +233,9 @@ Return type: util::Map
*/
util::Map UserManagementService::getUsers()
{
- return m_dataStore.getUsers();
+ DataStoreLockGuard lock(m_dataStore);
+ auto users = util::getObjects(m_dataStore.getUsers());
+ return users;
}
/*
@@ -281,10 +246,12 @@ Return type: User*
*/
User* UserManagementService::getUser(const std::string& userID)
{
- int index = m_dataStore.getUsers().find(userID);
+ DataStoreLockGuard lock(m_dataStore);
+ auto& trackedUsersMap = m_dataStore.getUsers();
+ int index = trackedUsersMap.find(userID);
if (index != -1)
{
- return m_dataStore.getUsers().getValueAt(index);
+ return trackedUsersMap.getValueAt(index).data;
}
return nullptr;
}
@@ -300,35 +267,53 @@ void UserManagementService::removeUser(const std::string& userID)
InventoryManagementService inventoryManagementService;
PaymentManagementService paymentManagementService;
ServiceManagementService serviceManagementService;
- int index = m_dataStore.getUsers().find(userID);
+ DataStoreLockGuard lock(m_dataStore);
+ auto& trackedUsersMap = m_dataStore.getUsers();
+ int index = trackedUsersMap.find(userID);
if (index != -1)
{
- User* user = m_dataStore.getUsers().getValueAt(index);
+ User* user = trackedUsersMap.getValueAt(index).data;
if (user != nullptr)
{
if (user->getUserType() == util::UserType::CUSTOMER)
{
- serviceManagementService.cancelCustomerServiceBookings(userID);
+ serviceManagementService.cancelCustomerServiceBookings(userID);
}
if (user->getUserType() == util::UserType::TECHNICIAN)
{
serviceManagementService.cancelTechnicianJobs(userID);
}
- user->setState(util::State::INACTIVE);
inventoryManagementService.detach(user);
paymentManagementService.detach(user);
serviceManagementService.detach(user);
+ user->setState(util::State::INACTIVE);
+ trackedUsersMap.getValueAt(index).state = RecordState::MODIFIED;
+ m_dataStore.saveUsers();
}
}
}
-util::Map UserManagementService::getUsers(util::UserType type)
+/*
+Function: getUsers
+Description: Retrieves all active users of the specified type from
+ the DataStore.
+Parameters:
+ - type: The user type to filter by
+ (ADMIN, CUSTOMER, or TECHNICIAN).
+Returns:
+ - util::Map:
+ Collection of active users matching the specified type,
+ keyed by user ID.
+*/
+util::Map UserManagementService::getUsers(util::UserType type)
{
- util::Map& currentUsers = m_dataStore.getUsers();
+ DataStoreLockGuard lock(m_dataStore);
+ auto& trackedUsersMap = m_dataStore.getUsers();
+ util::Map currentUsers = util::getObjects(trackedUsersMap);
util::Map filteredUsersMap;
- for (int iterator = 0; iterator < currentUsers.getSize(); iterator++)
+ for (int index = 0; index < currentUsers.getSize(); index++)
{
- User* currentUser = currentUsers.getValueAt(iterator);
+ User* currentUser = currentUsers.getValueAt(index);
if (currentUser && currentUser->getState() == util::State::ACTIVE && currentUser->getUserType() == type)
{
filteredUsersMap.insert(currentUser->getId(), currentUser);
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.h
index b448872..28aa446 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.h
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.h
@@ -31,6 +31,4 @@ public:
util::Vector getUserNotifications(const std::string& userID);
void deleteNotification(const std::string& notificationID, const std::string& userID);
void ensureAdminExists();
- void loadUsers();
- void saveUsers();
};
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Config.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Config.h
index 2eef19d..a2995b4 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Config.h
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Config.h
@@ -29,6 +29,7 @@ namespace config
namespace file
{
const size_t INITIAL_CAPACITY = 100;
+ const size_t GROWTH_FACTOR = 2;
constexpr const char* DIRECTORY = "files/";
constexpr const char* INVENTORYITEM_FILE = "files/InventoryItem.dat";
constexpr const char* USER_FILE = "files/User.dat";
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileHelper.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileHelper.h
index c8bf96f..f73fba4 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileHelper.h
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileHelper.h
@@ -43,67 +43,4 @@ 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: Vector containing all records (excluding header)
- Throws:
- - None (creates file if missing)
- */
- inline util::Vector loadRecords(const std::string& filePath)
- {
- util::Vector 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&, 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& 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';
- }
- }
}
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileManager.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileManager.h
deleted file mode 100644
index 1ea66c7..0000000
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileManager.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
-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
-#include
-#include
-#include "Vector.h"
-#include "Map.h"
-#include "FileHelper.h"
-
-namespace util
-{
- template using objects = util::Map;
-
- template
- class FileManager
- {
- private:
- std::string m_filePath;
- public:
- FileManager() : m_filePath("") {}
- FileManager(const std::string& filePath) : m_filePath(filePath) {}
- objects load();
- void save(const objects&);
- };
-
- /*
- 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 containing deserialized objects
- Throws:
- - std::runtime_error if deserialization fails for any record
- */
- template
- objects FileManager::load()
- {
- objects 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 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&, map of objects to save
- Returns:
- - void
- Throws:
- - std::runtime_error if the file cannot be opened for writing
- */
- template
- void FileManager::save(const objects& records)
- {
- util::Vector 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';
- }
- }
-}
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/InputHelper.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/InputHelper.h
index dffc199..065a197 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/InputHelper.h
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/InputHelper.h
@@ -28,7 +28,7 @@ namespace util
if (!(std::cin >> value))
{
std::cin.clear();
- std::cin.ignore(std::numeric_limits::max(), '\n');
+ std::cin.ignore((std::numeric_limits::max)(), '\n');
throw std::runtime_error("Invalid console input");
}
}
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h
index 9b6bc9d..56dd765 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h
@@ -54,52 +54,6 @@ 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
Map getObjects(const Map>& trackedRecords);
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.cpp
index 4596d9b..926fc9e 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.cpp
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.cpp
@@ -27,8 +27,11 @@ void UserInterface::run()
{
try
{
- m_controller.loadSystemData();
- m_controller.runSystemChecks();
+ if (!m_controller.initialize())
+ {
+ std::cout << "Error: Failed to initialize the system!";
+ return;
+ }
bool isMenuActive = true;
while (isMenuActive)
{
@@ -49,7 +52,7 @@ void UserInterface::run()
util::pressEnter();
}
}
- m_controller.saveSystemData();
+ m_controller.shutdown();
}
catch (const std::invalid_argument& exception)
{