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 8627061..e554d2b 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj
@@ -102,7 +102,7 @@
true
_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
- $(ProjectDir)models;$(ProjectDir)controllers;$(ProjectDir)factories;$(ProjectDir)views;$(ProjectDir)services;$(ProjectDir)utilities;$(ProjectDir)core\patterns;$(ProjectDir)datastores;%(AdditionalIncludeDirectories)
+ $(ProjectDir)models;$(ProjectDir)controllers;$(ProjectDir)factories;$(ProjectDir)views;$(ProjectDir)services;$(ProjectDir)utilities;$(ProjectDir)core\patterns;$(ProjectDir)datastores;$(ProjectDir)core\sharedmemory;$(ProjectDir)core\events;%(AdditionalIncludeDirectories)
Console
@@ -117,7 +117,7 @@
true
NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
- $(ProjectDir)models;$(ProjectDir)controllers;$(ProjectDir)factories;$(ProjectDir)views;$(ProjectDir)services;$(ProjectDir)utilities;$(ProjectDir)core\patterns;$(ProjectDir)datastores;%(AdditionalIncludeDirectories)
+ $(ProjectDir)models;$(ProjectDir)controllers;$(ProjectDir)factories;$(ProjectDir)views;$(ProjectDir)services;$(ProjectDir)utilities;$(ProjectDir)core\patterns;$(ProjectDir)datastores;$(ProjectDir)core\sharedmemory;$(ProjectDir)core\events;%(AdditionalIncludeDirectories)
Console
@@ -126,8 +126,10 @@
+
+
@@ -139,7 +141,6 @@
-
@@ -148,14 +149,23 @@
+
+
+
+
+
+
+
+
+
@@ -174,7 +184,6 @@
-
@@ -185,6 +194,7 @@
+
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters
index 73b9291..ac65e97 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters
@@ -64,6 +64,18 @@
{8057b93d-51a9-42df-b06e-01ce395f6308}
+
+ {d9da9793-fe6f-4914-bee3-99d5934da228}
+
+
+ {0769afb6-f57d-4ae3-a1cf-ceca6e606af0}
+
+
+ {85029bdb-6941-41dc-a3a7-9e5841671d8c}
+
+
+ {1050aca7-6f2c-4ccb-a446-db9c898c3599}
+
@@ -108,9 +120,6 @@
Source Files\DataStores
-
- Source Files\Services
-
Source Files\Core\Patterns
@@ -141,6 +150,15 @@
Source Files\Models
+
+ Source Files\Core\SharedMemory
+
+
+ Source Files\Core\Events
+
+
+ Source Files\Views
+
@@ -236,9 +254,6 @@
Header Files\Utilities
-
- Header Files\Utilities
-
Header Files\Utilities
@@ -251,5 +266,32 @@
Header Files\Views
+
+ Header Files\DataStores
+
+
+ Header Files\Core\SharedMemory
+
+
+ Header Files\Core\SharedMemory
+
+
+ Header Files\Core\SharedMemory
+
+
+ Header Files\Core\SharedMemory
+
+
+ Header Files\Core\SharedMemory
+
+
+ Header Files\Core\SharedMemory
+
+
+ Header Files\Core\Events
+
+
+ Header Files\Views
+
\ 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 e3a85b0..28441fb 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp
@@ -6,6 +6,7 @@ Description: Implementation file containing the method definitions of the
Author: Trenser
Date:19-May-2026
*/
+
#include "ComboPackage.h"
#include "Controller.h"
#include "Enums.h"
@@ -233,6 +234,17 @@ void Controller::removeInventoryItem(const std::string& inventoryItemID)
m_inventoryManagementService.removeInventoryItem(inventoryItemID);
}
+/*
+Function: removeServiceBooking
+Description: Removes a service booking from the service management system by its booking ID.
+Parameter: const std::string& bookingID - ID of the service booking
+Return type: void
+*/
+void Controller::removeServiceBooking(const std::string& bookingID)
+{
+ m_serviceManagementService.removeServiceBooking(bookingID);
+}
+
/*
Function: addInventoryItemStock
Description: Adds stock to an existing inventory item in the inventory management service.
@@ -264,6 +276,7 @@ util::Map Controller::getServiceBookings()
return readOnlyServiceBookings;
}
+
/*
Function: getServiceBookingsByUser
Description: Retrieves all service bookings for a specific user.
@@ -587,63 +600,50 @@ 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();
+}
+
+/*
+Function: registerEvents
+Description: Registers menu event handles with the authentication
+ service.
+Parameter: HANDLE accountDisabledEvent - account disabled event handle
+ HANDLE notificationAvailableEvent - notification event handle
+Return type: void
+*/
+void Controller::registerEvents(HANDLE accountDisabledEvent, HANDLE notificationAvailableEvent)
+{
+ m_authenticationManagementService.registerEvents(accountDisabledEvent, notificationAvailableEvent);
+}
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h
index 35241a0..2120fe5 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h
@@ -8,6 +8,7 @@ Date:19-May-2026
*/
#pragma once
+#include
#include
#include "AuthenticationManagementService.h"
#include "Enums.h"
@@ -57,6 +58,7 @@ public:
util::Map getUsers(util::UserType userType);
void createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID);
void createService(const std::string& name, const util::Vector& inventoryItemIDs, double laborCost);
+ void removeServiceBooking(const std::string& bookingID);
void removeService(const std::string& serviceID);
util::Map getJobCardsByUser();
void updateJobStatus(const std::string& jobID);
@@ -70,7 +72,7 @@ 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();
+ void registerEvents(HANDLE accountDisabledEvent, HANDLE notificationAvailableEvent);
};
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/events/EventManager.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/events/EventManager.cpp
new file mode 100644
index 0000000..568a0e6
--- /dev/null
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/events/EventManager.cpp
@@ -0,0 +1,225 @@
+/*
+File: EventManager.cpp
+Description: Implementation file containing the method definitions of the
+ EventManager class, including listener management and
+ interprocess event publishing.
+Author: Trenser
+Date:15-Jun-2026
+*/
+
+#include
+#include
+#include "EventManager.h"
+
+namespace
+{
+ const std::string USER_DISABLED_EVENT = "userDisabled_";
+
+ const std::string NOTIFICATION_AVAILABLE_EVENT = "notificationAvailable_";
+}
+
+/*
+Function: EventManager
+Description: Constructs an EventManager instance with default values.
+Parameter: None
+Return type: None
+*/
+EventManager::EventManager()
+ :
+ m_userDisabledEvent(NULL),
+ m_notificationAvailableEvent(NULL),
+ m_shutdownEvent(NULL),
+ m_running(false) {}
+
+/*
+Function: ~EventManager
+Description: Destroys the EventManager and performs final cleanup.
+Parameter: None
+Return type: None
+*/
+EventManager::~EventManager()
+{
+ shutdown();
+ if (m_listenerThread.joinable())
+ {
+ m_listenerThread.join();
+ }
+}
+
+/*
+Function: initialize
+Description: Creates the user-specific events and starts the listener
+ thread.
+Parameter: const std::string& userId - unique identifier of the user
+ std::function userDisabledCallback - callback for
+ user disable events
+ std::function notificationCallback - callback for
+ notification events
+Return type: bool - true if initialization succeeds, false otherwise
+*/
+bool EventManager::initialize(const std::string& userId, std::function userDisabledCallback, std::function notificationCallback)
+{
+ if (m_running.load())
+ {
+ return false;
+ }
+ m_userDisabledCallback = userDisabledCallback;
+ m_notificationCallback = notificationCallback;
+ m_userDisabledEvent = CreateEventA(NULL, FALSE, FALSE, (USER_DISABLED_EVENT + userId).c_str());
+ if (!m_userDisabledEvent)
+ {
+ return false;
+ }
+ if (GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ CloseHandle(m_userDisabledEvent);
+ m_userDisabledEvent = NULL;
+ throw std::runtime_error("Only one session allowed per user.");
+ }
+ m_notificationAvailableEvent = CreateEventA(NULL, FALSE, FALSE, (NOTIFICATION_AVAILABLE_EVENT + userId).c_str());
+ if (!m_notificationAvailableEvent)
+ {
+ CloseHandle(m_userDisabledEvent);
+ m_userDisabledEvent = NULL;
+ return false;
+ }
+ m_shutdownEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
+ if (!m_shutdownEvent)
+ {
+ CloseHandle(m_userDisabledEvent);
+ CloseHandle(m_notificationAvailableEvent);
+ m_userDisabledEvent = NULL;
+ m_notificationAvailableEvent = NULL;
+ return false;
+ }
+ m_running.store(true);
+ m_listenerThread = std::thread(&EventManager::run, this);
+ return true;
+}
+
+/*
+Function: shutdown
+Description: Stops the listener thread and releases event resources.
+Parameter: None
+Return type: None
+*/
+void EventManager::shutdown()
+{
+ if (!m_running.load())
+ {
+ return;
+ }
+ m_running.store(false);
+ if (m_shutdownEvent)
+ {
+ SetEvent(m_shutdownEvent);
+ }
+ if (m_listenerThread.joinable())
+ {
+ if (std::this_thread::get_id() != m_listenerThread.get_id())
+ {
+ m_listenerThread.join();
+ }
+ }
+ if (m_userDisabledEvent)
+ {
+ CloseHandle(m_userDisabledEvent);
+ m_userDisabledEvent = NULL;
+ }
+ if (m_notificationAvailableEvent)
+ {
+ CloseHandle(m_notificationAvailableEvent);
+ m_notificationAvailableEvent = NULL;
+ }
+ if (m_shutdownEvent)
+ {
+ CloseHandle(m_shutdownEvent);
+ m_shutdownEvent = NULL;
+ }
+}
+
+/*
+Function: run
+Description: Waits for and dispatches user-related events.
+Parameter: None
+Return type: void
+*/
+void EventManager::run()
+{
+ HANDLE handles[3];
+ handles[0] = m_userDisabledEvent;
+ handles[1] = m_notificationAvailableEvent;
+ handles[2] = m_shutdownEvent;
+ while (m_running.load())
+ {
+ DWORD result = WaitForMultipleObjects(3, handles, FALSE, INFINITE);
+ switch (result)
+ {
+ case WAIT_OBJECT_0:
+ try
+ {
+ if (m_userDisabledCallback)
+ {
+ m_userDisabledCallback();
+ }
+ }
+ catch (const std::exception& exception)
+ {
+ std::cout << exception.what() << std::endl;
+ }
+ break;
+ case WAIT_OBJECT_0 + 1:
+ try
+ {
+ if (m_notificationCallback)
+ {
+ m_notificationCallback();
+ }
+ }
+ catch (const std::exception& exception)
+ {
+ std::cout << exception.what() << std::endl;
+ }
+ break;
+ case WAIT_OBJECT_0 + 2:
+ return;
+ default:
+ break;
+ }
+ }
+}
+
+/*
+Function: sendUserDisabledEvent
+Description: Publishes a user disabled event for a specific user.
+Parameter: const std::string& userId - target user identifier
+Return type: void
+*/
+void EventManager::sendUserDisabledEvent(const std::string& userId)
+{
+ HANDLE eventHandle = CreateEventA(NULL, FALSE, FALSE, (USER_DISABLED_EVENT + userId).c_str());
+ if (!eventHandle)
+ {
+ return;
+ }
+ SetEvent(eventHandle);
+ CloseHandle(eventHandle);
+}
+
+/*
+Function: sendNotificationAvailableEvent
+Description: Publishes a notification available event for a specific
+ user.
+Parameter: const std::string& userId - target user identifier
+Return type: void
+*/
+void EventManager::sendNotificationAvailableEvent(const std::string& userId)
+{
+ HANDLE eventHandle = CreateEventA(NULL, FALSE, FALSE, (NOTIFICATION_AVAILABLE_EVENT + userId).c_str());
+ if (!eventHandle)
+ {
+ return;
+ }
+ SetEvent(eventHandle);
+ CloseHandle(eventHandle);
+}
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/events/EventManager.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/events/EventManager.h
new file mode 100644
index 0000000..01de6c4
--- /dev/null
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/events/EventManager.h
@@ -0,0 +1,37 @@
+/*
+File: EventManager.h
+Description: Header file declaring the EventManager class, which manages
+ user-specific interprocess events for user disable and
+ notification availability updates.
+Author: Trenser
+Date:15-Jun-2026
+*/
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+class EventManager
+{
+private:
+ HANDLE m_userDisabledEvent;
+ HANDLE m_notificationAvailableEvent;
+ HANDLE m_shutdownEvent;
+ std::atomic m_running;
+ std::thread m_listenerThread;
+ std::function m_userDisabledCallback;
+ std::function m_notificationCallback;
+ void run();
+
+public:
+ EventManager();
+ ~EventManager();
+ bool initialize(const std::string& userId, std::function userDisabledCallback, std::function notificationCallback);
+ void shutdown();
+ static void sendUserDisabledEvent(const std::string& userId);
+ static void sendNotificationAvailableEvent(const std::string& userId);
+};
\ 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/core/sharedmemory/FileHeader.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/sharedmemory/FileHeader.h
new file mode 100644
index 0000000..929dbf4
--- /dev/null
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/sharedmemory/FileHeader.h
@@ -0,0 +1,17 @@
+/*
+File: FileHeader.h
+Description: Defines the FileHeader structure used to store
+ metadata for binary record files, including
+ record count and capacity.
+Author: Trenser
+Created: 10-June-2026
+*/
+
+#pragma once
+#include
+
+struct FileHeader
+{
+ size_t recordCount;
+ size_t capacity;
+};
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/sharedmemory/MappingInfo.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/sharedmemory/MappingInfo.h
new file mode 100644
index 0000000..ebd5123
--- /dev/null
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/sharedmemory/MappingInfo.h
@@ -0,0 +1,29 @@
+/*
+File: MappingInfo.h
+Description: Defines the MappingInfo structure used for
+ managing Windows file mapping operations.
+ Stores handles, mapped view pointer,
+ file metadata, and capacity information.
+Author: Trenser
+Created: 10-June-2026
+*/
+
+#pragma once
+#include
+#include
+
+struct MappingInfo
+{
+ HANDLE fileHandle;
+ HANDLE mappingHandle;
+ void* mappedView;
+ std::string fileName;
+ size_t recordSize;
+ size_t mappedCapacity;
+ MappingInfo()
+ : fileHandle(NULL),
+ mappingHandle(NULL),
+ mappedView(nullptr),
+ recordSize(0),
+ mappedCapacity(0) {}
+};
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/sharedmemory/RecordState.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/sharedmemory/RecordState.h
new file mode 100644
index 0000000..95402fd
--- /dev/null
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/sharedmemory/RecordState.h
@@ -0,0 +1,17 @@
+/*
+File: RecordState.h
+Description: Defines the RecordState enumeration used to
+ represent the state of a record in storage.
+ States include CLEAN, NEW_RECORD, and MODIFIED.
+Author: Trenser
+Created: 10-June-2026
+*/
+
+#pragma once
+
+enum class RecordState : int
+{
+ CLEAN,
+ NEW_RECORD,
+ MODIFIED
+};
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/sharedmemory/SerializedRecords.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/sharedmemory/SerializedRecords.h
new file mode 100644
index 0000000..2d18842
--- /dev/null
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/sharedmemory/SerializedRecords.h
@@ -0,0 +1,109 @@
+/*
+File: SerializedRecords.h
+Description: Defines serialized structures for persistent storage
+ and retrieval of system entities including User,
+ Notification, Service, ComboPackage, InventoryItem,
+ ServiceBooking, JobCard, Invoice, and Observer.
+ These structures use fixed-size character arrays
+ and primitive types for binary serialization.
+Author: Trenser
+Created: 10-June-2026
+*/
+
+#pragma once
+#include "Utility.h"
+#include "Enums.h"
+#include "Timestamp.h"
+
+struct SerializedUser
+{
+ char id[64];
+ char username[64];
+ char password[64];
+ char name[128];
+ char phone[32];
+ char email[128];
+ util::UserType userType;
+ util::State status;
+};
+
+struct SerializedNotification
+{
+ char id[64];
+ char recipientUserId[64];
+ char title[128];
+ char message[1024];
+ util::Timestamp createdAt;
+ util::State state;
+};
+
+struct SerializedService
+{
+ char id[64];
+ char name[128];
+ char inventoryItemIDs[1024];
+ double laborCost;
+ util::State status;
+};
+
+struct SerializedComboPackage
+{
+ char id[64];
+ char packageName[128];
+ double discountPercentage;
+ char serviceIDs[1024];
+ util::State status;
+};
+
+struct SerializedInventoryItem
+{
+ char id[64];
+ char partName[128];
+ int quantity;
+ double price;
+ util::State status;
+};
+
+struct SerializedServiceBooking
+{
+ char id[64];
+ util::ServiceJobStatus status;
+ char serviceIDs[1024];
+ char customerId[64];
+ char vehicleNumber[64];
+ char vehicleBrand[64];
+ char vehicleModel[64];
+ char assignedTechnicianId[64];
+ double discountPercentage;
+};
+
+struct SerializedJobCard
+{
+ char id[64];
+ char bookingId[64];
+ char serviceId[64];
+ char technicianId[64];
+ util::Timestamp assignedDate;
+ util::ServiceJobStatus status;
+ util::Timestamp completionDate;
+};
+
+struct SerializedInvoice
+{
+ char id[64];
+ char bookingId[64];
+ util::Timestamp invoiceDate;
+ char partIDs[1024];
+ double laborCost;
+ double partsCost;
+ double discountPercentage;
+ double totalAmount;
+ util::Timestamp paymentDate;
+ util::PaymentMode paymentMethod;
+ util::PaymentStatus status;
+};
+
+struct SerializedObserver
+{
+ char id[64];
+};
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/sharedmemory/SharedMemory.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/sharedmemory/SharedMemory.cpp
new file mode 100644
index 0000000..0c5c7b1
--- /dev/null
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/sharedmemory/SharedMemory.cpp
@@ -0,0 +1,386 @@
+/*
+File: SharedMemory.cpp
+Description: Implements shared memory utilities for managing
+ Windows file mapping operations. Provides functions
+ to create, open, resize, and close mappings, as well
+ as access headers, records, and ensure synchronization
+ across processes.
+Author: Trenser
+Created: 11-June-2026
+*/
+
+#include "SharedMemory.h"
+#include "Windows.h"
+#include "Config.h"
+
+/*
+Function: invalidateMapping
+Description: Releases all mapping resources and resets the mapping to an invalid state.
+Parameters:
+ - mapping: MappingInfo&, mapping information and handles
+Returns:
+ - None
+*/
+static void invalidateMapping(MappingInfo& mapping)
+{
+ if (mapping.mappedView != nullptr)
+ {
+ UnmapViewOfFile(mapping.mappedView);
+ mapping.mappedView = nullptr;
+ }
+ if (mapping.mappingHandle != NULL)
+ {
+ CloseHandle(mapping.mappingHandle);
+ mapping.mappingHandle = NULL;
+ }
+ if (mapping.fileHandle != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(mapping.fileHandle);
+ mapping.fileHandle = INVALID_HANDLE_VALUE;
+ }
+ mapping.mappedCapacity = 0;
+}
+
+/*
+Function: createOrOpenMapping
+Description: Creates or opens a file mapping and maps it into the process address space.
+Parameters:
+ - mapping: MappingInfo&, mapping information and handles
+Returns:
+ - bool: True if the mapping was successfully created/opened, otherwise false
+*/
+bool SharedMemory::createOrOpenMapping(MappingInfo& mapping)
+{
+ if (mapping.recordSize == 0)
+ {
+ return false;
+ }
+ mapping.fileHandle =
+ CreateFileA(
+ mapping.fileName.c_str(),
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (mapping.fileHandle == INVALID_HANDLE_VALUE)
+ {
+ return false;
+ }
+ LARGE_INTEGER fileSize;
+ if (!GetFileSizeEx(mapping.fileHandle, &fileSize))
+ {
+ invalidateMapping(mapping);
+ return false;
+ }
+ bool isNewFile = (fileSize.QuadPart == 0);
+ const size_t initialCapacity = config::file::INITIAL_CAPACITY;
+ if (isNewFile)
+ {
+ LARGE_INTEGER newSize;
+ newSize.QuadPart = sizeof(FileHeader) + initialCapacity * mapping.recordSize;
+ if (!SetFilePointerEx(mapping.fileHandle, newSize, NULL, FILE_BEGIN))
+ {
+ invalidateMapping(mapping);
+ return false;
+ }
+ if (!SetEndOfFile(mapping.fileHandle))
+ {
+ invalidateMapping(mapping);
+ return false;
+ }
+ }
+ mapping.mappingHandle =
+ CreateFileMappingA(
+ mapping.fileHandle,
+ NULL,
+ PAGE_READWRITE,
+ 0,
+ 0,
+ NULL);
+ if (mapping.mappingHandle == NULL)
+ {
+ invalidateMapping(mapping);
+ return false;
+ }
+ mapping.mappedView =
+ MapViewOfFile(
+ mapping.mappingHandle,
+ FILE_MAP_ALL_ACCESS,
+ 0,
+ 0,
+ 0);
+ if (mapping.mappedView == nullptr)
+ {
+ invalidateMapping(mapping);
+ return false;
+ }
+ FileHeader* header = getHeader(mapping);
+ if (header == nullptr)
+ {
+ invalidateMapping(mapping);
+ return false;
+ }
+ if (isNewFile)
+ {
+ header->recordCount = 0;
+ header->capacity = initialCapacity;
+ }
+ mapping.mappedCapacity = header->capacity;
+ return true;
+}
+
+/*
+Function: closeMapping
+Description: Unmaps and closes all resources associated with a file mapping.
+Parameters:
+ - mapping: MappingInfo&, mapping to close
+Returns:
+ - None
+*/
+void SharedMemory::closeMapping(MappingInfo& mapping)
+{
+ invalidateMapping(mapping);
+}
+
+/*
+Function: getHeader
+Description: Returns the file header stored at the beginning of the mapped memory region.
+Parameters:
+ - mapping: MappingInfo&, mapping information and handles
+Returns:
+ - FileHeader*: Pointer to the file header, or nullptr if the mapping is not valid
+*/
+FileHeader* SharedMemory::getHeader(MappingInfo& mapping)
+{
+ if (mapping.mappedView == nullptr)
+ {
+ return nullptr;
+ }
+ return reinterpret_cast(mapping.mappedView);
+}
+
+/*
+Function: getRecordAddress
+Description: Returns the address of a record at the specified index within the mapped memory region.
+Parameters:
+ - mapping: MappingInfo&, mapping information and handles
+ - index: size_t, record index
+Returns:
+ - void*: Pointer to the record, or nullptr if the mapping is not valid
+*/
+void* SharedMemory::getRecordAddress(MappingInfo& mapping, size_t index)
+{
+ if (mapping.mappedView == nullptr)
+ {
+ return nullptr;
+ }
+ return reinterpret_cast(mapping.mappedView) + sizeof(FileHeader) + index * mapping.recordSize;
+}
+
+/*
+Function: getRecordCount
+Description: Returns the number of records currently stored in the mapping.
+Parameters:
+ - mapping: MappingInfo&, mapping information and handles
+Returns:
+ - size_t: Number of records in the mapping
+*/
+size_t SharedMemory::getRecordCount(MappingInfo& mapping)
+{
+ FileHeader* header = getHeader(mapping);
+ if (header == nullptr)
+ {
+ return 0;
+ }
+ return header->recordCount;
+}
+
+/*
+Function: setRecordCount
+Description: Updates the number of records stored in the mapping.
+Parameters:
+ - mapping: MappingInfo&, mapping information and handles
+ - count: size_t, new record count
+Returns:
+ - None
+*/
+void SharedMemory::setRecordCount(MappingInfo& mapping, size_t count)
+{
+ FileHeader* header = getHeader(mapping);
+ if (header == nullptr)
+ {
+ return;
+ }
+ header->recordCount = count;
+}
+
+/*
+Function: getCapacity
+Description: Returns the current capacity of the mapping.
+Parameters:
+ - mapping: MappingInfo&, mapping information and handles
+Returns:
+ - size_t: Maximum number of records that can be stored in the mapping
+*/
+size_t SharedMemory::getCapacity(MappingInfo& mapping)
+{
+ FileHeader* header = getHeader(mapping);
+ if (header == nullptr)
+ {
+ return 0;
+ }
+ return header->capacity;
+}
+
+/*
+Function: resizeMapping
+Description: Resizes the file mapping to the specified capacity.
+Parameters:
+ - mapping: MappingInfo&, mapping information and handles
+ - newCapacity: size_t, new mapping capacity
+Returns:
+ - bool: True if the resize succeeded, otherwise false
+*/
+bool SharedMemory::resizeMapping(MappingInfo& mapping, size_t newCapacity)
+{
+ FileHeader* header = getHeader(mapping);
+ if (header == nullptr)
+ {
+ invalidateMapping(mapping);
+ return false;
+ }
+ header->capacity = newCapacity;
+ if (!FlushViewOfFile(mapping.mappedView, sizeof(FileHeader)))
+ {
+ return false;
+ }
+ if (!UnmapViewOfFile(mapping.mappedView))
+ {
+ return false;
+ }
+ mapping.mappedView = nullptr;
+ CloseHandle(mapping.mappingHandle);
+ mapping.mappingHandle = NULL;
+ LARGE_INTEGER newSize;
+ newSize.QuadPart = sizeof(FileHeader) + newCapacity * mapping.recordSize;
+ if (!SetFilePointerEx(mapping.fileHandle, newSize, NULL, FILE_BEGIN))
+ {
+ invalidateMapping(mapping);
+ return false;
+ }
+ if (!SetEndOfFile(mapping.fileHandle))
+ {
+ invalidateMapping(mapping);
+ return false;
+ }
+ mapping.mappingHandle =
+ CreateFileMappingA(
+ mapping.fileHandle,
+ NULL,
+ PAGE_READWRITE,
+ 0,
+ 0,
+ NULL);
+ if (mapping.mappingHandle == NULL)
+ {
+ invalidateMapping(mapping);
+ return false;
+ }
+ mapping.mappedView =
+ MapViewOfFile(
+ mapping.mappingHandle,
+ FILE_MAP_ALL_ACCESS,
+ 0,
+ 0,
+ 0);
+ if (mapping.mappedView == nullptr)
+ {
+ invalidateMapping(mapping);
+ return false;
+ }
+ mapping.mappedCapacity = newCapacity;
+ return true;
+}
+
+/*
+Function: ensureCapacityForInsert
+Description: Ensures that the mapping has space for at least one additional record, growing it if necessary.
+Parameters:
+ - mapping: MappingInfo&, mapping information and handles
+Returns:
+ - bool: True if capacity is available, otherwise false
+*/
+bool SharedMemory::ensureCapacityForInsert(MappingInfo& mapping)
+{
+ size_t recordCount = getRecordCount(mapping);
+ size_t capacity = getCapacity(mapping);
+ if (recordCount < capacity)
+ {
+ return true;
+ }
+ return resizeMapping(mapping, capacity * config::file::GROWTH_FACTOR);
+}
+
+/*
+Function: ensureLatestMapping
+Description: Remaps the file if another process has resized it.
+Parameters:
+ - mapping: MappingInfo&, mapping information and handles
+Returns:
+ - bool: True if the mapping is valid and up to date, otherwise false
+*/
+bool SharedMemory::ensureLatestMapping(MappingInfo& mapping)
+{
+ FileHeader* header = getHeader(mapping);
+ if (header == nullptr)
+ {
+ return false;
+ }
+ if (header->capacity == mapping.mappedCapacity)
+ {
+ return true;
+ }
+ if (!UnmapViewOfFile(mapping.mappedView))
+ {
+ invalidateMapping(mapping);
+ return false;
+ }
+ mapping.mappedView = nullptr;
+ CloseHandle(mapping.mappingHandle);
+ mapping.mappingHandle = NULL;
+ mapping.mappingHandle =
+ CreateFileMappingA(
+ mapping.fileHandle,
+ NULL,
+ PAGE_READWRITE,
+ 0,
+ 0,
+ NULL);
+ if (mapping.mappingHandle == NULL)
+ {
+ invalidateMapping(mapping);
+ return false;
+ }
+ mapping.mappedView =
+ MapViewOfFile(
+ mapping.mappingHandle,
+ FILE_MAP_ALL_ACCESS,
+ 0,
+ 0,
+ 0);
+ if (mapping.mappedView == nullptr)
+ {
+ invalidateMapping(mapping);
+ return false;
+ }
+ header = getHeader(mapping);
+ if (header == nullptr)
+ {
+ invalidateMapping(mapping);
+ return false;
+ }
+ mapping.mappedCapacity = header->capacity;
+ return true;
+}
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/sharedmemory/SharedMemory.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/sharedmemory/SharedMemory.h
new file mode 100644
index 0000000..a288ab3
--- /dev/null
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/sharedmemory/SharedMemory.h
@@ -0,0 +1,29 @@
+/*
+File: SharedMemory.h
+Description: Declares functions for managing Windows file
+ mapping and shared memory operations. Provides
+ utilities for creating, resizing, and closing
+ mappings, as well as accessing headers and
+ record data.
+Author: Trenser
+Created: 10-June-2026
+*/
+
+#pragma once
+#include
+#include "MappingInfo.h"
+#include "FileHeader.h"
+
+namespace SharedMemory
+{
+ bool createOrOpenMapping(MappingInfo& mapping);
+ void closeMapping(MappingInfo& mapping);
+ bool ensureLatestMapping(MappingInfo& mapping);
+ bool resizeMapping(MappingInfo& mapping, size_t newCapacity);
+ FileHeader* getHeader(MappingInfo& mapping);
+ void* getRecordAddress(MappingInfo& mapping, size_t index);
+ size_t getRecordCount(MappingInfo& mapping);
+ void setRecordCount(MappingInfo& mapping, size_t count);
+ size_t getCapacity(MappingInfo& mapping);
+ bool ensureCapacityForInsert(MappingInfo& mapping);
+};
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/sharedmemory/TrackedRecord.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/sharedmemory/TrackedRecord.h
new file mode 100644
index 0000000..5ff9ac9
--- /dev/null
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/sharedmemory/TrackedRecord.h
@@ -0,0 +1,33 @@
+/*
+File: TrackedRecord.h
+Description: Defines the TrackedRecord template structure used
+ to manage objects with associated record state and
+ slot index. Supports tracking of CLEAN, NEW_RECORD,
+ and MODIFIED states for persistence and synchronization.
+Author: Trenser
+Created: 10-June-2026
+*/
+
+#pragma once
+#include "RecordState.h"
+
+static const size_t INVALID_SLOT = static_cast(-1);
+
+template
+struct TrackedRecord
+{
+ T* data;
+ RecordState state;
+ size_t slotIndex;
+ TrackedRecord()
+ : data(nullptr),
+ state(RecordState::CLEAN),
+ slotIndex(INVALID_SLOT) {}
+ TrackedRecord(
+ T* object,
+ RecordState recordState,
+ size_t slot)
+ : data(object),
+ state(recordState),
+ slotIndex(slot) {}
+};
\ 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 3419f44..06d4dda 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp
@@ -9,6 +9,197 @@ Date: 19-May-2026
*/
#include "DataStore.h"
+#include "Config.h"
+#include "SerializedRecords.h"
+#include "FileHelper.h"
+#include "ServiceBooking.h"
+#include "JobCard.h"
+#include "Invoice.h"
+
+/*
+Function: DataStore
+Description: Constructs the DataStore singleton and initializes
+ internal handles to their default values.
+Parameters:
+ - None
+Returns:
+ - None
+*/
+DataStore::DataStore() :
+ m_globalMutex(NULL) {}
+
+/*
+Function: ~DataStore
+Description: Destroys the DataStore singleton and releases all
+ cached application objects owned by the datastore.
+ This includes users, notifications, services,
+ combo packages, inventory items, service bookings,
+ job cards, and invoices.
+Parameters:
+ - None
+Returns:
+ - None
+*/
+DataStore::~DataStore()
+{
+ clearCache(m_userCache);
+ clearCache(m_notificationCache);
+ clearCache(m_serviceCache);
+ clearCache(m_comboPackageCache);
+ clearCache(m_inventoryItemCache);
+ clearCache(m_serviceBookingCache);
+ clearCache(m_jobCardCache);
+ clearCache(m_invoiceCache);
+}
+
+/*
+Function: initialize
+Description: Initializes the shared-memory datastore.
+ Creates or opens the global datastore mutex,
+ configures all mapping metadata, and creates
+ or opens the file mappings used to persist
+ application data. After successful completion,
+ all datastore files are mapped into memory and
+ ready for use by the application.
+Parameter: None
+Return type: bool
+ - true : Initialization completed successfully.
+ - false : Failed to create the mutex or open
+ one or more file mappings.
+*/
+bool DataStore::initialize()
+{
+ m_globalMutex = CreateMutexA(NULL, FALSE, "VehicleServiceSystemMutex");
+ if (m_globalMutex == NULL)
+ {
+ return false;
+ }
+ if (!lockDataStore())
+ {
+ CloseHandle(m_globalMutex);
+ m_globalMutex = NULL;
+ return false;
+ }
+ bool success = true;
+ do
+ {
+ util::ensureDirectoryExists(config::file::DIRECTORY);
+ m_users.fileName = config::file::USER_FILE;
+ m_users.recordSize = sizeof(SerializedUser);
+ m_notifications.fileName = config::file::NOTIFICATION_FILE;
+ m_notifications.recordSize = sizeof(SerializedNotification);
+ m_services.fileName = config::file::SERVICE_FILE;
+ m_services.recordSize = sizeof(SerializedService);
+ m_comboPackages.fileName = config::file::COMBOPACKAGE_FILE;
+ m_comboPackages.recordSize = sizeof(SerializedComboPackage);
+ m_inventoryItems.fileName = config::file::INVENTORYITEM_FILE;
+ m_inventoryItems.recordSize = sizeof(SerializedInventoryItem);
+ m_serviceBookings.fileName = config::file::SERVICEBOOKING_FILE;
+ m_serviceBookings.recordSize = sizeof(SerializedServiceBooking);
+ m_jobCards.fileName = config::file::JOBCARD_FILE;
+ m_jobCards.recordSize = sizeof(SerializedJobCard);
+ m_invoices.fileName = config::file::INVOICE_FILE;
+ m_invoices.recordSize = sizeof(SerializedInvoice);
+ m_serviceManagementObservers.fileName = config::file::SERVICEMANAGEMENTOBSERVERS;
+ m_serviceManagementObservers.recordSize = sizeof(SerializedObserver);
+ m_paymentManagementObservers.fileName = config::file::PAYMENTMANAGEMENTOBSERVERS;
+ m_paymentManagementObservers.recordSize = sizeof(SerializedObserver);
+ m_inventoryManagementObservers.fileName = config::file::INVENTORYMANAGEMENTOBSERVERS;
+ m_inventoryManagementObservers.recordSize = sizeof(SerializedObserver);
+ if (!SharedMemory::createOrOpenMapping(m_users))
+ {
+ success = false;
+ break;
+ }
+ if (!SharedMemory::createOrOpenMapping(m_notifications))
+ {
+ success = false;
+ break;
+ }
+ if (!SharedMemory::createOrOpenMapping(m_services))
+ {
+ success = false;
+ break;
+ }
+
+ if (!SharedMemory::createOrOpenMapping(m_comboPackages))
+ {
+ success = false;
+ break;
+ }
+ if (!SharedMemory::createOrOpenMapping(m_inventoryItems))
+ {
+ success = false;
+ break;
+ }
+ if (!SharedMemory::createOrOpenMapping(m_serviceBookings))
+ {
+ success = false;
+ break;
+ }
+ if (!SharedMemory::createOrOpenMapping(m_jobCards))
+ {
+ success = false;
+ break;
+ }
+ if (!SharedMemory::createOrOpenMapping(m_invoices))
+ {
+ success = false;
+ break;
+ }
+ if (!SharedMemory::createOrOpenMapping(m_serviceManagementObservers))
+ {
+ success = false;
+ break;
+ }
+ if (!SharedMemory::createOrOpenMapping(m_paymentManagementObservers))
+ {
+ success = false;
+ break;
+ }
+ if (!SharedMemory::createOrOpenMapping(m_inventoryManagementObservers))
+ {
+ success = false;
+ break;
+ }
+ } while (false);
+ unlockDataStore();
+ if (!success)
+ {
+ shutdown();
+ }
+ return success;
+}
+
+/*
+Function: shutdown
+Description: Releases all shared-memory resources owned by the
+ datastore. Closes every file mapping, unmaps all
+ mapped views, and releases the datastore mutex.
+ After this call, the datastore must be initialized
+ again before use.
+Parameter: None
+Return type: void
+*/
+void DataStore::shutdown()
+{
+ SharedMemory::closeMapping(m_users);
+ SharedMemory::closeMapping(m_notifications);
+ SharedMemory::closeMapping(m_services);
+ SharedMemory::closeMapping(m_comboPackages);
+ SharedMemory::closeMapping(m_inventoryItems);
+ SharedMemory::closeMapping(m_serviceBookings);
+ SharedMemory::closeMapping(m_jobCards);
+ SharedMemory::closeMapping(m_invoices);
+ SharedMemory::closeMapping(m_serviceManagementObservers);
+ SharedMemory::closeMapping(m_paymentManagementObservers);
+ SharedMemory::closeMapping(m_inventoryManagementObservers);
+ if (m_globalMutex != NULL)
+ {
+ CloseHandle(m_globalMutex);
+ m_globalMutex = NULL;
+ }
+}
/*
Function: getInstance
@@ -26,104 +217,567 @@ DataStore& DataStore::getInstance()
/*
Function: getUsers
-Description: Retrieves the internal map of users.
+Description: Retrieves all user records from the datastore.
Parameters:
- None
Returns:
- - Reference to util::Map containing all users.
+ - util::Map>: Collection of user records
*/
-util::Map& DataStore::getUsers()
+util::Map>& DataStore::getUsers()
{
- return m_users;
+ auto users = loadRecords(m_users);
+ refreshCache(m_userCache, users);
+ return m_userCache;
+}
+
+/*
+Function: getNotifications
+Description: Retrieves all notification records from the datastore.
+Parameters:
+ - None
+Returns:
+ - util::Map>: Collection of notification records
+*/
+util::Map>& DataStore::getNotifications()
+{
+ auto notifications = loadRecords(m_notifications);
+ refreshCache(m_notificationCache, notifications);
+ return m_notificationCache;
}
/*
Function: getServices
-Description: Retrieves the internal map of services.
+Description: Retrieves all service records from the datastore.
Parameters:
- None
Returns:
- - Reference to util::Map containing all services.
+ - util::Map>: Collection of service records
*/
-util::Map& DataStore::getServices()
+util::Map>& DataStore::getServices()
{
- return m_services;
+ 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;
}
/*
Function: getComboPackages
-Description: Retrieves the internal map of combo packages.
+Description: Retrieves all combo package records from the datastore.
Parameters:
- None
Returns:
- - Reference to util::Map containing all combo packages.
+ - util::Map>: Collection of combo package records
*/
-util::Map& DataStore::getComboPackages()
+util::Map>& DataStore::getComboPackages()
{
- return m_comboPackages;
-}
-
-/*
-Function: getServiceBookings
-Description: Retrieves the internal map of service bookings.
-Parameters:
- - None
-Returns:
- - Reference to util::Map containing all service bookings.
-*/
-util::Map& DataStore::getServiceBookings()
-{
- return m_serviceBookings;
-}
-
-/*
-Function: getJobCards
-Description: Retrieves the internal map of job cards.
-Parameters:
- - None
-Returns:
- - Reference to util::Map containing all job cards.
-*/
-util::Map& DataStore::getJobCards()
-{
- return m_jobCards;
+ 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;
}
/*
Function: getInventoryItems
-Description: Retrieves the internal map of inventory items.
+Description: Retrieves all inventory item records from the datastore.
Parameters:
- None
Returns:
- - Reference to util::Map containing all inventory items.
+ - util::Map>: Collection of inventory item records
*/
-util::Map& DataStore::getInventoryItems()
+util::Map>& DataStore::getInventoryItems()
{
- return m_inventoryItems;
+ auto inventoryItems = loadRecords(m_inventoryItems);
+ refreshCache(m_inventoryItemCache, inventoryItems);
+ return m_inventoryItemCache;
}
+/*
+Function: getServiceBookings
+Description: Retrieves all service booking records from the datastore.
+Parameters:
+ - None
+Returns:
+ - util::Map>: Collection of service booking records
+*/
+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;
+}
+
+/*
+Function: getJobCards
+Description: Retrieves all job card records from the datastore.
+Parameters:
+ - None
+Returns:
+ - util::Map>: Collection of job card records
+*/
+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 the internal map of invoices.
+Description: Retrieves all invoice records from the datastore.
Parameters:
- None
Returns:
- - Reference to util::Map containing all invoices.
+ - util::Map>: Collection of invoice records
*/
-util::Map& DataStore::getInvoices()
+util::Map>& DataStore::getInvoices()
{
- return m_invoices;
+ auto& serviceBookings = getServiceBookings();
+ auto& inventoryItems = getInventoryItems();
+ util::Map> invoices = loadRecords(m_invoices);
+ refreshCache(m_invoiceCache, invoices);
+ for (int iterator = 0; iterator < m_invoiceCache.getSize(); iterator++)
+ {
+ auto& trackedInvoice = m_invoiceCache.getValueAt(iterator);
+ Invoice* invoice = trackedInvoice.data;
+ if (!invoice)
+ {
+ continue;
+ }
+ const std::string& currentBookingId = invoice->getBookingId();
+ int currentBookingIndex = serviceBookings.find(currentBookingId);
+ if (currentBookingIndex == -1)
+ {
+ throw std::runtime_error("Invalid Service Booking Index.");
+ }
+ ServiceBooking* currentBooking = serviceBookings.getValueAt(currentBookingIndex).data;
+ auto& currentInventoryItemIds = invoice->getPartIDs();
+ util::Map currentInventoryItems;
+ for (int iterator = 0; iterator < currentInventoryItemIds.getSize(); iterator++)
+ {
+ const std::string& currentItemId = currentInventoryItemIds[iterator];
+ int currentItemIndex = inventoryItems.find(currentItemId);
+ if (currentItemIndex == -1)
+ {
+ throw std::runtime_error("Invalid Inventory item id.");
+ }
+ InventoryItem* currentItem = inventoryItems.getValueAt(currentItemIndex).data;
+ if (!currentItem)
+ {
+ continue;
+ }
+ currentInventoryItems[currentItemId] = currentItem;
+ }
+ invoice->setBooking(currentBooking);
+ invoice->setParts(currentInventoryItems);
+ }
+ return m_invoiceCache;
}
/*
-Function: getPayments
-Description: Retrieves the internal map of payments.
+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.
Parameters:
- None
Returns:
- - Reference to util::Map containing all payments.
+ - util::Map: Collection of observer records
*/
-util::Map& DataStore::getPayments()
+util::Map DataStore::getServiceManagementObservers()
{
- return m_payments;
+ return getObservers(m_serviceManagementObservers);
+}
+
+/*
+Function: getPaymentManagementObservers
+Description: Retrieves all payment management observer records from the datastore.
+Parameters:
+ - None
+Returns:
+ - util::Map: Collection of observer records
+*/
+util::Map DataStore::getPaymentManagementObservers()
+{
+ return getObservers(m_paymentManagementObservers);
+}
+
+/*
+Function: getInventoryManagementObservers
+Description: Retrieves all inventory management observer records from the datastore.
+Parameters:
+ - None
+Returns:
+ - util::Map: Collection of observer records
+*/
+util::Map DataStore::getInventoryManagementObservers()
+{
+ return getObservers(m_inventoryManagementObservers);
+}
+
+/*
+Function: saveUsers
+Description: Persists all user records to the datastore.
+Parameters:
+ - None
+Returns:
+ - None
+*/
+void DataStore::saveUsers()
+{
+ saveRecords(m_users, m_userCache);
+}
+
+/*
+Function: saveNotifications
+Description: Persists all notification records to the datastore.
+Parameters:
+ - None
+Returns:
+ - None
+*/
+void DataStore::saveNotifications()
+{
+ saveRecords(m_notifications, m_notificationCache);
+}
+
+/*
+Function: saveServices
+Description: Persists all service records to the datastore.
+Parameters:
+ - None
+Returns:
+ - None
+*/
+void DataStore::saveServices()
+{
+ saveRecords(m_services, m_serviceCache);
+}
+
+/*
+Function: saveComboPackages
+Description: Persists all combo package records to the datastore.
+Parameters:
+ - None
+Returns:
+ - None
+*/
+void DataStore::saveComboPackages()
+{
+ saveRecords(m_comboPackages, m_comboPackageCache);
+}
+
+/*
+Function: saveInventoryItems
+Description: Persists all inventory item records to the datastore.
+Parameters:
+ - None
+Returns:
+ - None
+*/
+void DataStore::saveInventoryItems()
+{
+ saveRecords(m_inventoryItems, m_inventoryItemCache);
+}
+
+/*
+Function: saveServiceBookings
+Description: Persists all service booking records to the datastore.
+Parameters:
+ - None
+Returns:
+ - None
+*/
+void DataStore::saveServiceBookings()
+{
+ saveRecords(m_serviceBookings, m_serviceBookingCache);
+}
+
+/*
+Function: saveJobCards
+Description: Persists all job card records to the datastore.
+Parameters:
+ - None
+Returns:
+ - None
+*/
+void DataStore::saveJobCards()
+{
+ saveRecords(m_jobCards, m_jobCardCache);
+}
+
+/*
+Function: saveInvoices
+Description: Persists all invoice records to the datastore.
+Parameters:
+ - None
+Returns:
+ - None
+*/
+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
+Returns:
+ - None
+*/
+void DataStore::saveServiceManagementObservers(util::Map& observers)
+{
+ saveObservers(m_serviceManagementObservers, observers);
+}
+
+/*
+Function: savePaymentManagementObservers
+Description: Persists all payment management observer records to the datastore.
+Parameters:
+ - observers: util::Map&, collection of observer records
+Returns:
+ - None
+*/
+void DataStore::savePaymentManagementObservers(util::Map& observers)
+{
+ saveObservers(m_paymentManagementObservers, observers);
+}
+
+/*
+Function: saveInventoryManagementObservers
+Description: Persists all inventory management observer records to the datastore.
+Parameters:
+ - observers: util::Map&, collection of observer records
+Returns:
+ - None
+*/
+void DataStore::saveInventoryManagementObservers(util::Map& observers)
+{
+ saveObservers(m_inventoryManagementObservers, observers);
+}
+
+/*
+Function: lockDataStore
+Description: Acquires the datastore mutex, providing
+ exclusive access to the shared-memory
+ datastore. This function blocks until
+ the mutex becomes available or an error
+ occurs.
+Parameter: None
+Return type:
+ bool
+ - true : Mutex successfully acquired.
+ - false : Failed to acquire the mutex.
+*/
+bool DataStore::lockDataStore()
+{
+ if (m_globalMutex == NULL)
+ {
+ return false;
+ }
+ DWORD result = WaitForSingleObject(m_globalMutex, INFINITE);
+ return result == WAIT_OBJECT_0;
+}
+
+/*
+Function: unlockDataStore
+Description: Releases the datastore mutex after a
+ successful call to lockDataStore(),
+ allowing other processes to access the
+ shared-memory datastore.
+Parameter: None
+Return type:
+ bool
+ - true : Mutex successfully released.
+ - false : Failed to release the mutex.
+*/
+bool DataStore::unlockDataStore()
+{
+ if (m_globalMutex == NULL)
+ {
+ return false;
+ }
+ return ReleaseMutex(m_globalMutex) != 0;
}
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h
index cde9b4e..03eb0eb 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h
@@ -6,42 +6,248 @@ Date: 19-May-2026
*/
#pragma once
+#include
#include
#include "Map.h"
-
-class User;
-class Service;
-class ComboPackage;
-class ServiceBooking;
-class JobCard;
-class InventoryItem;
-class Invoice;
-class Payment;
+#include "MappingInfo.h"
+#include "TrackedRecord.h"
+#include "SerializedRecords.h"
+#include "SharedMemory.h"
+#include "User.h"
+#include "Notification.h"
+#include "Service.h"
+#include "ComboPackage.h"
+#include "InventoryItem.h"
+#include "ServiceBooking.h"
+#include "JobCard.h"
+#include "Invoice.h"
class DataStore
{
private:
- util::Map m_users;
- util::Map m_services;
- util::Map m_comboPackages;
- util::Map m_serviceBookings;
- util::Map m_jobCards;
- util::Map m_inventoryItems;
- util::Map m_invoices;
- util::Map m_payments;
- DataStore() {}
-public:
- static DataStore& getInstance();
+ DataStore();
+ ~DataStore();
DataStore(const DataStore&) = delete;
DataStore& operator=(const DataStore&) = delete;
DataStore(DataStore&&) = delete;
DataStore& operator=(DataStore&&) = delete;
- util::Map& getUsers();
- util::Map& getServices();
- util::Map& getComboPackages();
- util::Map& getServiceBookings();
- util::Map& getJobCards();
- util::Map& getInventoryItems();
- util::Map& getInvoices();
- util::Map& getPayments();
-};
\ No newline at end of file
+ HANDLE m_globalMutex;
+ MappingInfo m_users;
+ MappingInfo m_notifications;
+ MappingInfo m_services;
+ MappingInfo m_comboPackages;
+ MappingInfo m_inventoryItems;
+ MappingInfo m_serviceBookings;
+ MappingInfo m_jobCards;
+ MappingInfo m_invoices;
+ MappingInfo m_serviceManagementObservers;
+ MappingInfo m_paymentManagementObservers;
+ MappingInfo m_inventoryManagementObservers;
+ util::Map> m_userCache;
+ util::Map> m_notificationCache;
+ util::Map> m_serviceCache;
+ util::Map> m_comboPackageCache;
+ util::Map> m_inventoryItemCache;
+ util::Map> m_serviceBookingCache;
+ util::Map> m_jobCardCache;
+ util::Map> m_invoiceCache;
+public:
+ static DataStore& getInstance();
+ bool initialize();
+ void shutdown();
+ util::Map>& getUsers();
+ util::Map>& getNotifications();
+ util::Map>& getServices();
+ util::Map>& getComboPackages();
+ util::Map>& getInventoryItems();
+ util::Map>& getServiceBookings();
+ util::Map>& getJobCards();
+ util::Map>& getInvoices();
+ util::Map getServiceManagementObservers();
+ util::Map getPaymentManagementObservers();
+ util::Map getInventoryManagementObservers();
+ void saveUsers();
+ void saveNotifications();
+ void saveServices();
+ void saveComboPackages();
+ void saveInventoryItems();
+ void saveServiceBookings();
+ void saveJobCards();
+ void saveInvoices();
+ void saveServiceManagementObservers(util::Map& observers);
+ void savePaymentManagementObservers(util::Map& observers);
+ void saveInventoryManagementObservers(util::Map& observers);
+ bool lockDataStore();
+ bool unlockDataStore();
+private:
+ template
+ util::Map> loadRecords(MappingInfo& mapping);
+ template
+ 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);
+};
+
+/*
+Function: loadRecords
+Description: Loads all serialized records from the specified
+ shared-memory mapping, deserializes them into
+ application objects, and returns them as a map
+ of tracked records. Each loaded record is marked
+ as CLEAN and assigned its corresponding slot index
+ within the mapping so that future modifications
+ can be written back efficiently.
+Parameter:
+ - mapping: Reference to the mapping containing the
+ serialized records.
+Return type:
+ util::Map>
+ A map containing all loaded records keyed by
+ their unique identifier.
+*/
+template
+util::Map> DataStore::loadRecords(MappingInfo& mapping)
+{
+ util::Map> records;
+ SharedMemory::ensureLatestMapping(mapping);
+ size_t recordCount = SharedMemory::getRecordCount(mapping);
+ for (size_t index = 0; index < recordCount; ++index)
+ {
+ TSerialized* serialized = static_cast(SharedMemory::getRecordAddress(mapping,index));
+ TObject* object = TObject::deserialize(*serialized);
+ TrackedRecord trackedRecord;
+ trackedRecord.data = object;
+ trackedRecord.state = RecordState::CLEAN;
+ trackedRecord.slotIndex = index;
+ records.insert(object->getId(), trackedRecord);
+ }
+ return records;
+}
+
+/*
+Function: saveRecords
+Description: Persists all modified and newly added records
+ contained in the provided map to the specified
+ shared-memory mapping. Modified records overwrite
+ their existing slots, while new records are
+ appended to the end of the mapping. Records marked
+ as CLEAN are ignored.
+Parameter:
+ - mapping: Reference to the mapping where records are
+ stored.
+ - records: Map containing the records to be persisted.
+Return type: void
+*/
+template void DataStore::saveRecords(MappingInfo& mapping, util::Map>& records)
+{
+ SharedMemory::ensureLatestMapping(mapping);
+ for (int index = 0; index < records.getSize(); ++index)
+ {
+ TrackedRecord& record = records.getValueAt(index);
+ if (record.state == RecordState::CLEAN)
+ {
+ continue;
+ }
+ TSerialized serialized = record.data->serialize();
+ if (record.state == RecordState::MODIFIED)
+ {
+ TSerialized* destination = static_cast(SharedMemory::getRecordAddress(mapping, record.slotIndex));
+ if (destination)
+ {
+ *destination = serialized;
+ }
+ }
+ else if (record.state == RecordState::NEW_RECORD)
+ {
+ if (!SharedMemory::ensureCapacityForInsert(mapping))
+ {
+ continue;
+ }
+ size_t recordCount = SharedMemory::getRecordCount(mapping);
+ TSerialized* destination = static_cast(SharedMemory::getRecordAddress(mapping,recordCount));
+ *destination = serialized;
+ SharedMemory::setRecordCount(mapping, recordCount + 1);
+ record.slotIndex = recordCount;
+ }
+ record.state = RecordState::CLEAN;
+ }
+}
+
+/*
+Function: clearCache
+Description: Releases all objects owned by the cache and
+ clears the cache contents.
+Parameters:
+ - cache: Cache to be cleared.
+Returns:
+ - None
+*/
+template
+void DataStore::clearCache(util::Map>&cache)
+{
+ for (int index = 0; index < cache.getSize(); ++index)
+ {
+ delete cache.getValueAt(index).data;
+ cache.getValueAt(index).data = nullptr;
+ }
+ cache.clear();
+}
+
+/*
+Function: refreshCache
+Description: Refreshes the cache while preserving object addresses
+ for records that already exist. Existing objects are
+ updated in-place so that pointers held elsewhere remain
+ valid after the refresh.
+Parameters:
+ - cache: Existing cache to refresh.
+ - refreshedCache: Newly loaded cache contents.
+Returns:
+ - None
+*/
+template
+void DataStore::refreshCache(util::Map>& cache, util::Map>& refreshedCache)
+{
+ util::Map> oldCache = cache;
+ cache.clear();
+ for (int index = 0; index < refreshedCache.getSize(); ++index)
+ {
+ const std::string& id = refreshedCache.getKeyAt(index);
+ TrackedRecord& refreshedRecord = refreshedCache.getValueAt(index);
+ int oldIndex = oldCache.find(id);
+ if (oldIndex != -1)
+ {
+ TrackedRecord& oldRecord = oldCache.getValueAt(oldIndex);
+ if (oldRecord.state == RecordState::MODIFIED)
+ {
+ delete refreshedRecord.data;
+ cache.insert(id, oldRecord);
+ continue;
+ }
+ *oldRecord.data = *refreshedRecord.data;
+ oldRecord.slotIndex = refreshedRecord.slotIndex;
+ oldRecord.state = refreshedRecord.state;
+ delete refreshedRecord.data;
+ refreshedRecord.data = oldRecord.data;
+ }
+ cache.insert(id, refreshedRecord);
+ }
+ 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)
+ {
+ 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/DataStoreLockGuard.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStoreLockGuard.h
new file mode 100644
index 0000000..2e04eb0
--- /dev/null
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStoreLockGuard.h
@@ -0,0 +1,28 @@
+/*
+File: DataStoreLockGuard.h
+Description: Defines the DataStoreLockGuard class used to manage DataStore
+ locking and unlocking automatically within a scope.
+Author: Trenser
+Date: 12-June-2026
+*/
+
+#pragma once
+#include "DataStore.h"
+
+class DataStoreLockGuard
+{
+public:
+ explicit DataStoreLockGuard(DataStore& dataStore)
+ : m_dataStore(dataStore)
+ {
+ m_dataStore.lockDataStore();
+ }
+ ~DataStoreLockGuard()
+ {
+ m_dataStore.unlockDataStore();
+ }
+ DataStoreLockGuard(const DataStoreLockGuard&) = delete;
+ DataStoreLockGuard& operator=(const DataStoreLockGuard&) = delete;
+private:
+ DataStore& m_dataStore;
+};
\ No newline at end of file
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/Invoice.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.cpp
index f24a013..7788b84 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.cpp
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.cpp
@@ -9,6 +9,7 @@ Date: 19-May-2026
#include
#include
+#include "SerializedRecords.h"
#include "Invoice.h"
#include "Factory.h"
#include "InventoryItem.h"
@@ -34,7 +35,8 @@ Invoice::Invoice()
m_discountPercentage(0.0),
m_totalAmount(0.0),
m_paymentMethod(util::PaymentMode()),
- m_status(util::PaymentStatus()) {}
+ m_status(util::PaymentStatus()) {
+}
/*
Function: Invoice
@@ -57,16 +59,16 @@ Returns:
Invoice::Invoice(
const std::string& bookingId,
ServiceBooking* booking,
- const util::Timestamp& invoiceDate,
- double laborCost,
+ const util::Timestamp& invoiceDate,
+ double laborCost,
const util::Map& parts,
double partsCost,
- double discountPercentage,
- double totalAmount,
- const util::Timestamp& paymentDate,
- util::PaymentMode paymentMethod,
+ double discountPercentage,
+ double totalAmount,
+ const util::Timestamp& paymentDate,
+ util::PaymentMode paymentMethod,
util::PaymentStatus status
- )
+)
: m_id("INV" + std::to_string(++m_uid)),
m_bookingId(bookingId),
m_booking(booking),
@@ -78,7 +80,7 @@ Invoice::Invoice(
m_totalAmount(totalAmount),
m_paymentDate(paymentDate),
m_paymentMethod(paymentMethod),
- m_status(status)
+ m_status(status)
{
int numberOfParts = m_parts.getSize();
auto partPointers = m_parts.getValues();
@@ -473,100 +475,50 @@ static util::Vector getPartIDsAsVector(const std::string& partIDsSt
/*
Function: serialize
-Description: Serializes the invoice into a CSV-formatted string.
+Description: Serializes the Invoice object into a SerializedInvoice record.
Parameters:
- None
Returns:
- - std::string: Serialized invoice record
+ - SerializedInvoice: Serialized representation of the invoice
*/
-std::string Invoice::serialize() const
+SerializedInvoice Invoice::serialize() const
{
- std::ostringstream serializedInvoice;
- serializedInvoice << m_id << ','
- << m_bookingId << ','
- << m_invoiceDate.toString() << ','
- << m_laborCost << ','
- << getPartIDsAsString(m_partIDs) << ','
- << m_partsCost << ','
- << m_discountPercentage << ','
- << m_totalAmount << ','
- << m_paymentDate.toString() << ','
- << util::getPaymentModeString(m_paymentMethod) << ','
- << util::getPaymentStatusString(m_status);
- return serializedInvoice.str();
+ SerializedInvoice 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.partIDs, sizeof(serialized.partIDs), getPartIDsAsString(m_partIDs).c_str());
+ serialized.invoiceDate = m_invoiceDate;
+ serialized.laborCost = m_laborCost;
+ serialized.partsCost = m_partsCost;
+ serialized.discountPercentage = m_discountPercentage;
+ serialized.totalAmount = m_totalAmount;
+ serialized.paymentDate = m_paymentDate;
+ serialized.paymentMethod = m_paymentMethod;
+ serialized.status = m_status;
+ return serialized;
}
/*
Function: deserialize
-Description: Deserializes a CSV-formatted string into an Invoice object.
+Description: Deserializes a SerializedInvoice record into an Invoice object.
Parameters:
- - record: const std::string&, serialized invoice record
+ - serializedInvoice: const SerializedInvoice&, serialized invoice record
Returns:
- Invoice*: Pointer to the deserialized Invoice object
-Throws:
- - std::runtime_error if data is invalid
*/
-Invoice* Invoice::deserialize(const std::string& record)
+Invoice* Invoice::deserialize(const SerializedInvoice& serializedInvoice)
{
- std::string id, bookingId;
- std::string invoiceDateString, laborCostString, partIDsString;
- std::string partsCostString, discountPercentageString, totalAmountString;
- std::string paymentDateString, paymentMethodString, statusString;
- double laborCost, partsCost, discountPercentage, totalAmount;
- std::istringstream serializedInvoice(record);
- getline(serializedInvoice, id, ',');
- getline(serializedInvoice, bookingId, ',');
- getline(serializedInvoice, invoiceDateString, ',');
- getline(serializedInvoice, laborCostString, ',');
- getline(serializedInvoice, partIDsString, ',');
- getline(serializedInvoice, partsCostString, ',');
- getline(serializedInvoice, discountPercentageString, ',');
- getline(serializedInvoice, totalAmountString, ',');
- getline(serializedInvoice, paymentDateString, ',');
- getline(serializedInvoice, paymentMethodString, ',');
- getline(serializedInvoice, statusString, ',');
- util::Timestamp invoiceDate;
- util::Timestamp paymentDate;
- try
- {
- invoiceDate = util::Timestamp::fromString(invoiceDateString);
- paymentDate = util::Timestamp::fromString(paymentDateString);
- laborCost = std::stod(laborCostString);
- partsCost = std::stod(partsCostString);
- discountPercentage = std::stod(discountPercentageString);
- totalAmount = std::stod(totalAmountString);
- }
- catch (...)
- {
- throw std::runtime_error("Invalid invoice data");
- }
- util::Vector partIDs = getPartIDsAsVector(partIDsString);
- util::PaymentMode paymentMethod = util::getPaymentMode(paymentMethodString);
- util::PaymentStatus status = util::getPaymentStatus(statusString);
+ util::Vector partIDs = getPartIDsAsVector(serializedInvoice.partIDs);
return Factory::getObject(
- id,
- bookingId,
- invoiceDate,
+ serializedInvoice.id,
+ serializedInvoice.bookingId,
+ serializedInvoice.invoiceDate,
partIDs,
- laborCost,
- partsCost,
- discountPercentage,
- totalAmount,
- paymentDate,
- paymentMethod,
- status
- );
-}
-
-/*
-Function: getHeaders
-Description: Retrieves the CSV headers for invoice serialization.
-Parameters:
- - None
-Returns:
- - std::string: Header string ("ID,BookingID,InvoiceDate,LaborCost,PartIDs,PartsCost,DiscountPercentage,TotalAmount,PaymentDate,PaymentMethod,Status")
-*/
-std::string Invoice::getHeaders()
-{
- return "ID,BookingID,InvoiceDate,LaborCost,PartIDs,PartsCost,DiscountPercentage,TotalAmount,PaymentDate,PaymentMethod,Status";
+ serializedInvoice.laborCost,
+ serializedInvoice.partsCost,
+ serializedInvoice.discountPercentage,
+ serializedInvoice.totalAmount,
+ serializedInvoice.paymentDate,
+ serializedInvoice.paymentMethod,
+ serializedInvoice.status);
}
\ No newline at end of file
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.h
index 3374de9..11343e7 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.h
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.h
@@ -6,7 +6,6 @@ Author: Trenser
Date: 19-May-2026
*/
-
#pragma once
#include
#include "Map.h"
@@ -16,6 +15,7 @@ Date: 19-May-2026
class ServiceBooking;
class InventoryItem;
+struct SerializedInvoice;
class Invoice
{
@@ -39,14 +39,14 @@ public:
Invoice(
const std::string& bookingId,
ServiceBooking* booking,
- const util::Timestamp& invoiceDate,
- double laborCost,
- const util::Map& parts,
+ const util::Timestamp& invoiceDate,
+ double laborCost,
+ const util::Map& parts,
double partsCost,
- double discountPercentage,
- double totalAmount,
- const util::Timestamp& paymentDate,
- util::PaymentMode paymentMethod,
+ double discountPercentage,
+ double totalAmount,
+ const util::Timestamp& paymentDate,
+ util::PaymentMode paymentMethod,
util::PaymentStatus status
);
Invoice(
@@ -87,7 +87,6 @@ public:
void setPaymentDate(const util::Timestamp& paymentDate);
void setPaymentMethod(util::PaymentMode paymentMethod);
void setStatus(util::PaymentStatus status);
- std::string serialize() const;
- static Invoice* deserialize(const std::string&);
- static std::string getHeaders();
+ SerializedInvoice serialize() const;
+ static Invoice* deserialize(const SerializedInvoice&);
};
\ 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..dd80cd9 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.cpp
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.cpp
@@ -10,8 +10,32 @@ Date:19-May-2026
#include
#include "AuthenticationManagementService.h"
#include "User.h"
+#include "Utility.h"
+#include "DataStoreLockGuard.h"
User* AuthenticationManagementService::m_authenticatedUser = nullptr;
+bool AuthenticationManagementService::m_isAuthorized = false;
+EventManager AuthenticationManagementService::m_eventManager;
+HANDLE AuthenticationManagementService::m_accountDisabledEvent = NULL;
+HANDLE AuthenticationManagementService::m_notificationsAvailableEvent = NULL;
+
+
+/*
+Function: ensureAuthorization
+Description: Verifies that a user is currently authenticated before allowing
+ access to a protected operation. Throws an exception if no
+ authorized user session exists.
+Parameter: None
+Return type: void
+Throws: std::runtime_error - if the user is not authorized
+*/
+void AuthenticationManagementService::ensureAuthorization()
+{
+ if (!m_authenticatedUser || !m_isAuthorized)
+ {
+ throw std::runtime_error("You are not authorized to do this operation!");
+ }
+}
/*
Function: login
@@ -24,16 +48,35 @@ 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())
{
m_authenticatedUser = user;
+ m_isAuthorized = true;
+ m_eventManager.initialize(
+ user->getId(),
+ []()
+ {
+ if (m_accountDisabledEvent)
+ {
+ AuthenticationManagementService::m_isAuthorized = false;
+ SetEvent(m_accountDisabledEvent);
+ }
+ },
+ []()
+ {
+ if (m_notificationsAvailableEvent)
+ {
+ SetEvent(m_notificationsAvailableEvent);
+ }
+ });
return true;
}
return false;
@@ -62,7 +105,11 @@ Return type: void
*/
void AuthenticationManagementService::logout()
{
+ m_eventManager.shutdown();
m_authenticatedUser = nullptr;
+ m_isAuthorized = false;
+ m_accountDisabledEvent = NULL;
+ m_notificationsAvailableEvent = NULL;
}
/*
@@ -74,9 +121,33 @@ Return type: void
*/
void AuthenticationManagementService::changePassword(const std::string& newPassword)
{
+ AuthenticationManagementService::ensureAuthorization();
+ 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();
+}
+
+/*
+Function: registerEvents
+Description: Registers menu event handles used to notify the active
+ menu of account disable and notification events.
+Parameter: HANDLE accountDisabledEvent - account disabled event handle
+ HANDLE notificationAvailableEvent - notification event handle
+Return type: void
+*/
+void AuthenticationManagementService::registerEvents(HANDLE accountDisabledEvent, HANDLE notificationAvailableEvent)
+{
+ m_accountDisabledEvent = accountDisabledEvent;
+ m_notificationsAvailableEvent = notificationAvailableEvent;
}
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.h
index 47266a1..e927187 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.h
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/AuthenticationManagementService.h
@@ -9,6 +9,8 @@ Date:19-May-2026
#pragma once
#include
+#include
+#include "EventManager.h"
#include "DataStore.h"
class User;
@@ -17,11 +19,17 @@ class AuthenticationManagementService
{
private:
static User* m_authenticatedUser;
+ static bool m_isAuthorized;
+ static EventManager m_eventManager;
+ static HANDLE m_accountDisabledEvent;
+ static HANDLE m_notificationsAvailableEvent;
DataStore& m_dataStore;
public:
AuthenticationManagementService() : m_dataStore(DataStore::getInstance()) {}
+ static void ensureAuthorization();
bool login(const std::string& username, const std::string& password);
void logout();
void changePassword(const std::string& newPassword);
User* getAuthenticatedUser();
+ void registerEvents(HANDLE accountDisabledEvent, HANDLE notificationAvailableEvent);
};
diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp
index d08d957..6152fd3 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp
@@ -12,14 +12,15 @@ Date: 22-May-2026
#include "Config.h"
#include "Enums.h"
#include "Factory.h"
-#include "FileManager.h"
#include "InventoryItem.h"
#include "InventoryManagementService.h"
+#include "AuthenticationManagementService.h"
#include "Timestamp.h"
#include "User.h"
#include "Utility.h"
#include "Vector.h"
-
+#include "DataStoreLockGuard.h"
+#include "EventManager.h"
util::Map InventoryManagementService::m_observers{};
@@ -58,18 +59,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 +84,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 +92,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 +103,12 @@ Return type: void
*/
void InventoryManagementService::addInventoryItem(const std::string& partName, int quantity, double price)
{
+ AuthenticationManagementService::ensureAuthorization();
+ 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 +120,23 @@ 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);
- }
- }
+ AuthenticationManagementService::ensureAuthorization();
+ 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 +147,11 @@ Return type: util::Map
*/
util::Map InventoryManagementService::getInventoryItems()
{
- return m_dataStore.getInventoryItems();
+ AuthenticationManagementService::ensureAuthorization();
+ DataStoreLockGuard lock(m_dataStore);
+ auto& trackedInventoryItemMap = m_dataStore.getInventoryItems();
+ auto inventoryMap = util::getObjects(trackedInventoryItemMap);
+ return inventoryMap;
}
/*
@@ -234,15 +162,22 @@ 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);
- }
- }
+ AuthenticationManagementService::ensureAuthorization();
+ 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 +188,20 @@ Return type: InventoryItem*
*/
InventoryItem* InventoryManagementService::getInventoryItem(const std::string& inventoryItemID)
{
- int index = m_dataStore.getInventoryItems().find(inventoryItemID);
- if (index != -1)
+ AuthenticationManagementService::ensureAuthorization();
+ 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 +214,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 +225,7 @@ void InventoryManagementService::attach(User* user)
m_observers[userID] = user;
}
}
+ m_dataStore.saveInventoryManagementObservers(m_observers);
}
/*
@@ -291,6 +238,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 +249,7 @@ void InventoryManagementService::detach(User* user)
m_observers.remove(userID);
}
}
+ m_dataStore.saveInventoryManagementObservers(m_observers);
}
/*
@@ -315,27 +266,28 @@ 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;
+ }
+ auto& trackedNotificationsMap = m_dataStore.getNotifications();
+ Notification* notification = Factory::getObject(
+ user->getId(),
+ title,
+ message,
+ util::Timestamp());
+ if (!notification)
+ {
+ throw std::runtime_error("Failed to create notification");
+ }
+ trackedNotificationsMap.insert(notification->getId(), util::createNewRecord(notification));
+ m_dataStore.saveNotifications();
+ EventManager::sendNotificationAvailableEvent(user->getId());
}
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 1fc1ff8..b09b9bf 100644
--- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp
+++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp
@@ -11,16 +11,19 @@ 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"
#include "PaymentManagementService.h"
+#include "AuthenticationManagementService.h"
+#include "DataStoreLockGuard.h"
#include "Service.h"
#include "ServiceBooking.h"
#include "Timestamp.h"
#include "User.h"
#include "Utility.h"
+#include "DataStoreLockGuard.h"
+#include "EventManager.h"
util::Map PaymentManagementService::m_observers{};
@@ -34,6 +37,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();
@@ -42,6 +48,7 @@ void PaymentManagementService::attach(User* user)
m_observers[userID] = user;
}
}
+ m_dataStore.savePaymentManagementObservers(m_observers);
}
/*
@@ -54,6 +61,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();
@@ -62,6 +72,7 @@ void PaymentManagementService::detach(User* user)
m_observers.remove(userID);
}
}
+ m_dataStore.savePaymentManagementObservers(m_observers);
}
/*
@@ -78,28 +89,29 @@ 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;
+ }
+ auto& trackedNotificationsMap = m_dataStore.getNotifications();
+ Notification* notification = Factory::getObject