diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp index 52b3e57..8de85a6 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.cpp @@ -12,6 +12,8 @@ Date: 19-May-2026 #include "Config.h" #include "SerializedRecords.h" #include "FileHelper.h" +#include "ServiceBooking.h" +#include "JobCard.h" /* Function: DataStore @@ -252,6 +254,28 @@ Returns: */ util::Map>& DataStore::getServices() { + util::Map> services = loadRecords(m_services); + refreshCache(m_serviceCache, services); + util::Map>& inventoryItems = getInventoryItems(); + size_t numberOfServices = m_serviceCache.getSize(); + for (int iteratorOne =0; iteratorOne < numberOfServices; iteratorOne++) + { + Service* currentService = m_serviceCache.getValueAt(iteratorOne).data; + util::Map inventoryItemMap; + util::Vector currentServiceInventoryItem = currentService->getRequiredInventoryItemIDs(); + for (int iteratorTwo = 0; iteratorTwo < currentServiceInventoryItem.getSize(); iteratorTwo++) + { + const std::string& currentInventoryItemId = currentServiceInventoryItem[iteratorTwo]; + int currentInventoryItemIndex = inventoryItems.find(currentInventoryItemId); + if (currentInventoryItemIndex == -1) + { + throw std::runtime_error("Invalid inventory item ID"); + } + InventoryItem* currentItem = inventoryItems.getValueAt(currentInventoryItemIndex).data; + inventoryItemMap[currentInventoryItemId] = currentItem; + } + currentService->setRequiredInventoryItems(inventoryItemMap); + } return m_serviceCache; } @@ -265,6 +289,28 @@ Returns: */ util::Map>& DataStore::getComboPackages() { + util::Map> comboPackages = loadRecords(m_comboPackages); + refreshCache(m_comboPackageCache, comboPackages); + util::Map>& services = getServices(); + size_t numberOfComboPackages = m_comboPackageCache.getSize(); + for (int iteratorOne = 0; iteratorOne < numberOfComboPackages; iteratorOne++) + { + ComboPackage* currentComboPackage = m_comboPackageCache.getValueAt(iteratorOne).data; + util::Vector currentServiceIds = currentComboPackage->getServiceIDs(); + util::Map currentComboPackageServices; + for (int iteratorTwo = 0; iteratorTwo < currentServiceIds.getSize(); iteratorTwo++) + { + const std::string& currentServiceId = currentServiceIds[iteratorTwo]; + int serviceIndex = services.find(currentServiceId); + if (serviceIndex == -1) + { + throw std::runtime_error("Invalid service ID"); + } + Service* currentService = services.getValueAt(serviceIndex).data; + currentComboPackageServices[currentServiceId] = currentService; + } + currentComboPackage->setServices(currentComboPackageServices); + } return m_comboPackageCache; } @@ -291,6 +337,49 @@ Returns: */ util::Map>& DataStore::getServiceBookings() { + util::Map> serviceBookings = loadRecords(m_serviceBookings); + refreshCache(m_serviceBookingCache, serviceBookings); + auto& users = getUsers(); + auto& services = getServices(); + size_t numberOfServiceBookings = m_serviceBookingCache.getSize(); + for (int iteratorOne = 0; iteratorOne < numberOfServiceBookings; iteratorOne++) + { + ServiceBooking* serviceBooking = m_serviceBookingCache.getValueAt(iteratorOne).data; + auto& serviceIds = serviceBooking->getServiceIDs(); + util::Map servicesInBooking; + for (int iteratorTwo = 0; iteratorTwo < serviceIds.getSize(); iteratorTwo++) + { + const std::string& currentServiceId = serviceIds[iteratorTwo]; + int serviceIndex = services.find(currentServiceId); + if (serviceIndex == -1) + { + throw std::runtime_error("Invalid service index."); + } + auto currentService = services.getValueAt(serviceIndex); + servicesInBooking[currentServiceId] = currentService.data; + } + serviceBooking->setServices(servicesInBooking); + if (!serviceBooking->getCustomerId().empty()) + { + int userIndex = users.find(serviceBooking->getCustomerId()); + if (userIndex == -1) + { + throw std::runtime_error("Invalid user index."); + } + auto customer = users.getValueAt(userIndex); + serviceBooking->setCustomer(customer.data); + } + if (!serviceBooking->getAssignedTechnicianId().empty()) + { + int technicianIndex = users.find(serviceBooking->getAssignedTechnicianId()); + if (technicianIndex == -1) + { + throw std::runtime_error("Invalid technician index."); + } + auto technician = users.getValueAt(technicianIndex); + serviceBooking->setAssignedTechnician(technician.data); + } + } return m_serviceBookingCache; } @@ -304,9 +393,51 @@ Returns: */ util::Map>& DataStore::getJobCards() { + util::Map> jobCards = loadRecords(m_jobCards); + refreshCache(m_jobCardCache, jobCards); + auto& serviceBookings = getServiceBookings(); + auto& services = getServices(); + auto& users = getUsers(); + int numberOfJobCards = m_jobCardCache.getSize(); + for (int iterator = 0; iterator < numberOfJobCards; iterator++) + { + JobCard* jobCard = m_jobCardCache.getValueAt(iterator).data; + if (!jobCard) + { + continue; + } + const std::string& bookingId = jobCard->getBookingId(); + int bookingIndex = serviceBookings.find(bookingId); + if (bookingIndex == -1) + { + throw std::runtime_error("Invalid booking ID: " + bookingId); + } + auto trackedBooking = serviceBookings.getValueAt(bookingIndex); + jobCard->setBooking(trackedBooking.data); + const std::string& serviceId = jobCard->getServiceId(); + int serviceIndex = services.find(serviceId); + if (serviceIndex == -1) + { + throw std::runtime_error("Invalid service ID: " + serviceId); + } + auto trackedService = services.getValueAt(serviceIndex); + jobCard->setService(trackedService.data); + const std::string& technicianId = jobCard->getTechnicianId(); + if (!technicianId.empty()) + { + int technicianIndex = users.find(technicianId); + if (technicianIndex == -1) + { + throw std::runtime_error("Invalid technician ID: " + technicianId); + } + auto trackedTechnician = users.getValueAt(technicianIndex); + jobCard->setTechnician(trackedTechnician.data); + } + } return m_jobCardCache; } + /* Function: getInvoices Description: Retrieves all invoice records from the datastore. @@ -426,6 +557,7 @@ Returns: */ void DataStore::saveServices() { + saveRecords(m_services, m_serviceCache); } /* @@ -438,6 +570,7 @@ Returns: */ void DataStore::saveComboPackages() { + saveRecords(m_comboPackages, m_comboPackageCache); } /* @@ -462,6 +595,7 @@ Returns: */ void DataStore::saveServiceBookings() { + saveRecords(m_serviceBookings, m_serviceBookingCache); } /* @@ -474,6 +608,7 @@ Returns: */ void DataStore::saveJobCards() { + saveRecords(m_jobCards, m_jobCardCache); } /* diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h index 265f8df..021d831 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/datastores/DataStore.h @@ -11,6 +11,7 @@ Date: 19-May-2026 #include "Map.h" #include "MappingInfo.h" #include "TrackedRecord.h" +#include "SerializedRecords.h" #include "SharedMemory.h" #include "User.h" #include "Notification.h" diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.cpp index 4e69d9f..7e9d1a9 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.cpp @@ -9,6 +9,7 @@ Date: 19-May-2026 #include #include +#include "SerializedRecords.h" #include "ComboPackage.h" #include "Service.h" #include "Factory.h" @@ -28,7 +29,8 @@ Returns: ComboPackage::ComboPackage() : m_id("CMP" + std::to_string(++m_uid)), m_status(util::State::ACTIVE), - m_discountPercentage(0.0) {} + m_discountPercentage(0.0) { +} /* Function: ComboPackage @@ -270,72 +272,38 @@ static util::Vector getServiceIDsAsVector(const std::string& servic /* Function: serialize -Description: Serializes the combo package into a CSV-formatted string. +Description: Serializes the ComboPackage object into a SerializedComboPackage record. Parameters: - None Returns: - - std::string: Serialized combo package record + - SerializedComboPackage: Serialized representation of the combo package */ -std::string ComboPackage::serialize() const +SerializedComboPackage ComboPackage::serialize() const { - std::ostringstream serializedComboPackage; - serializedComboPackage << m_id << ',' - << m_packageName << ',' - << m_discountPercentage << ',' - << getServiceIDsAsString(m_serviceIDs) << ',' - << util::getStateString(m_status); - return serializedComboPackage.str(); + SerializedComboPackage serialized = {}; + strcpy_s(serialized.id, sizeof(serialized.id), m_id.c_str()); + strcpy_s(serialized.packageName, sizeof(serialized.packageName), m_packageName.c_str()); + strcpy_s(serialized.serviceIDs, sizeof(serialized.serviceIDs), getServiceIDsAsString(m_serviceIDs).c_str()); + serialized.discountPercentage = m_discountPercentage; + serialized.status = m_status; + return serialized; } /* Function: deserialize -Description: Deserializes a CSV-formatted string into a ComboPackage object. +Description: Deserializes a SerializedComboPackage record into a ComboPackage object. Parameters: - - record: const std::string&, serialized combo package record + - serializedComboPackage: const SerializedComboPackage&, serialized combo package record Returns: - ComboPackage*: Pointer to the deserialized ComboPackage object -Throws: - - std::runtime_error if data is invalid */ -ComboPackage* ComboPackage::deserialize(const std::string& record) +ComboPackage* ComboPackage::deserialize(const SerializedComboPackage& serializedComboPackage) { - std::string id, packageName; - std::string discountPercentageString, serviceIDsString, statusString; - double discountPercentage; - std::istringstream serializedComboPackage(record); - getline(serializedComboPackage, id, ','); - getline(serializedComboPackage, packageName, ','); - getline(serializedComboPackage, discountPercentageString, ','); - getline(serializedComboPackage, serviceIDsString, ','); - getline(serializedComboPackage, statusString, ','); - try - { - discountPercentage = std::stod(discountPercentageString); - } - catch (...) - { - throw std::runtime_error("Invalid combo package data"); - } - util::Vector serviceIDs = getServiceIDsAsVector(serviceIDsString); - util::State status = util::getState(statusString); + util::Vector serviceIDs = getServiceIDsAsVector(serializedComboPackage.serviceIDs); return Factory::getObject( - id, - packageName, - discountPercentage, + serializedComboPackage.id, + serializedComboPackage.packageName, + serializedComboPackage.discountPercentage, serviceIDs, - status - ); -} - -/* -Function: getHeaders -Description: Retrieves the CSV headers for combo package serialization. -Parameters: - - None -Returns: - - std::string: Header string ("ID,PackageName,DiscountPercentage,ServiceIDs,Status") -*/ -std::string ComboPackage::getHeaders() -{ - return "ID,PackageName,DiscountPercentage,ServiceIDs,Status"; -} + serializedComboPackage.status); +} \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.h index 29be6a9..671e346 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ComboPackage.h @@ -39,7 +39,6 @@ public: void setDiscountPercentage(double discountPercentage); void setServices(const util::Map& services); void setState(util::State status); - std::string serialize() const; - static ComboPackage* deserialize(const std::string&); - static std::string getHeaders(); + SerializedComboPackage serialize() const; + static ComboPackage* deserialize(const SerializedComboPackage&); }; \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp index 214a8e0..0bea7c2 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.cpp @@ -9,6 +9,7 @@ Date:19-May-2026 #include #include +#include "SerializedRecords.h" #include "JobCard.h" #include "Factory.h" #include "StringHelper.h" @@ -28,7 +29,8 @@ JobCard::JobCard() m_booking(nullptr), m_service(nullptr), m_technician(nullptr), - m_status(util::ServiceJobStatus()) {} + m_status(util::ServiceJobStatus()) { +} /* Function: JobCard @@ -65,7 +67,8 @@ JobCard::JobCard(const std::string& bookingId, m_technician(technician), m_assignedDate(assignedDate), m_status(status), - m_completionDate(completionDate) {} + m_completionDate(completionDate) { +} /* Function: JobCard (parameterized constructor with ID) @@ -351,79 +354,41 @@ void JobCard::setCompletionDate(const util::Timestamp& completionDate) /* Function: serialize -Description: Serializes the job card into a CSV-formatted string. +Description: Serializes the JobCard object into a SerializedJobCard record. Parameters: - None Returns: - - std::string: Serialized job card record + - SerializedJobCard: Serialized representation of the job card */ -std::string JobCard::serialize() const +SerializedJobCard JobCard::serialize() const { - std::ostringstream serializedJobCard; - serializedJobCard << m_id << ',' - << m_bookingId << ',' - << m_serviceId << ',' - << m_technicianId << ',' - << m_assignedDate.toString() << ',' - << util::getServiceJobStatusString(m_status) << ',' - << m_completionDate.toString(); - return serializedJobCard.str(); + SerializedJobCard serialized = {}; + strcpy_s(serialized.id, sizeof(serialized.id), m_id.c_str()); + strcpy_s(serialized.bookingId, sizeof(serialized.bookingId), m_bookingId.c_str()); + strcpy_s(serialized.serviceId, sizeof(serialized.serviceId), m_serviceId.c_str()); + strcpy_s(serialized.technicianId, sizeof(serialized.technicianId), m_technicianId.c_str()); + serialized.assignedDate = m_assignedDate; + serialized.status = m_status; + serialized.completionDate = m_completionDate; + return serialized; } /* Function: deserialize -Description: Deserializes a CSV-formatted string into a JobCard object. +Description: Deserializes a SerializedJobCard record into a JobCard object. Parameters: - - record: const std::string&, serialized job card record + - serializedJobCard: const SerializedJobCard&, serialized job card record Returns: - JobCard*: Pointer to the deserialized JobCard object -Throws: - - std::runtime_error if timestamp parsing fails */ -JobCard* JobCard::deserialize(const std::string& record) +JobCard* JobCard::deserialize(const SerializedJobCard& serializedJobCard) { - std::string id, bookingId, serviceId, technicianId; - std::string assignedDateString, statusString, completionDateString; - std::istringstream serializedJobCard(record); - getline(serializedJobCard, id, ','); - getline(serializedJobCard, bookingId, ','); - getline(serializedJobCard, serviceId, ','); - getline(serializedJobCard, technicianId, ','); - getline(serializedJobCard, assignedDateString, ','); - getline(serializedJobCard, statusString, ','); - getline(serializedJobCard, completionDateString, ','); - util::Timestamp assignedDate; - util::Timestamp completionDate; - try - { - assignedDate = util::Timestamp::fromString(assignedDateString); - completionDate = util::Timestamp::fromString(completionDateString); - } - catch (...) - { - throw std::runtime_error("Invalid timestamp"); - } - util::ServiceJobStatus status = util::getServiceJobStatus(statusString); return Factory::getObject( - id, - bookingId, - serviceId, - technicianId, - assignedDate, - status, - completionDate - ); -} - -/* -Function: getHeaders -Description: Retrieves the CSV headers for job card serialization. -Parameters: - - None -Returns: - - std::string: Header string ("ID,BookingID,ServiceID,TechnicianID,AssignedDate,Status,CompletionDate") -*/ -std::string JobCard::getHeaders() -{ - return "ID,BookingID,ServiceID,TechnicianID,AssignedDate,Status,CompletionDate"; + serializedJobCard.id, + serializedJobCard.bookingId, + serializedJobCard.serviceId, + serializedJobCard.technicianId, + serializedJobCard.assignedDate, + serializedJobCard.status, + serializedJobCard.completionDate); } \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h index a845263..ed243e8 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/JobCard.h @@ -15,6 +15,7 @@ Date:19-May-2026 class ServiceBooking; class Service; class User; +struct SerializedJobCard; class JobCard { @@ -34,11 +35,11 @@ public: JobCard(); JobCard(const std::string& bookingId, ServiceBooking* booking, - Service* service, - const std::string& serviceId, - const std::string& technicianId, - User* technician, - const util::Timestamp& assignedDate, + Service* service, + const std::string& serviceId, + const std::string& technicianId, + User* technician, + const util::Timestamp& assignedDate, util::ServiceJobStatus status, const util::Timestamp& completionDate ); @@ -70,7 +71,6 @@ public: void setAssignedDate(const util::Timestamp& assignedDate); void setStatus(util::ServiceJobStatus status); void setCompletionDate(const util::Timestamp& completionDate); - std::string serialize() const; - static JobCard* deserialize(const std::string&); - static std::string getHeaders(); + SerializedJobCard serialize() const; + static JobCard* deserialize(const SerializedJobCard&); }; \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.cpp index 0717467..fc39531 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.cpp @@ -8,6 +8,7 @@ Date: 19-May-2026 */ #include +#include "SerializedRecords.h" #include "Service.h" #include "InventoryItem.h" #include "StringHelper.h" @@ -27,7 +28,8 @@ Returns: Service::Service() : m_id("SRV" + std::to_string(++m_uid)), m_status(util::State::ACTIVE), - m_laborCost(0.0) {} + m_laborCost(0.0) { +} /* Function: Service @@ -44,7 +46,7 @@ Service::Service(const std::string& name, const util::Map getInventoryItemIDsAsVector(const std::string& /* Function: serialize -Description: Serializes the service into a CSV-formatted string. +Description: Serializes the Service object into a SerializedService record. Parameters: - None Returns: - - std::string: Serialized service record + - SerializedService: Serialized representation of the service */ -std::string Service::serialize() const +SerializedService Service::serialize() const { - std::ostringstream serializedService; - serializedService << m_id << ',' - << m_name << ',' - << getInventoryItemIDsAsString(m_requiredInventoryItemIDs) << ',' - << m_laborCost << ',' - << util::getStateString(m_status); - return serializedService.str(); + SerializedService serialized = {}; + strcpy_s(serialized.id, sizeof(serialized.id), m_id.c_str()); + strcpy_s(serialized.name, sizeof(serialized.name), m_name.c_str()); + strcpy_s(serialized.inventoryItemIDs, sizeof(serialized.inventoryItemIDs), getInventoryItemIDsAsString(m_requiredInventoryItemIDs).c_str()); + serialized.laborCost = m_laborCost; + serialized.status = m_status; + return serialized; } /* Function: deserialize -Description: Deserializes a CSV-formatted string into a Service object. +Description: Deserializes a SerializedService record into a Service object. Parameters: - - record: const std::string&, serialized service record + - serializedService: const SerializedService&, serialized service record Returns: - Service*: Pointer to the deserialized Service object -Throws: - - std::runtime_error if labor cost parsing fails */ -Service* Service::deserialize(const std::string& record) +Service* Service::deserialize(const SerializedService& serializedService) { - std::string id, name; - std::string inventoryItemIDsString, laborCostString, statusString; - double laborCost; - std::istringstream serializedService(record); - getline(serializedService, id, ','); - getline(serializedService, name, ','); - getline(serializedService, inventoryItemIDsString, ','); - getline(serializedService, laborCostString, ','); - getline(serializedService, statusString, ','); - util::Vector inventoryItemIDs = getInventoryItemIDsAsVector(inventoryItemIDsString); - try - { - laborCost = std::stod(laborCostString); - } - catch (...) - { - throw std::runtime_error("Invalid labor cost"); - } - util::State status = util::getState(statusString); + util::Vector inventoryItemIDs = getInventoryItemIDsAsVector(serializedService.inventoryItemIDs); return Factory::getObject( - id, - name, + serializedService.id, + serializedService.name, inventoryItemIDs, - laborCost, - status - ); -} - -/* -Function: getHeaders -Description: Retrieves the CSV headers for service serialization. -Parameters: - - None -Returns: - - std::string: Header string ("ID,Name,InventoryIDs,LaborCost,Status") -*/ -std::string Service::getHeaders() -{ - return "ID,Name,InventoryIDs,LaborCost,Status"; + serializedService.laborCost, + serializedService.status); } \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.h index b80e674..bff13d6 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/Service.h @@ -6,7 +6,6 @@ Author: Trenser Date: 19-May-2026 */ - #pragma once #include #include "Map.h" @@ -14,6 +13,7 @@ Date: 19-May-2026 #include "Enums.h" class InventoryItem; +struct SerializedService; class Service { @@ -40,7 +40,6 @@ public: void setRequiredInventoryItems(const util::Map& requiredInventoryItems); void setLaborCost(double laborCost); void setState(util::State status); - std::string serialize() const; - static Service* deserialize(const std::string&); - static std::string getHeaders(); + SerializedService serialize() const; + static Service* deserialize(const SerializedService&); }; \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp index 31b9d87..bd7d4d1 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.cpp @@ -6,8 +6,10 @@ Description: Implementation file containing the method definitions of the Author: Trenser Date:19-May-2026 */ + #include #include +#include "SerializedRecords.h" #include "ServiceBooking.h" #include "Service.h" #include "Enums.h" @@ -28,7 +30,8 @@ ServiceBooking::ServiceBooking() m_customer(nullptr), m_assignedTechnician(nullptr), m_status(util::ServiceJobStatus::PENDING), - m_discountPercentage(0.0) {} + m_discountPercentage(0.0) { +} /* Function: ServiceBooking @@ -437,84 +440,46 @@ static util::Vector getServiceIDsAsVector(const std::string& servic /* Function: serialize -Description: Serializes the service booking into a CSV-formatted string. +Description: Serializes the ServiceBooking object into a SerializedServiceBooking record. Parameters: - None Returns: - - std::string: Serialized booking record + - SerializedServiceBooking: Serialized representation of the service booking */ -std::string ServiceBooking::serialize() const +SerializedServiceBooking ServiceBooking::serialize() const { - std::ostringstream serializedBooking; - serializedBooking << m_id << ',' - << util::getServiceJobStatusString(m_status) << ',' - << getServiceIDsAsString(m_serviceIDs) << ',' - << m_customerId << ',' - << m_vehicleNumber << ',' - << m_vehicleBrand << ',' - << m_vehicleModel << ',' - << m_assignedTechnicianId << ',' - << m_discountPercentage << ','; - return serializedBooking.str(); + SerializedServiceBooking serialized = {}; + strcpy_s(serialized.id, sizeof(serialized.id), m_id.c_str()); + strcpy_s(serialized.serviceIDs, sizeof(serialized.serviceIDs), getServiceIDsAsString(m_serviceIDs).c_str()); + strcpy_s(serialized.customerId, sizeof(serialized.customerId), m_customerId.c_str()); + strcpy_s(serialized.vehicleNumber, sizeof(serialized.vehicleNumber), m_vehicleNumber.c_str()); + strcpy_s(serialized.vehicleBrand, sizeof(serialized.vehicleBrand), m_vehicleBrand.c_str()); + strcpy_s(serialized.vehicleModel, sizeof(serialized.vehicleModel), m_vehicleModel.c_str()); + strcpy_s(serialized.assignedTechnicianId, sizeof(serialized.assignedTechnicianId), m_assignedTechnicianId.c_str()); + serialized.status = m_status; + serialized.discountPercentage = m_discountPercentage; + return serialized; } /* Function: deserialize -Description: Deserializes a CSV-formatted string into a ServiceBooking object. +Description: Deserializes a SerializedServiceBooking record into a ServiceBooking object. Parameters: - - record: const std::string&, serialized booking record + - serializedServiceBooking: const SerializedServiceBooking&, serialized service booking record Returns: - ServiceBooking*: Pointer to the deserialized ServiceBooking object -Throws: - - std::runtime_error if discount percentage parsing fails */ -ServiceBooking* ServiceBooking::deserialize(const std::string& record) +ServiceBooking* ServiceBooking::deserialize(const SerializedServiceBooking& serializedServiceBooking) { - std::string id, customerId, vehicleNumber, vehicleBrand, vehicleModel, assignedTechnicianId; - std::string serviceJobStatusString, serviceIDsString, discountPercentageString; - double discountPercentage; - std::istringstream serializedBooking(record); - getline(serializedBooking, id, ','); - getline(serializedBooking, serviceJobStatusString, ','); - getline(serializedBooking, serviceIDsString, ','); - getline(serializedBooking, customerId, ','); - getline(serializedBooking, vehicleNumber, ','); - getline(serializedBooking, vehicleBrand, ','); - getline(serializedBooking, vehicleModel, ','); - getline(serializedBooking, assignedTechnicianId, ','); - getline(serializedBooking, discountPercentageString, ','); - util::Vector serviceIDs = getServiceIDsAsVector(serviceIDsString); - try - { - discountPercentage = std::stod(discountPercentageString); - } - catch (...) - { - throw std::runtime_error("Invalid discount percentage"); - } - util::ServiceJobStatus status = util::getServiceJobStatus(serviceJobStatusString); + util::Vector serviceIDs = getServiceIDsAsVector(serializedServiceBooking.serviceIDs); return Factory::getObject( - id, - status, + serializedServiceBooking.id, + serializedServiceBooking.status, serviceIDs, - customerId, - vehicleNumber, - vehicleBrand, - vehicleModel, - assignedTechnicianId, - discountPercentage - ); -} - -/* -Function: getHeaders -Description: Retrieves the CSV headers for service booking serialization. -Parameters: - - None -Returns: - - std::string: Header string ("ID,Status,ServiceIDs,CustomerID,VehicleNumber,VehicleBrand,VehicleModel,AssignedTechnicianID,DiscountPercentage") -*/ -std::string ServiceBooking::getHeaders() -{ - return "ID,Status,ServiceIDs,CustomerID,VehicleNumber,VehicleBrand,VehicleModel,AssignedTechnicianID,DiscountPercentage"; + serializedServiceBooking.customerId, + serializedServiceBooking.vehicleNumber, + serializedServiceBooking.vehicleBrand, + serializedServiceBooking.vehicleModel, + serializedServiceBooking.assignedTechnicianId, + serializedServiceBooking.discountPercentage); } \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h index 24acb32..433d9d1 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/models/ServiceBooking.h @@ -6,6 +6,7 @@ Description: Header file declaring the ServiceBooking class, which represents Author: Trenser Date:19-May-2026 */ + #pragma once #include #include "Map.h" @@ -14,6 +15,7 @@ Date:19-May-2026 class Service; class User; +struct SerializedServiceBooking; class ServiceBooking { @@ -78,7 +80,6 @@ public: void setAssignedTechnicianId(const std::string& assignedTechnicianId); void setAssignedTechnician(User* assignedTechnician); void setDiscountPercentage(double discountPercentage); - std::string serialize() const; - static ServiceBooking* deserialize(const std::string&); - static std::string getHeaders(); + SerializedServiceBooking serialize() const; + static ServiceBooking* deserialize(const SerializedServiceBooking&); }; \ No newline at end of file diff --git a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp index e294249..ed59380 100644 --- a/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp +++ b/Trenser.VehicleServiceSystem/Trenser.VehicleServiceSystem/services/ServiceManagementService.cpp @@ -24,6 +24,7 @@ Date:19-May-2026 #include "Timestamp.h" #include "User.h" #include "UserManagementService.h" +#include "DataStoreLockGuard.h" #include "Utility.h" #include "DataStoreLockGuard.h" @@ -46,18 +47,19 @@ void ServiceManagementService::purchaseService(const util::Vector& { throw std::runtime_error("No user is currently logged in!"); } - auto& servicesMap = m_dataStore.getServices(); - auto& serviceBookingMap = m_dataStore.getServiceBookings(); + DataStoreLockGuard lock(m_dataStore); + auto& trackedServicesMap = m_dataStore.getServices(); + auto& trackedServiceBookingMap = m_dataStore.getServiceBookings(); util::Map selectedServices; int selectedServicesCount = serviceIDs.getSize(); for (int index = 0; index < selectedServicesCount; index++) { - int serviceIndex = servicesMap.find(serviceIDs[index]); + int serviceIndex = trackedServicesMap.find(serviceIDs[index]); if (serviceIndex == -1) { throw std::runtime_error("Service not found!"); } - Service* service = servicesMap.getValueAt(serviceIndex); + Service* service = trackedServicesMap.getValueAt(serviceIndex).data; selectedServices[service->getId()] = service; } ServiceBooking* serviceBooking = Factory::getObject(util::ServiceJobStatus::PENDING, selectedServices, authenticatedUser->getId(), authenticatedUser, vehicleNumber, vehicleBrand, vehicleModel, 0); @@ -65,7 +67,7 @@ void ServiceManagementService::purchaseService(const util::Vector& { throw std::runtime_error("Failed to create service booking"); } - serviceBookingMap[serviceBooking->getId()] = serviceBooking; + trackedServiceBookingMap[serviceBooking->getId()] = util::createNewRecord(serviceBooking); std::string title = "Service Booking succeeded"; std::string message = "Your service booking has been successfully placed with ID " + serviceBooking->getId(); sendNotification(authenticatedUser, title, message); @@ -90,21 +92,22 @@ void ServiceManagementService::purchaseComboPackage(const std::string& comboPack { throw std::runtime_error("No user is currently logged in!"); } - auto& comboPackagesMap = m_dataStore.getComboPackages(); - auto& serviceBookingMap = m_dataStore.getServiceBookings(); - int comboPackageIndex = comboPackagesMap.find(comboPackageID); + DataStoreLockGuard lock(m_dataStore); + auto& trackedComboPackagesMap = m_dataStore.getComboPackages(); + auto& trackedServiceBookingMap = m_dataStore.getServiceBookings(); + int comboPackageIndex = trackedComboPackagesMap.find(comboPackageID); if (comboPackageIndex == -1) { throw std::runtime_error("Combo Package not found!"); } - const ComboPackage* comboPackage = comboPackagesMap[comboPackageID]; + const ComboPackage* comboPackage = trackedComboPackagesMap[comboPackageID].data; util::Map selectedServices = comboPackage->getServices(); ServiceBooking* serviceBooking = Factory::getObject(util::ServiceJobStatus::PENDING, selectedServices, authenticatedUser->getId(), authenticatedUser, vehicleNumber, vehicleBrand, vehicleModel, comboPackage->getDiscountPercentage()); if (serviceBooking == nullptr) { throw std::runtime_error("Failed to create combo package service booking"); } - serviceBookingMap[serviceBooking->getId()] = serviceBooking; + trackedServiceBookingMap[serviceBooking->getId()] = util::createNewRecord(serviceBooking); std::string title = "Combo Package Service Booking succeeded"; std::string message = "Your service booking for the combo package has been successfully placed with ID " + serviceBooking->getId(); sendNotification(authenticatedUser, title, message); @@ -205,7 +208,7 @@ Description: Restores inventory quantities for all required items in the service Parameter: ServiceBooking* booking - Pointer to the booking whose inventory items need to be restored Return type: void */ -static void restoreInventory(ServiceBooking* booking) +static void restoreInventory(ServiceBooking* booking, util::Map>& trackedInventoryItems) { const int INCREMENT_VALUE = 1; if (!booking) @@ -224,9 +227,17 @@ static void restoreInventory(ServiceBooking* booking) for (int InventoryIterator = 0; InventoryIterator < items.getSize(); ++InventoryIterator) { InventoryItem* item = items.getValueAt(InventoryIterator); + const std::string& currentItemId = item->getId(); + int itemIndex = trackedInventoryItems.find(currentItemId); + if (itemIndex == -1) + { + continue; + } + auto& currentTrackedInventoryItem = trackedInventoryItems.getValueAt(itemIndex); if (item) { item->setQuantity(item->getQuantity() + INCREMENT_VALUE); + currentTrackedInventoryItem.state = RecordState::MODIFIED; } } } @@ -244,23 +255,28 @@ Parameters: util::UserType userType - Type of user initiating cancellation (CUSTOMER or TECHNICIAN) Return type: void */ -static void processBookingCancellation(ServiceBooking* booking, - util::Map& jobs, +static void processBookingCancellation(TrackedRecord& trackedBooking, + util::Map>& jobs, ServiceManagementService& currentService, - util::UserType userType) + util::UserType userType, + util::Map>& trackedInventoryItems) { + ServiceBooking* booking = trackedBooking.data; if (!booking) { return; } + const std::string& bookingId = booking->getId(); for (int jobIterator = 0; jobIterator < jobs.getSize(); ++jobIterator) { - JobCard* jobCard = jobs.getValueAt(jobIterator); + auto& trackedJobCard = jobs.getValueAt(jobIterator); + JobCard* jobCard = trackedJobCard.data; if (!jobCard || jobCard->getBookingId() != booking->getId() || jobCard->getStatus() == util::ServiceJobStatus::CANCELLED) { continue; } jobCard->setStatus(util::ServiceJobStatus::CANCELLED); + trackedJobCard.state = RecordState::MODIFIED; if (userType == util::UserType::CUSTOMER) { if (User* technician = booking->getAssignedTechnician()) @@ -293,7 +309,8 @@ static void processBookingCancellation(ServiceBooking* booking, } booking->setAssignedTechnician(nullptr); booking->setAssignedTechnicianId(""); - restoreInventory(booking); + trackedBooking.state = RecordState::MODIFIED; + restoreInventory(booking, trackedInventoryItems); } /* @@ -306,22 +323,25 @@ Return type: void */ void ServiceManagementService::cancelCustomerServiceBookings(const std::string& customerID) { - auto& users = m_dataStore.getUsers(); - int userIndex = users.find(customerID); + DataStoreLockGuard lock(m_dataStore); + auto& trackedUsers = m_dataStore.getUsers(); + int userIndex = trackedUsers.find(customerID); if (userIndex == -1) { throw std::runtime_error("User not found: " + customerID); } - User* customer = users.getValueAt(userIndex); + User* customer = trackedUsers.getValueAt(userIndex).data; if (!customer) { throw std::runtime_error("User not found: " + customerID); } - auto& bookings = m_dataStore.getServiceBookings(); - auto& jobs = m_dataStore.getJobCards(); - for (int iteratorOne = 0; iteratorOne < bookings.getSize(); iteratorOne++) + auto& trackedBookings = m_dataStore.getServiceBookings(); + auto& trackedJobs = m_dataStore.getJobCards(); + auto& trackedInventoryItems = m_dataStore.getInventoryItems(); + for (int iteratorOne = 0; iteratorOne < trackedBookings.getSize(); iteratorOne++) { - ServiceBooking* booking = bookings.getValueAt(iteratorOne); + auto& trackedBooking = trackedBookings.getValueAt(iteratorOne); + ServiceBooking* booking = trackedBooking.data; if (!booking) { continue; @@ -336,8 +356,12 @@ void ServiceManagementService::cancelCustomerServiceBookings(const std::string& { continue; } - processBookingCancellation(booking, jobs, *this, util::UserType::CUSTOMER); + processBookingCancellation(trackedBooking, trackedJobs, *this, util::UserType::CUSTOMER, trackedInventoryItems); } + m_dataStore.saveUsers(); + m_dataStore.saveServiceBookings(); + m_dataStore.saveJobCards(); + m_dataStore.saveInventoryItems(); } /* @@ -349,22 +373,25 @@ Return type: void */ void ServiceManagementService::cancelTechnicianJobs(const std::string& technicianID) { - auto& users = m_dataStore.getUsers(); - int userIndex = users.find(technicianID); + DataStoreLockGuard lock(m_dataStore); + auto& trackedUsers = m_dataStore.getUsers(); + int userIndex = trackedUsers.find(technicianID); if (userIndex == -1) { throw std::runtime_error("User not found: " + technicianID); } - User* technician = users.getValueAt(userIndex); + User* technician = trackedUsers.getValueAt(userIndex).data; if (!technician) { throw std::runtime_error("User not found: " + technicianID); } - auto& bookings = m_dataStore.getServiceBookings(); - auto& jobs = m_dataStore.getJobCards(); - for (int iteratorOne = 0; iteratorOne < bookings.getSize(); iteratorOne++) + auto& trackedBookings = m_dataStore.getServiceBookings(); + auto& trackedJobs = m_dataStore.getJobCards(); + auto& trackedInventoryItems = m_dataStore.getInventoryItems(); + for (int iteratorOne = 0; iteratorOne < trackedBookings.getSize(); iteratorOne++) { - ServiceBooking* booking = bookings.getValueAt(iteratorOne); + auto& trackedBooking = trackedBookings.getValueAt(iteratorOne); + ServiceBooking* booking = trackedBooking.data; if (!booking) { continue; @@ -385,8 +412,12 @@ void ServiceManagementService::cancelTechnicianJobs(const std::string& technicia { continue; } - processBookingCancellation(booking, jobs, *this, util::UserType::TECHNICIAN); + processBookingCancellation(trackedBooking, trackedJobs, *this, util::UserType::TECHNICIAN, trackedInventoryItems); } + m_dataStore.saveUsers(); + m_dataStore.saveInventoryItems(); + m_dataStore.saveServiceBookings(); + m_dataStore.saveJobCards(); } /* @@ -400,6 +431,7 @@ Return type: void */ void ServiceManagementService::createComboPackage(const std::string& packageName, const util::Vector& serviceIDsInNewCombo, double discountPercentage) { + DataStoreLockGuard lock(m_dataStore); if (packageName.empty()) { throw std::invalid_argument("The Combo Package Name cannot be empty.\n"); @@ -412,19 +444,19 @@ void ServiceManagementService::createComboPackage(const std::string& packageName { throw std::invalid_argument("Discount percentage must be between 0 and 100."); } - auto& servicesMap = m_dataStore.getServices(); + auto& trackedServicesMap = m_dataStore.getServices(); for (int index = 0; index < serviceIDsInNewCombo.getSize(); index++) { - const std::string serviceid = serviceIDsInNewCombo[index]; - if (servicesMap.find(serviceid) == -1) + const std::string& serviceid = serviceIDsInNewCombo[index]; + if (trackedServicesMap.find(serviceid) == -1) { throw std::runtime_error("Service ID not found: " + serviceid); } } - auto& comboPackageMap = m_dataStore.getComboPackages(); - for (int iterator = 0; iterator < comboPackageMap.getSize(); iterator++) + auto& trackedComboPackageMap = m_dataStore.getComboPackages(); + for (int iterator = 0; iterator < trackedComboPackageMap.getSize(); iterator++) { - ComboPackage* existingCombos = comboPackageMap.getValueAt(iterator); + ComboPackage* existingCombos = trackedComboPackageMap.getValueAt(iterator).data; const util::Map& servicesInsideExistingCombos = existingCombos->getServices(); if (servicesInsideExistingCombos.getSize() == serviceIDsInNewCombo.getSize()) { @@ -448,15 +480,16 @@ void ServiceManagementService::createComboPackage(const std::string& packageName for (int iteratorOne = 0; iteratorOne < serviceIDsInNewCombo.getSize(); iteratorOne++) { const std::string& serviceId = serviceIDsInNewCombo[iteratorOne]; - int serviceIndex = servicesMap.find(serviceId); + int serviceIndex = trackedServicesMap.find(serviceId); if (serviceIndex == -1) { throw std::runtime_error("Service ID not found: " + serviceId); } - selectedServices.insert(serviceId, servicesMap.getValueAt(serviceIndex)); + selectedServices.insert(serviceId, trackedServicesMap.getValueAt(serviceIndex).data); } ComboPackage* newComboPackage = Factory::getObject(packageName, discountPercentage, selectedServices); - comboPackageMap.insert(newComboPackage->getId(), newComboPackage); + trackedComboPackageMap.insert(newComboPackage->getId(), util::createNewRecord(newComboPackage)); + m_dataStore.saveComboPackages(); } /* @@ -467,7 +500,10 @@ Return type: util::Map */ util::Map ServiceManagementService::getComboPackages() { - return m_dataStore.getComboPackages(); + DataStoreLockGuard lock(m_dataStore); + util::Map comboPackages; + comboPackages = util::getObjects(m_dataStore.getComboPackages()); + return comboPackages; } /* @@ -478,14 +514,17 @@ Return type: void */ void ServiceManagementService::removeComboPackage(const std::string& comboPackageID) { + DataStoreLockGuard lock(m_dataStore); bool removed = false; - util::Map& currentComboPackages = m_dataStore.getComboPackages(); - for (int iterator = 0; iterator < currentComboPackages.getSize(); iterator++) + auto& trackedComboPackages = m_dataStore.getComboPackages(); + for (int iterator = 0; iterator < trackedComboPackages.getSize(); iterator++) { - ComboPackage* currentComboPackage = currentComboPackages.getValueAt(iterator); + auto& comboPackage = trackedComboPackages.getValueAt(iterator); + ComboPackage* currentComboPackage = comboPackage.data; if (currentComboPackage && currentComboPackage->getId() == comboPackageID) { currentComboPackage->setState(util::State::INACTIVE); + comboPackage.state = RecordState::MODIFIED; removed = true; break; } @@ -494,6 +533,7 @@ void ServiceManagementService::removeComboPackage(const std::string& comboPackag { throw std::runtime_error("Combo package with ID '" + comboPackageID + "' not found."); } + m_dataStore.saveComboPackages(); } /* @@ -506,7 +546,10 @@ Returns: */ util::Map ServiceManagementService::getServiceBookings() { - return m_dataStore.getServiceBookings(); + DataStoreLockGuard lock(m_dataStore); + util::Map serviceBookings; + serviceBookings = util::getObjects(m_dataStore.getServiceBookings()); + return serviceBookings; } /* @@ -545,9 +588,10 @@ Throws: */ void ServiceManagementService::createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID) { + DataStoreLockGuard lock(m_dataStore); UserManagementService m_userManagementService; ServiceBooking* currentBooking = getServiceBooking(bookingID); - auto& currentJobCards = m_dataStore.getJobCards(); + auto& currentTrackedJobCards = m_dataStore.getJobCards(); if (currentBooking == nullptr) { throw std::runtime_error("Service Booking not available"); @@ -593,7 +637,7 @@ void ServiceManagementService::createJobCard(const std::string& bookingID, const JobCard* jobCard = Factory::getObject(bookingID, currentBooking, currentService, serviceID, technicianID, selectedTechnician, util::Timestamp(), util::ServiceJobStatus::STARTED, util::Timestamp()); if (jobCard) { - currentJobCards.insert(jobCard->getId(), jobCard); + currentTrackedJobCards.insert(jobCard->getId(), util::createNewRecord(jobCard)); sendNotification(selectedTechnician, title, message); } else @@ -603,6 +647,7 @@ void ServiceManagementService::createJobCard(const std::string& bookingID, const title = "Technician assigned"; message = "A technician has been assigned to your Service Booking with ID " + bookingID; sendNotification(currentBooking->getCustomer(), title, message); + m_dataStore.saveJobCards(); } /* @@ -620,15 +665,17 @@ Throws: */ void ServiceManagementService::createService(const std::string& name, const util::Vector& inventoryItemIDs, double laborCost) { + DataStoreLockGuard lock(m_dataStore); util::Map currentServiceInventoryItems; - auto inventoryItems = m_dataStore.getInventoryItems(); + auto& trackedInventoryItems = m_dataStore.getInventoryItems(); + auto& currentServices = m_dataStore.getServices(); for (int iteratorOne =0; iteratorOne < inventoryItemIDs.getSize(); iteratorOne++) { std::string currentItemID = inventoryItemIDs[iteratorOne]; bool itemFound = false; - for (int iteratorTwo = 0; iteratorTwo < inventoryItems.getSize(); iteratorTwo++) + for (int iteratorTwo = 0; iteratorTwo < trackedInventoryItems.getSize(); iteratorTwo++) { - InventoryItem* currentInventoryItem = inventoryItems.getValueAt(iteratorTwo); + InventoryItem* currentInventoryItem = trackedInventoryItems.getValueAt(iteratorTwo).data; if (currentInventoryItem && currentInventoryItem->getId() == currentItemID) { itemFound = true; @@ -646,12 +693,12 @@ void ServiceManagementService::createService(const std::string& name, const util { throw std::runtime_error("Unable to create new service."); } - util::Map& currentServices = m_dataStore.getServices(); if (currentServices.find(newService->getId()) != -1) { throw std::runtime_error("Service with this ID Already exists."); } - currentServices.insert(newService->getId(), newService); + currentServices.insert(newService->getId(), util::createNewRecord(newService)); + m_dataStore.saveServices(); } /* @@ -664,7 +711,10 @@ Returns: */ util::Map ServiceManagementService::getServices() { - return m_dataStore.getServices(); + DataStoreLockGuard lock(m_dataStore); + util::Map services; + services = util::getObjects(m_dataStore.getServices()); + return services; } /* @@ -679,14 +729,19 @@ Throws: */ void ServiceManagementService::removeService(const std::string& serviceID) { - util::Map& currentServices = m_dataStore.getServices(); - util::Map& currentComboPackages = m_dataStore.getComboPackages(); - if (currentServices.find(serviceID) != -1) + DataStoreLockGuard lock(m_dataStore); + auto& currentTrackedServices = m_dataStore.getServices(); + auto& currentTrackedComboPackages = m_dataStore.getComboPackages(); + if (currentTrackedServices.find(serviceID) != -1) { - currentServices.getValueAt(currentServices.find(serviceID))->setState(util::State::INACTIVE); - for (int iterator = 0; iterator < currentComboPackages.getSize(); iterator++) + int serviceIndex, comboPackageIndex; + serviceIndex = currentTrackedServices.find(serviceID); + currentTrackedServices.getValueAt(serviceIndex).data->setState(util::State::INACTIVE); + currentTrackedServices.getValueAt(serviceIndex).state = RecordState::MODIFIED; + for (int iterator = 0; iterator < currentTrackedComboPackages.getSize(); iterator++) { - ComboPackage* currentComboPackage = currentComboPackages.getValueAt(iterator); + comboPackageIndex = iterator; + ComboPackage* currentComboPackage = currentTrackedComboPackages.getValueAt(iterator).data; if (currentComboPackage && currentComboPackage->getState() == util::State::ACTIVE) { util::Map currentServices = currentComboPackage->getServices(); @@ -696,6 +751,7 @@ void ServiceManagementService::removeService(const std::string& serviceID) if (currentService->getId() == serviceID) { currentComboPackage->setState(util::State::INACTIVE); + currentTrackedComboPackages.getValueAt(comboPackageIndex).state = RecordState::MODIFIED; break; } } @@ -706,6 +762,8 @@ void ServiceManagementService::removeService(const std::string& serviceID) { throw std::runtime_error("Service not found."); } + m_dataStore.saveServices(); + m_dataStore.saveComboPackages(); } /* @@ -744,11 +802,12 @@ Returns: */ util::Map ServiceManagementService::getJobCards(const std::string& technicianID) { - util::Map jobCards = m_dataStore.getJobCards(); + DataStoreLockGuard lock(m_dataStore); + auto& trackedJobCards = m_dataStore.getJobCards(); util::Map technicianJobCards; - for (int iterator = 0; iterator < jobCards.getSize(); iterator++) + for (int iterator = 0; iterator < trackedJobCards.getSize(); iterator++) { - JobCard* currentJobCard = jobCards.getValueAt(iterator); + JobCard* currentJobCard = trackedJobCards.getValueAt(iterator).data; if (currentJobCard->getTechnicianId() == technicianID) { technicianJobCards.insert(currentJobCard->getId(), currentJobCard); @@ -797,6 +856,7 @@ Returns: */ void ServiceManagementService::updateJobStatus(const std::string& jobID) { + DataStoreLockGuard lock(m_dataStore); AuthenticationManagementService authenticationManagementService; PaymentManagementService paymentManagementService; bool jobStatusUpdated = false, serviceBookingCompleted; @@ -811,8 +871,15 @@ void ServiceManagementService::updateJobStatus(const std::string& jobID) { throw std::runtime_error("No job cards assigned to the technician."); } + auto& trackedJobCards = m_dataStore.getJobCards(); + auto& trackedServiceBookings = m_dataStore.getServiceBookings(); if (currentAssignedJobs.find(jobID) != -1) { + int jobIndex = trackedJobCards.find(jobID); + if (jobIndex == -1) + { + throw std::runtime_error("Unable to fetch current job."); + } currentJob = currentAssignedJobs.getValueAt(currentAssignedJobs.find(jobID)); if (currentJob == nullptr) { @@ -821,16 +888,20 @@ void ServiceManagementService::updateJobStatus(const std::string& jobID) if (currentJob->getStatus() == util::ServiceJobStatus::STARTED) { currentJob->setStatus(util::ServiceJobStatus::IN_PROGRESS); + trackedJobCards.getValueAt(jobIndex).state = RecordState::MODIFIED; jobStatusUpdated = true; } else if (currentJob->getStatus() == util::ServiceJobStatus::IN_PROGRESS) { currentJob->setStatus(util::ServiceJobStatus::COMPLETED); + trackedJobCards.getValueAt(jobIndex).state = RecordState::MODIFIED; jobStatusUpdated = true; serviceBookingCompleted = hasCompletedAllJobs(currentJob->getBookingId(), currentAssignedJobs); if (serviceBookingCompleted) { + const std::string& bookingId = currentJob->getBookingId(); currentJob->getBooking()->setStatus(util::ServiceJobStatus::COMPLETED); + trackedServiceBookings.getValueAt(trackedServiceBookings.find(bookingId)).state = RecordState::MODIFIED; paymentManagementService.generateInvoice(currentJob->getBooking()); std::string title = "Service Booking completed. Invoice Generated."; std::string message = "Services completed for the booking and invoice generated."; @@ -846,4 +917,6 @@ void ServiceManagementService::updateJobStatus(const std::string& jobID) { throw std::runtime_error("Failed to update job status. Job may already be completed."); } + m_dataStore.saveJobCards(); + m_dataStore.saveServiceBookings(); } \ No newline at end of file