Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 623cff9cfd | |||
| 3d884c8329 | |||
| 79d6b47aa8 |
+2
-2
@@ -427,5 +427,5 @@ FodyWeavers.xsd
|
|||||||
*.msm
|
*.msm
|
||||||
*.msp
|
*.msp
|
||||||
|
|
||||||
# DAT Files
|
# CSV Files
|
||||||
*.dat
|
*.csv
|
||||||
|
|||||||
+1
@@ -181,6 +181,7 @@
|
|||||||
<ClInclude Include="utilities\Config.h" />
|
<ClInclude Include="utilities\Config.h" />
|
||||||
<ClInclude Include="utilities\Enums.h" />
|
<ClInclude Include="utilities\Enums.h" />
|
||||||
<ClInclude Include="utilities\FileHelper.h" />
|
<ClInclude Include="utilities\FileHelper.h" />
|
||||||
|
<ClInclude Include="utilities\FileManager.h" />
|
||||||
<ClInclude Include="utilities\InputHelper.h" />
|
<ClInclude Include="utilities\InputHelper.h" />
|
||||||
<ClInclude Include="utilities\Map.h" />
|
<ClInclude Include="utilities\Map.h" />
|
||||||
<ClInclude Include="utilities\OutputHelper.h" />
|
<ClInclude Include="utilities\OutputHelper.h" />
|
||||||
|
|||||||
+4
-1
@@ -242,6 +242,9 @@
|
|||||||
<ClInclude Include="utilities\Config.h">
|
<ClInclude Include="utilities\Config.h">
|
||||||
<Filter>Header Files\Utilities</Filter>
|
<Filter>Header Files\Utilities</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="utilities\FileManager.h">
|
||||||
|
<Filter>Header Files\Utilities</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="utilities\StringHelper.h">
|
<ClInclude Include="utilities\StringHelper.h">
|
||||||
<Filter>Header Files\Utilities</Filter>
|
<Filter>Header Files\Utilities</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -273,7 +276,7 @@
|
|||||||
<Filter>Header Files\DataStores\SharedMemory</Filter>
|
<Filter>Header Files\DataStores\SharedMemory</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="datastores\DataStoreLockGuard.h">
|
<ClInclude Include="datastores\DataStoreLockGuard.h">
|
||||||
<Filter>Header Files\DataStores</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -7,6 +7,8 @@ Date: 19-May-2026
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
class Notification;
|
||||||
|
|
||||||
class Observer
|
class Observer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
+33
-136
@@ -12,8 +12,6 @@ Date: 19-May-2026
|
|||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "SerializedRecords.h"
|
#include "SerializedRecords.h"
|
||||||
#include "FileHelper.h"
|
#include "FileHelper.h"
|
||||||
#include "ServiceBooking.h"
|
|
||||||
#include "JobCard.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: DataStore
|
Function: DataStore
|
||||||
@@ -146,6 +144,11 @@ bool DataStore::initialize()
|
|||||||
success = false;
|
success = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!SharedMemory::createOrOpenMapping(m_payments))
|
||||||
|
{
|
||||||
|
success = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (!SharedMemory::createOrOpenMapping(m_serviceManagementObservers))
|
if (!SharedMemory::createOrOpenMapping(m_serviceManagementObservers))
|
||||||
{
|
{
|
||||||
success = false;
|
success = false;
|
||||||
@@ -190,6 +193,7 @@ void DataStore::shutdown()
|
|||||||
SharedMemory::closeMapping(m_serviceBookings);
|
SharedMemory::closeMapping(m_serviceBookings);
|
||||||
SharedMemory::closeMapping(m_jobCards);
|
SharedMemory::closeMapping(m_jobCards);
|
||||||
SharedMemory::closeMapping(m_invoices);
|
SharedMemory::closeMapping(m_invoices);
|
||||||
|
SharedMemory::closeMapping(m_payments);
|
||||||
SharedMemory::closeMapping(m_serviceManagementObservers);
|
SharedMemory::closeMapping(m_serviceManagementObservers);
|
||||||
SharedMemory::closeMapping(m_paymentManagementObservers);
|
SharedMemory::closeMapping(m_paymentManagementObservers);
|
||||||
SharedMemory::closeMapping(m_inventoryManagementObservers);
|
SharedMemory::closeMapping(m_inventoryManagementObservers);
|
||||||
@@ -254,28 +258,6 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
util::Map<std::string, TrackedRecord<Service>>& DataStore::getServices()
|
util::Map<std::string, TrackedRecord<Service>>& DataStore::getServices()
|
||||||
{
|
{
|
||||||
util::Map<std::string, TrackedRecord<Service>> services = loadRecords<Service, SerializedService>(m_services);
|
|
||||||
refreshCache(m_serviceCache, services);
|
|
||||||
util::Map<std::string, TrackedRecord<InventoryItem>>& inventoryItems = getInventoryItems();
|
|
||||||
size_t numberOfServices = m_serviceCache.getSize();
|
|
||||||
for (int iteratorOne =0; iteratorOne < numberOfServices; iteratorOne++)
|
|
||||||
{
|
|
||||||
Service* currentService = m_serviceCache.getValueAt(iteratorOne).data;
|
|
||||||
util::Map<std::string, InventoryItem*> inventoryItemMap;
|
|
||||||
util::Vector<std::string> 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;
|
return m_serviceCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,28 +271,6 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
util::Map<std::string, TrackedRecord<ComboPackage>>& DataStore::getComboPackages()
|
util::Map<std::string, TrackedRecord<ComboPackage>>& DataStore::getComboPackages()
|
||||||
{
|
{
|
||||||
util::Map<std::string, TrackedRecord<ComboPackage>> comboPackages = loadRecords<ComboPackage, SerializedComboPackage>(m_comboPackages);
|
|
||||||
refreshCache(m_comboPackageCache, comboPackages);
|
|
||||||
util::Map<std::string, TrackedRecord<Service>>& services = getServices();
|
|
||||||
size_t numberOfComboPackages = m_comboPackageCache.getSize();
|
|
||||||
for (int iteratorOne = 0; iteratorOne < numberOfComboPackages; iteratorOne++)
|
|
||||||
{
|
|
||||||
ComboPackage* currentComboPackage = m_comboPackageCache.getValueAt(iteratorOne).data;
|
|
||||||
util::Vector<std::string> currentServiceIds = currentComboPackage->getServiceIDs();
|
|
||||||
util::Map<std::string, Service*> 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;
|
return m_comboPackageCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,49 +297,6 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
util::Map<std::string, TrackedRecord<ServiceBooking>>& DataStore::getServiceBookings()
|
util::Map<std::string, TrackedRecord<ServiceBooking>>& DataStore::getServiceBookings()
|
||||||
{
|
{
|
||||||
util::Map<std::string, TrackedRecord<ServiceBooking>> serviceBookings = loadRecords<ServiceBooking, SerializedServiceBooking>(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<std::string, Service*> 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;
|
return m_serviceBookingCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,51 +310,9 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
util::Map<std::string, TrackedRecord<JobCard>>& DataStore::getJobCards()
|
util::Map<std::string, TrackedRecord<JobCard>>& DataStore::getJobCards()
|
||||||
{
|
{
|
||||||
util::Map<std::string, TrackedRecord<JobCard>> jobCards = loadRecords<JobCard, SerializedJobCard>(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;
|
return m_jobCardCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: getInvoices
|
Function: getInvoices
|
||||||
Description: Retrieves all invoice records from the datastore.
|
Description: Retrieves all invoice records from the datastore.
|
||||||
@@ -557,7 +432,6 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
void DataStore::saveServices()
|
void DataStore::saveServices()
|
||||||
{
|
{
|
||||||
saveRecords<Service, SerializedService>(m_services, m_serviceCache);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -570,7 +444,6 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
void DataStore::saveComboPackages()
|
void DataStore::saveComboPackages()
|
||||||
{
|
{
|
||||||
saveRecords<ComboPackage, SerializedComboPackage>(m_comboPackages, m_comboPackageCache);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -595,7 +468,6 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
void DataStore::saveServiceBookings()
|
void DataStore::saveServiceBookings()
|
||||||
{
|
{
|
||||||
saveRecords<ServiceBooking, SerializedServiceBooking>(m_serviceBookings, m_serviceBookingCache);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -608,7 +480,6 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
void DataStore::saveJobCards()
|
void DataStore::saveJobCards()
|
||||||
{
|
{
|
||||||
saveRecords<JobCard, SerializedJobCard>(m_jobCards, m_jobCardCache);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -649,7 +520,7 @@ void DataStore::saveObservers(MappingInfo& mapping, util::Map<std::string, User*
|
|||||||
{
|
{
|
||||||
SerializedObserver serializedObserver;
|
SerializedObserver serializedObserver;
|
||||||
User* user = observers.getValueAt(static_cast<int>(index));
|
User* user = observers.getValueAt(static_cast<int>(index));
|
||||||
strcpy_s(serializedObserver.id, sizeof(serializedObserver.id), user->getId().c_str());
|
strcpy_s(serializedObserver.id, user->getId().c_str());
|
||||||
SerializedObserver* destination = static_cast<SerializedObserver*>(SharedMemory::getRecordAddress(mapping, index));
|
SerializedObserver* destination = static_cast<SerializedObserver*>(SharedMemory::getRecordAddress(mapping, index));
|
||||||
*destination = serializedObserver;
|
*destination = serializedObserver;
|
||||||
}
|
}
|
||||||
@@ -694,6 +565,32 @@ void DataStore::saveInventoryManagementObservers(util::Map<std::string, User*>&
|
|||||||
saveObservers(m_inventoryManagementObservers, observers);
|
saveObservers(m_inventoryManagementObservers, observers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: lockDataStore
|
||||||
|
Description: Acquires exclusive access to the datastore.
|
||||||
|
Parameters:
|
||||||
|
- None
|
||||||
|
Returns:
|
||||||
|
- bool: True if the datastore was successfully locked, otherwise false
|
||||||
|
*/
|
||||||
|
bool DataStore::lockDataStore()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: unlockDataStore
|
||||||
|
Description: Releases exclusive access to the datastore.
|
||||||
|
Parameters:
|
||||||
|
- None
|
||||||
|
Returns:
|
||||||
|
- bool: True if the datastore was successfully unlocked, otherwise false
|
||||||
|
*/
|
||||||
|
bool DataStore::unlockDataStore()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: lockDataStore
|
Function: lockDataStore
|
||||||
Description: Acquires the datastore mutex, providing
|
Description: Acquires the datastore mutex, providing
|
||||||
|
|||||||
@@ -11,16 +11,15 @@ Date: 19-May-2026
|
|||||||
#include "Map.h"
|
#include "Map.h"
|
||||||
#include "MappingInfo.h"
|
#include "MappingInfo.h"
|
||||||
#include "TrackedRecord.h"
|
#include "TrackedRecord.h"
|
||||||
#include "SerializedRecords.h"
|
|
||||||
#include "SharedMemory.h"
|
#include "SharedMemory.h"
|
||||||
#include "User.h"
|
class User;
|
||||||
#include "Notification.h"
|
class Notification;
|
||||||
#include "Service.h"
|
class Service;
|
||||||
#include "ComboPackage.h"
|
class ComboPackage;
|
||||||
#include "InventoryItem.h"
|
class InventoryItem;
|
||||||
#include "ServiceBooking.h"
|
class ServiceBooking;
|
||||||
#include "JobCard.h"
|
class JobCard;
|
||||||
#include "Invoice.h"
|
class Invoice;
|
||||||
|
|
||||||
class DataStore
|
class DataStore
|
||||||
{
|
{
|
||||||
@@ -40,6 +39,7 @@ private:
|
|||||||
MappingInfo m_serviceBookings;
|
MappingInfo m_serviceBookings;
|
||||||
MappingInfo m_jobCards;
|
MappingInfo m_jobCards;
|
||||||
MappingInfo m_invoices;
|
MappingInfo m_invoices;
|
||||||
|
MappingInfo m_payments;
|
||||||
MappingInfo m_serviceManagementObservers;
|
MappingInfo m_serviceManagementObservers;
|
||||||
MappingInfo m_paymentManagementObservers;
|
MappingInfo m_paymentManagementObservers;
|
||||||
MappingInfo m_inventoryManagementObservers;
|
MappingInfo m_inventoryManagementObservers;
|
||||||
@@ -231,17 +231,9 @@ void DataStore::refreshCache(util::Map<std::string, TrackedRecord<TObject>>& cac
|
|||||||
for (int index = 0; index < oldCache.getSize(); ++index)
|
for (int index = 0; index < oldCache.getSize(); ++index)
|
||||||
{
|
{
|
||||||
const std::string& id = oldCache.getKeyAt(index);
|
const std::string& id = oldCache.getKeyAt(index);
|
||||||
const TrackedRecord<TObject>& localTrackedRecord = oldCache.getValueAt(index);
|
|
||||||
if (cache.find(id) == -1)
|
if (cache.find(id) == -1)
|
||||||
{
|
{
|
||||||
if (localTrackedRecord.state == RecordState::NEW_RECORD)
|
delete oldCache.getValueAt(index).data;
|
||||||
{
|
|
||||||
cache.insert(id, localTrackedRecord);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
delete localTrackedRecord.data;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,6 @@ Date: 19-May-2026
|
|||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include "SerializedRecords.h"
|
|
||||||
#include "ComboPackage.h"
|
#include "ComboPackage.h"
|
||||||
#include "Service.h"
|
#include "Service.h"
|
||||||
#include "Factory.h"
|
#include "Factory.h"
|
||||||
@@ -29,8 +28,7 @@ Returns:
|
|||||||
ComboPackage::ComboPackage()
|
ComboPackage::ComboPackage()
|
||||||
: m_id("CMP" + std::to_string(++m_uid)),
|
: m_id("CMP" + std::to_string(++m_uid)),
|
||||||
m_status(util::State::ACTIVE),
|
m_status(util::State::ACTIVE),
|
||||||
m_discountPercentage(0.0) {
|
m_discountPercentage(0.0) {}
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: ComboPackage
|
Function: ComboPackage
|
||||||
@@ -272,38 +270,72 @@ static util::Vector<std::string> getServiceIDsAsVector(const std::string& servic
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Function: serialize
|
Function: serialize
|
||||||
Description: Serializes the ComboPackage object into a SerializedComboPackage record.
|
Description: Serializes the combo package into a CSV-formatted string.
|
||||||
Parameters:
|
Parameters:
|
||||||
- None
|
- None
|
||||||
Returns:
|
Returns:
|
||||||
- SerializedComboPackage: Serialized representation of the combo package
|
- std::string: Serialized combo package record
|
||||||
*/
|
*/
|
||||||
SerializedComboPackage ComboPackage::serialize() const
|
std::string ComboPackage::serialize() const
|
||||||
{
|
{
|
||||||
SerializedComboPackage serialized = {};
|
std::ostringstream serializedComboPackage;
|
||||||
strcpy_s(serialized.id, sizeof(serialized.id), m_id.c_str());
|
serializedComboPackage << m_id << ','
|
||||||
strcpy_s(serialized.packageName, sizeof(serialized.packageName), m_packageName.c_str());
|
<< m_packageName << ','
|
||||||
strcpy_s(serialized.serviceIDs, sizeof(serialized.serviceIDs), getServiceIDsAsString(m_serviceIDs).c_str());
|
<< m_discountPercentage << ','
|
||||||
serialized.discountPercentage = m_discountPercentage;
|
<< getServiceIDsAsString(m_serviceIDs) << ','
|
||||||
serialized.status = m_status;
|
<< util::getStateString(m_status);
|
||||||
return serialized;
|
return serializedComboPackage.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: deserialize
|
Function: deserialize
|
||||||
Description: Deserializes a SerializedComboPackage record into a ComboPackage object.
|
Description: Deserializes a CSV-formatted string into a ComboPackage object.
|
||||||
Parameters:
|
Parameters:
|
||||||
- serializedComboPackage: const SerializedComboPackage&, serialized combo package record
|
- record: const std::string&, serialized combo package record
|
||||||
Returns:
|
Returns:
|
||||||
- ComboPackage*: Pointer to the deserialized ComboPackage object
|
- ComboPackage*: Pointer to the deserialized ComboPackage object
|
||||||
|
Throws:
|
||||||
|
- std::runtime_error if data is invalid
|
||||||
*/
|
*/
|
||||||
ComboPackage* ComboPackage::deserialize(const SerializedComboPackage& serializedComboPackage)
|
ComboPackage* ComboPackage::deserialize(const std::string& record)
|
||||||
{
|
{
|
||||||
util::Vector<std::string> serviceIDs = getServiceIDsAsVector(serializedComboPackage.serviceIDs);
|
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<std::string> serviceIDs = getServiceIDsAsVector(serviceIDsString);
|
||||||
|
util::State status = util::getState(statusString);
|
||||||
return Factory::getObject<ComboPackage>(
|
return Factory::getObject<ComboPackage>(
|
||||||
serializedComboPackage.id,
|
id,
|
||||||
serializedComboPackage.packageName,
|
packageName,
|
||||||
serializedComboPackage.discountPercentage,
|
discountPercentage,
|
||||||
serviceIDs,
|
serviceIDs,
|
||||||
serializedComboPackage.status);
|
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";
|
||||||
}
|
}
|
||||||
@@ -12,7 +12,6 @@ Date: 19-May-2026
|
|||||||
#include "Enums.h"
|
#include "Enums.h"
|
||||||
|
|
||||||
class Service;
|
class Service;
|
||||||
struct SerializedComboPackage;
|
|
||||||
|
|
||||||
class ComboPackage
|
class ComboPackage
|
||||||
{
|
{
|
||||||
@@ -39,6 +38,7 @@ public:
|
|||||||
void setDiscountPercentage(double discountPercentage);
|
void setDiscountPercentage(double discountPercentage);
|
||||||
void setServices(const util::Map<std::string, Service*>& services);
|
void setServices(const util::Map<std::string, Service*>& services);
|
||||||
void setState(util::State status);
|
void setState(util::State status);
|
||||||
SerializedComboPackage serialize() const;
|
std::string serialize() const;
|
||||||
static ComboPackage* deserialize(const SerializedComboPackage&);
|
static ComboPackage* deserialize(const std::string&);
|
||||||
|
static std::string getHeaders();
|
||||||
};
|
};
|
||||||
@@ -9,7 +9,6 @@ Date:19-May-2026
|
|||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include "SerializedRecords.h"
|
|
||||||
#include "JobCard.h"
|
#include "JobCard.h"
|
||||||
#include "Factory.h"
|
#include "Factory.h"
|
||||||
#include "StringHelper.h"
|
#include "StringHelper.h"
|
||||||
@@ -29,8 +28,7 @@ JobCard::JobCard()
|
|||||||
m_booking(nullptr),
|
m_booking(nullptr),
|
||||||
m_service(nullptr),
|
m_service(nullptr),
|
||||||
m_technician(nullptr),
|
m_technician(nullptr),
|
||||||
m_status(util::ServiceJobStatus()) {
|
m_status(util::ServiceJobStatus()) {}
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: JobCard
|
Function: JobCard
|
||||||
@@ -67,8 +65,7 @@ JobCard::JobCard(const std::string& bookingId,
|
|||||||
m_technician(technician),
|
m_technician(technician),
|
||||||
m_assignedDate(assignedDate),
|
m_assignedDate(assignedDate),
|
||||||
m_status(status),
|
m_status(status),
|
||||||
m_completionDate(completionDate) {
|
m_completionDate(completionDate) {}
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: JobCard (parameterized constructor with ID)
|
Function: JobCard (parameterized constructor with ID)
|
||||||
@@ -354,41 +351,79 @@ void JobCard::setCompletionDate(const util::Timestamp& completionDate)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Function: serialize
|
Function: serialize
|
||||||
Description: Serializes the JobCard object into a SerializedJobCard record.
|
Description: Serializes the job card into a CSV-formatted string.
|
||||||
Parameters:
|
Parameters:
|
||||||
- None
|
- None
|
||||||
Returns:
|
Returns:
|
||||||
- SerializedJobCard: Serialized representation of the job card
|
- std::string: Serialized job card record
|
||||||
*/
|
*/
|
||||||
SerializedJobCard JobCard::serialize() const
|
std::string JobCard::serialize() const
|
||||||
{
|
{
|
||||||
SerializedJobCard serialized = {};
|
std::ostringstream serializedJobCard;
|
||||||
strcpy_s(serialized.id, sizeof(serialized.id), m_id.c_str());
|
serializedJobCard << m_id << ','
|
||||||
strcpy_s(serialized.bookingId, sizeof(serialized.bookingId), m_bookingId.c_str());
|
<< m_bookingId << ','
|
||||||
strcpy_s(serialized.serviceId, sizeof(serialized.serviceId), m_serviceId.c_str());
|
<< m_serviceId << ','
|
||||||
strcpy_s(serialized.technicianId, sizeof(serialized.technicianId), m_technicianId.c_str());
|
<< m_technicianId << ','
|
||||||
serialized.assignedDate = m_assignedDate;
|
<< m_assignedDate.toString() << ','
|
||||||
serialized.status = m_status;
|
<< util::getServiceJobStatusString(m_status) << ','
|
||||||
serialized.completionDate = m_completionDate;
|
<< m_completionDate.toString();
|
||||||
return serialized;
|
return serializedJobCard.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: deserialize
|
Function: deserialize
|
||||||
Description: Deserializes a SerializedJobCard record into a JobCard object.
|
Description: Deserializes a CSV-formatted string into a JobCard object.
|
||||||
Parameters:
|
Parameters:
|
||||||
- serializedJobCard: const SerializedJobCard&, serialized job card record
|
- record: const std::string&, serialized job card record
|
||||||
Returns:
|
Returns:
|
||||||
- JobCard*: Pointer to the deserialized JobCard object
|
- JobCard*: Pointer to the deserialized JobCard object
|
||||||
|
Throws:
|
||||||
|
- std::runtime_error if timestamp parsing fails
|
||||||
*/
|
*/
|
||||||
JobCard* JobCard::deserialize(const SerializedJobCard& serializedJobCard)
|
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<JobCard>(
|
return Factory::getObject<JobCard>(
|
||||||
serializedJobCard.id,
|
id,
|
||||||
serializedJobCard.bookingId,
|
bookingId,
|
||||||
serializedJobCard.serviceId,
|
serviceId,
|
||||||
serializedJobCard.technicianId,
|
technicianId,
|
||||||
serializedJobCard.assignedDate,
|
assignedDate,
|
||||||
serializedJobCard.status,
|
status,
|
||||||
serializedJobCard.completionDate);
|
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";
|
||||||
}
|
}
|
||||||
@@ -15,7 +15,6 @@ Date:19-May-2026
|
|||||||
class ServiceBooking;
|
class ServiceBooking;
|
||||||
class Service;
|
class Service;
|
||||||
class User;
|
class User;
|
||||||
struct SerializedJobCard;
|
|
||||||
|
|
||||||
class JobCard
|
class JobCard
|
||||||
{
|
{
|
||||||
@@ -71,6 +70,7 @@ public:
|
|||||||
void setAssignedDate(const util::Timestamp& assignedDate);
|
void setAssignedDate(const util::Timestamp& assignedDate);
|
||||||
void setStatus(util::ServiceJobStatus status);
|
void setStatus(util::ServiceJobStatus status);
|
||||||
void setCompletionDate(const util::Timestamp& completionDate);
|
void setCompletionDate(const util::Timestamp& completionDate);
|
||||||
SerializedJobCard serialize() const;
|
std::string serialize() const;
|
||||||
static JobCard* deserialize(const SerializedJobCard&);
|
static JobCard* deserialize(const std::string&);
|
||||||
|
static std::string getHeaders();
|
||||||
};
|
};
|
||||||
@@ -8,7 +8,6 @@ Date: 19-May-2026
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "SerializedRecords.h"
|
|
||||||
#include "Service.h"
|
#include "Service.h"
|
||||||
#include "InventoryItem.h"
|
#include "InventoryItem.h"
|
||||||
#include "StringHelper.h"
|
#include "StringHelper.h"
|
||||||
@@ -28,8 +27,7 @@ Returns:
|
|||||||
Service::Service()
|
Service::Service()
|
||||||
: m_id("SRV" + std::to_string(++m_uid)),
|
: m_id("SRV" + std::to_string(++m_uid)),
|
||||||
m_status(util::State::ACTIVE),
|
m_status(util::State::ACTIVE),
|
||||||
m_laborCost(0.0) {
|
m_laborCost(0.0) {}
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: Service
|
Function: Service
|
||||||
@@ -268,38 +266,72 @@ static util::Vector<std::string> getInventoryItemIDsAsVector(const std::string&
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Function: serialize
|
Function: serialize
|
||||||
Description: Serializes the Service object into a SerializedService record.
|
Description: Serializes the service into a CSV-formatted string.
|
||||||
Parameters:
|
Parameters:
|
||||||
- None
|
- None
|
||||||
Returns:
|
Returns:
|
||||||
- SerializedService: Serialized representation of the service
|
- std::string: Serialized service record
|
||||||
*/
|
*/
|
||||||
SerializedService Service::serialize() const
|
std::string Service::serialize() const
|
||||||
{
|
{
|
||||||
SerializedService serialized = {};
|
std::ostringstream serializedService;
|
||||||
strcpy_s(serialized.id, sizeof(serialized.id), m_id.c_str());
|
serializedService << m_id << ','
|
||||||
strcpy_s(serialized.name, sizeof(serialized.name), m_name.c_str());
|
<< m_name << ','
|
||||||
strcpy_s(serialized.inventoryItemIDs, sizeof(serialized.inventoryItemIDs), getInventoryItemIDsAsString(m_requiredInventoryItemIDs).c_str());
|
<< getInventoryItemIDsAsString(m_requiredInventoryItemIDs) << ','
|
||||||
serialized.laborCost = m_laborCost;
|
<< m_laborCost << ','
|
||||||
serialized.status = m_status;
|
<< util::getStateString(m_status);
|
||||||
return serialized;
|
return serializedService.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: deserialize
|
Function: deserialize
|
||||||
Description: Deserializes a SerializedService record into a Service object.
|
Description: Deserializes a CSV-formatted string into a Service object.
|
||||||
Parameters:
|
Parameters:
|
||||||
- serializedService: const SerializedService&, serialized service record
|
- record: const std::string&, serialized service record
|
||||||
Returns:
|
Returns:
|
||||||
- Service*: Pointer to the deserialized Service object
|
- Service*: Pointer to the deserialized Service object
|
||||||
|
Throws:
|
||||||
|
- std::runtime_error if labor cost parsing fails
|
||||||
*/
|
*/
|
||||||
Service* Service::deserialize(const SerializedService& serializedService)
|
Service* Service::deserialize(const std::string& record)
|
||||||
{
|
{
|
||||||
util::Vector<std::string> inventoryItemIDs = getInventoryItemIDsAsVector(serializedService.inventoryItemIDs);
|
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<std::string> 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<Service>(
|
return Factory::getObject<Service>(
|
||||||
serializedService.id,
|
id,
|
||||||
serializedService.name,
|
name,
|
||||||
inventoryItemIDs,
|
inventoryItemIDs,
|
||||||
serializedService.laborCost,
|
laborCost,
|
||||||
serializedService.status);
|
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";
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,7 @@ Author: Trenser
|
|||||||
Date: 19-May-2026
|
Date: 19-May-2026
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "Map.h"
|
#include "Map.h"
|
||||||
@@ -13,7 +14,6 @@ Date: 19-May-2026
|
|||||||
#include "Enums.h"
|
#include "Enums.h"
|
||||||
|
|
||||||
class InventoryItem;
|
class InventoryItem;
|
||||||
struct SerializedService;
|
|
||||||
|
|
||||||
class Service
|
class Service
|
||||||
{
|
{
|
||||||
@@ -40,6 +40,7 @@ public:
|
|||||||
void setRequiredInventoryItems(const util::Map<std::string, InventoryItem*>& requiredInventoryItems);
|
void setRequiredInventoryItems(const util::Map<std::string, InventoryItem*>& requiredInventoryItems);
|
||||||
void setLaborCost(double laborCost);
|
void setLaborCost(double laborCost);
|
||||||
void setState(util::State status);
|
void setState(util::State status);
|
||||||
SerializedService serialize() const;
|
std::string serialize() const;
|
||||||
static Service* deserialize(const SerializedService&);
|
static Service* deserialize(const std::string&);
|
||||||
|
static std::string getHeaders();
|
||||||
};
|
};
|
||||||
+65
-30
@@ -6,10 +6,8 @@ Description: Implementation file containing the method definitions of the
|
|||||||
Author: Trenser
|
Author: Trenser
|
||||||
Date:19-May-2026
|
Date:19-May-2026
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "SerializedRecords.h"
|
|
||||||
#include "ServiceBooking.h"
|
#include "ServiceBooking.h"
|
||||||
#include "Service.h"
|
#include "Service.h"
|
||||||
#include "Enums.h"
|
#include "Enums.h"
|
||||||
@@ -30,8 +28,7 @@ ServiceBooking::ServiceBooking()
|
|||||||
m_customer(nullptr),
|
m_customer(nullptr),
|
||||||
m_assignedTechnician(nullptr),
|
m_assignedTechnician(nullptr),
|
||||||
m_status(util::ServiceJobStatus::PENDING),
|
m_status(util::ServiceJobStatus::PENDING),
|
||||||
m_discountPercentage(0.0) {
|
m_discountPercentage(0.0) {}
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: ServiceBooking
|
Function: ServiceBooking
|
||||||
@@ -440,46 +437,84 @@ static util::Vector<std::string> getServiceIDsAsVector(const std::string& servic
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Function: serialize
|
Function: serialize
|
||||||
Description: Serializes the ServiceBooking object into a SerializedServiceBooking record.
|
Description: Serializes the service booking into a CSV-formatted string.
|
||||||
Parameters:
|
Parameters:
|
||||||
- None
|
- None
|
||||||
Returns:
|
Returns:
|
||||||
- SerializedServiceBooking: Serialized representation of the service booking
|
- std::string: Serialized booking record
|
||||||
*/
|
*/
|
||||||
SerializedServiceBooking ServiceBooking::serialize() const
|
std::string ServiceBooking::serialize() const
|
||||||
{
|
{
|
||||||
SerializedServiceBooking serialized = {};
|
std::ostringstream serializedBooking;
|
||||||
strcpy_s(serialized.id, sizeof(serialized.id), m_id.c_str());
|
serializedBooking << m_id << ','
|
||||||
strcpy_s(serialized.serviceIDs, sizeof(serialized.serviceIDs), getServiceIDsAsString(m_serviceIDs).c_str());
|
<< util::getServiceJobStatusString(m_status) << ','
|
||||||
strcpy_s(serialized.customerId, sizeof(serialized.customerId), m_customerId.c_str());
|
<< getServiceIDsAsString(m_serviceIDs) << ','
|
||||||
strcpy_s(serialized.vehicleNumber, sizeof(serialized.vehicleNumber), m_vehicleNumber.c_str());
|
<< m_customerId << ','
|
||||||
strcpy_s(serialized.vehicleBrand, sizeof(serialized.vehicleBrand), m_vehicleBrand.c_str());
|
<< m_vehicleNumber << ','
|
||||||
strcpy_s(serialized.vehicleModel, sizeof(serialized.vehicleModel), m_vehicleModel.c_str());
|
<< m_vehicleBrand << ','
|
||||||
strcpy_s(serialized.assignedTechnicianId, sizeof(serialized.assignedTechnicianId), m_assignedTechnicianId.c_str());
|
<< m_vehicleModel << ','
|
||||||
serialized.status = m_status;
|
<< m_assignedTechnicianId << ','
|
||||||
serialized.discountPercentage = m_discountPercentage;
|
<< m_discountPercentage << ',';
|
||||||
return serialized;
|
return serializedBooking.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: deserialize
|
Function: deserialize
|
||||||
Description: Deserializes a SerializedServiceBooking record into a ServiceBooking object.
|
Description: Deserializes a CSV-formatted string into a ServiceBooking object.
|
||||||
Parameters:
|
Parameters:
|
||||||
- serializedServiceBooking: const SerializedServiceBooking&, serialized service booking record
|
- record: const std::string&, serialized booking record
|
||||||
Returns:
|
Returns:
|
||||||
- ServiceBooking*: Pointer to the deserialized ServiceBooking object
|
- ServiceBooking*: Pointer to the deserialized ServiceBooking object
|
||||||
|
Throws:
|
||||||
|
- std::runtime_error if discount percentage parsing fails
|
||||||
*/
|
*/
|
||||||
ServiceBooking* ServiceBooking::deserialize(const SerializedServiceBooking& serializedServiceBooking)
|
ServiceBooking* ServiceBooking::deserialize(const std::string& record)
|
||||||
{
|
{
|
||||||
util::Vector<std::string> serviceIDs = getServiceIDsAsVector(serializedServiceBooking.serviceIDs);
|
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<std::string> 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<ServiceBooking>(
|
return Factory::getObject<ServiceBooking>(
|
||||||
serializedServiceBooking.id,
|
id,
|
||||||
serializedServiceBooking.status,
|
status,
|
||||||
serviceIDs,
|
serviceIDs,
|
||||||
serializedServiceBooking.customerId,
|
customerId,
|
||||||
serializedServiceBooking.vehicleNumber,
|
vehicleNumber,
|
||||||
serializedServiceBooking.vehicleBrand,
|
vehicleBrand,
|
||||||
serializedServiceBooking.vehicleModel,
|
vehicleModel,
|
||||||
serializedServiceBooking.assignedTechnicianId,
|
assignedTechnicianId,
|
||||||
serializedServiceBooking.discountPercentage);
|
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";
|
||||||
}
|
}
|
||||||
@@ -6,7 +6,6 @@ Description: Header file declaring the ServiceBooking class, which represents
|
|||||||
Author: Trenser
|
Author: Trenser
|
||||||
Date:19-May-2026
|
Date:19-May-2026
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "Map.h"
|
#include "Map.h"
|
||||||
@@ -15,7 +14,6 @@ Date:19-May-2026
|
|||||||
|
|
||||||
class Service;
|
class Service;
|
||||||
class User;
|
class User;
|
||||||
struct SerializedServiceBooking;
|
|
||||||
|
|
||||||
class ServiceBooking
|
class ServiceBooking
|
||||||
{
|
{
|
||||||
@@ -80,6 +78,7 @@ public:
|
|||||||
void setAssignedTechnicianId(const std::string& assignedTechnicianId);
|
void setAssignedTechnicianId(const std::string& assignedTechnicianId);
|
||||||
void setAssignedTechnician(User* assignedTechnician);
|
void setAssignedTechnician(User* assignedTechnician);
|
||||||
void setDiscountPercentage(double discountPercentage);
|
void setDiscountPercentage(double discountPercentage);
|
||||||
SerializedServiceBooking serialize() const;
|
std::string serialize() const;
|
||||||
static ServiceBooking* deserialize(const SerializedServiceBooking&);
|
static ServiceBooking* deserialize(const std::string&);
|
||||||
|
static std::string getHeaders();
|
||||||
};
|
};
|
||||||
+4
-16
@@ -10,8 +10,6 @@ Date:19-May-2026
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include "AuthenticationManagementService.h"
|
#include "AuthenticationManagementService.h"
|
||||||
#include "User.h"
|
#include "User.h"
|
||||||
#include "Utility.h"
|
|
||||||
#include "DataStoreLockGuard.h"
|
|
||||||
|
|
||||||
User* AuthenticationManagementService::m_authenticatedUser = nullptr;
|
User* AuthenticationManagementService::m_authenticatedUser = nullptr;
|
||||||
|
|
||||||
@@ -26,12 +24,11 @@ Return type: bool - true if login successful, false otherwise
|
|||||||
*/
|
*/
|
||||||
bool AuthenticationManagementService::login(const std::string& username, const std::string& password)
|
bool AuthenticationManagementService::login(const std::string& username, const std::string& password)
|
||||||
{
|
{
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
util::Map<std::string, User*> users = m_dataStore.getUsers();
|
||||||
auto& trackedUserMap = m_dataStore.getUsers();
|
int usersMapSize = users.getSize();
|
||||||
int trackedUserMapSize = trackedUserMap.getSize();
|
for (int index = 0; index < usersMapSize; index++)
|
||||||
for (int index = 0; index < trackedUserMapSize; index++)
|
|
||||||
{
|
{
|
||||||
User* user = trackedUserMap.getValueAt(index).data;
|
User* user = users.getValueAt(index);
|
||||||
if (username == user->getUserName())
|
if (username == user->getUserName())
|
||||||
{
|
{
|
||||||
if (password == user->getPassword())
|
if (password == user->getPassword())
|
||||||
@@ -77,18 +74,9 @@ Return type: void
|
|||||||
*/
|
*/
|
||||||
void AuthenticationManagementService::changePassword(const std::string& newPassword)
|
void AuthenticationManagementService::changePassword(const std::string& newPassword)
|
||||||
{
|
{
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
|
||||||
auto& trackedUsersMap = m_dataStore.getUsers();
|
|
||||||
if (m_authenticatedUser == nullptr)
|
if (m_authenticatedUser == nullptr)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("There is no user currently logged in!");
|
throw std::runtime_error("There is no user currently logged in!");
|
||||||
}
|
}
|
||||||
int index = trackedUsersMap.find(m_authenticatedUser->getId());
|
|
||||||
if (index == -1)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("User does not exist!\n");
|
|
||||||
}
|
|
||||||
m_authenticatedUser->setPassword(newPassword);
|
m_authenticatedUser->setPassword(newPassword);
|
||||||
trackedUsersMap.getValueAt(index).state = RecordState::MODIFIED;
|
|
||||||
m_dataStore.saveUsers();
|
|
||||||
}
|
}
|
||||||
|
|||||||
+90
@@ -12,6 +12,7 @@ Date: 22-May-2026
|
|||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "Enums.h"
|
#include "Enums.h"
|
||||||
#include "Factory.h"
|
#include "Factory.h"
|
||||||
|
#include "FileManager.h"
|
||||||
#include "InventoryItem.h"
|
#include "InventoryItem.h"
|
||||||
#include "InventoryManagementService.h"
|
#include "InventoryManagementService.h"
|
||||||
#include "Timestamp.h"
|
#include "Timestamp.h"
|
||||||
@@ -89,6 +90,95 @@ void InventoryManagementService::sendLowStockAlerts()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: getObserverIDs
|
||||||
|
Description: Retrieves the IDs of all observers currently attached to the
|
||||||
|
InventoryManagementService.
|
||||||
|
Parameters:
|
||||||
|
- None
|
||||||
|
Returns:
|
||||||
|
- util::Vector<std::string>: Vector of observer user IDs
|
||||||
|
*/
|
||||||
|
util::Vector<std::string> InventoryManagementService::getObserverIDs()
|
||||||
|
{
|
||||||
|
util::Vector<std::string> 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<InventoryItem> 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<InventoryItem> inventoryItemFileManager(config::file::INVENTORYITEM_FILE);
|
||||||
|
auto& inventoryItems = m_dataStore.getInventoryItems();
|
||||||
|
inventoryItemFileManager.save(inventoryItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: loadObservers
|
||||||
|
Description: Loads observer IDs from persistent storage and attaches corresponding
|
||||||
|
users as observers to the InventoryManagementService.
|
||||||
|
Parameters:
|
||||||
|
- None
|
||||||
|
Returns:
|
||||||
|
- void
|
||||||
|
*/
|
||||||
|
void InventoryManagementService::loadObservers()
|
||||||
|
{
|
||||||
|
util::loadObservers(config::file::INVENTORYMANAGEMENTOBSERVERS, this, m_dataStore);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: saveObservers
|
||||||
|
Description: Saves the current observer IDs of the InventoryManagementService
|
||||||
|
to persistent storage for future retrieval.
|
||||||
|
Parameters:
|
||||||
|
- None
|
||||||
|
Returns:
|
||||||
|
- void
|
||||||
|
*/
|
||||||
|
void InventoryManagementService::saveObservers()
|
||||||
|
{
|
||||||
|
util::saveObservers(config::file::INVENTORYMANAGEMENTOBSERVERS, this);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: addInventoryItem
|
Function: addInventoryItem
|
||||||
Description: Creates a new inventory item using the Factory and inserts it
|
Description: Creates a new inventory item using the Factory and inserts it
|
||||||
|
|||||||
+5
@@ -21,6 +21,7 @@ class InventoryManagementService : public NotificationManagementService
|
|||||||
private:
|
private:
|
||||||
DataStore& m_dataStore;
|
DataStore& m_dataStore;
|
||||||
static util::Map<std::string, User*> m_observers;
|
static util::Map<std::string, User*> m_observers;
|
||||||
|
util::Vector<std::string> getObserverIDs() override;
|
||||||
public:
|
public:
|
||||||
InventoryManagementService() : m_dataStore(DataStore::getInstance()) {}
|
InventoryManagementService() : m_dataStore(DataStore::getInstance()) {}
|
||||||
util::Map<std::string, InventoryItem*> getInventoryItems();
|
util::Map<std::string, InventoryItem*> getInventoryItems();
|
||||||
@@ -32,4 +33,8 @@ public:
|
|||||||
void sendNotification(User* user, const std::string& title, const std::string& message) override;
|
void sendNotification(User* user, const std::string& title, const std::string& message) override;
|
||||||
void attach(User* user) override;
|
void attach(User* user) override;
|
||||||
void detach(User* user) override;
|
void detach(User* user) override;
|
||||||
|
void loadInventoryItems();
|
||||||
|
void saveInventoryItems();
|
||||||
|
void loadObservers();
|
||||||
|
void saveObservers();
|
||||||
};
|
};
|
||||||
|
|||||||
+1
@@ -19,4 +19,5 @@ public:
|
|||||||
virtual void sendNotification(User* recipient, const std::string& title, const std::string& message) = 0;
|
virtual void sendNotification(User* recipient, const std::string& title, const std::string& message) = 0;
|
||||||
virtual void attach(User* user) = 0;
|
virtual void attach(User* user) = 0;
|
||||||
virtual void detach(User* user) = 0;
|
virtual void detach(User* user) = 0;
|
||||||
|
virtual util::Vector<std::string> getObserverIDs() = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
+118
@@ -11,6 +11,7 @@ Date: 20-May-2026
|
|||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "Enums.h"
|
#include "Enums.h"
|
||||||
#include "Factory.h"
|
#include "Factory.h"
|
||||||
|
#include "FileManager.h"
|
||||||
#include "InventoryItem.h"
|
#include "InventoryItem.h"
|
||||||
#include "Invoice.h"
|
#include "Invoice.h"
|
||||||
#include "JobCard.h"
|
#include "JobCard.h"
|
||||||
@@ -148,6 +149,123 @@ void PaymentManagementService::sendPaymentReminders()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: getObserverIDs
|
||||||
|
Description: Retrieves the IDs of all observers currently attached to the
|
||||||
|
PaymentManagementService.
|
||||||
|
Parameters:
|
||||||
|
- None
|
||||||
|
Returns:
|
||||||
|
- util::Vector<std::string>: Vector of observer user IDs
|
||||||
|
*/
|
||||||
|
util::Vector<std::string> PaymentManagementService::getObserverIDs()
|
||||||
|
{
|
||||||
|
util::Vector<std::string> 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<Invoice> 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<std::string, InventoryItem*> 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<Invoice> invoiceFileManager(config::file::INVOICE_FILE);
|
||||||
|
auto& invoices = m_dataStore.getInvoices();
|
||||||
|
invoiceFileManager.save(invoices);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: loadObservers
|
||||||
|
Description: Loads observer IDs from persistent storage and attaches corresponding
|
||||||
|
users as observers to the PaymentManagementService.
|
||||||
|
Parameters:
|
||||||
|
- None
|
||||||
|
Returns:
|
||||||
|
- void
|
||||||
|
Throws:
|
||||||
|
- std::runtime_error if an observer ID is invalid (not found in datastore)
|
||||||
|
*/
|
||||||
|
void PaymentManagementService::loadObservers()
|
||||||
|
{
|
||||||
|
util::loadObservers(config::file::PAYMENTMANAGEMENTOBSERVERS, this, m_dataStore);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: saveObservers
|
||||||
|
Description: Saves the current observer IDs of the PaymentManagementService
|
||||||
|
to persistent storage for future retrieval.
|
||||||
|
Parameters:
|
||||||
|
- None
|
||||||
|
Returns:
|
||||||
|
- void
|
||||||
|
*/
|
||||||
|
void PaymentManagementService::saveObservers()
|
||||||
|
{
|
||||||
|
util::saveObservers(config::file::PAYMENTMANAGEMENTOBSERVERS, this);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: createInventoryItemsMap (static helper)
|
Function: createInventoryItemsMap (static helper)
|
||||||
Description: Builds a map of inventory items required for a given service and adds them to the booking’s inventory map.
|
Description: Builds a map of inventory items required for a given service and adds them to the booking’s inventory map.
|
||||||
|
|||||||
+5
@@ -22,6 +22,7 @@ class PaymentManagementService : public NotificationManagementService
|
|||||||
private:
|
private:
|
||||||
DataStore& m_dataStore;
|
DataStore& m_dataStore;
|
||||||
static util::Map<std::string, User*> m_observers;
|
static util::Map<std::string, User*> m_observers;
|
||||||
|
util::Vector<std::string> getObserverIDs() override;
|
||||||
public:
|
public:
|
||||||
PaymentManagementService() : m_dataStore(DataStore::getInstance()) {}
|
PaymentManagementService() : m_dataStore(DataStore::getInstance()) {}
|
||||||
void generateInvoice(ServiceBooking* booking);
|
void generateInvoice(ServiceBooking* booking);
|
||||||
@@ -33,4 +34,8 @@ public:
|
|||||||
void sendNotification(User* user, const std::string& title, const std::string& message) override;
|
void sendNotification(User* user, const std::string& title, const std::string& message) override;
|
||||||
void attach(User* user) override;
|
void attach(User* user) override;
|
||||||
void detach(User* user) override;
|
void detach(User* user) override;
|
||||||
|
void loadInvoices();
|
||||||
|
void saveInvoices();
|
||||||
|
void loadObservers();
|
||||||
|
void saveObservers();
|
||||||
};
|
};
|
||||||
|
|||||||
+357
-136
@@ -14,6 +14,7 @@ Date:19-May-2026
|
|||||||
#include "DataStore.h"
|
#include "DataStore.h"
|
||||||
#include "Enums.h"
|
#include "Enums.h"
|
||||||
#include "Factory.h"
|
#include "Factory.h"
|
||||||
|
#include "FileManager.h"
|
||||||
#include "InventoryItem.h"
|
#include "InventoryItem.h"
|
||||||
#include "JobCard.h"
|
#include "JobCard.h"
|
||||||
#include "NotificationManagementService.h"
|
#include "NotificationManagementService.h"
|
||||||
@@ -24,7 +25,6 @@ Date:19-May-2026
|
|||||||
#include "Timestamp.h"
|
#include "Timestamp.h"
|
||||||
#include "User.h"
|
#include "User.h"
|
||||||
#include "UserManagementService.h"
|
#include "UserManagementService.h"
|
||||||
#include "DataStoreLockGuard.h"
|
|
||||||
#include "Utility.h"
|
#include "Utility.h"
|
||||||
#include "DataStoreLockGuard.h"
|
#include "DataStoreLockGuard.h"
|
||||||
|
|
||||||
@@ -47,19 +47,18 @@ void ServiceManagementService::purchaseService(const util::Vector<std::string>&
|
|||||||
{
|
{
|
||||||
throw std::runtime_error("No user is currently logged in!");
|
throw std::runtime_error("No user is currently logged in!");
|
||||||
}
|
}
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
auto& servicesMap = m_dataStore.getServices();
|
||||||
auto& trackedServicesMap = m_dataStore.getServices();
|
auto& serviceBookingMap = m_dataStore.getServiceBookings();
|
||||||
auto& trackedServiceBookingMap = m_dataStore.getServiceBookings();
|
|
||||||
util::Map<std::string, Service*> selectedServices;
|
util::Map<std::string, Service*> selectedServices;
|
||||||
int selectedServicesCount = serviceIDs.getSize();
|
int selectedServicesCount = serviceIDs.getSize();
|
||||||
for (int index = 0; index < selectedServicesCount; index++)
|
for (int index = 0; index < selectedServicesCount; index++)
|
||||||
{
|
{
|
||||||
int serviceIndex = trackedServicesMap.find(serviceIDs[index]);
|
int serviceIndex = servicesMap.find(serviceIDs[index]);
|
||||||
if (serviceIndex == -1)
|
if (serviceIndex == -1)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Service not found!");
|
throw std::runtime_error("Service not found!");
|
||||||
}
|
}
|
||||||
Service* service = trackedServicesMap.getValueAt(serviceIndex).data;
|
Service* service = servicesMap.getValueAt(serviceIndex);
|
||||||
selectedServices[service->getId()] = service;
|
selectedServices[service->getId()] = service;
|
||||||
}
|
}
|
||||||
ServiceBooking* serviceBooking = Factory::getObject<ServiceBooking>(util::ServiceJobStatus::PENDING, selectedServices, authenticatedUser->getId(), authenticatedUser, vehicleNumber, vehicleBrand, vehicleModel, 0);
|
ServiceBooking* serviceBooking = Factory::getObject<ServiceBooking>(util::ServiceJobStatus::PENDING, selectedServices, authenticatedUser->getId(), authenticatedUser, vehicleNumber, vehicleBrand, vehicleModel, 0);
|
||||||
@@ -67,7 +66,7 @@ void ServiceManagementService::purchaseService(const util::Vector<std::string>&
|
|||||||
{
|
{
|
||||||
throw std::runtime_error("Failed to create service booking");
|
throw std::runtime_error("Failed to create service booking");
|
||||||
}
|
}
|
||||||
trackedServiceBookingMap[serviceBooking->getId()] = util::createNewRecord(serviceBooking);
|
serviceBookingMap[serviceBooking->getId()] = serviceBooking;
|
||||||
std::string title = "Service Booking succeeded";
|
std::string title = "Service Booking succeeded";
|
||||||
std::string message = "Your service booking has been successfully placed with ID " + serviceBooking->getId();
|
std::string message = "Your service booking has been successfully placed with ID " + serviceBooking->getId();
|
||||||
sendNotification(authenticatedUser, title, message);
|
sendNotification(authenticatedUser, title, message);
|
||||||
@@ -92,22 +91,21 @@ void ServiceManagementService::purchaseComboPackage(const std::string& comboPack
|
|||||||
{
|
{
|
||||||
throw std::runtime_error("No user is currently logged in!");
|
throw std::runtime_error("No user is currently logged in!");
|
||||||
}
|
}
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
auto& comboPackagesMap = m_dataStore.getComboPackages();
|
||||||
auto& trackedComboPackagesMap = m_dataStore.getComboPackages();
|
auto& serviceBookingMap = m_dataStore.getServiceBookings();
|
||||||
auto& trackedServiceBookingMap = m_dataStore.getServiceBookings();
|
int comboPackageIndex = comboPackagesMap.find(comboPackageID);
|
||||||
int comboPackageIndex = trackedComboPackagesMap.find(comboPackageID);
|
|
||||||
if (comboPackageIndex == -1)
|
if (comboPackageIndex == -1)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Combo Package not found!");
|
throw std::runtime_error("Combo Package not found!");
|
||||||
}
|
}
|
||||||
const ComboPackage* comboPackage = trackedComboPackagesMap[comboPackageID].data;
|
const ComboPackage* comboPackage = comboPackagesMap[comboPackageID];
|
||||||
util::Map<std::string, Service*> selectedServices = comboPackage->getServices();
|
util::Map<std::string, Service*> selectedServices = comboPackage->getServices();
|
||||||
ServiceBooking* serviceBooking = Factory::getObject<ServiceBooking>(util::ServiceJobStatus::PENDING, selectedServices, authenticatedUser->getId(), authenticatedUser, vehicleNumber, vehicleBrand, vehicleModel, comboPackage->getDiscountPercentage());
|
ServiceBooking* serviceBooking = Factory::getObject<ServiceBooking>(util::ServiceJobStatus::PENDING, selectedServices, authenticatedUser->getId(), authenticatedUser, vehicleNumber, vehicleBrand, vehicleModel, comboPackage->getDiscountPercentage());
|
||||||
if (serviceBooking == nullptr)
|
if (serviceBooking == nullptr)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Failed to create combo package service booking");
|
throw std::runtime_error("Failed to create combo package service booking");
|
||||||
}
|
}
|
||||||
trackedServiceBookingMap[serviceBooking->getId()] = util::createNewRecord(serviceBooking);
|
serviceBookingMap[serviceBooking->getId()] = serviceBooking;
|
||||||
std::string title = "Combo Package Service Booking succeeded";
|
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();
|
std::string message = "Your service booking for the combo package has been successfully placed with ID " + serviceBooking->getId();
|
||||||
sendNotification(authenticatedUser, title, message);
|
sendNotification(authenticatedUser, title, message);
|
||||||
@@ -201,6 +199,299 @@ void ServiceManagementService::sendNotification(User* user, const std::string& t
|
|||||||
m_dataStore.saveNotifications();
|
m_dataStore.saveNotifications();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
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<Service> 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<std::string, InventoryItem*> 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<Service> 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<ComboPackage> 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<std::string, Service*> 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<ComboPackage> 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<ServiceBooking> 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<std::string, Service*> 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<ServiceBooking> 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<JobCard> 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<JobCard> 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);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: restoreInventory
|
Function: restoreInventory
|
||||||
Description: Restores inventory quantities for all required items in the services associated
|
Description: Restores inventory quantities for all required items in the services associated
|
||||||
@@ -208,7 +499,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
|
Parameter: ServiceBooking* booking - Pointer to the booking whose inventory items need to be restored
|
||||||
Return type: void
|
Return type: void
|
||||||
*/
|
*/
|
||||||
static void restoreInventory(ServiceBooking* booking, util::Map<std::string, TrackedRecord<InventoryItem>>& trackedInventoryItems)
|
static void restoreInventory(ServiceBooking* booking)
|
||||||
{
|
{
|
||||||
const int INCREMENT_VALUE = 1;
|
const int INCREMENT_VALUE = 1;
|
||||||
if (!booking)
|
if (!booking)
|
||||||
@@ -227,17 +518,9 @@ static void restoreInventory(ServiceBooking* booking, util::Map<std::string, Tra
|
|||||||
for (int InventoryIterator = 0; InventoryIterator < items.getSize(); ++InventoryIterator)
|
for (int InventoryIterator = 0; InventoryIterator < items.getSize(); ++InventoryIterator)
|
||||||
{
|
{
|
||||||
InventoryItem* item = items.getValueAt(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)
|
if (item)
|
||||||
{
|
{
|
||||||
item->setQuantity(item->getQuantity() + INCREMENT_VALUE);
|
item->setQuantity(item->getQuantity() + INCREMENT_VALUE);
|
||||||
currentTrackedInventoryItem.state = RecordState::MODIFIED;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -255,28 +538,23 @@ Parameters:
|
|||||||
util::UserType userType - Type of user initiating cancellation (CUSTOMER or TECHNICIAN)
|
util::UserType userType - Type of user initiating cancellation (CUSTOMER or TECHNICIAN)
|
||||||
Return type: void
|
Return type: void
|
||||||
*/
|
*/
|
||||||
static void processBookingCancellation(TrackedRecord<ServiceBooking>& trackedBooking,
|
static void processBookingCancellation(ServiceBooking* booking,
|
||||||
util::Map<std::string, TrackedRecord<JobCard>>& jobs,
|
util::Map<std::string, JobCard*>& jobs,
|
||||||
ServiceManagementService& currentService,
|
ServiceManagementService& currentService,
|
||||||
util::UserType userType,
|
util::UserType userType)
|
||||||
util::Map<std::string, TrackedRecord<InventoryItem>>& trackedInventoryItems)
|
|
||||||
{
|
{
|
||||||
ServiceBooking* booking = trackedBooking.data;
|
|
||||||
if (!booking)
|
if (!booking)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const std::string& bookingId = booking->getId();
|
|
||||||
for (int jobIterator = 0; jobIterator < jobs.getSize(); ++jobIterator)
|
for (int jobIterator = 0; jobIterator < jobs.getSize(); ++jobIterator)
|
||||||
{
|
{
|
||||||
auto& trackedJobCard = jobs.getValueAt(jobIterator);
|
JobCard* jobCard = jobs.getValueAt(jobIterator);
|
||||||
JobCard* jobCard = trackedJobCard.data;
|
|
||||||
if (!jobCard || jobCard->getBookingId() != booking->getId() || jobCard->getStatus() == util::ServiceJobStatus::CANCELLED)
|
if (!jobCard || jobCard->getBookingId() != booking->getId() || jobCard->getStatus() == util::ServiceJobStatus::CANCELLED)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
jobCard->setStatus(util::ServiceJobStatus::CANCELLED);
|
jobCard->setStatus(util::ServiceJobStatus::CANCELLED);
|
||||||
trackedJobCard.state = RecordState::MODIFIED;
|
|
||||||
if (userType == util::UserType::CUSTOMER)
|
if (userType == util::UserType::CUSTOMER)
|
||||||
{
|
{
|
||||||
if (User* technician = booking->getAssignedTechnician())
|
if (User* technician = booking->getAssignedTechnician())
|
||||||
@@ -309,8 +587,7 @@ static void processBookingCancellation(TrackedRecord<ServiceBooking>& trackedBoo
|
|||||||
}
|
}
|
||||||
booking->setAssignedTechnician(nullptr);
|
booking->setAssignedTechnician(nullptr);
|
||||||
booking->setAssignedTechnicianId("");
|
booking->setAssignedTechnicianId("");
|
||||||
trackedBooking.state = RecordState::MODIFIED;
|
restoreInventory(booking);
|
||||||
restoreInventory(booking, trackedInventoryItems);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -323,25 +600,22 @@ Return type: void
|
|||||||
*/
|
*/
|
||||||
void ServiceManagementService::cancelCustomerServiceBookings(const std::string& customerID)
|
void ServiceManagementService::cancelCustomerServiceBookings(const std::string& customerID)
|
||||||
{
|
{
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
auto& users = m_dataStore.getUsers();
|
||||||
auto& trackedUsers = m_dataStore.getUsers();
|
int userIndex = users.find(customerID);
|
||||||
int userIndex = trackedUsers.find(customerID);
|
|
||||||
if (userIndex == -1)
|
if (userIndex == -1)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("User not found: " + customerID);
|
throw std::runtime_error("User not found: " + customerID);
|
||||||
}
|
}
|
||||||
User* customer = trackedUsers.getValueAt(userIndex).data;
|
User* customer = users.getValueAt(userIndex);
|
||||||
if (!customer)
|
if (!customer)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("User not found: " + customerID);
|
throw std::runtime_error("User not found: " + customerID);
|
||||||
}
|
}
|
||||||
auto& trackedBookings = m_dataStore.getServiceBookings();
|
auto& bookings = m_dataStore.getServiceBookings();
|
||||||
auto& trackedJobs = m_dataStore.getJobCards();
|
auto& jobs = m_dataStore.getJobCards();
|
||||||
auto& trackedInventoryItems = m_dataStore.getInventoryItems();
|
for (int iteratorOne = 0; iteratorOne < bookings.getSize(); iteratorOne++)
|
||||||
for (int iteratorOne = 0; iteratorOne < trackedBookings.getSize(); iteratorOne++)
|
|
||||||
{
|
{
|
||||||
auto& trackedBooking = trackedBookings.getValueAt(iteratorOne);
|
ServiceBooking* booking = bookings.getValueAt(iteratorOne);
|
||||||
ServiceBooking* booking = trackedBooking.data;
|
|
||||||
if (!booking)
|
if (!booking)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -356,12 +630,8 @@ void ServiceManagementService::cancelCustomerServiceBookings(const std::string&
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
processBookingCancellation(trackedBooking, trackedJobs, *this, util::UserType::CUSTOMER, trackedInventoryItems);
|
processBookingCancellation(booking, jobs, *this, util::UserType::CUSTOMER);
|
||||||
}
|
}
|
||||||
m_dataStore.saveUsers();
|
|
||||||
m_dataStore.saveServiceBookings();
|
|
||||||
m_dataStore.saveJobCards();
|
|
||||||
m_dataStore.saveInventoryItems();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -373,25 +643,22 @@ Return type: void
|
|||||||
*/
|
*/
|
||||||
void ServiceManagementService::cancelTechnicianJobs(const std::string& technicianID)
|
void ServiceManagementService::cancelTechnicianJobs(const std::string& technicianID)
|
||||||
{
|
{
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
auto& users = m_dataStore.getUsers();
|
||||||
auto& trackedUsers = m_dataStore.getUsers();
|
int userIndex = users.find(technicianID);
|
||||||
int userIndex = trackedUsers.find(technicianID);
|
|
||||||
if (userIndex == -1)
|
if (userIndex == -1)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("User not found: " + technicianID);
|
throw std::runtime_error("User not found: " + technicianID);
|
||||||
}
|
}
|
||||||
User* technician = trackedUsers.getValueAt(userIndex).data;
|
User* technician = users.getValueAt(userIndex);
|
||||||
if (!technician)
|
if (!technician)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("User not found: " + technicianID);
|
throw std::runtime_error("User not found: " + technicianID);
|
||||||
}
|
}
|
||||||
auto& trackedBookings = m_dataStore.getServiceBookings();
|
auto& bookings = m_dataStore.getServiceBookings();
|
||||||
auto& trackedJobs = m_dataStore.getJobCards();
|
auto& jobs = m_dataStore.getJobCards();
|
||||||
auto& trackedInventoryItems = m_dataStore.getInventoryItems();
|
for (int iteratorOne = 0; iteratorOne < bookings.getSize(); iteratorOne++)
|
||||||
for (int iteratorOne = 0; iteratorOne < trackedBookings.getSize(); iteratorOne++)
|
|
||||||
{
|
{
|
||||||
auto& trackedBooking = trackedBookings.getValueAt(iteratorOne);
|
ServiceBooking* booking = bookings.getValueAt(iteratorOne);
|
||||||
ServiceBooking* booking = trackedBooking.data;
|
|
||||||
if (!booking)
|
if (!booking)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -412,12 +679,8 @@ void ServiceManagementService::cancelTechnicianJobs(const std::string& technicia
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
processBookingCancellation(trackedBooking, trackedJobs, *this, util::UserType::TECHNICIAN, trackedInventoryItems);
|
processBookingCancellation(booking, jobs, *this, util::UserType::TECHNICIAN);
|
||||||
}
|
}
|
||||||
m_dataStore.saveUsers();
|
|
||||||
m_dataStore.saveInventoryItems();
|
|
||||||
m_dataStore.saveServiceBookings();
|
|
||||||
m_dataStore.saveJobCards();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -431,7 +694,6 @@ Return type: void
|
|||||||
*/
|
*/
|
||||||
void ServiceManagementService::createComboPackage(const std::string& packageName, const util::Vector<std::string>& serviceIDsInNewCombo, double discountPercentage)
|
void ServiceManagementService::createComboPackage(const std::string& packageName, const util::Vector<std::string>& serviceIDsInNewCombo, double discountPercentage)
|
||||||
{
|
{
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
|
||||||
if (packageName.empty())
|
if (packageName.empty())
|
||||||
{
|
{
|
||||||
throw std::invalid_argument("The Combo Package Name cannot be empty.\n");
|
throw std::invalid_argument("The Combo Package Name cannot be empty.\n");
|
||||||
@@ -444,19 +706,19 @@ void ServiceManagementService::createComboPackage(const std::string& packageName
|
|||||||
{
|
{
|
||||||
throw std::invalid_argument("Discount percentage must be between 0 and 100.");
|
throw std::invalid_argument("Discount percentage must be between 0 and 100.");
|
||||||
}
|
}
|
||||||
auto& trackedServicesMap = m_dataStore.getServices();
|
auto& servicesMap = m_dataStore.getServices();
|
||||||
for (int index = 0; index < serviceIDsInNewCombo.getSize(); index++)
|
for (int index = 0; index < serviceIDsInNewCombo.getSize(); index++)
|
||||||
{
|
{
|
||||||
const std::string& serviceid = serviceIDsInNewCombo[index];
|
const std::string serviceid = serviceIDsInNewCombo[index];
|
||||||
if (trackedServicesMap.find(serviceid) == -1)
|
if (servicesMap.find(serviceid) == -1)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Service ID not found: " + serviceid);
|
throw std::runtime_error("Service ID not found: " + serviceid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto& trackedComboPackageMap = m_dataStore.getComboPackages();
|
auto& comboPackageMap = m_dataStore.getComboPackages();
|
||||||
for (int iterator = 0; iterator < trackedComboPackageMap.getSize(); iterator++)
|
for (int iterator = 0; iterator < comboPackageMap.getSize(); iterator++)
|
||||||
{
|
{
|
||||||
ComboPackage* existingCombos = trackedComboPackageMap.getValueAt(iterator).data;
|
ComboPackage* existingCombos = comboPackageMap.getValueAt(iterator);
|
||||||
const util::Map<std::string, Service*>& servicesInsideExistingCombos = existingCombos->getServices();
|
const util::Map<std::string, Service*>& servicesInsideExistingCombos = existingCombos->getServices();
|
||||||
if (servicesInsideExistingCombos.getSize() == serviceIDsInNewCombo.getSize())
|
if (servicesInsideExistingCombos.getSize() == serviceIDsInNewCombo.getSize())
|
||||||
{
|
{
|
||||||
@@ -480,16 +742,15 @@ void ServiceManagementService::createComboPackage(const std::string& packageName
|
|||||||
for (int iteratorOne = 0; iteratorOne < serviceIDsInNewCombo.getSize(); iteratorOne++)
|
for (int iteratorOne = 0; iteratorOne < serviceIDsInNewCombo.getSize(); iteratorOne++)
|
||||||
{
|
{
|
||||||
const std::string& serviceId = serviceIDsInNewCombo[iteratorOne];
|
const std::string& serviceId = serviceIDsInNewCombo[iteratorOne];
|
||||||
int serviceIndex = trackedServicesMap.find(serviceId);
|
int serviceIndex = servicesMap.find(serviceId);
|
||||||
if (serviceIndex == -1)
|
if (serviceIndex == -1)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Service ID not found: " + serviceId);
|
throw std::runtime_error("Service ID not found: " + serviceId);
|
||||||
}
|
}
|
||||||
selectedServices.insert(serviceId, trackedServicesMap.getValueAt(serviceIndex).data);
|
selectedServices.insert(serviceId, servicesMap.getValueAt(serviceIndex));
|
||||||
}
|
}
|
||||||
ComboPackage* newComboPackage = Factory::getObject<ComboPackage>(packageName, discountPercentage, selectedServices);
|
ComboPackage* newComboPackage = Factory::getObject<ComboPackage>(packageName, discountPercentage, selectedServices);
|
||||||
trackedComboPackageMap.insert(newComboPackage->getId(), util::createNewRecord(newComboPackage));
|
comboPackageMap.insert(newComboPackage->getId(), newComboPackage);
|
||||||
m_dataStore.saveComboPackages();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -500,10 +761,7 @@ Return type: util::Map<std::string, ComboPackage*>
|
|||||||
*/
|
*/
|
||||||
util::Map<std::string, ComboPackage*> ServiceManagementService::getComboPackages()
|
util::Map<std::string, ComboPackage*> ServiceManagementService::getComboPackages()
|
||||||
{
|
{
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
return m_dataStore.getComboPackages();
|
||||||
util::Map<std::string, ComboPackage*> comboPackages;
|
|
||||||
comboPackages = util::getObjects(m_dataStore.getComboPackages());
|
|
||||||
return comboPackages;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -514,17 +772,14 @@ Return type: void
|
|||||||
*/
|
*/
|
||||||
void ServiceManagementService::removeComboPackage(const std::string& comboPackageID)
|
void ServiceManagementService::removeComboPackage(const std::string& comboPackageID)
|
||||||
{
|
{
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
|
||||||
bool removed = false;
|
bool removed = false;
|
||||||
auto& trackedComboPackages = m_dataStore.getComboPackages();
|
util::Map<std::string, ComboPackage*>& currentComboPackages = m_dataStore.getComboPackages();
|
||||||
for (int iterator = 0; iterator < trackedComboPackages.getSize(); iterator++)
|
for (int iterator = 0; iterator < currentComboPackages.getSize(); iterator++)
|
||||||
{
|
{
|
||||||
auto& comboPackage = trackedComboPackages.getValueAt(iterator);
|
ComboPackage* currentComboPackage = currentComboPackages.getValueAt(iterator);
|
||||||
ComboPackage* currentComboPackage = comboPackage.data;
|
|
||||||
if (currentComboPackage && currentComboPackage->getId() == comboPackageID)
|
if (currentComboPackage && currentComboPackage->getId() == comboPackageID)
|
||||||
{
|
{
|
||||||
currentComboPackage->setState(util::State::INACTIVE);
|
currentComboPackage->setState(util::State::INACTIVE);
|
||||||
comboPackage.state = RecordState::MODIFIED;
|
|
||||||
removed = true;
|
removed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -533,7 +788,6 @@ void ServiceManagementService::removeComboPackage(const std::string& comboPackag
|
|||||||
{
|
{
|
||||||
throw std::runtime_error("Combo package with ID '" + comboPackageID + "' not found.");
|
throw std::runtime_error("Combo package with ID '" + comboPackageID + "' not found.");
|
||||||
}
|
}
|
||||||
m_dataStore.saveComboPackages();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -546,10 +800,7 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
util::Map<std::string, ServiceBooking*> ServiceManagementService::getServiceBookings()
|
util::Map<std::string, ServiceBooking*> ServiceManagementService::getServiceBookings()
|
||||||
{
|
{
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
return m_dataStore.getServiceBookings();
|
||||||
util::Map<std::string, ServiceBooking*> serviceBookings;
|
|
||||||
serviceBookings = util::getObjects(m_dataStore.getServiceBookings());
|
|
||||||
return serviceBookings;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -588,10 +839,9 @@ Throws:
|
|||||||
*/
|
*/
|
||||||
void ServiceManagementService::createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID)
|
void ServiceManagementService::createJobCard(const std::string& bookingID, const std::string& technicianID, const std::string& serviceID)
|
||||||
{
|
{
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
|
||||||
UserManagementService m_userManagementService;
|
UserManagementService m_userManagementService;
|
||||||
ServiceBooking* currentBooking = getServiceBooking(bookingID);
|
ServiceBooking* currentBooking = getServiceBooking(bookingID);
|
||||||
auto& currentTrackedJobCards = m_dataStore.getJobCards();
|
auto& currentJobCards = m_dataStore.getJobCards();
|
||||||
if (currentBooking == nullptr)
|
if (currentBooking == nullptr)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Service Booking not available");
|
throw std::runtime_error("Service Booking not available");
|
||||||
@@ -637,7 +887,7 @@ void ServiceManagementService::createJobCard(const std::string& bookingID, const
|
|||||||
JobCard* jobCard = Factory::getObject<JobCard>(bookingID, currentBooking, currentService, serviceID, technicianID, selectedTechnician, util::Timestamp(), util::ServiceJobStatus::STARTED, util::Timestamp());
|
JobCard* jobCard = Factory::getObject<JobCard>(bookingID, currentBooking, currentService, serviceID, technicianID, selectedTechnician, util::Timestamp(), util::ServiceJobStatus::STARTED, util::Timestamp());
|
||||||
if (jobCard)
|
if (jobCard)
|
||||||
{
|
{
|
||||||
currentTrackedJobCards.insert(jobCard->getId(), util::createNewRecord(jobCard));
|
currentJobCards.insert(jobCard->getId(), jobCard);
|
||||||
sendNotification(selectedTechnician, title, message);
|
sendNotification(selectedTechnician, title, message);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -647,7 +897,6 @@ void ServiceManagementService::createJobCard(const std::string& bookingID, const
|
|||||||
title = "Technician assigned";
|
title = "Technician assigned";
|
||||||
message = "A technician has been assigned to your Service Booking with ID " + bookingID;
|
message = "A technician has been assigned to your Service Booking with ID " + bookingID;
|
||||||
sendNotification(currentBooking->getCustomer(), title, message);
|
sendNotification(currentBooking->getCustomer(), title, message);
|
||||||
m_dataStore.saveJobCards();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -665,17 +914,15 @@ Throws:
|
|||||||
*/
|
*/
|
||||||
void ServiceManagementService::createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost)
|
void ServiceManagementService::createService(const std::string& name, const util::Vector<std::string>& inventoryItemIDs, double laborCost)
|
||||||
{
|
{
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
|
||||||
util::Map<std::string, InventoryItem*> currentServiceInventoryItems;
|
util::Map<std::string, InventoryItem*> currentServiceInventoryItems;
|
||||||
auto& trackedInventoryItems = m_dataStore.getInventoryItems();
|
auto inventoryItems = m_dataStore.getInventoryItems();
|
||||||
auto& currentServices = m_dataStore.getServices();
|
|
||||||
for (int iteratorOne =0; iteratorOne < inventoryItemIDs.getSize(); iteratorOne++)
|
for (int iteratorOne =0; iteratorOne < inventoryItemIDs.getSize(); iteratorOne++)
|
||||||
{
|
{
|
||||||
std::string currentItemID = inventoryItemIDs[iteratorOne];
|
std::string currentItemID = inventoryItemIDs[iteratorOne];
|
||||||
bool itemFound = false;
|
bool itemFound = false;
|
||||||
for (int iteratorTwo = 0; iteratorTwo < trackedInventoryItems.getSize(); iteratorTwo++)
|
for (int iteratorTwo = 0; iteratorTwo < inventoryItems.getSize(); iteratorTwo++)
|
||||||
{
|
{
|
||||||
InventoryItem* currentInventoryItem = trackedInventoryItems.getValueAt(iteratorTwo).data;
|
InventoryItem* currentInventoryItem = inventoryItems.getValueAt(iteratorTwo);
|
||||||
if (currentInventoryItem && currentInventoryItem->getId() == currentItemID)
|
if (currentInventoryItem && currentInventoryItem->getId() == currentItemID)
|
||||||
{
|
{
|
||||||
itemFound = true;
|
itemFound = true;
|
||||||
@@ -693,12 +940,12 @@ void ServiceManagementService::createService(const std::string& name, const util
|
|||||||
{
|
{
|
||||||
throw std::runtime_error("Unable to create new service.");
|
throw std::runtime_error("Unable to create new service.");
|
||||||
}
|
}
|
||||||
|
util::Map<std::string, Service*>& currentServices = m_dataStore.getServices();
|
||||||
if (currentServices.find(newService->getId()) != -1)
|
if (currentServices.find(newService->getId()) != -1)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Service with this ID Already exists.");
|
throw std::runtime_error("Service with this ID Already exists.");
|
||||||
}
|
}
|
||||||
currentServices.insert(newService->getId(), util::createNewRecord(newService));
|
currentServices.insert(newService->getId(), newService);
|
||||||
m_dataStore.saveServices();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -711,10 +958,7 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
util::Map<std::string, Service*> ServiceManagementService::getServices()
|
util::Map<std::string, Service*> ServiceManagementService::getServices()
|
||||||
{
|
{
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
return m_dataStore.getServices();
|
||||||
util::Map<std::string, Service*> services;
|
|
||||||
services = util::getObjects(m_dataStore.getServices());
|
|
||||||
return services;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -729,19 +973,14 @@ Throws:
|
|||||||
*/
|
*/
|
||||||
void ServiceManagementService::removeService(const std::string& serviceID)
|
void ServiceManagementService::removeService(const std::string& serviceID)
|
||||||
{
|
{
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
util::Map<std::string, Service*>& currentServices = m_dataStore.getServices();
|
||||||
auto& currentTrackedServices = m_dataStore.getServices();
|
util::Map<std::string, ComboPackage*>& currentComboPackages = m_dataStore.getComboPackages();
|
||||||
auto& currentTrackedComboPackages = m_dataStore.getComboPackages();
|
if (currentServices.find(serviceID) != -1)
|
||||||
if (currentTrackedServices.find(serviceID) != -1)
|
|
||||||
{
|
{
|
||||||
int serviceIndex, comboPackageIndex;
|
currentServices.getValueAt(currentServices.find(serviceID))->setState(util::State::INACTIVE);
|
||||||
serviceIndex = currentTrackedServices.find(serviceID);
|
for (int iterator = 0; iterator < currentComboPackages.getSize(); iterator++)
|
||||||
currentTrackedServices.getValueAt(serviceIndex).data->setState(util::State::INACTIVE);
|
|
||||||
currentTrackedServices.getValueAt(serviceIndex).state = RecordState::MODIFIED;
|
|
||||||
for (int iterator = 0; iterator < currentTrackedComboPackages.getSize(); iterator++)
|
|
||||||
{
|
{
|
||||||
comboPackageIndex = iterator;
|
ComboPackage* currentComboPackage = currentComboPackages.getValueAt(iterator);
|
||||||
ComboPackage* currentComboPackage = currentTrackedComboPackages.getValueAt(iterator).data;
|
|
||||||
if (currentComboPackage && currentComboPackage->getState() == util::State::ACTIVE)
|
if (currentComboPackage && currentComboPackage->getState() == util::State::ACTIVE)
|
||||||
{
|
{
|
||||||
util::Map<std::string, Service*> currentServices = currentComboPackage->getServices();
|
util::Map<std::string, Service*> currentServices = currentComboPackage->getServices();
|
||||||
@@ -751,7 +990,6 @@ void ServiceManagementService::removeService(const std::string& serviceID)
|
|||||||
if (currentService->getId() == serviceID)
|
if (currentService->getId() == serviceID)
|
||||||
{
|
{
|
||||||
currentComboPackage->setState(util::State::INACTIVE);
|
currentComboPackage->setState(util::State::INACTIVE);
|
||||||
currentTrackedComboPackages.getValueAt(comboPackageIndex).state = RecordState::MODIFIED;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -762,8 +1000,6 @@ void ServiceManagementService::removeService(const std::string& serviceID)
|
|||||||
{
|
{
|
||||||
throw std::runtime_error("Service not found.");
|
throw std::runtime_error("Service not found.");
|
||||||
}
|
}
|
||||||
m_dataStore.saveServices();
|
|
||||||
m_dataStore.saveComboPackages();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -802,12 +1038,11 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
util::Map<std::string, JobCard*> ServiceManagementService::getJobCards(const std::string& technicianID)
|
util::Map<std::string, JobCard*> ServiceManagementService::getJobCards(const std::string& technicianID)
|
||||||
{
|
{
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
util::Map<std::string, JobCard*> jobCards = m_dataStore.getJobCards();
|
||||||
auto& trackedJobCards = m_dataStore.getJobCards();
|
|
||||||
util::Map<std::string, JobCard*> technicianJobCards;
|
util::Map<std::string, JobCard*> technicianJobCards;
|
||||||
for (int iterator = 0; iterator < trackedJobCards.getSize(); iterator++)
|
for (int iterator = 0; iterator < jobCards.getSize(); iterator++)
|
||||||
{
|
{
|
||||||
JobCard* currentJobCard = trackedJobCards.getValueAt(iterator).data;
|
JobCard* currentJobCard = jobCards.getValueAt(iterator);
|
||||||
if (currentJobCard->getTechnicianId() == technicianID)
|
if (currentJobCard->getTechnicianId() == technicianID)
|
||||||
{
|
{
|
||||||
technicianJobCards.insert(currentJobCard->getId(), currentJobCard);
|
technicianJobCards.insert(currentJobCard->getId(), currentJobCard);
|
||||||
@@ -856,7 +1091,6 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
void ServiceManagementService::updateJobStatus(const std::string& jobID)
|
void ServiceManagementService::updateJobStatus(const std::string& jobID)
|
||||||
{
|
{
|
||||||
DataStoreLockGuard lock(m_dataStore);
|
|
||||||
AuthenticationManagementService authenticationManagementService;
|
AuthenticationManagementService authenticationManagementService;
|
||||||
PaymentManagementService paymentManagementService;
|
PaymentManagementService paymentManagementService;
|
||||||
bool jobStatusUpdated = false, serviceBookingCompleted;
|
bool jobStatusUpdated = false, serviceBookingCompleted;
|
||||||
@@ -871,15 +1105,8 @@ void ServiceManagementService::updateJobStatus(const std::string& jobID)
|
|||||||
{
|
{
|
||||||
throw std::runtime_error("No job cards assigned to the technician.");
|
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)
|
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));
|
currentJob = currentAssignedJobs.getValueAt(currentAssignedJobs.find(jobID));
|
||||||
if (currentJob == nullptr)
|
if (currentJob == nullptr)
|
||||||
{
|
{
|
||||||
@@ -888,20 +1115,16 @@ void ServiceManagementService::updateJobStatus(const std::string& jobID)
|
|||||||
if (currentJob->getStatus() == util::ServiceJobStatus::STARTED)
|
if (currentJob->getStatus() == util::ServiceJobStatus::STARTED)
|
||||||
{
|
{
|
||||||
currentJob->setStatus(util::ServiceJobStatus::IN_PROGRESS);
|
currentJob->setStatus(util::ServiceJobStatus::IN_PROGRESS);
|
||||||
trackedJobCards.getValueAt(jobIndex).state = RecordState::MODIFIED;
|
|
||||||
jobStatusUpdated = true;
|
jobStatusUpdated = true;
|
||||||
}
|
}
|
||||||
else if (currentJob->getStatus() == util::ServiceJobStatus::IN_PROGRESS)
|
else if (currentJob->getStatus() == util::ServiceJobStatus::IN_PROGRESS)
|
||||||
{
|
{
|
||||||
currentJob->setStatus(util::ServiceJobStatus::COMPLETED);
|
currentJob->setStatus(util::ServiceJobStatus::COMPLETED);
|
||||||
trackedJobCards.getValueAt(jobIndex).state = RecordState::MODIFIED;
|
|
||||||
jobStatusUpdated = true;
|
jobStatusUpdated = true;
|
||||||
serviceBookingCompleted = hasCompletedAllJobs(currentJob->getBookingId(), currentAssignedJobs);
|
serviceBookingCompleted = hasCompletedAllJobs(currentJob->getBookingId(), currentAssignedJobs);
|
||||||
if (serviceBookingCompleted)
|
if (serviceBookingCompleted)
|
||||||
{
|
{
|
||||||
const std::string& bookingId = currentJob->getBookingId();
|
|
||||||
currentJob->getBooking()->setStatus(util::ServiceJobStatus::COMPLETED);
|
currentJob->getBooking()->setStatus(util::ServiceJobStatus::COMPLETED);
|
||||||
trackedServiceBookings.getValueAt(trackedServiceBookings.find(bookingId)).state = RecordState::MODIFIED;
|
|
||||||
paymentManagementService.generateInvoice(currentJob->getBooking());
|
paymentManagementService.generateInvoice(currentJob->getBooking());
|
||||||
std::string title = "Service Booking completed. Invoice Generated.";
|
std::string title = "Service Booking completed. Invoice Generated.";
|
||||||
std::string message = "Services completed for the booking and invoice generated.";
|
std::string message = "Services completed for the booking and invoice generated.";
|
||||||
@@ -917,6 +1140,4 @@ void ServiceManagementService::updateJobStatus(const std::string& jobID)
|
|||||||
{
|
{
|
||||||
throw std::runtime_error("Failed to update job status. Job may already be completed.");
|
throw std::runtime_error("Failed to update job status. Job may already be completed.");
|
||||||
}
|
}
|
||||||
m_dataStore.saveJobCards();
|
|
||||||
m_dataStore.saveServiceBookings();
|
|
||||||
}
|
}
|
||||||
+9
@@ -23,6 +23,7 @@ class ServiceManagementService : public NotificationManagementService
|
|||||||
private:
|
private:
|
||||||
DataStore& m_dataStore;
|
DataStore& m_dataStore;
|
||||||
static util::Map<std::string, User*> m_observers;
|
static util::Map<std::string, User*> m_observers;
|
||||||
|
util::Vector<std::string> getObserverIDs() override;
|
||||||
public:
|
public:
|
||||||
ServiceManagementService() : m_dataStore(DataStore::getInstance()) {}
|
ServiceManagementService() : m_dataStore(DataStore::getInstance()) {}
|
||||||
util::Map<std::string, Service*> getServices();
|
util::Map<std::string, Service*> getServices();
|
||||||
@@ -44,4 +45,12 @@ public:
|
|||||||
void sendNotification(User* user, const std::string& title, const std::string& message) override;
|
void sendNotification(User* user, const std::string& title, const std::string& message) override;
|
||||||
void attach(User* user) override;
|
void attach(User* user) override;
|
||||||
void detach(User* user) override;
|
void detach(User* user) override;
|
||||||
|
void loadServices();
|
||||||
|
void saveServices();
|
||||||
|
void loadComboPackages();
|
||||||
|
void saveComboPackages();
|
||||||
|
void loadServiceBookings();
|
||||||
|
void saveServiceBookings();
|
||||||
|
void loadJobCards();
|
||||||
|
void saveJobCards();
|
||||||
};
|
};
|
||||||
|
|||||||
+4
-5
@@ -11,6 +11,7 @@ Date:19-May-2026
|
|||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "Enums.h"
|
#include "Enums.h"
|
||||||
#include "Factory.h"
|
#include "Factory.h"
|
||||||
|
#include "FileManager.h"
|
||||||
#include "InventoryManagementService.h"
|
#include "InventoryManagementService.h"
|
||||||
#include "Notification.h"
|
#include "Notification.h"
|
||||||
#include "PaymentManagementService.h"
|
#include "PaymentManagementService.h"
|
||||||
@@ -180,6 +181,7 @@ util::Vector<Notification*> UserManagementService::getUserNotifications(const st
|
|||||||
notificationsVector.push_back(notification);
|
notificationsVector.push_back(notification);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_dataStore.unlockDataStore();
|
||||||
return notificationsVector;
|
return notificationsVector;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -211,18 +213,15 @@ void UserManagementService::deleteNotification(const std::string& notificationID
|
|||||||
{
|
{
|
||||||
throw std::runtime_error("No user found with given UserID");
|
throw std::runtime_error("No user found with given UserID");
|
||||||
}
|
}
|
||||||
|
User* user = trackedUsersMap.getValueAt(userIndex).data;
|
||||||
int notificationIndex = trackedNotificationsMap.find(notificationID);
|
int notificationIndex = trackedNotificationsMap.find(notificationID);
|
||||||
if (notificationIndex == -1)
|
if (notificationIndex == -1)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("No notification found with given NotificationID");
|
throw std::runtime_error("No notification found with given NotificationID");
|
||||||
}
|
}
|
||||||
Notification* notification = trackedNotificationsMap.getValueAt(notificationIndex).data;
|
trackedNotificationsMap.getValueAt(notificationIndex).data->setState(util::State::INACTIVE);
|
||||||
if (notification->getRecipientUserId() == userID)
|
|
||||||
{
|
|
||||||
notification->setState(util::State::INACTIVE);
|
|
||||||
trackedNotificationsMap.getValueAt(notificationIndex).state = RecordState::MODIFIED;
|
trackedNotificationsMap.getValueAt(notificationIndex).state = RecordState::MODIFIED;
|
||||||
m_dataStore.saveNotifications();
|
m_dataStore.saveNotifications();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -43,4 +43,67 @@ namespace util
|
|||||||
position++;
|
position++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: loadRecords
|
||||||
|
Description: Loads records from a given file path into a vector of strings.
|
||||||
|
Skips the header line if present. Creates the file if it does not exist.
|
||||||
|
Parameters:
|
||||||
|
- filePath: const std::string&, path to the file
|
||||||
|
Returns:
|
||||||
|
- util::Vector<std::string>: Vector containing all records (excluding header)
|
||||||
|
Throws:
|
||||||
|
- None (creates file if missing)
|
||||||
|
*/
|
||||||
|
inline util::Vector<std::string> loadRecords(const std::string& filePath)
|
||||||
|
{
|
||||||
|
util::Vector<std::string> records;
|
||||||
|
std::ifstream file(filePath);
|
||||||
|
if (!file.is_open())
|
||||||
|
{
|
||||||
|
ensureDirectoryExists(filePath);
|
||||||
|
std::ofstream newFile(filePath);
|
||||||
|
newFile.close();
|
||||||
|
file.open(filePath);
|
||||||
|
}
|
||||||
|
std::string line;
|
||||||
|
bool isHeader = true;
|
||||||
|
while (std::getline(file, line))
|
||||||
|
{
|
||||||
|
if (isHeader)
|
||||||
|
{
|
||||||
|
isHeader = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
records.push_back(line);
|
||||||
|
}
|
||||||
|
return records;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: saveRecords
|
||||||
|
Description: Saves records to a given file path. Overwrites existing content
|
||||||
|
and writes a header line followed by all records.
|
||||||
|
Parameters:
|
||||||
|
- filePath: const std::string&, path to the file
|
||||||
|
- records: const util::Vector<std::string>&, 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<std::string>& 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';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
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 <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
#include "Vector.h"
|
||||||
|
#include "Map.h"
|
||||||
|
#include "FileHelper.h"
|
||||||
|
|
||||||
|
namespace util
|
||||||
|
{
|
||||||
|
template <typename T> using objects = util::Map<std::string, T*>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class FileManager
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::string m_filePath;
|
||||||
|
public:
|
||||||
|
FileManager() : m_filePath("") {}
|
||||||
|
FileManager(const std::string& filePath) : m_filePath(filePath) {}
|
||||||
|
objects<T> load();
|
||||||
|
void save(const objects<T>&);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
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<std::string, T*> containing deserialized objects
|
||||||
|
Throws:
|
||||||
|
- std::runtime_error if deserialization fails for any record
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
objects<T> FileManager<T>::load()
|
||||||
|
{
|
||||||
|
objects<T> records;
|
||||||
|
std::ifstream file(m_filePath);
|
||||||
|
if (!file.is_open())
|
||||||
|
{
|
||||||
|
ensureDirectoryExists(m_filePath);
|
||||||
|
std::ofstream newFile(m_filePath);
|
||||||
|
newFile.close();
|
||||||
|
file.open(m_filePath);
|
||||||
|
}
|
||||||
|
util::Vector<std::string> 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<std::string, T*>&, map of objects to save
|
||||||
|
Returns:
|
||||||
|
- void
|
||||||
|
Throws:
|
||||||
|
- std::runtime_error if the file cannot be opened for writing
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
void FileManager<T>::save(const objects<T>& records)
|
||||||
|
{
|
||||||
|
util::Vector<std::string> 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';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,7 +28,7 @@ namespace util
|
|||||||
if (!(std::cin >> value))
|
if (!(std::cin >> value))
|
||||||
{
|
{
|
||||||
std::cin.clear();
|
std::cin.clear();
|
||||||
std::cin.ignore((std::numeric_limits<std::streamsize>::max)(), '\n');
|
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||||
throw std::runtime_error("Invalid console input");
|
throw std::runtime_error("Invalid console input");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,52 @@ namespace util
|
|||||||
return cost;
|
return cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: loadObservers
|
||||||
|
Description: Loads observer IDs from a file and attaches the corresponding users
|
||||||
|
to the notification management service. Validates that each observer ID
|
||||||
|
exists in the datastore before attaching.
|
||||||
|
Parameters:
|
||||||
|
- filePath: const std::string&, path to the file containing observer IDs
|
||||||
|
- service: NotificationManagementService*, pointer to the notification service
|
||||||
|
- dataStore: DataStore&, reference to the datastore containing users
|
||||||
|
Returns:
|
||||||
|
- void
|
||||||
|
Throws:
|
||||||
|
- std::runtime_error if an observer ID is invalid (not found in datastore)
|
||||||
|
*/
|
||||||
|
inline void loadObservers(const std::string& filePath, NotificationManagementService* service, DataStore& dataStore)
|
||||||
|
{
|
||||||
|
auto observerIDs = util::loadRecords(filePath);
|
||||||
|
auto& users = dataStore.getUsers();
|
||||||
|
for (int index = 0; index < observerIDs.getSize(); index++)
|
||||||
|
{
|
||||||
|
const std::string& observerID = observerIDs[index];
|
||||||
|
int userIndex = users.find(observerID);
|
||||||
|
if (userIndex == -1)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Invalid Observer ID");
|
||||||
|
}
|
||||||
|
service->attach(users.getValueAt(userIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: saveObservers
|
||||||
|
Description: Saves the current observer IDs from the notification management service
|
||||||
|
to a file for persistence.
|
||||||
|
Parameters:
|
||||||
|
- filePath: const std::string&, path to the file where observer IDs will be saved
|
||||||
|
- service: NotificationManagementService*, pointer to the notification service
|
||||||
|
Returns:
|
||||||
|
- void
|
||||||
|
*/
|
||||||
|
inline void saveObservers(const std::string& filePath, NotificationManagementService* service)
|
||||||
|
{
|
||||||
|
auto observerIDs = service->getObserverIDs();
|
||||||
|
util::saveRecords(filePath, observerIDs);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename TObject>
|
template<typename TObject>
|
||||||
Map<std::string, TObject*> getObjects(const Map<std::string, TrackedRecord<TObject>>& trackedRecords);
|
Map<std::string, TObject*> getObjects(const Map<std::string, TrackedRecord<TObject>>& trackedRecords);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user