diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj index 063f776..8627061 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj @@ -173,9 +173,12 @@ + + + diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters index c72bd44..73b9291 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem.vcxproj.filters @@ -233,6 +233,21 @@ Header Files\Models + + Header Files\Utilities + + + Header Files\Utilities + + + Header Files\Utilities + + + Header Files\Utilities + + + Header Files\Utilities + Header Files\Views diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp index e6ead9e..b0c4802 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.cpp @@ -288,6 +288,54 @@ 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. +Parameters: + - None +Returns: + - void +*/ +void Controller::loadSystemData() +{ + 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(); +} + +/* +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. diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h index 9139d5d..1b534ea 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/controllers/Controller.h @@ -15,6 +15,10 @@ Date:19-May-2026 #include "PaymentManagementService.h" #include "ServiceManagementService.h" #include "UserManagementService.h" +#include "InventoryManagementService.h" +#include "UserManagementService.h" +#include "ServiceManagementService.h" +#include "PaymentManagementService.h" class Service; class ComboPackage; @@ -66,5 +70,7 @@ public: util::Vector getNotifications(); void deleteNotification(const std::string& notificationID); void configureNotifications(bool paymentNotifications, bool serviceNotifications); + void loadSystemData(); + void saveSystemData(); void runSystemChecks(); }; \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/patterns/Subject.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/patterns/Subject.h index 4cfe5ce..09b8ac3 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/patterns/Subject.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/core/patterns/Subject.h @@ -8,6 +8,7 @@ Date: 19-May-2026 #pragma once #include #include "Map.h" +#include "Vector.h" class User; class Notification; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/files/README.md b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/files/README.md new file mode 100644 index 0000000..6e6b93e --- /dev/null +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/files/README.md @@ -0,0 +1 @@ +Place files here. \ 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 41e75d0..4e69d9f 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.cpp @@ -7,7 +7,12 @@ Author: Trenser Date: 19-May-2026 */ +#include +#include #include "ComboPackage.h" +#include "Service.h" +#include "Factory.h" +#include "StringHelper.h" int ComboPackage::m_uid = 0; @@ -41,7 +46,42 @@ ComboPackage::ComboPackage(const std::string& packageName, double discountPercen m_packageName(packageName), m_discountPercentage(discountPercentage), m_status(util::State::ACTIVE), - m_services(services) {} + m_services(services) +{ + int numberOfServices = m_services.getSize(); + auto servicePointers = m_services.getValues(); + for (int index = 0; index < numberOfServices; index++) + { + m_serviceIDs.push_back(servicePointers[index]->getId()); + } +} + +/* +Function: ComboPackage (parameterized constructor with ID) +Description: Initializes a combo package with an existing ID, name, discount percentage, + service IDs, and state. Updates UID tracking based on ID. +Parameters: + - id: const std::string&, unique ID of the package + - packageName: const std::string&, name of the package + - discountPercentage: double, discount percentage applied + - serviceIDs: const util::Vector&, IDs of services included + - status: util::State, state of the package (ACTIVE/INACTIVE) +Returns: + - A new ComboPackage object +*/ +ComboPackage::ComboPackage(const std::string& id, const std::string& packageName, double discountPercentage, const util::Vector& serviceIDs, util::State status) + : m_id(id), + m_packageName(packageName), + m_discountPercentage(discountPercentage), + m_serviceIDs(serviceIDs), + m_status(status) +{ + int idNumber = util::extractNumber(m_id); + if (idNumber > m_uid) + { + m_uid = idNumber; + } +} /* Function: getId @@ -95,6 +135,11 @@ util::State ComboPackage::getState() const return m_status; } +const util::Vector& ComboPackage::getServiceIDs() const +{ + return m_serviceIDs; +} + /* Function: getServices Description: Retrieves the map of services included in the combo package. @@ -158,6 +203,13 @@ Returns: void ComboPackage::setServices(const util::Map& services) { m_services = services; + m_serviceIDs.clear(); + int numberOfServices = m_services.getSize(); + auto servicePointers = m_services.getValues(); + for (int index = 0; index < numberOfServices; index++) + { + m_serviceIDs.push_back(servicePointers[index]->getId()); + } } /* @@ -172,3 +224,118 @@ void ComboPackage::setState(util::State status) { m_status = status; } + +/* +Function: getServiceIDsAsString (static helper) +Description: Converts a vector of service IDs into a single string separated by '|'. +Parameters: + - serviceIDs: const util::Vector&, vector of service IDs +Returns: + - std::string: Concatenated service IDs string +*/ +static std::string getServiceIDsAsString(const util::Vector& serviceIDs) +{ + int numberOfServices = serviceIDs.getSize(); + std::string serviceIDsString; + for (int index = 0; index < numberOfServices; index++) + { + serviceIDsString += serviceIDs[index]; + if (index < numberOfServices - 1) + { + serviceIDsString += '|'; + } + } + return serviceIDsString; +} + +/* +Function: getServiceIDsAsVector (static helper) +Description: Converts a string of service IDs separated by '|' into a vector. +Parameters: + - serviceIDsString: const std::string&, concatenated service IDs string +Returns: + - util::Vector: Vector of service IDs +*/ +static util::Vector getServiceIDsAsVector(const std::string& serviceIDsString) +{ + util::Vector serviceIDs; + std::string serviceID; + std::istringstream serializedServiceIDs(serviceIDsString); + while (getline(serializedServiceIDs, serviceID, '|')) + { + serviceIDs.push_back(serviceID); + } + return serviceIDs; +} + +/* +Function: serialize +Description: Serializes the combo package into a CSV-formatted string. +Parameters: + - None +Returns: + - std::string: Serialized combo package record +*/ +std::string ComboPackage::serialize() const +{ + std::ostringstream serializedComboPackage; + serializedComboPackage << m_id << ',' + << m_packageName << ',' + << m_discountPercentage << ',' + << getServiceIDsAsString(m_serviceIDs) << ',' + << util::getStateString(m_status); + return serializedComboPackage.str(); +} + +/* +Function: deserialize +Description: Deserializes a CSV-formatted string into a ComboPackage object. +Parameters: + - record: const std::string&, 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) +{ + 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); + return Factory::getObject( + id, + packageName, + 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"; +} diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.h index a620ee4..941c2b3 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.h @@ -8,6 +8,7 @@ Date: 19-May-2026 #pragma once #include #include "Map.h" +#include "Vector.h" #include "Enums.h" class Service; @@ -19,14 +20,17 @@ private: std::string m_id; std::string m_packageName; double m_discountPercentage; + util::Vector m_serviceIDs; util::Map m_services; util::State m_status; public: ComboPackage(); ComboPackage(const std::string& packageName, double discountPercentage, const util::Map& services); + ComboPackage(const std::string& id, const std::string& packageName, double discountPercentage, const util::Vector& serviceIDs, util::State status); const std::string& getId() const; const std::string& getPackageName() const; double getDiscountPercentage() const; + const util::Vector& getServiceIDs() const; const util::Map& getServices() const; util::State getState() const; void setId(const std::string& id); @@ -34,4 +38,7 @@ 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(); }; \ 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 edc8654..f34b8a5 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/InventoryItem.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/InventoryItem.cpp @@ -6,6 +6,10 @@ Author: Trenser Date: 19-May-2026 */ +#include +#include +#include "Factory.h" +#include "StringHelper.h" #include "InventoryItem.h" int InventoryItem::m_uid = 0; @@ -43,6 +47,33 @@ InventoryItem::InventoryItem(const std::string& partName, int quantity, double p m_status(util::State::ACTIVE), m_price(price) {} +/* +Function: InventoryItem (parameterized constructor with ID) +Description: Initializes an inventory item with an existing ID, part name, quantity, + price, and state. Updates UID tracking based on ID. +Parameters: + - id: const std::string&, unique ID of the item + - partName: const std::string&, name of the part + - quantity: int, quantity of the part + - price: double, price of the part + - status: util::State, state of the item (ACTIVE/INACTIVE) +Returns: + - A new InventoryItem object +*/ +InventoryItem::InventoryItem(const std::string& id, const std::string& partName, int quantity, double price, util::State status) + : m_id(id), + m_partName(partName), + m_quantity(quantity), + m_status(status), + m_price(price) +{ + int idNumber = util::extractNumber(m_id); + if (idNumber > m_uid) + { + m_uid = idNumber; + } +} + /* Function: getId Description: Retrieves the unique ID of the inventory item. @@ -171,4 +202,77 @@ Returns: void InventoryItem::setState(util::State status) { m_status = status; +} + +/* +Function: serialize +Description: Serializes the inventory item into a CSV-formatted string. +Parameters: + - None +Returns: + - std::string: Serialized inventory item record +*/ +std::string InventoryItem::serialize() const +{ + std::ostringstream serializedInventoryItem; + serializedInventoryItem << m_id << ',' + << m_partName << ',' + << m_quantity << ',' + << m_price << ',' + << util::getStateString(m_status); + return serializedInventoryItem.str(); +} + +/* +Function: deserialize +Description: Deserializes a CSV-formatted string into an InventoryItem object. +Parameters: + - record: const std::string&, 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) +{ + 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"; } \ 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 0cb36ac..5808e8f 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/InventoryItem.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/InventoryItem.h @@ -23,6 +23,7 @@ private: public: InventoryItem(); InventoryItem(const std::string& partName, int quantity, double price); + InventoryItem(const std::string& id, const std::string& partName, int quantity, double price, util::State status); const std::string& getId() const; const std::string& getPartName() const; int getQuantity() const; @@ -33,4 +34,7 @@ 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(); }; \ 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 7c06e5b..d1dc0c4 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.cpp @@ -7,7 +7,12 @@ Author: Trenser Date: 19-May-2026 */ +#include +#include #include "Invoice.h" +#include "Factory.h" +#include "InventoryItem.h" +#include "StringHelper.h" int Invoice::m_uid = 0; @@ -53,7 +58,7 @@ Invoice::Invoice( const std::string& bookingId, ServiceBooking* booking, const util::Timestamp& invoiceDate, - double laborCost, const util::Map& parts, double partsCost, double discountPercentage, @@ -73,7 +78,48 @@ 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(); + for (int index = 0; index < numberOfParts; index++) + { + m_partIDs.push_back(partPointers[index]->getId()); + } +} + +Invoice::Invoice( + const std::string& id, + const std::string& bookingId, + const util::Timestamp& invoiceDate, + const util::Vector& partIDs, + double laborCost, + double partsCost, + double discountPercentage, + double totalAmount, + const util::Timestamp& paymentDate, + util::PaymentMode paymentMethod, + util::PaymentStatus status +) + : m_id(id), + m_bookingId(bookingId), + m_booking(nullptr), + m_invoiceDate(invoiceDate), + m_partIDs(partIDs), + m_laborCost(laborCost), + m_partsCost(partsCost), + m_discountPercentage(discountPercentage), + m_totalAmount(totalAmount), + m_paymentDate(paymentDate), + m_paymentMethod(paymentMethod), + m_status(status) +{ + int idNumber = util::extractNumber(m_id); + if (idNumber > m_uid) + { + m_uid = idNumber; + } +} /* Function: getId @@ -130,13 +176,26 @@ double Invoice::getLaborCost() const return m_laborCost; } +/* +Function: getPartIDs +Description: Retrieves the IDs of parts used in the invoice. +Parameters: + - None +Returns: + - const util::Vector&: Part IDs +*/ +const util::Vector& Invoice::getPartIDs() const +{ + return m_partIDs; +} + /* Function: getParts Description: Retrieves the map of inventory items used in the service. Returns: - const util::Map& representing the parts. */ -const util::Map& Invoice::getParts() const +const util::Map& Invoice::getParts() const { return m_parts; } @@ -280,9 +339,16 @@ Parameters: Returns: - void */ -void Invoice::setParts(const util::Map& parts) +void Invoice::setParts(const util::Map& parts) { m_parts = parts; + m_partIDs.clear(); + int numberOfParts = m_parts.getSize(); + auto partPointers = m_parts.getValues(); + for (int index = 0; index < numberOfParts; index++) + { + m_partIDs.push_back(partPointers[index]->getId()); + } } /* @@ -361,4 +427,147 @@ Returns: void Invoice::setStatus(util::PaymentStatus status) { m_status = status; +} + +/* +Function: getPartIDsAsString (static helper) +Description: Converts a vector of part IDs into a single string separated by '|'. +Parameters: + - partIDs: const util::Vector&, vector of part IDs +Returns: + - std::string: Concatenated part IDs string +*/ +static std::string getPartIDsAsString(const util::Vector& partIDs) +{ + int numberOfParts = partIDs.getSize(); + std::string partIDsString; + for (int index = 0; index < numberOfParts; index++) + { + partIDsString += partIDs[index]; + if (index < numberOfParts - 1) + { + partIDsString += '|'; + } + } + return partIDsString; +} + +/* +Function: getPartIDsAsVector (static helper) +Description: Converts a string of part IDs separated by '|' into a vector. +Parameters: + - partIDsString: const std::string&, concatenated part IDs string +Returns: + - util::Vector: Vector of part IDs +*/ +static util::Vector getPartIDsAsVector(const std::string& partIDsString) +{ + util::Vector partIDs; + std::string partID; + std::istringstream serializedPartIDs(partIDsString); + while (getline(serializedPartIDs, partID, '|')) + { + partIDs.push_back(partID); + } + return partIDs; +} + +/* +Function: serialize +Description: Serializes the invoice into a CSV-formatted string. +Parameters: + - None +Returns: + - std::string: Serialized invoice record +*/ +std::string 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(); +} + +/* +Function: deserialize +Description: Deserializes a CSV-formatted string into an Invoice object. +Parameters: + - record: const std::string&, 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) +{ + 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); + return Factory::getObject( + id, + bookingId, + 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"; } \ 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 b93cd77..a226038 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Invoice.h @@ -10,6 +10,7 @@ Date: 19-May-2026 #pragma once #include #include "Map.h" +#include "Vector.h" #include "Timestamp.h" #include "Enums.h" @@ -25,21 +26,21 @@ private: ServiceBooking* m_booking; util::Timestamp m_invoiceDate; double m_laborCost; - util::Map m_parts; + util::Vector m_partIDs; + util::Map m_parts; double m_partsCost; double m_discountPercentage; double m_totalAmount; util::Timestamp m_paymentDate; util::PaymentMode m_paymentMethod; util::PaymentStatus m_status; - public: Invoice(); Invoice( const std::string& bookingId, ServiceBooking* booking, const util::Timestamp& invoiceDate, - double laborCost, const util::Map& parts, double partsCost, double discountPercentage, @@ -48,12 +49,26 @@ public: util::PaymentMode paymentMethod, util::PaymentStatus status ); + Invoice( + const std::string& id, + const std::string& bookingId, + const util::Timestamp& invoiceDate, + const util::Vector& partIDs, + double laborCost, + double partsCost, + double discountPercentage, + double totalAmount, + const util::Timestamp& paymentDate, + util::PaymentMode paymentMethod, + util::PaymentStatus status + ); const std::string& getId() const; const std::string& getBookingId() const; ServiceBooking* getBooking() const; const util::Timestamp& getInvoiceDate() const; double getLaborCost() const; - const util::Map& getParts() const; + const util::Vector& getPartIDs() const; + const util::Map& getParts() const; double getPartsCost() const; double getDiscountPercentage() const; double getTotalAmount() const; @@ -65,11 +80,14 @@ public: void setBooking(ServiceBooking* booking); void setInvoiceDate(const util::Timestamp& invoiceDate); void setLaborCost(double laborCost); - void setParts(const util::Map& parts); + void setParts(const util::Map& parts); void setPartsCost(double partsCost); void setDiscountPercentage(double discountPercentage); void setTotalAmount(double totalAmount); 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(); }; \ 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 747da0f..132e82c 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp @@ -7,7 +7,12 @@ Author: Trenser Date: 19-May-2026 */ +#include +#include #include "JobCard.h" +#include "Factory.h" +#include "StringHelper.h" +#include "Enums.h" int JobCard::m_uid = 0; @@ -25,7 +30,7 @@ JobCard::JobCard() m_booking(nullptr), m_service(nullptr), m_technician(nullptr), - m_status(ServiceJobStatus()) {} + m_status(util::ServiceJobStatus()) {} /* Function: JobCard @@ -50,7 +55,7 @@ JobCard::JobCard(const std::string& bookingId, const std::string& technicianId, User* technician, const util::Timestamp& assignedDate, - ServiceJobStatus status, + util::ServiceJobStatus status, const util::Timestamp& completionDate ) : m_id("JC" + std::to_string(++m_uid)), @@ -64,6 +69,48 @@ JobCard::JobCard(const std::string& bookingId, m_status(status), m_completionDate(completionDate) {} +/* +Function: JobCard (parameterized constructor with ID) +Description: Initializes a job card with an existing ID, booking ID, service ID, + technician ID, assignment date, completion date, and status. + Updates UID tracking based on ID. +Parameters: + - id: const std::string&, unique job card ID + - bookingId: const std::string&, ID of the booking + - serviceId: const std::string&, ID of the service + - technicianId: const std::string&, ID of the technician + - assignedDate: const util::Timestamp&, date of assignment + - status: util::ServiceJobStatus, job status + - completionDate: const util::Timestamp&, date of completion +Returns: + - A new JobCard object +*/ +JobCard::JobCard(const std::string& id, + const std::string& bookingId, + const std::string& serviceId, + const std::string& technicianId, + const util::Timestamp& assignedDate, + util::ServiceJobStatus status, + const util::Timestamp& completionDate +) + : m_id(id), + m_bookingId(bookingId), + m_booking(nullptr), + m_service(nullptr), + m_serviceId(serviceId), + m_technicianId(technicianId), + m_technician(nullptr), + m_assignedDate(assignedDate), + m_status(status), + m_completionDate(completionDate) +{ + int idNumber = util::extractNumber(m_id); + if (idNumber > m_uid) + { + m_uid = idNumber; + } +} + /* Function: getId Description: Retrieves the unique ID of the job card. @@ -158,7 +205,7 @@ Description: Retrieves the current status of the job. Returns: - ServiceJobStatus representing the job status. */ -ServiceJobStatus JobCard::getStatus() const +util::ServiceJobStatus JobCard::getStatus() const { return m_status; } @@ -286,7 +333,7 @@ Parameters: Returns: - void */ -void JobCard::setStatus(ServiceJobStatus status) +void JobCard::setStatus(util::ServiceJobStatus status) { m_status = status; } @@ -302,4 +349,83 @@ Returns: void JobCard::setCompletionDate(const util::Timestamp& completionDate) { m_completionDate = completionDate; +} + +/* +Function: serialize +Description: Serializes the job card into a CSV-formatted string. +Parameters: + - None +Returns: + - std::string: Serialized job card record +*/ +std::string 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(); +} + +/* +Function: deserialize +Description: Deserializes a CSV-formatted string into a JobCard object. +Parameters: + - record: const std::string&, 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) +{ + 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"; } \ 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 bdc736d..b8a1cdd 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h @@ -9,13 +9,12 @@ Date: 19-May-2026 #pragma once #include #include "Timestamp.h" +#include "Enums.h" class ServiceBooking; class Service; class User; -enum class ServiceJobStatus : int; - class JobCard { private: @@ -28,7 +27,7 @@ private: std::string m_technicianId; User* m_technician; util::Timestamp m_assignedDate; - ServiceJobStatus m_status; + util::ServiceJobStatus m_status; util::Timestamp m_completionDate; public: @@ -40,7 +39,15 @@ public: const std::string& technicianId, User* technician, const util::Timestamp& assignedDate, - ServiceJobStatus status, + util::ServiceJobStatus status, + const util::Timestamp& completionDate + ); + JobCard(const std::string& id, + const std::string& bookingId, + const std::string& serviceId, + const std::string& technicianId, + const util::Timestamp& assignedDate, + util::ServiceJobStatus status, const util::Timestamp& completionDate ); const std::string& getId() const; @@ -51,7 +58,7 @@ public: const std::string& getTechnicianId() const; User* getTechnician() const; const util::Timestamp& getAssignedDate() const; - ServiceJobStatus getStatus() const; + util::ServiceJobStatus getStatus() const; const util::Timestamp& getCompletionDate() const; void setId(const std::string& id); void setBookingId(const std::string& bookingId); @@ -61,6 +68,9 @@ public: void setTechnicianId(const std::string& technicianId); void setTechnician(User* technician); void setAssignedDate(const util::Timestamp& assignedDate); - void setStatus(ServiceJobStatus status); + 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(); }; \ 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 353bcb2..0bae917 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.cpp @@ -6,7 +6,10 @@ Author: Trenser Date: 19-May-2026 */ +#include #include "Notification.h" +#include "StringHelper.h" +#include "Factory.h" int Notification::m_uid = 0; @@ -42,6 +45,34 @@ Notification::Notification(const std::string& recipientUserId, User* recipient, m_message(message), m_createdAt(createdAt) {} +/* +Function: Notification (parameterized constructor with ID) +Description: Initializes a notification with an existing ID, recipient details, + title, message, and creation timestamp. Updates UID tracking based on ID. +Parameters: + - id: const std::string&, unique notification ID + - recipientUserId: const std::string&, ID of the recipient user + - title: const std::string&, notification title + - message: const std::string&, notification message + - createdAt: const util::Timestamp&, timestamp of creation +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) + : m_id(id), + m_recipientUserId(recipientUserId), + m_recipient(nullptr), + m_title(title), + m_message(message), + m_createdAt(createdAt) +{ + int idNumber = util::extractNumber(m_id); + if (idNumber > m_uid) + { + m_uid = idNumber; + } +} + /* Function: getId Description: Retrieves the unique ID of the notification. @@ -184,4 +215,73 @@ Returns: void Notification::setCreatedAt(const util::Timestamp& createdAt) { m_createdAt = createdAt; +} + +/* +Function: serialize +Description: Serializes the notification into a CSV-formatted string. +Parameters: + - None +Returns: + - std::string: Serialized notification record +*/ +std::string Notification::serialize() const +{ + std::ostringstream serializedNotification; + serializedNotification << m_id << ',' + << m_recipientUserId << ',' + << m_title << ',' + << m_message << ',' + << m_createdAt.toString(); + return serializedNotification.str(); +} + +/* +Function: deserialize +Description: Deserializes a CSV-formatted string into a Notification object. +Parameters: + - record: const std::string&, 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) +{ + 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"; } \ 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 0ba780b..57869fa 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Notification.h @@ -25,6 +25,7 @@ private: 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); const std::string& getId() const; const std::string& getRecipientUserId() const; User* getRecipient() const; @@ -37,4 +38,7 @@ 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(); }; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.cpp index 02fe9ea..0717467 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.cpp @@ -7,7 +7,11 @@ Author: Trenser Date: 19-May-2026 */ +#include #include "Service.h" +#include "InventoryItem.h" +#include "StringHelper.h" +#include "Factory.h" int Service::m_uid = 0; @@ -40,7 +44,42 @@ Service::Service(const std::string& name, const util::MapgetId()); + } +} + +/* +Function: Service (parameterized constructor with ID) +Description: Initializes a service with an existing ID, name, inventory item IDs, + labor cost, and state. Updates UID tracking based on ID. +Parameters: + - id: const std::string&, unique service ID + - name: const std::string&, name of the service + - requiredInventoryItemIDs: const util::Vector&, IDs of required inventory items + - laborCost: double, labor cost of the service + - status: util::State, state of the service (ACTIVE/INACTIVE) +Returns: + - A new Service object +*/ +Service::Service(const std::string& id, const std::string& name, const util::Vector& requiredInventoryItemIDs, double laborCost, util::State status) + : m_id(id), + m_name(name), + m_requiredInventoryItemIDs(requiredInventoryItemIDs), + m_status(status), + m_laborCost(laborCost) +{ + int idNumber = util::extractNumber(m_id); + if (idNumber > m_uid) + { + m_uid = idNumber; + } +} /* Function: getId @@ -64,6 +103,19 @@ const std::string& Service::getName() const return m_name; } +/* +Function: getRequiredInventoryItemIDs +Description: Retrieves the IDs of required inventory items for the service. +Parameters: + - None +Returns: + - const util::Vector&: Inventory item IDs +*/ +const util::Vector& Service::getRequiredInventoryItemIDs() const +{ + return m_requiredInventoryItemIDs; +} + /* Function: getRequiredInventoryItems Description: Retrieves the map of inventory items required for the service. @@ -134,6 +186,13 @@ Returns: void Service::setRequiredInventoryItems(const util::Map& requiredInventoryItems) { m_requiredInventoryItems = requiredInventoryItems; + m_requiredInventoryItemIDs.clear(); + int numberOfRequiredInventoryItems = m_requiredInventoryItems.getSize(); + auto inventoryItemPointers = m_requiredInventoryItems.getValues(); + for (int index = 0; index < numberOfRequiredInventoryItems; index++) + { + m_requiredInventoryItemIDs.push_back(inventoryItemPointers[index]->getId()); + } } /* @@ -160,4 +219,119 @@ Returns: void Service::setState(util::State status) { m_status = status; +} + +/* +Function: getInventoryItemIDsAsString (static helper) +Description: Converts a vector of inventory item IDs into a single string separated by '|'. +Parameters: + - inventoryItemIds: const util::Vector&, vector of inventory item IDs +Returns: + - std::string: Concatenated inventory item IDs string +*/ +static std::string getInventoryItemIDsAsString(const util::Vector& inventoryItemIds) +{ + int numberOfInventoryItems = inventoryItemIds.getSize(); + std::string inventoryItemIDs; + for (int index = 0; index < numberOfInventoryItems; index++) + { + inventoryItemIDs += inventoryItemIds[index]; + if (index < numberOfInventoryItems - 1) + { + inventoryItemIDs += '|'; + } + } + return inventoryItemIDs; +} + +/* +Function: getInventoryItemIDsAsVector (static helper) +Description: Converts a string of inventory item IDs separated by '|' into a vector. +Parameters: + - inventoryItemIDsString: const std::string&, concatenated inventory item IDs string +Returns: + - util::Vector: Vector of inventory item IDs +*/ +static util::Vector getInventoryItemIDsAsVector(const std::string& inventoryItemIDsString) +{ + util::Vector inventoryItemIDs; + std::string inventoryItemID; + std::istringstream serializedInventoryItemIDs(inventoryItemIDsString); + while (getline(serializedInventoryItemIDs, inventoryItemID, '|')) + { + inventoryItemIDs.push_back(inventoryItemID); + } + return inventoryItemIDs; +} + +/* +Function: serialize +Description: Serializes the service into a CSV-formatted string. +Parameters: + - None +Returns: + - std::string: Serialized service record +*/ +std::string Service::serialize() const +{ + std::ostringstream serializedService; + serializedService << m_id << ',' + << m_name << ',' + << getInventoryItemIDsAsString(m_requiredInventoryItemIDs) << ',' + << m_laborCost << ',' + << util::getStateString(m_status); + return serializedService.str(); +} + +/* +Function: deserialize +Description: Deserializes a CSV-formatted string into a Service object. +Parameters: + - record: const std::string&, 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) +{ + 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); + return Factory::getObject( + id, + 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"; } \ 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 7d15ebe..b80e674 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.h @@ -10,6 +10,7 @@ Date: 19-May-2026 #pragma once #include #include "Map.h" +#include "Vector.h" #include "Enums.h" class InventoryItem; @@ -20,14 +21,17 @@ private: static int m_uid; std::string m_id; std::string m_name; + util::Vector m_requiredInventoryItemIDs; util::Map m_requiredInventoryItems; double m_laborCost; util::State m_status; public: Service(); Service(const std::string& name, const util::Map& requiredInventoryItems, double laborCost); + Service(const std::string& id, const std::string& name, const util::Vector& requiredInventoryItemIDs, double laborCost, util::State state); const std::string& getId() const; const std::string& getName() const; + const util::Vector& getRequiredInventoryItemIDs() const; const util::Map& getRequiredInventoryItems() const; double getLaborCost() const; util::State getState() const; @@ -36,4 +40,7 @@ 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(); }; \ 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 18702ac..a049a86 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp @@ -6,7 +6,13 @@ Description: Implementation file containing the method definitions of the Author: Trenser Date:19-May-2026 */ +#include +#include #include "ServiceBooking.h" +#include "Service.h" +#include "Enums.h" +#include "Factory.h" +#include "StringHelper.h" int ServiceBooking::m_uid = 0; @@ -64,6 +70,60 @@ ServiceBooking::ServiceBooking( m_assignedTechnician(nullptr), m_discountPercentage(discountPercentage) { + int numberOfServices = m_services.getSize(); + auto servicePointers = m_services.getValues(); + for (int index = 0; index < numberOfServices; index++) + { + m_serviceIDs.push_back(servicePointers[index]->getId()); + } +} + +/* +Function: ServiceBooking (parameterized constructor with ID) +Description: Initializes a service booking with an existing ID, status, service IDs, + customer details, vehicle details, technician ID, and discount percentage. + Updates UID tracking based on ID. +Parameters: + - id: const std::string&, unique booking ID + - status: util::ServiceJobStatus, job status of the booking + - serviceIDs: const util::Vector&, IDs of booked services + - customerId: const std::string&, ID of the customer + - vehicleNumber: const std::string&, vehicle number + - vehicleBrand: const std::string&, vehicle brand + - vehicleModel: const std::string&, vehicle model + - assignedTechnicianId: const std::string&, ID of the assigned technician + - discountPercentage: double, discount applied +Returns: + - A new ServiceBooking object +*/ +ServiceBooking::ServiceBooking( + const std::string& id, + util::ServiceJobStatus status, + const util::Vector& serviceIDs, + const std::string& customerId, + const std::string& vehicleNumber, + const std::string& vehicleBrand, + const std::string& vehicleModel, + const std::string& assignedTechnicianId, + double discountPercentage +) + : m_id(id), + m_status(status), + m_serviceIDs(serviceIDs), + m_customerId(customerId), + m_customer(nullptr), + m_vehicleNumber(vehicleNumber), + m_vehicleBrand(vehicleBrand), + m_vehicleModel(vehicleModel), + m_assignedTechnicianId(assignedTechnicianId), + m_assignedTechnician(nullptr), + m_discountPercentage(discountPercentage) +{ + int idNumber = util::extractNumber(m_id); + if (idNumber > m_uid) + { + m_uid = idNumber; + } } /* @@ -88,6 +148,19 @@ util::ServiceJobStatus ServiceBooking::getStatus() const return m_status; } +/* +Function: getServiceIDs +Description: Retrieves the IDs of services booked. +Parameters: + - None +Returns: + - const util::Vector&: Service IDs +*/ +const util::Vector& ServiceBooking::getServiceIDs() const +{ + return m_serviceIDs; +} + /* Function: getServices Description: Retrieves the services associated with the booking. @@ -217,6 +290,13 @@ Return type: void void ServiceBooking::setServices(const util::Map& services) { m_services = services; + m_serviceIDs.clear(); + int numberOfServices = m_services.getSize(); + auto servicePointers = m_services.getValues(); + for (int index = 0; index < numberOfServices; index++) + { + m_serviceIDs.push_back(servicePointers[index]->getId()); + } } /* @@ -305,4 +385,131 @@ Return type: void void ServiceBooking::setDiscountPercentage(double discountPercentage) { m_discountPercentage = discountPercentage; +} + +/* +Function: getServiceIDsAsString (static helper) +Description: Converts a vector of service IDs into a single string separated by '|'. +Parameters: + - serviceIDs: const util::Vector&, vector of service IDs +Returns: + - std::string: Concatenated service IDs string +*/ +static std::string getServiceIDsAsString(const util::Vector& serviceIDs) +{ + int numberOfServices = serviceIDs.getSize(); + std::string serviceIDsString; + for (int index = 0; index < numberOfServices; index++) + { + serviceIDsString += serviceIDs[index]; + if (index < numberOfServices - 1) + { + serviceIDsString += '|'; + } + } + return serviceIDsString; +} + +/* +Function: getServiceIDsAsVector (static helper) +Description: Converts a string of service IDs separated by '|' into a vector. +Parameters: + - serviceIDsString: const std::string&, concatenated service IDs string +Returns: + - util::Vector: Vector of service IDs +*/ +static util::Vector getServiceIDsAsVector(const std::string& serviceIDsString) +{ + util::Vector serviceIDs; + std::string serviceID; + std::istringstream serializedServiceIDs(serviceIDsString); + while (getline(serializedServiceIDs, serviceID, '|')) + { + serviceIDs.push_back(serviceID); + } + return serviceIDs; +} + +/* +Function: serialize +Description: Serializes the service booking into a CSV-formatted string. +Parameters: + - None +Returns: + - std::string: Serialized booking record +*/ +std::string 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(); +} + +/* +Function: deserialize +Description: Deserializes a CSV-formatted string into a ServiceBooking object. +Parameters: + - record: const std::string&, serialized 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) +{ + 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); + return Factory::getObject( + id, + 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"; } \ 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 48e3ba9..24acb32 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h @@ -9,6 +9,7 @@ Date:19-May-2026 #pragma once #include #include "Map.h" +#include "Vector.h" #include "Enums.h" class Service; @@ -20,6 +21,7 @@ private: static int m_uid; std::string m_id; util::ServiceJobStatus m_status; + util::Vector m_serviceIDs; util::Map m_services; std::string m_customerId; User* m_customer; @@ -42,8 +44,20 @@ public: const std::string& vehicleModel, double discountPercentage ); + ServiceBooking( + const std::string& id, + util::ServiceJobStatus status, + const util::Vector& serviceIDs, + const std::string& customerId, + const std::string& vehicleNumber, + const std::string& vehicleBrand, + const std::string& vehicleModel, + const std::string& assignedTechnicianId, + double discountPercentage + ); const std::string& getId() const; util::ServiceJobStatus getStatus() const; + const util::Vector& getServiceIDs() const; const util::Map& getServices() const; const std::string& getCustomerId() const; User* getCustomer() const; @@ -64,4 +78,7 @@ 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(); }; \ 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 0b0fa58..0b4e86e 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.cpp @@ -7,9 +7,12 @@ Author: Trenser Date: 19-May-2026 */ +#include #include "User.h" #include "Notification.h" #include "Enums.h" +#include "Factory.h" +#include "StringHelper.h" int User::m_uid = 0; @@ -50,6 +53,39 @@ User::User(const std::string& userName, const std::string& password, const std:: m_type(role), m_status(util::State::ACTIVE) {} +/* +Function: User (parameterized constructor with ID) +Description: Initializes a user with an existing ID, credentials, personal details, + role, and state. Updates UID tracking based on ID. +Parameters: + - userId: const std::string&, unique user ID + - userName: const std::string&, username + - password: const std::string&, password + - name: const std::string&, full name + - phone: const std::string&, phone number + - email: const std::string&, email address + - role: util::UserType, role of the user + - status: util::State, state of the user (ACTIVE/INACTIVE) +Returns: + - A new User object +*/ +User::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) + : m_id(userId), + m_userName(userName), + m_password(password), + m_name(name), + m_phone(phone), + m_email(email), + m_type(role), + m_status(status) +{ + int idNumber = util::extractNumber(m_id); + if (idNumber > m_uid) + { + m_uid = idNumber; + } +} + /* Function: ~User Description: Destructor that cleans up dynamically allocated notifications associated with the user. @@ -60,9 +96,10 @@ Returns: */ User::~User() { - for (int index = 0; index < m_notifications.getSize(); index++) + auto values = m_notifications.getValues(); + for (int index = 0; index < values.getSize(); index++) { - delete m_notifications.getValues()[index]; + delete values[index]; } } @@ -284,3 +321,71 @@ void User::setState(util::State status) { m_status = status; } + +/* +Function: serialize +Description: Serializes the user into a CSV-formatted string. +Parameters: + - None +Returns: + - std::string: Serialized user record +*/ +std::string 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(); +} + +/* +Function: deserialize +Description: Deserializes a CSV-formatted string into a User object. +Parameters: + - record: const std::string&, serialized user record +Returns: + - User*: Pointer to the deserialized User object +*/ +User* User::deserialize(const std::string& record) +{ + 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"; +} \ 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 1c5c215..12923f6 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/User.h @@ -31,6 +31,7 @@ private: 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(); const std::string& getId() const; const std::string& getUserName() const; @@ -50,4 +51,7 @@ 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(); }; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp index 4b2f003..6f675eb 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.cpp @@ -1,12 +1,24 @@ +/* +File: InventoryManagementService.cpp +Description: Implements the InventoryManagementService class, which manages inventory + items and observer relationships within the system. Provides methods + for loading and saving inventory items from persistent storage, as well + as attaching and persisting observers for notification handling. +Author: Trenser +Date: 22-May-2026 +*/ + #include -#include "InventoryManagementService.h" -#include "Vector.h" -#include "Enums.h" -#include "InventoryItem.h" #include "Config.h" -#include "User.h" +#include "Enums.h" #include "Factory.h" +#include "FileManager.h" +#include "InventoryItem.h" +#include "InventoryManagementService.h" #include "Timestamp.h" +#include "User.h" +#include "Utility.h" +#include "Vector.h" util::Map InventoryManagementService::m_observers{}; @@ -103,3 +115,93 @@ 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); +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.h index da63a84..a56cd37 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/InventoryManagementService.h @@ -9,6 +9,7 @@ Date: 19-May-2026 #pragma once #include #include "Map.h" +#include "Vector.h" #include "NotificationManagementService.h" #include "DataStore.h" @@ -19,6 +20,7 @@ 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(); @@ -29,4 +31,8 @@ public: void sendNotification(User* user, const std::string& title, const std::string& message) override; void attach(User* user) override; void detach(User* user) override; + void loadInventoryItems(); + void saveInventoryItems(); + void loadObservers(); + void saveObservers(); }; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/NotificationManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/NotificationManagementService.h index 18d0dda..33d214a 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/NotificationManagementService.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/NotificationManagementService.h @@ -19,4 +19,5 @@ public: virtual void sendNotification(User* recipient, const std::string& title, const std::string& message) = 0; virtual void attach(User* user) = 0; virtual void detach(User* user) = 0; + virtual util::Vector getObserverIDs() = 0; }; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp index 12082cf..b7946bf 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.cpp @@ -8,14 +8,17 @@ Date: 20-May-2026 */ #include -#include "PaymentManagementService.h" -#include "Invoice.h" -#include "ServiceBooking.h" -#include "Enums.h" -#include "Timestamp.h" #include "Config.h" -#include "User.h" +#include "Enums.h" #include "Factory.h" +#include "FileManager.h" +#include "Invoice.h" +#include "PaymentManagementService.h" +#include "ServiceBooking.h" +#include "Timestamp.h" +#include "User.h" +#include "Utility.h" + util::Map PaymentManagementService::m_observers{}; @@ -134,3 +137,120 @@ void PaymentManagementService::sendPaymentReminders() } } } + +/* +Function: getObserverIDs +Description: Retrieves the IDs of all observers currently attached to the + PaymentManagementService. +Parameters: + - None +Returns: + - util::Vector: Vector of observer user IDs +*/ +util::Vector PaymentManagementService::getObserverIDs() +{ + util::Vector observerIDs; + int numberOfObservers = m_observers.getSize(); + for (int index = 0; index < numberOfObservers; index++) + { + User* observer = m_observers.getValueAt(index); + if (observer) + { + observerIDs.push_back(observer->getId()); + } + } + return observerIDs; +} + +/* +Function: loadInvoices +Description: Loads invoices from persistent storage into the datastore. + Validates associated service bookings and inventory parts before + attaching them to each invoice. Throws exceptions if invalid IDs + are encountered. +Parameters: + - None +Returns: + - void +Throws: + - std::runtime_error if a booking ID or part ID is invalid +*/ +void PaymentManagementService::loadInvoices() +{ + util::FileManager invoiceFileManager(config::file::INVOICE_FILE); + auto& invoices = m_dataStore.getInvoices(); + auto& serviceBookings = m_dataStore.getServiceBookings(); + auto& inventoryItems = m_dataStore.getInventoryItems(); + auto invoicesMap = invoiceFileManager.load(); + for (int invoiceIndex = 0; invoiceIndex < invoicesMap.getSize(); invoiceIndex++) + { + Invoice* invoice = invoicesMap.getValueAt(invoiceIndex); + int bookingIndex = serviceBookings.find(invoice->getBookingId()); + if (bookingIndex == -1) + { + throw std::runtime_error("Invalid Booking ID"); + } + ServiceBooking* booking = serviceBookings.getValueAt(bookingIndex); + invoice->setBooking(booking); + util::Map invoiceParts; + auto& partIDs = invoice->getPartIDs(); + for (int partIndex = 0; partIndex < partIDs.getSize(); partIndex++) + { + const std::string& partID = partIDs[partIndex]; + int inventoryIndex = inventoryItems.find(partID); + if (inventoryIndex == -1) + { + throw std::runtime_error("Invalid Part ID"); + } + invoiceParts[partID] = inventoryItems.getValueAt(inventoryIndex); + } + invoice->setParts(invoiceParts); + invoices[invoice->getId()] = invoice; + } +} + +/* +Function: saveInvoices +Description: Saves invoices from the datastore to persistent storage. + Uses FileManager to serialize invoices into the configured file. +Parameters: + - None +Returns: + - void +*/ +void PaymentManagementService::saveInvoices() +{ + util::FileManager invoiceFileManager(config::file::INVOICE_FILE); + auto& invoices = m_dataStore.getInvoices(); + invoiceFileManager.save(invoices); +} + +/* +Function: loadObservers +Description: Loads observer IDs from persistent storage and attaches corresponding + users as observers to the PaymentManagementService. +Parameters: + - None +Returns: + - void +Throws: + - std::runtime_error if an observer ID is invalid (not found in datastore) +*/ +void PaymentManagementService::loadObservers() +{ + util::loadObservers(config::file::PAYMENTMANAGEMENTOBSERVERS, this, m_dataStore); +} + +/* +Function: saveObservers +Description: Saves the current observer IDs of the PaymentManagementService + to persistent storage for future retrieval. +Parameters: + - None +Returns: + - void +*/ +void PaymentManagementService::saveObservers() +{ + util::saveObservers(config::file::PAYMENTMANAGEMENTOBSERVERS, this); +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.h index c6e43a0..14b8c11 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/PaymentManagementService.h @@ -22,6 +22,7 @@ class PaymentManagementService : public NotificationManagementService private: DataStore& m_dataStore; static util::Map m_observers; + util::Vector getObserverIDs() override; public: PaymentManagementService() : m_dataStore(DataStore::getInstance()) {} void generateInvoice(ServiceBooking* booking); @@ -31,4 +32,8 @@ public: void sendNotification(User* user, const std::string& title, const std::string& message) override; void attach(User* user) override; void detach(User* user) override; + void loadInvoices(); + void saveInvoices(); + void loadObservers(); + void saveObservers(); }; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp index de777ec..e958839 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp @@ -6,15 +6,20 @@ Description: Implementation file containing the method definitions of the Author: Trenser Date:19-May-2026 */ + #include #include "AuthenticationManagementService.h" #include "ComboPackage.h" +#include "Config.h" #include "Factory.h" +#include "FileManager.h" +#include "JobCard.h" #include "Service.h" #include "ServiceBooking.h" #include "ServiceManagementService.h" #include "Timestamp.h" #include "User.h" +#include "Utility.h" /* Function: purchaseService @@ -178,3 +183,320 @@ void ServiceManagementService::sendNotification(User* user, const std::string& t } } } + +/* +Function: getObserverIDs +Description: Retrieves the IDs of all observers currently attached to the + ServiceManagementService. +Parameters: + - None +Returns: + - util::Vector: Vector of observer user IDs +*/ +util::Vector ServiceManagementService::getObserverIDs() +{ + util::Vector observerIDs; + int numberOfObservers = m_observers.getSize(); + for (int index = 0; index < numberOfObservers; index++) + { + User* observer = m_observers.getValueAt(index); + if (observer) + { + observerIDs.push_back(observer->getId()); + } + } + return observerIDs; +} + +/* +Function: loadServices +Description: Loads services from persistent storage into the datastore. + Validates required inventory items and attaches them to each service. +Parameters: + - None +Returns: + - void +Throws: + - std::runtime_error if an inventory item ID is invalid +*/ +void ServiceManagementService::loadServices() +{ + util::FileManager serviceFileManager(config::file::SERVICE_FILE); + auto& services = m_dataStore.getServices(); + auto& inventoryItems = m_dataStore.getInventoryItems(); + auto servicesMap = serviceFileManager.load(); + for (int serviceIndex = 0; serviceIndex < servicesMap.getSize(); serviceIndex++) + { + Service* service = servicesMap.getValueAt(serviceIndex); + services[service->getId()] = service; + util::Map inventoryItemsMap; + auto& inventoryItemIDs = service->getRequiredInventoryItemIDs(); + for (int inventoryItemIndex = 0; inventoryItemIndex < inventoryItemIDs.getSize(); inventoryItemIndex++) + { + const std::string& inventoryItemID = inventoryItemIDs[inventoryItemIndex]; + int index = inventoryItems.find(inventoryItemID); + if (index == -1) + { + throw std::runtime_error("Invalid Inventory Item ID"); + } + inventoryItemsMap[inventoryItemID] = inventoryItems.getValueAt(index); + } + service->setRequiredInventoryItems(inventoryItemsMap); + } +} + +/* +Function: saveServices +Description: Saves services from the datastore to persistent storage. + Uses FileManager to serialize services into the configured file. +Parameters: + - None +Returns: + - void +*/ +void ServiceManagementService::saveServices() +{ + util::FileManager serviceFileManager(config::file::SERVICE_FILE); + auto& services = m_dataStore.getServices(); + serviceFileManager.save(services); +} + +/* +Function: loadComboPackages +Description: Loads combo packages from persistent storage into the datastore. + Validates associated services and attaches them to each package. +Parameters: + - None +Returns: + - void +Throws: + - std::runtime_error if a service ID is invalid +*/ +void ServiceManagementService::loadComboPackages() +{ + util::FileManager comboPackageFileManager(config::file::COMBOPACKAGE_FILE); + auto& comboPackages = m_dataStore.getComboPackages(); + auto& services = m_dataStore.getServices(); + auto comboPackagesMap = comboPackageFileManager.load(); + for (int packageIndex = 0; packageIndex < comboPackagesMap.getSize(); packageIndex++) + { + ComboPackage* comboPackage = comboPackagesMap.getValueAt(packageIndex); + util::Map packageServices; + auto& serviceIDs = comboPackage->getServiceIDs(); + for (int serviceIndex = 0; serviceIndex < serviceIDs.getSize(); serviceIndex++) + { + const std::string& serviceID = serviceIDs[serviceIndex]; + int serviceMapIndex = services.find(serviceID); + if (serviceMapIndex == -1) + { + throw std::runtime_error("Invalid Service ID"); + } + packageServices[serviceID] = services.getValueAt(serviceMapIndex); + } + comboPackage->setServices(packageServices); + comboPackages[comboPackage->getId()] = comboPackage; + } +} + +/* +Function: saveComboPackages +Description: Saves combo packages from the datastore to persistent storage. + Uses FileManager to serialize combo packages into the configured file. +Parameters: + - None +Returns: + - void +*/ +void ServiceManagementService::saveComboPackages() +{ + util::FileManager comboPackageFileManager(config::file::COMBOPACKAGE_FILE); + auto& comboPackages = m_dataStore.getComboPackages(); + comboPackageFileManager.save(comboPackages); +} + +/* +Function: loadServiceBookings +Description: Loads service bookings from persistent storage into the datastore. + Validates associated services, customers, and technicians before + attaching them to each booking. +Parameters: + - None +Returns: + - void +Throws: + - std::runtime_error if a service ID, customer ID, or technician ID is invalid + - std::runtime_error if a user is not of the expected type (customer/technician) +*/ +void ServiceManagementService::loadServiceBookings() +{ + util::FileManager bookingFileManager(config::file::SERVICEBOOKING_FILE); + auto& serviceBookings = m_dataStore.getServiceBookings(); + auto& services = m_dataStore.getServices(); + auto& users = m_dataStore.getUsers(); + auto bookingsMap = bookingFileManager.load(); + for (int bookingIndex = 0; bookingIndex < bookingsMap.getSize(); bookingIndex++) + { + ServiceBooking* booking = bookingsMap.getValueAt(bookingIndex); + util::Map bookingServices; + auto& serviceIDs = booking->getServiceIDs(); + for (int serviceIndex = 0; serviceIndex < serviceIDs.getSize(); serviceIndex++) + { + const std::string& serviceID = serviceIDs[serviceIndex]; + int serviceMapIndex = services.find(serviceID); + if (serviceMapIndex == -1) + { + throw std::runtime_error("Invalid Service ID"); + } + + bookingServices[serviceID] = services.getValueAt(serviceMapIndex); + } + booking->setServices(bookingServices); + int customerIndex = users.find(booking->getCustomerId()); + if (customerIndex == -1) + { + throw std::runtime_error("Invalid Customer ID"); + } + User* customer = users.getValueAt(customerIndex); + if (customer->getUserType() != util::UserType::CUSTOMER) + { + throw std::runtime_error("User is not a customer"); + } + booking->setCustomer(customer); + const std::string& technicianId = booking->getAssignedTechnicianId(); + if (!technicianId.empty()) + { + int technicianIndex = users.find(technicianId); + if (technicianIndex == -1) + { + throw std::runtime_error("Invalid Technician ID"); + } + User* technician = users.getValueAt(technicianIndex); + if (technician->getUserType() != util::UserType::TECHNICIAN) + { + throw std::runtime_error("User is not a technician"); + } + booking->setAssignedTechnician(technician); + } + serviceBookings[booking->getId()] = booking; + } +} + +/* +Function: saveServiceBookings +Description: Saves service bookings from the datastore to persistent storage. + Uses FileManager to serialize bookings into the configured file. +Parameters: + - None +Returns: + - void +*/ +void ServiceManagementService::saveServiceBookings() +{ + util::FileManager bookingFileManager(config::file::SERVICEBOOKING_FILE); + auto& serviceBookings = m_dataStore.getServiceBookings(); + bookingFileManager.save(serviceBookings); +} + +/* +Function: loadJobCards +Description: Loads job cards from persistent storage into the datastore. + Validates associated bookings, services, and technicians before + attaching them to each job card. +Parameters: + - None +Returns: + - void +Throws: + - std::runtime_error if a booking ID, service ID, or technician ID is invalid + - std::runtime_error if a service does not belong to the booking + - std::runtime_error if a user is not a technician +*/ +void ServiceManagementService::loadJobCards() +{ + util::FileManager jobCardFileManager(config::file::JOBCARD_FILE); + auto& jobCards = m_dataStore.getJobCards(); + auto& serviceBookings = m_dataStore.getServiceBookings(); + auto& services = m_dataStore.getServices(); + auto& users = m_dataStore.getUsers(); + auto jobCardsMap = jobCardFileManager.load(); + for (int jobCardIndex = 0; jobCardIndex < jobCardsMap.getSize(); jobCardIndex++) + { + JobCard* jobCard = jobCardsMap.getValueAt(jobCardIndex); + int bookingIndex = serviceBookings.find(jobCard->getBookingId()); + if (bookingIndex == -1) + { + throw std::runtime_error("Invalid Booking ID"); + } + ServiceBooking* booking = serviceBookings.getValueAt(bookingIndex); + jobCard->setBooking(booking); + int serviceIndex = services.find(jobCard->getServiceId()); + if (serviceIndex == -1) + { + throw std::runtime_error("Invalid Service ID"); + } + Service* service = services.getValueAt(serviceIndex); + if (booking->getServices().find(jobCard->getServiceId()) == -1) + { + throw std::runtime_error("Service does not belong to booking"); + } + jobCard->setService(service); + int technicianIndex = users.find(jobCard->getTechnicianId()); + if (technicianIndex == -1) + { + throw std::runtime_error("Invalid Technician ID"); + } + User* technician = users.getValueAt(technicianIndex); + if (technician->getUserType() != util::UserType::TECHNICIAN) + { + throw std::runtime_error("User is not a technician"); + } + jobCard->setTechnician(technician); + jobCards[jobCard->getId()] = jobCard; + } +} + +/* +Function: saveJobCards +Description: Saves job cards from the datastore to persistent storage. + Uses FileManager to serialize job cards into the configured file. +Parameters: + - None +Returns: + - void +*/ +void ServiceManagementService::saveJobCards() +{ + util::FileManager jobCardFileManager(config::file::JOBCARD_FILE); + auto& jobCards = m_dataStore.getJobCards(); + jobCardFileManager.save(jobCards); +} + +/* +Function: loadObservers +Description: Loads observer IDs from persistent storage and attaches corresponding + users as observers to the ServiceManagementService. +Parameters: + - None +Returns: + - void +Throws: + - std::runtime_error if an observer ID is invalid (not found in datastore) +*/ +void ServiceManagementService::loadObservers() +{ + util::loadObservers(config::file::SERVICEMANAGEMENTOBSERVERS, this, m_dataStore); +} + +/* +Function: saveObservers +Description: Saves the current observer IDs of the ServiceManagementService + to persistent storage for future retrieval. +Parameters: + - None +Returns: + - void +*/ +void ServiceManagementService::saveObservers() +{ + util::saveObservers(config::file::SERVICEMANAGEMENTOBSERVERS, this); +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h index e1dfb91..119af04 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.h @@ -22,6 +22,7 @@ class ServiceManagementService : public NotificationManagementService private: DataStore& m_dataStore; static util::Map m_observers; + util::Vector getObserverIDs() override; public: ServiceManagementService() : m_dataStore(DataStore::getInstance()) {} util::Map getServices(); @@ -42,4 +43,14 @@ public: void sendNotification(User* user, const std::string& title, const std::string& message) override; void attach(User* user) override; void detach(User* user) override; + void loadServices(); + void saveServices(); + void loadComboPackages(); + void saveComboPackages(); + void loadServiceBookings(); + void saveServiceBookings(); + void loadJobCards(); + void saveJobCards(); + void loadObservers(); + void saveObservers(); }; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp index 63732a5..0503019 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.cpp @@ -10,7 +10,9 @@ Date:19-May-2026 #include "Config.h" #include "Enums.h" #include "Factory.h" +#include "FileManager.h" #include "InventoryManagementService.h" +#include "Notification.h" #include "PaymentManagementService.h" #include "ServiceManagementService.h" #include "User.h" @@ -173,4 +175,72 @@ void UserManagementService::deleteNotification(const std::string& notificationID throw std::runtime_error("No notification found with given NotificationID"); } notifications.remove(notificationID); +} + +/* +Function: loadUsers +Description: Loads users and notifications from persistent storage into the datastore. + Validates that each notification’s recipient exists and attaches the + notification to the corresponding user. +Parameters: + - None +Returns: + - void +Throws: + - std::runtime_error if a notification recipient user ID is invalid +*/ +void UserManagementService::loadUsers() +{ + util::FileManager userFileManager(config::file::USER_FILE); + util::FileManager notificationFileManager(config::file::NOTIFICATION_FILE); + auto& users = m_dataStore.getUsers(); + auto usersMap = userFileManager.load(); + auto notificationsMap = notificationFileManager.load(); + int numberOfUsers = usersMap.getSize(); + int numberOfNotifications = notificationsMap.getSize(); + for (int index = 0; index < numberOfUsers; index++) + { + users[usersMap.getKeyAt(index)] = usersMap.getValueAt(index); + } + for (int index = 0; index < numberOfNotifications; index++) + { + Notification* notification = notificationsMap.getValueAt(index); + const std::string& recipientUserId = notification->getRecipientUserId(); + int userIndex = users.find(recipientUserId); + if (userIndex == -1) + { + throw std::runtime_error("Invalid recipient user ID"); + } + User* user = users.getValueAt(userIndex); + user->addNotification(notification); + } +} + +/* +Function: saveUsers +Description: Saves users and their notifications from the datastore to persistent storage. + Collects notifications from all users into a single map before saving. +Parameters: + - None +Returns: + - void +*/ +void UserManagementService::saveUsers() +{ + util::FileManager userFileManager(config::file::USER_FILE); + util::FileManager notificationFileManager(config::file::NOTIFICATION_FILE); + auto& users = m_dataStore.getUsers(); + util::Map notifications; + for (int userIndex = 0; userIndex < users.getSize(); userIndex++) + { + User* user = users.getValueAt(userIndex); + auto& userNotifications = user->getNotifications(); + for (int notificationIndex = 0; notificationIndex < userNotifications.getSize(); notificationIndex++) + { + notifications[userNotifications.getKeyAt(notificationIndex)] = + userNotifications.getValueAt(notificationIndex); + } + } + userFileManager.save(users); + notificationFileManager.save(notifications); } \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.h index 313b8d6..6b9f518 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/UserManagementService.h @@ -30,4 +30,6 @@ public: util::Vector getUserNotifications(const std::string& userID); void deleteNotification(const std::string& notificationID, const std::string& userID); void ensureAdminExists(); + void loadUsers(); + void saveUsers(); }; diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Config.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Config.h index f55529e..30bfad9 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Config.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Config.h @@ -25,4 +25,19 @@ namespace config constexpr int INVENTORY_LOW_STOCK_THRESHOLD = 5; constexpr int PAYMENT_REMINDER_THRESHOLD_HOURS = 168; } + + 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"; + } } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h index 60f2d9b..9e8b1b9 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Enums.h @@ -236,9 +236,9 @@ namespace util switch (status) { case State::ACTIVE: - return "STARTED"; + return "ACTIVE"; case State::INACTIVE: - return "COMPLETED"; + return "INACTIVE"; } throw std::invalid_argument("Invalid State"); } @@ -259,7 +259,7 @@ namespace util { return State::ACTIVE; } - if (value == "COMPLETED") + if (value == "INACTIVE") { return State::INACTIVE; } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileHelper.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileHelper.h new file mode 100644 index 0000000..3a532b1 --- /dev/null +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileHelper.h @@ -0,0 +1,79 @@ +/* +File: FileHelper.h +Description: Provides utility functions for loading and saving records + from and to CSV-like text files. Ensures files are created + if missing and supports simple record persistence. +Author: Trenser +Date: 22-May-2026 +*/ + +#pragma once +#include +#include +#include +#include "Vector.h" + +namespace util +{ + /* + Function: loadRecords + Description: Loads records from a given file path into a vector of strings. + Skips the header line if present. Creates the file if it does not exist. + Parameters: + - filePath: const std::string&, path to the file + Returns: + - util::Vector: Vector containing all records (excluding header) + Throws: + - None (creates file if missing) + */ + inline util::Vector loadRecords(const std::string& filePath) + { + util::Vector records; + std::ifstream file(filePath); + if (!file.is_open()) + { + std::ofstream newFile(filePath); + newFile.close(); + file.open(filePath); + } + std::string line; + bool isHeader = true; + while (std::getline(file, line)) + { + if (isHeader) + { + isHeader = false; + continue; + } + records.push_back(line); + } + return records; + } + + /* + Function: saveRecords + Description: Saves records to a given file path. Overwrites existing content + and writes a header line followed by all records. + Parameters: + - filePath: const std::string&, path to the file + - records: const util::Vector&, vector of records to save + Returns: + - void + Throws: + - std::runtime_error if the file cannot be opened for writing + */ + inline void saveRecords(const std::string& filePath, const util::Vector& records) + { + std::ofstream file(filePath, std::ios::trunc); + if (!file.is_open()) + { + throw std::runtime_error("Failed to open file " + filePath); + } + file << "Values" << '\n'; + int numberOfRecords = records.getSize(); + for (int index = 0; index < numberOfRecords; index++) + { + file << records[index] << '\n'; + } + } +} diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileManager.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileManager.h new file mode 100644 index 0000000..35d2935 --- /dev/null +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/FileManager.h @@ -0,0 +1,117 @@ +/* +File: FileManager.h +Description: Declares and implements a generic FileManager template class for + loading and saving objects to and from files. Uses serialization + and deserialization methods defined in the object type T. + Provides persistence support for system entities such as Users, + Services, InventoryItems, etc. +Author: Trenser +Date: 22-May-2026 +*/ + +#pragma once +#include +#include +#include +#include "Vector.h" +#include "Map.h" + +namespace util +{ + template using objects = util::Map; + + template + class FileManager + { + private: + std::string m_filePath; + public: + FileManager() : m_filePath("") {} + FileManager(const std::string& filePath) : m_filePath(filePath) {} + objects load(); + void save(const objects&); + }; + + /* + Function: load + Description: Loads records from the file into a map of objects. + Skips the header line, deserializes each record into an object of type T, + and stores them in a map keyed by object ID. + Parameters: + - None + Returns: + - util::Map containing deserialized objects + Throws: + - std::runtime_error if deserialization fails for any record + */ + template + objects FileManager::load() + { + objects records; + std::ifstream file(m_filePath); + if (!file.is_open()) + { + std::ofstream newFile(m_filePath); + newFile.close(); + file.open(m_filePath); + } + util::Vector lines; + std::string line; + while (std::getline(file, line)) + { + lines.push_back(line); + } + int numberOfLines = lines.getSize(); + bool isHeader = true; + for (int lineIndex = 0; lineIndex < numberOfLines; lineIndex++) + { + const auto& record = lines[lineIndex]; + if (isHeader) + { + isHeader = false; + continue; + } + auto object = T::deserialize(record); + if (!object) + { + throw std::runtime_error("Failed to deserialize record"); + } + records[object->getId()] = object; + } + return records; + } + + /* + Function: save + Description: Saves records to the file. Serializes each object of type T into a string, + writes a header line, and then writes all serialized records to the file. + Parameters: + - records: const util::Map&, map of objects to save + Returns: + - void + Throws: + - std::runtime_error if the file cannot be opened for writing + */ + template + void FileManager::save(const objects& records) + { + util::Vector lines; + lines.push_back(T::getHeaders()); + int numberOfRecords = records.getSize(); + for (int recordIndex = 0; recordIndex < numberOfRecords; recordIndex++) + { + const auto& record = records.getValueAt(recordIndex); + lines.push_back(record->serialize()); + } + std::ofstream file(m_filePath, std::ios::trunc); + if (!file.is_open()) + { + throw std::runtime_error("Failed to open file " + m_filePath); + } + int numberOfLines = lines.getSize(); + for (int lineIndex = 0; lineIndex < numberOfLines; lineIndex++) + { + file << lines[lineIndex] << '\n'; + } + } +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/InputHelper.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/InputHelper.h index d8fee08..e789442 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/InputHelper.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/InputHelper.h @@ -34,7 +34,7 @@ namespace util /* * Function: read - * Description: Reads a line of text input from console into a string. + * Description: Reads a line of text input from console into a string and cleans it up. * Parameters: * value - reference to a string where the input will be stored * Returns: @@ -43,6 +43,15 @@ namespace util inline void read(std::string& value) { std::getline(std::cin >> std::ws, value); + std::string cleanedValue; + for (int index = 0; index < value.length(); index++) + { + if (value[index] != ',') + { + cleanedValue += value[index]; + } + } + value = cleanedValue; } /* diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/StringHelper.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/StringHelper.h new file mode 100644 index 0000000..0d7839a --- /dev/null +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/StringHelper.h @@ -0,0 +1,36 @@ +/* +File: StringHelper.h +Description: Provides utility functions for extracting numeric values from strings. + Useful for parsing IDs, codes, or mixed alphanumeric inputs where + digits need to be isolated and converted into integers. +Author: Trenser +Date: 22-May-2026 +*/ + +#include +#include + +namespace util +{ + /* + Function: extractNumber + Description: Extracts all digits from the given string and converts them into an integer. + Ignores non-digit characters. For example, "abc123xyz" returns 123. + Parameters: + - input: const std::string&, the input string containing digits and/or other characters + Returns: + - int: The integer value formed by concatenating all digits in the string + */ + inline int extractNumber(const std::string& input) + { + int result = 0; + for (char character : input) + { + if (std::isdigit(static_cast(character))) + { + result = result * 10 + (character - '0'); + } + } + return result; + } +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h index ca1fd37..396fd4b 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/utilities/Utility.h @@ -5,45 +5,99 @@ Description: Header file declaring utility functions used across the system, Author: Trenser Date:19-May-2026 */ + #pragma once -#include "Service.h" +#include "DataStore.h" +#include "FileHelper.h" #include "InventoryItem.h" +#include "NotificationManagementService.h" +#include "Service.h" +#include "ComboPackage.h" -/* -Function: calculatePartsCost -Description: Calculates the total cost of parts required for a given service - by summing the prices of all associated inventory items. -Parameter: const Service* service - pointer to the service object -Return type: double - total cost of required parts -*/ -inline double calculatePartsCost(const Service* service) +namespace util { - double cost = 0; - auto& requiredInventoryItems = service->getRequiredInventoryItems(); - int requiredInventoryItemsSize = requiredInventoryItems.getSize(); - for (int index = 0; index < requiredInventoryItemsSize; index++) + /* + Function: calculatePartsCost + Description: Calculates the total cost of parts required for a given service + by summing the prices of all associated inventory items. + Parameter: const Service* service - pointer to the service object + Return type: double - total cost of required parts + */ + inline double calculatePartsCost(const Service* service) { - cost += requiredInventoryItems.getValueAt(index)->getPrice(); + double cost = 0; + auto& requiredInventoryItems = service->getRequiredInventoryItems(); + int requiredInventoryItemsSize = requiredInventoryItems.getSize(); + for (int index = 0; index < requiredInventoryItemsSize; index++) + { + cost += requiredInventoryItems.getValueAt(index)->getPrice(); + } + return cost; } - return cost; -} -/* -Function: calculateComboServiceEstimatedCost -Description: Calculates the estimated total cost of a combo package by summing - the labor and parts costs of all services included in the package. -Parameter: const ComboPackage* comboPackage - pointer to the combo package object -Return type: double - estimated total cost of the combo package -*/ -inline double calculateComboServiceEstimatedCost(const ComboPackage* comboPackage) -{ - double cost = 0; - auto& services = comboPackage->getServices(); - int servicesSize = services.getSize(); - for (int index = 0; index < servicesSize; index++) + /* + Function: calculateComboServiceEstimatedCost + Description: Calculates the estimated total cost of a combo package by summing + the labor and parts costs of all services included in the package. + Parameter: const ComboPackage* comboPackage - pointer to the combo package object + Return type: double - estimated total cost of the combo package + */ + inline double calculateComboServiceEstimatedCost(const ComboPackage* comboPackage) { - const Service* service = services.getValueAt(index); - cost += calculatePartsCost(service) + service->getLaborCost(); + double cost = 0; + auto& services = comboPackage->getServices(); + int servicesSize = services.getSize(); + for (int index = 0; index < servicesSize; index++) + { + const Service* service = services.getValueAt(index); + cost += calculatePartsCost(service) + service->getLaborCost(); + } + return cost; + } + + /* + Function: loadObservers + Description: Loads observer IDs from a file and attaches the corresponding users + to the notification management service. Validates that each observer ID + exists in the datastore before attaching. + Parameters: + - filePath: const std::string&, path to the file containing observer IDs + - service: NotificationManagementService*, pointer to the notification service + - dataStore: DataStore&, reference to the datastore containing users + Returns: + - void + Throws: + - std::runtime_error if an observer ID is invalid (not found in datastore) + */ + inline void loadObservers(const std::string& filePath, NotificationManagementService* service, DataStore& dataStore) + { + auto observerIDs = util::loadRecords(filePath); + auto& users = dataStore.getUsers(); + for (int index = 0; index < observerIDs.getSize(); index++) + { + const std::string& observerID = observerIDs[index]; + int userIndex = users.find(observerID); + if (userIndex == -1) + { + throw std::runtime_error("Invalid Observer ID"); + } + service->attach(users.getValueAt(userIndex)); + } + } + + /* + Function: saveObservers + Description: Saves the current observer IDs from the notification management service + to a file for persistence. + Parameters: + - filePath: const std::string&, path to the file where observer IDs will be saved + - service: NotificationManagementService*, pointer to the notification service + Returns: + - void + */ + inline void saveObservers(const std::string& filePath, NotificationManagementService* service) + { + auto observerIDs = service->getObserverIDs(); + util::saveRecords(filePath, observerIDs); } - return cost; } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp index c812089..213fb0d 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/CustomerMenu.cpp @@ -196,7 +196,7 @@ static const Service* selectServiceFromServices(const util::MapgetId() @@ -282,7 +282,7 @@ static const ComboPackage* selectComboPackageFromPackages(const util::MapgetId() << std::setw(25) << currentComboPackage->getPackageName() - << std::setw(15) << calculateComboServiceEstimatedCost(currentComboPackage) + << std::setw(15) << util::calculateComboServiceEstimatedCost(currentComboPackage) << std::endl; currentIndex++; } diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.cpp index 571cd33..4f91641 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/views/UserInterface.cpp @@ -22,6 +22,7 @@ Return type: void */ void UserInterface::run() { + m_controller.loadSystemData(); m_controller.runSystemChecks(); bool isMenuActive = true; while (isMenuActive) @@ -43,6 +44,7 @@ void UserInterface::run() util::pressEnter(); } } + m_controller.saveSystemData(); } /*