diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj index 8627061..6a269f5 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)datastores\sharedmemory;%(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)datastores\sharedmemory;%(AdditionalIncludeDirectories) Console @@ -129,6 +129,7 @@ + @@ -156,6 +157,12 @@ + + + + + + diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters index 73b9291..7e74b19 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters @@ -64,6 +64,12 @@ {8057b93d-51a9-42df-b06e-01ce395f6308} + + {ec639004-44c6-4bd6-9963-077adde82b5f} + + + {7aa8722e-adfa-466e-8211-de63f3b7892b} + @@ -141,6 +147,9 @@ Source Files\Models + + Source Files\DataStores\SharedMemory + @@ -251,5 +260,23 @@ Header Files\Views + + Header Files\DataStores\SharedMemory + + + Header Files\DataStores\SharedMemory + + + Header Files\DataStores\SharedMemory + + + Header Files\DataStores\SharedMemory + + + Header Files\DataStores\SharedMemory + + + Header Files\DataStores\SharedMemory + \ 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..9bc1d86 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" diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp index 3419f44..feed084 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp @@ -9,6 +9,167 @@ Date: 19-May-2026 */ #include "DataStore.h" +#include "Config.h" +#include "SerializedRecords.h" +#include "FileHelper.h" + +DataStore::DataStore() : + m_globalMutex(NULL) {} + +/* +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_payments)) + { + 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_payments); + 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 +187,370 @@ 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; + return util::Map>(); +} + +/* +Function: getNotifications +Description: Retrieves all notification records from the datastore. +Parameters: + - None +Returns: + - util::Map>: Collection of notification records +*/ +util::Map> DataStore::getNotifications() +{ + return util::Map>(); } /* 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; + return util::Map>(); } /* 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; + return util::Map>(); } /* 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; + return util::Map>(); +} + +/* +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() +{ + return util::Map>(); +} + +/* +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() +{ + return util::Map>(); } /* 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; + return util::Map>(); } /* Function: getPayments -Description: Retrieves the internal map of payments. +Description: Retrieves all payment records from the datastore. Parameters: - None Returns: - - Reference to util::Map containing all payments. + - util::Map>: Collection of payment records */ -util::Map& DataStore::getPayments() +util::Map> DataStore::getPayments() { - return m_payments; + return util::Map>(); +} + +/* +Function: getServiceManagementObservers +Description: Retrieves all service management observer records from the datastore. +Parameters: + - None +Returns: + - util::Map>: Collection of observer records +*/ +util::Map> DataStore::getServiceManagementObservers() +{ + return util::Map>(); +} + +/* +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 util::Map>(); +} + +/* +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 util::Map>(); +} + +/* +Function: saveUsers +Description: Persists all user records to the datastore. +Parameters: + - users: util::Map>&, collection of user records +Returns: + - None +*/ +void DataStore::saveUsers(util::Map>& users) +{ +} + +/* +Function: saveNotifications +Description: Persists all notification records to the datastore. +Parameters: + - notifications: util::Map>&, collection of notification records +Returns: + - None +*/ +void DataStore::saveNotifications(util::Map>& notifications) +{ +} + +/* +Function: saveServices +Description: Persists all service records to the datastore. +Parameters: + - services: util::Map>&, collection of service records +Returns: + - None +*/ +void DataStore::saveServices(util::Map>& services) +{ +} + +/* +Function: saveComboPackages +Description: Persists all combo package records to the datastore. +Parameters: + - comboPackages: util::Map>&, collection of combo package records +Returns: + - None +*/ +void DataStore::saveComboPackages(util::Map>& comboPackages) +{ +} + +/* +Function: saveInventoryItems +Description: Persists all inventory item records to the datastore. +Parameters: + - inventoryItems: util::Map>&, collection of inventory item records +Returns: + - None +*/ +void DataStore::saveInventoryItems(util::Map>& inventoryItems) +{ +} + +/* +Function: saveServiceBookings +Description: Persists all service booking records to the datastore. +Parameters: + - bookings: util::Map>&, collection of service booking records +Returns: + - None +*/ +void DataStore::saveServiceBookings(util::Map>& bookings) +{ +} + +/* +Function: saveJobCards +Description: Persists all job card records to the datastore. +Parameters: + - jobCards: util::Map>&, collection of job card records +Returns: + - None +*/ +void DataStore::saveJobCards(util::Map>& jobCards) +{ +} + +/* +Function: saveInvoices +Description: Persists all invoice records to the datastore. +Parameters: + - invoices: util::Map>&, collection of invoice records +Returns: + - None +*/ +void DataStore::saveInvoices(util::Map>& invoices) +{ +} + +/* +Function: savePayments +Description: Persists all payment records to the datastore. +Parameters: + - payments: util::Map>&, collection of payment records +Returns: + - None +*/ +void DataStore::savePayments(util::Map>& payments) +{ +} + +/* +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) +{ +} + +/* +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) +{ +} + +/* +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) +{ +} + +/* +Function: lockDataStore +Description: Acquires exclusive access to the datastore. +Parameters: + - None +Returns: + - bool: True if the datastore was successfully locked, otherwise false +*/ +bool DataStore::lockDataStore() +{ + return false; +} + +/* +Function: unlockDataStore +Description: Releases exclusive access to the datastore. +Parameters: + - None +Returns: + - bool: True if the datastore was successfully unlocked, otherwise false +*/ +bool DataStore::unlockDataStore() +{ + return false; +} + +/* +Function: lockDataStore +Description: Acquires the datastore mutex, providing + 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..f1dcd2e 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h @@ -6,42 +6,166 @@ Date: 19-May-2026 */ #pragma once +#include #include #include "Map.h" - +#include "MappingInfo.h" +#include "TrackedRecord.h" +#include "SharedMemory.h" class User; +class Notification; class Service; class ComboPackage; +class InventoryItem; class ServiceBooking; class JobCard; -class InventoryItem; class Invoice; class Payment; 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(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_payments; + MappingInfo m_serviceManagementObservers; + MappingInfo m_paymentManagementObservers; + MappingInfo m_inventoryManagementObservers; +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> getPayments(); + util::Map> getServiceManagementObservers(); + util::Map> getPaymentManagementObservers(); + util::Map> getInventoryManagementObservers(); + void saveUsers(util::Map>& users); + void saveNotifications(util::Map>& notifications); + void saveServices(util::Map>& services); + void saveComboPackages(util::Map>& comboPackages); + void saveInventoryItems(util::Map>& inventoryItems); + void saveServiceBookings(util::Map>& bookings); + void saveJobCards(util::Map>& jobCards); + void saveInvoices(util::Map>& invoices); + void savePayments(util::Map>& payments); + 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); +}; + +/* +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. After persistence, all + temporary objects owned by the tracked records are + destroyed to release memory. +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); + } + } + for (int index = 0; index < records.getSize(); ++index) + { + delete records.getValueAt(index).data; + records.getValueAt(index).data = nullptr; + } +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/FileHeader.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/FileHeader.h new file mode 100644 index 0000000..929dbf4 --- /dev/null +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/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/datastores/sharedmemory/MappingInfo.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/MappingInfo.h new file mode 100644 index 0000000..ebd5123 --- /dev/null +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/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/datastores/sharedmemory/RecordState.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/RecordState.h new file mode 100644 index 0000000..95402fd --- /dev/null +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/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/datastores/sharedmemory/SerializedRecords.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/SerializedRecords.h new file mode 100644 index 0000000..2d18842 --- /dev/null +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/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/datastores/sharedmemory/SharedMemory.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/SharedMemory.cpp new file mode 100644 index 0000000..6a10c9f --- /dev/null +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/SharedMemory.cpp @@ -0,0 +1,385 @@ +/* +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 "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 * 2); +} + +/* +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/datastores/sharedmemory/SharedMemory.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/SharedMemory.h new file mode 100644 index 0000000..a288ab3 --- /dev/null +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/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/datastores/sharedmemory/TrackedRecord.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/sharedmemory/TrackedRecord.h new file mode 100644 index 0000000..5ff9ac9 --- /dev/null +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/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/models/ComboPackage.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.cpp index 4e69d9f..64c1e89 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" @@ -270,72 +271,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..4e29310 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; +class 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..981513d 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" @@ -206,73 +207,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..ddc3973 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" @@ -473,100 +474,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..3f2a727 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.h @@ -16,6 +16,7 @@ Date: 19-May-2026 class ServiceBooking; class InventoryItem; +struct SerializedInvoice; class Invoice { @@ -87,7 +88,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..ba3b9b3 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" @@ -351,79 +352,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..d981f8c 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 { @@ -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..0c5a007 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.cpp @@ -7,6 +7,7 @@ Date: 19-May-2026 */ #include +#include "SerializedRecords.h" #include "Notification.h" #include "StringHelper.h" #include "Factory.h" @@ -23,7 +24,7 @@ Returns: */ Notification::Notification() : m_id("NOT" + std::to_string(++m_uid)), - m_recipient(nullptr) {} + m_recipient(nullptr), m_state(util::State::ACTIVE) {} /* Function: Notification @@ -43,7 +44,8 @@ Notification::Notification(const std::string& recipientUserId, User* recipient, 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,14 @@ 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) @@ -219,69 +222,39 @@ void Notification::setCreatedAt(const util::Timestamp& createdAt) /* 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..48fe15f 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 { @@ -22,10 +24,11 @@ private: 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& 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; @@ -38,7 +41,8 @@ public: 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(); + 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..3ee3b82 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" @@ -266,72 +267,38 @@ static util::Vector 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..ab5d6a6 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" @@ -437,84 +439,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..94aa02b 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" @@ -324,68 +325,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..1026bd3 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 { @@ -51,7 +52,6 @@ public: 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/UserManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.h index 6b9f518..b448872 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.h @@ -6,6 +6,7 @@ Description: Header file declaring the UserManagementService class, which manage Author: Trenser Date:19-May-2026 */ + #pragma once #include #include "Map.h" diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Config.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Config.h index b0bd19d..2eef19d 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Config.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Config.h @@ -28,16 +28,18 @@ namespace config namespace file { - constexpr const char* INVENTORYITEM_FILE = "files/InventoryItem.csv"; - constexpr const char* USER_FILE = "files/User.csv"; - constexpr const char* NOTIFICATION_FILE = "files/Notification.csv"; - constexpr const char* SERVICE_FILE = "files/Service.csv"; - constexpr const char* COMBOPACKAGE_FILE = "files/ComboPackage.csv"; - constexpr const char* SERVICEBOOKING_FILE = "files/ServiceBooking.csv"; - constexpr const char* JOBCARD_FILE = "files/JobCard.csv"; - constexpr const char* INVOICE_FILE = "files/Invoice.csv"; - constexpr const char* SERVICEMANAGEMENTOBSERVERS = "files/ServiceManagementObservers.csv"; - constexpr const char* PAYMENTMANAGEMENTOBSERVERS = "files/PaymentManagementObservers.csv"; - constexpr const char* INVENTORYMANAGEMENTOBSERVERS = "files/InventoryManagementObservers.csv"; + const size_t INITIAL_CAPACITY = 100; + constexpr const char* DIRECTORY = "files/"; + constexpr const char* INVENTORYITEM_FILE = "files/InventoryItem.dat"; + constexpr const char* USER_FILE = "files/User.dat"; + constexpr const char* NOTIFICATION_FILE = "files/Notification.dat"; + constexpr const char* SERVICE_FILE = "files/Service.dat"; + constexpr const char* COMBOPACKAGE_FILE = "files/ComboPackage.dat"; + constexpr const char* SERVICEBOOKING_FILE = "files/ServiceBooking.dat"; + constexpr const char* JOBCARD_FILE = "files/JobCard.dat"; + constexpr const char* INVOICE_FILE = "files/Invoice.dat"; + constexpr const char* SERVICEMANAGEMENTOBSERVERS = "files/ServiceManagementObservers.dat"; + constexpr const char* PAYMENTMANAGEMENTOBSERVERS = "files/PaymentManagementObservers.dat"; + constexpr const char* INVENTORYMANAGEMENTOBSERVERS = "files/InventoryManagementObservers.dat"; } } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h index 7585abc..b908f51 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h @@ -12,28 +12,28 @@ Date: 19-May-2026 namespace util { - enum class UserType + enum class UserType : int { ADMIN, TECHNICIAN, CUSTOMER }; - enum class PaymentMode + enum class PaymentMode : int { ONLINE, OFFLINE, NOTSET }; - enum class PaymentStatus + enum class PaymentStatus : int { PENDING, COMPLETED, PAID }; - enum class ServiceJobStatus + enum class ServiceJobStatus : int { PENDING, STARTED, @@ -42,7 +42,7 @@ namespace util CANCELLED }; - enum class State + enum class State : int { ACTIVE, INACTIVE diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileHelper.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileHelper.h index 2b3e94a..c8bf96f 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileHelper.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileHelper.h @@ -106,4 +106,4 @@ namespace util file << records[index] << '\n'; } } -} +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/InputHelper.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/InputHelper.h index 75d8bbc..dffc199 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/InputHelper.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/InputHelper.h @@ -10,6 +10,7 @@ #include #include #include +#include namespace util { @@ -54,6 +55,48 @@ namespace util value = cleanedValue; } + /* + * Function: readPassword + * Description: Reads a password from console without echoing characters; + * displays '*' for each character typed, handles backspace, + * and cleans commas from the result. + * Parameters: + * value - reference to a string where the password will be stored + * Returns: + * void - no return value + */ + inline void readPassword(std::string& value) + { + value.clear(); + char currentCharacter; + while ((currentCharacter = _getch()) != '\r') + { + if (currentCharacter == '\b') + { + if (!value.empty()) + { + value.pop_back(); + std::cout << "\b \b"; + } + } + else + { + value += currentCharacter; + std::cout << '*'; + } + } + std::cout << std::endl; + std::string cleanedValue; + for (int iterator = 0; iterator < value.length(); iterator++) + { + if (value[iterator] != ',') + { + cleanedValue += value[iterator]; + } + } + value = cleanedValue; + } + /* * Function: pressEnter * Description: Pauses execution until the user presses Enter. diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp index 3e56d99..0d60f97 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp @@ -30,7 +30,6 @@ Description: Displays the customer menu and handles user input until logout is s Parameter: None Return type: void */ - void CustomerMenu::showMenu() { while (true) diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h index 83720c0..c6ebaa6 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/MenuHelper.h @@ -914,7 +914,7 @@ inline void changePasswordHelper(Controller& controller) util::clear(); std::cout << "Change Password\n"; std::cout << "Enter new password: "; - util::read(newPassword); + util::readPassword(newPassword); if (!util::isPasswordValid(newPassword)) { std::cout << "Error: Password is not strong enough!\n"; @@ -928,7 +928,7 @@ inline void changePasswordHelper(Controller& controller) continue; } std::cout << "Confirm new password: "; - util::read(confirmedPassword); + util::readPassword(confirmedPassword); if (confirmedPassword != newPassword) { std::cout << "Passwords are different. Try again\n"; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.h index a17ccb1..2d118a0 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/TechnicianMenu.h @@ -22,4 +22,4 @@ public: void viewNotifications(); void logout(); void changePassword(); -}; +}; \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.cpp index 841e2ea..4596d9b 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.cpp @@ -106,7 +106,7 @@ void UserInterface::login() std::cout << "Enter username: "; util::read(username); std::cout << "Enter password: "; - util::read(password); + util::readPassword(password); if (m_controller.login(username, password)) { const User* authenticatedUser = m_controller.getAuthenticatedUser(); @@ -167,7 +167,7 @@ void UserInterface::registerCustomer() return; } std::cout << "Enter password: "; - util::read(password); + util::readPassword(password); if (!util::isPasswordValid(password)) { std::cout << "Error: Password is invalid!"; @@ -185,4 +185,4 @@ void UserInterface::registerCustomer() m_controller.createCustomer(username, name, password, email, phone); std::cout << "Registration is successful"; util::pressEnter(); -} +} \ No newline at end of file