Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d8ef54ddd0 | |||
| 5fb92fba0e | |||
| 95d1c9a04e | |||
| 2963d05ea1 | |||
| d2a7420db5 | |||
| 7047e96b3c | |||
| f545d57f79 | |||
| f0c7d27e6c | |||
| b98062d45c |
@@ -14,6 +14,7 @@ Date: 19-May-2026
|
|||||||
#include "FileHelper.h"
|
#include "FileHelper.h"
|
||||||
#include "ServiceBooking.h"
|
#include "ServiceBooking.h"
|
||||||
#include "JobCard.h"
|
#include "JobCard.h"
|
||||||
|
#include "Invoice.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: DataStore
|
Function: DataStore
|
||||||
@@ -324,6 +325,8 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
util::Map<std::string, TrackedRecord<InventoryItem>>& DataStore::getInventoryItems()
|
util::Map<std::string, TrackedRecord<InventoryItem>>& DataStore::getInventoryItems()
|
||||||
{
|
{
|
||||||
|
auto inventoryItems = loadRecords<InventoryItem, SerializedInventoryItem>(m_inventoryItems);
|
||||||
|
refreshCache(m_inventoryItemCache, inventoryItems);
|
||||||
return m_inventoryItemCache;
|
return m_inventoryItemCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -448,6 +451,45 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
util::Map<std::string, TrackedRecord<Invoice>>& DataStore::getInvoices()
|
util::Map<std::string, TrackedRecord<Invoice>>& DataStore::getInvoices()
|
||||||
{
|
{
|
||||||
|
auto& serviceBookings = getServiceBookings();
|
||||||
|
auto& inventoryItems = getInventoryItems();
|
||||||
|
util::Map<std::string, TrackedRecord<Invoice>> invoices = loadRecords<Invoice, SerializedInvoice>(m_invoices);
|
||||||
|
refreshCache(m_invoiceCache, invoices);
|
||||||
|
for (int iterator = 0; iterator < m_invoiceCache.getSize(); iterator++)
|
||||||
|
{
|
||||||
|
auto& trackedInvoice = m_invoiceCache.getValueAt(iterator);
|
||||||
|
Invoice* invoice = trackedInvoice.data;
|
||||||
|
if (!invoice)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const std::string& currentBookingId = invoice->getBookingId();
|
||||||
|
int currentBookingIndex = serviceBookings.find(currentBookingId);
|
||||||
|
if (currentBookingIndex == -1)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Invalid Service Booking Index.");
|
||||||
|
}
|
||||||
|
ServiceBooking* currentBooking = serviceBookings.getValueAt(currentBookingIndex).data;
|
||||||
|
auto& currentInventoryItemIds = invoice->getPartIDs();
|
||||||
|
util::Map<std::string, InventoryItem*> currentInventoryItems;
|
||||||
|
for (int iterator = 0; iterator < currentInventoryItemIds.getSize(); iterator++)
|
||||||
|
{
|
||||||
|
const std::string& currentItemId = currentInventoryItemIds[iterator];
|
||||||
|
int currentItemIndex = inventoryItems.find(currentItemId);
|
||||||
|
if (currentItemIndex == -1)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Invalid Inventory item id.");
|
||||||
|
}
|
||||||
|
InventoryItem* currentItem = inventoryItems.getValueAt(currentItemIndex).data;
|
||||||
|
if (!currentItem)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
currentInventoryItems[currentItemId] = currentItem;
|
||||||
|
}
|
||||||
|
invoice->setBooking(currentBooking);
|
||||||
|
invoice->setParts(currentInventoryItems);
|
||||||
|
}
|
||||||
return m_invoiceCache;
|
return m_invoiceCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -583,6 +625,7 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
void DataStore::saveInventoryItems()
|
void DataStore::saveInventoryItems()
|
||||||
{
|
{
|
||||||
|
saveRecords<InventoryItem, SerializedInventoryItem>(m_inventoryItems, m_inventoryItemCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -621,6 +664,7 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
void DataStore::saveInvoices()
|
void DataStore::saveInvoices()
|
||||||
{
|
{
|
||||||
|
saveRecords<Invoice, SerializedInvoice>(m_invoices, m_invoiceCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -737,4 +781,3 @@ bool DataStore::unlockDataStore()
|
|||||||
}
|
}
|
||||||
return ReleaseMutex(m_globalMutex) != 0;
|
return ReleaseMutex(m_globalMutex) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+23
-56
@@ -8,6 +8,7 @@ Date: 19-May-2026
|
|||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include "SerializedRecords.h"
|
||||||
#include "Factory.h"
|
#include "Factory.h"
|
||||||
#include "StringHelper.h"
|
#include "StringHelper.h"
|
||||||
#include "InventoryItem.h"
|
#include "InventoryItem.h"
|
||||||
@@ -27,7 +28,8 @@ InventoryItem::InventoryItem()
|
|||||||
: m_id("IIM" + std::to_string(++m_uid)),
|
: m_id("IIM" + std::to_string(++m_uid)),
|
||||||
m_quantity(0),
|
m_quantity(0),
|
||||||
m_status(util::State::ACTIVE),
|
m_status(util::State::ACTIVE),
|
||||||
m_price(0.0) {}
|
m_price(0.0) {
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: InventoryItem
|
Function: InventoryItem
|
||||||
@@ -45,7 +47,8 @@ InventoryItem::InventoryItem(const std::string& partName, int quantity, double p
|
|||||||
m_partName(partName),
|
m_partName(partName),
|
||||||
m_quantity(quantity),
|
m_quantity(quantity),
|
||||||
m_status(util::State::ACTIVE),
|
m_status(util::State::ACTIVE),
|
||||||
m_price(price) {}
|
m_price(price) {
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: InventoryItem (parameterized constructor with ID)
|
Function: InventoryItem (parameterized constructor with ID)
|
||||||
@@ -206,73 +209,37 @@ void InventoryItem::setState(util::State status)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Function: serialize
|
Function: serialize
|
||||||
Description: Serializes the inventory item into a CSV-formatted string.
|
Description: Serializes the InventoryItem object into a SerializedInventoryItem record.
|
||||||
Parameters:
|
Parameters:
|
||||||
- None
|
- None
|
||||||
Returns:
|
Returns:
|
||||||
- std::string: Serialized inventory item record
|
- SerializedInventoryItem: Serialized representation of the inventory item
|
||||||
*/
|
*/
|
||||||
std::string InventoryItem::serialize() const
|
SerializedInventoryItem InventoryItem::serialize() const
|
||||||
{
|
{
|
||||||
std::ostringstream serializedInventoryItem;
|
SerializedInventoryItem serialized = {};
|
||||||
serializedInventoryItem << m_id << ','
|
strcpy_s(serialized.id, sizeof(serialized.id), m_id.c_str());
|
||||||
<< m_partName << ','
|
strcpy_s(serialized.partName, sizeof(serialized.partName), m_partName.c_str());
|
||||||
<< m_quantity << ','
|
serialized.quantity = m_quantity;
|
||||||
<< m_price << ','
|
serialized.price = m_price;
|
||||||
<< util::getStateString(m_status);
|
serialized.status = m_status;
|
||||||
return serializedInventoryItem.str();
|
return serialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: deserialize
|
Function: deserialize
|
||||||
Description: Deserializes a CSV-formatted string into an InventoryItem object.
|
Description: Deserializes a SerializedInventoryItem record into an InventoryItem object.
|
||||||
Parameters:
|
Parameters:
|
||||||
- record: const std::string&, serialized inventory item record
|
- serializedInventoryItem: const SerializedInventoryItem&, serialized inventory item record
|
||||||
Returns:
|
Returns:
|
||||||
- InventoryItem*: Pointer to the deserialized InventoryItem object
|
- InventoryItem*: Pointer to the deserialized InventoryItem object
|
||||||
Throws:
|
|
||||||
- std::runtime_error if data is invalid
|
|
||||||
*/
|
*/
|
||||||
InventoryItem* InventoryItem::deserialize(const std::string& record)
|
InventoryItem* InventoryItem::deserialize(const SerializedInventoryItem& serializedInventoryItem)
|
||||||
{
|
{
|
||||||
std::string id, partName;
|
|
||||||
std::string quantityString, priceString, statusString;
|
|
||||||
int quantity;
|
|
||||||
double price;
|
|
||||||
std::istringstream serializedInventoryItem(record);
|
|
||||||
getline(serializedInventoryItem, id, ',');
|
|
||||||
getline(serializedInventoryItem, partName, ',');
|
|
||||||
getline(serializedInventoryItem, quantityString, ',');
|
|
||||||
getline(serializedInventoryItem, priceString, ',');
|
|
||||||
getline(serializedInventoryItem, statusString, ',');
|
|
||||||
try
|
|
||||||
{
|
|
||||||
quantity = std::stoi(quantityString);
|
|
||||||
price = std::stod(priceString);
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("Invalid inventory item data");
|
|
||||||
}
|
|
||||||
util::State status = util::getState(statusString);
|
|
||||||
return Factory::getObject<InventoryItem>(
|
return Factory::getObject<InventoryItem>(
|
||||||
id,
|
serializedInventoryItem.id,
|
||||||
partName,
|
serializedInventoryItem.partName,
|
||||||
quantity,
|
serializedInventoryItem.quantity,
|
||||||
price,
|
serializedInventoryItem.price,
|
||||||
status
|
serializedInventoryItem.status);
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Function: getHeaders
|
|
||||||
Description: Retrieves the CSV headers for inventory item serialization.
|
|
||||||
Parameters:
|
|
||||||
- None
|
|
||||||
Returns:
|
|
||||||
- std::string: Header string ("ID,PartName,Quantity,Price,Status")
|
|
||||||
*/
|
|
||||||
std::string InventoryItem::getHeaders()
|
|
||||||
{
|
|
||||||
return "ID,PartName,Quantity,Price,Status";
|
|
||||||
}
|
}
|
||||||
@@ -6,11 +6,12 @@ Author: Trenser
|
|||||||
Date: 19-May-2026
|
Date: 19-May-2026
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "Enums.h"
|
#include "Enums.h"
|
||||||
|
|
||||||
|
struct SerializedInventoryItem;
|
||||||
|
|
||||||
class InventoryItem
|
class InventoryItem
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@@ -34,7 +35,6 @@ public:
|
|||||||
void setQuantity(int quantity);
|
void setQuantity(int quantity);
|
||||||
void setPrice(double price);
|
void setPrice(double price);
|
||||||
void setState(util::State status);
|
void setState(util::State status);
|
||||||
std::string serialize() const;
|
SerializedInventoryItem serialize() const;
|
||||||
static InventoryItem* deserialize(const std::string&);
|
static InventoryItem* deserialize(const SerializedInventoryItem&);
|
||||||
static std::string getHeaders();
|
|
||||||
};
|
};
|
||||||
@@ -9,6 +9,7 @@ Date: 19-May-2026
|
|||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include "SerializedRecords.h"
|
||||||
#include "Invoice.h"
|
#include "Invoice.h"
|
||||||
#include "Factory.h"
|
#include "Factory.h"
|
||||||
#include "InventoryItem.h"
|
#include "InventoryItem.h"
|
||||||
@@ -34,7 +35,8 @@ Invoice::Invoice()
|
|||||||
m_discountPercentage(0.0),
|
m_discountPercentage(0.0),
|
||||||
m_totalAmount(0.0),
|
m_totalAmount(0.0),
|
||||||
m_paymentMethod(util::PaymentMode()),
|
m_paymentMethod(util::PaymentMode()),
|
||||||
m_status(util::PaymentStatus()) {}
|
m_status(util::PaymentStatus()) {
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: Invoice
|
Function: Invoice
|
||||||
@@ -473,100 +475,50 @@ static util::Vector<std::string> getPartIDsAsVector(const std::string& partIDsSt
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Function: serialize
|
Function: serialize
|
||||||
Description: Serializes the invoice into a CSV-formatted string.
|
Description: Serializes the Invoice object into a SerializedInvoice record.
|
||||||
Parameters:
|
Parameters:
|
||||||
- None
|
- None
|
||||||
Returns:
|
Returns:
|
||||||
- std::string: Serialized invoice record
|
- SerializedInvoice: Serialized representation of the invoice
|
||||||
*/
|
*/
|
||||||
std::string Invoice::serialize() const
|
SerializedInvoice Invoice::serialize() const
|
||||||
{
|
{
|
||||||
std::ostringstream serializedInvoice;
|
SerializedInvoice serialized = {};
|
||||||
serializedInvoice << m_id << ','
|
strcpy_s(serialized.id, sizeof(serialized.id), m_id.c_str());
|
||||||
<< m_bookingId << ','
|
strcpy_s(serialized.bookingId, sizeof(serialized.bookingId), m_bookingId.c_str());
|
||||||
<< m_invoiceDate.toString() << ','
|
strcpy_s(serialized.partIDs, sizeof(serialized.partIDs), getPartIDsAsString(m_partIDs).c_str());
|
||||||
<< m_laborCost << ','
|
serialized.invoiceDate = m_invoiceDate;
|
||||||
<< getPartIDsAsString(m_partIDs) << ','
|
serialized.laborCost = m_laborCost;
|
||||||
<< m_partsCost << ','
|
serialized.partsCost = m_partsCost;
|
||||||
<< m_discountPercentage << ','
|
serialized.discountPercentage = m_discountPercentage;
|
||||||
<< m_totalAmount << ','
|
serialized.totalAmount = m_totalAmount;
|
||||||
<< m_paymentDate.toString() << ','
|
serialized.paymentDate = m_paymentDate;
|
||||||
<< util::getPaymentModeString(m_paymentMethod) << ','
|
serialized.paymentMethod = m_paymentMethod;
|
||||||
<< util::getPaymentStatusString(m_status);
|
serialized.status = m_status;
|
||||||
return serializedInvoice.str();
|
return serialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: deserialize
|
Function: deserialize
|
||||||
Description: Deserializes a CSV-formatted string into an Invoice object.
|
Description: Deserializes a SerializedInvoice record into an Invoice object.
|
||||||
Parameters:
|
Parameters:
|
||||||
- record: const std::string&, serialized invoice record
|
- serializedInvoice: const SerializedInvoice&, serialized invoice record
|
||||||
Returns:
|
Returns:
|
||||||
- Invoice*: Pointer to the deserialized Invoice object
|
- Invoice*: Pointer to the deserialized Invoice object
|
||||||
Throws:
|
|
||||||
- std::runtime_error if data is invalid
|
|
||||||
*/
|
*/
|
||||||
Invoice* Invoice::deserialize(const std::string& record)
|
Invoice* Invoice::deserialize(const SerializedInvoice& serializedInvoice)
|
||||||
{
|
{
|
||||||
std::string id, bookingId;
|
util::Vector<std::string> partIDs = getPartIDsAsVector(serializedInvoice.partIDs);
|
||||||
std::string invoiceDateString, laborCostString, partIDsString;
|
|
||||||
std::string partsCostString, discountPercentageString, totalAmountString;
|
|
||||||
std::string paymentDateString, paymentMethodString, statusString;
|
|
||||||
double laborCost, partsCost, discountPercentage, totalAmount;
|
|
||||||
std::istringstream serializedInvoice(record);
|
|
||||||
getline(serializedInvoice, id, ',');
|
|
||||||
getline(serializedInvoice, bookingId, ',');
|
|
||||||
getline(serializedInvoice, invoiceDateString, ',');
|
|
||||||
getline(serializedInvoice, laborCostString, ',');
|
|
||||||
getline(serializedInvoice, partIDsString, ',');
|
|
||||||
getline(serializedInvoice, partsCostString, ',');
|
|
||||||
getline(serializedInvoice, discountPercentageString, ',');
|
|
||||||
getline(serializedInvoice, totalAmountString, ',');
|
|
||||||
getline(serializedInvoice, paymentDateString, ',');
|
|
||||||
getline(serializedInvoice, paymentMethodString, ',');
|
|
||||||
getline(serializedInvoice, statusString, ',');
|
|
||||||
util::Timestamp invoiceDate;
|
|
||||||
util::Timestamp paymentDate;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
invoiceDate = util::Timestamp::fromString(invoiceDateString);
|
|
||||||
paymentDate = util::Timestamp::fromString(paymentDateString);
|
|
||||||
laborCost = std::stod(laborCostString);
|
|
||||||
partsCost = std::stod(partsCostString);
|
|
||||||
discountPercentage = std::stod(discountPercentageString);
|
|
||||||
totalAmount = std::stod(totalAmountString);
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("Invalid invoice data");
|
|
||||||
}
|
|
||||||
util::Vector<std::string> partIDs = getPartIDsAsVector(partIDsString);
|
|
||||||
util::PaymentMode paymentMethod = util::getPaymentMode(paymentMethodString);
|
|
||||||
util::PaymentStatus status = util::getPaymentStatus(statusString);
|
|
||||||
return Factory::getObject<Invoice>(
|
return Factory::getObject<Invoice>(
|
||||||
id,
|
serializedInvoice.id,
|
||||||
bookingId,
|
serializedInvoice.bookingId,
|
||||||
invoiceDate,
|
serializedInvoice.invoiceDate,
|
||||||
partIDs,
|
partIDs,
|
||||||
laborCost,
|
serializedInvoice.laborCost,
|
||||||
partsCost,
|
serializedInvoice.partsCost,
|
||||||
discountPercentage,
|
serializedInvoice.discountPercentage,
|
||||||
totalAmount,
|
serializedInvoice.totalAmount,
|
||||||
paymentDate,
|
serializedInvoice.paymentDate,
|
||||||
paymentMethod,
|
serializedInvoice.paymentMethod,
|
||||||
status
|
serializedInvoice.status);
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Function: getHeaders
|
|
||||||
Description: Retrieves the CSV headers for invoice serialization.
|
|
||||||
Parameters:
|
|
||||||
- None
|
|
||||||
Returns:
|
|
||||||
- std::string: Header string ("ID,BookingID,InvoiceDate,LaborCost,PartIDs,PartsCost,DiscountPercentage,TotalAmount,PaymentDate,PaymentMethod,Status")
|
|
||||||
*/
|
|
||||||
std::string Invoice::getHeaders()
|
|
||||||
{
|
|
||||||
return "ID,BookingID,InvoiceDate,LaborCost,PartIDs,PartsCost,DiscountPercentage,TotalAmount,PaymentDate,PaymentMethod,Status";
|
|
||||||
}
|
}
|
||||||
@@ -6,7 +6,6 @@ Author: Trenser
|
|||||||
Date: 19-May-2026
|
Date: 19-May-2026
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "Map.h"
|
#include "Map.h"
|
||||||
@@ -16,6 +15,7 @@ Date: 19-May-2026
|
|||||||
|
|
||||||
class ServiceBooking;
|
class ServiceBooking;
|
||||||
class InventoryItem;
|
class InventoryItem;
|
||||||
|
struct SerializedInvoice;
|
||||||
|
|
||||||
class Invoice
|
class Invoice
|
||||||
{
|
{
|
||||||
@@ -87,7 +87,6 @@ public:
|
|||||||
void setPaymentDate(const util::Timestamp& paymentDate);
|
void setPaymentDate(const util::Timestamp& paymentDate);
|
||||||
void setPaymentMethod(util::PaymentMode paymentMethod);
|
void setPaymentMethod(util::PaymentMode paymentMethod);
|
||||||
void setStatus(util::PaymentStatus status);
|
void setStatus(util::PaymentStatus status);
|
||||||
std::string serialize() const;
|
SerializedInvoice serialize() const;
|
||||||
static Invoice* deserialize(const std::string&);
|
static Invoice* deserialize(const SerializedInvoice&);
|
||||||
static std::string getHeaders();
|
|
||||||
};
|
};
|
||||||
+51
-25
@@ -57,18 +57,19 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
void InventoryManagementService::sendLowStockAlerts()
|
void InventoryManagementService::sendLowStockAlerts()
|
||||||
{
|
{
|
||||||
auto& inventoryItems = m_dataStore.getInventoryItems();
|
DataStoreLockGuard lock(m_dataStore);
|
||||||
if (inventoryItems.isEmpty())
|
auto& trackedInventoryItemsMap = m_dataStore.getInventoryItems();
|
||||||
|
auto& trackedUserMap = m_dataStore.getUsers();
|
||||||
|
if (trackedInventoryItemsMap.isEmpty())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int inventoryItemsSize = inventoryItems.getSize();
|
int inventoryItemsSize = trackedInventoryItemsMap.getSize();
|
||||||
auto& usersMap = m_dataStore.getUsers();
|
int usersMapSize = trackedUserMap.getSize();
|
||||||
int usersMapSize = usersMap.getSize();
|
|
||||||
util::Vector<User*> adminUsers;
|
util::Vector<User*> adminUsers;
|
||||||
for (int index = 0; index < usersMapSize; index++)
|
for (int index = 0; index < usersMapSize; index++)
|
||||||
{
|
{
|
||||||
User* user = usersMap.getValueAt(index);
|
User* user = trackedUserMap.getValueAt(index).data;
|
||||||
if (user->getUserType() == util::UserType::ADMIN)
|
if (user->getUserType() == util::UserType::ADMIN)
|
||||||
{
|
{
|
||||||
adminUsers.push_back(user);
|
adminUsers.push_back(user);
|
||||||
@@ -81,7 +82,7 @@ void InventoryManagementService::sendLowStockAlerts()
|
|||||||
}
|
}
|
||||||
for (int index = 0; index < inventoryItemsSize; index++)
|
for (int index = 0; index < inventoryItemsSize; index++)
|
||||||
{
|
{
|
||||||
InventoryItem* inventoryItem = inventoryItems.getValueAt(index);
|
InventoryItem* inventoryItem = trackedInventoryItemsMap.getValueAt(index).data;
|
||||||
if (inventoryItem && inventoryItem->getQuantity() < config::threshold::INVENTORY_LOW_STOCK_THRESHOLD)
|
if (inventoryItem && inventoryItem->getQuantity() < config::threshold::INVENTORY_LOW_STOCK_THRESHOLD)
|
||||||
{
|
{
|
||||||
sendLowStockAlertsToAdmins(*this, inventoryItem, adminUsers);
|
sendLowStockAlertsToAdmins(*this, inventoryItem, adminUsers);
|
||||||
@@ -100,8 +101,11 @@ Return type: void
|
|||||||
*/
|
*/
|
||||||
void InventoryManagementService::addInventoryItem(const std::string& partName, int quantity, double price)
|
void InventoryManagementService::addInventoryItem(const std::string& partName, int quantity, double price)
|
||||||
{
|
{
|
||||||
|
DataStoreLockGuard lock(m_dataStore);
|
||||||
|
auto& trackedInventoryItemMap = m_dataStore.getInventoryItems();
|
||||||
InventoryItem* newItem = Factory::getObject<InventoryItem>(partName, quantity, price);
|
InventoryItem* newItem = Factory::getObject<InventoryItem>(partName, quantity, price);
|
||||||
m_dataStore.getInventoryItems().insert(newItem->getId(), newItem);
|
trackedInventoryItemMap.insert(newItem->getId(), util::createNewRecord(newItem));
|
||||||
|
m_dataStore.saveInventoryItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -113,16 +117,22 @@ Return type: void
|
|||||||
*/
|
*/
|
||||||
void InventoryManagementService::addInventoryItemStock(const std::string& selectedItemId, int quantity)
|
void InventoryManagementService::addInventoryItemStock(const std::string& selectedItemId, int quantity)
|
||||||
{
|
{
|
||||||
int index = m_dataStore.getInventoryItems().find(selectedItemId);
|
DataStoreLockGuard lock(m_dataStore);
|
||||||
if (index != -1)
|
auto& trackedInventoryItemMap = m_dataStore.getInventoryItems();
|
||||||
|
int index = trackedInventoryItemMap.find(selectedItemId);
|
||||||
|
if (index == -1)
|
||||||
{
|
{
|
||||||
InventoryItem* item = m_dataStore.getInventoryItems().getValueAt(index);
|
throw std::runtime_error("Inventory update failed: Item ID '" + selectedItemId + "' not found.");
|
||||||
if (item != nullptr)
|
}
|
||||||
|
InventoryItem* item = trackedInventoryItemMap.getValueAt(index).data;
|
||||||
|
if (item == nullptr)
|
||||||
{
|
{
|
||||||
|
throw std::runtime_error("Inventory update failed. Item does not exist.\n");
|
||||||
|
}
|
||||||
int totalQuantity = item->getQuantity() + quantity;
|
int totalQuantity = item->getQuantity() + quantity;
|
||||||
item->setQuantity(totalQuantity);
|
item->setQuantity(totalQuantity);
|
||||||
}
|
trackedInventoryItemMap.getValueAt(index).state = RecordState::MODIFIED;
|
||||||
}
|
m_dataStore.saveInventoryItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -133,7 +143,10 @@ Return type: util::Map<std::string, InventoryItem*>
|
|||||||
*/
|
*/
|
||||||
util::Map<std::string, InventoryItem*> InventoryManagementService::getInventoryItems()
|
util::Map<std::string, InventoryItem*> InventoryManagementService::getInventoryItems()
|
||||||
{
|
{
|
||||||
return m_dataStore.getInventoryItems();
|
DataStoreLockGuard lock(m_dataStore);
|
||||||
|
auto& trackedInventoryItemMap = m_dataStore.getInventoryItems();
|
||||||
|
auto inventoryMap = util::getObjects(trackedInventoryItemMap);
|
||||||
|
return inventoryMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -144,15 +157,21 @@ Return type: void
|
|||||||
*/
|
*/
|
||||||
void InventoryManagementService::removeInventoryItem(const std::string& inventoryItemID)
|
void InventoryManagementService::removeInventoryItem(const std::string& inventoryItemID)
|
||||||
{
|
{
|
||||||
int index = m_dataStore.getInventoryItems().find(inventoryItemID);
|
DataStoreLockGuard lock(m_dataStore);
|
||||||
if (index != -1)
|
auto& trackedInventoryItemMap = m_dataStore.getInventoryItems();
|
||||||
|
int index = trackedInventoryItemMap.find(inventoryItemID);
|
||||||
|
if (index == -1)
|
||||||
{
|
{
|
||||||
InventoryItem* item = m_dataStore.getInventoryItems().getValueAt(index);
|
throw std::runtime_error("Inventory removal failed: Item ID '" + inventoryItemID + "' not found.");
|
||||||
if (item != nullptr)
|
}
|
||||||
|
InventoryItem* item = trackedInventoryItemMap.getValueAt(index).data;
|
||||||
|
if (item == nullptr)
|
||||||
{
|
{
|
||||||
|
throw std::runtime_error("Inventory removal failed: Item ID does not exist.");
|
||||||
|
}
|
||||||
item->setState(util::State::INACTIVE);
|
item->setState(util::State::INACTIVE);
|
||||||
}
|
trackedInventoryItemMap.getValueAt(index).state = RecordState::MODIFIED;
|
||||||
}
|
m_dataStore.saveInventoryItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -163,13 +182,20 @@ Return type: InventoryItem*
|
|||||||
*/
|
*/
|
||||||
InventoryItem* InventoryManagementService::getInventoryItem(const std::string& inventoryItemID)
|
InventoryItem* InventoryManagementService::getInventoryItem(const std::string& inventoryItemID)
|
||||||
{
|
{
|
||||||
int index = m_dataStore.getInventoryItems().find(inventoryItemID);
|
DataStoreLockGuard lock(m_dataStore);
|
||||||
if (index != -1)
|
auto& trackedInventoryItemMap = m_dataStore.getInventoryItems();
|
||||||
|
int index = trackedInventoryItemMap.find(inventoryItemID);
|
||||||
|
if (index == -1)
|
||||||
{
|
{
|
||||||
return m_dataStore.getInventoryItems().getValueAt(index);
|
|
||||||
}
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
InventoryItem* inventoryItem = trackedInventoryItemMap.getValueAt(index).data;
|
||||||
|
if (inventoryItem == nullptr)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Item ID does not exist.");
|
||||||
|
}
|
||||||
|
return inventoryItem;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: attach
|
Function: attach
|
||||||
|
|||||||
+36
-20
@@ -15,6 +15,7 @@ Date: 20-May-2026
|
|||||||
#include "Invoice.h"
|
#include "Invoice.h"
|
||||||
#include "JobCard.h"
|
#include "JobCard.h"
|
||||||
#include "PaymentManagementService.h"
|
#include "PaymentManagementService.h"
|
||||||
|
#include "DataStoreLockGuard.h"
|
||||||
#include "Service.h"
|
#include "Service.h"
|
||||||
#include "ServiceBooking.h"
|
#include "ServiceBooking.h"
|
||||||
#include "Timestamp.h"
|
#include "Timestamp.h"
|
||||||
@@ -121,11 +122,12 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
void PaymentManagementService::sendPaymentReminders()
|
void PaymentManagementService::sendPaymentReminders()
|
||||||
{
|
{
|
||||||
auto& invoicesMap = m_dataStore.getInvoices();
|
DataStoreLockGuard lock(m_dataStore);
|
||||||
int invoicesMapSize = invoicesMap.getSize();
|
auto& trackedInvoicesMap = m_dataStore.getInvoices();
|
||||||
|
int invoicesMapSize = trackedInvoicesMap.getSize();
|
||||||
for (int index = 0; index < invoicesMapSize; index++)
|
for (int index = 0; index < invoicesMapSize; index++)
|
||||||
{
|
{
|
||||||
const Invoice* invoice = invoicesMap.getValueAt(index);
|
const Invoice* invoice = trackedInvoicesMap.getValueAt(index).data;
|
||||||
if (invoice && invoice->getStatus() == util::PaymentStatus::PENDING)
|
if (invoice && invoice->getStatus() == util::PaymentStatus::PENDING)
|
||||||
{
|
{
|
||||||
util::Timestamp invoiceCreationTimestamp = invoice->getInvoiceDate();
|
util::Timestamp invoiceCreationTimestamp = invoice->getInvoiceDate();
|
||||||
@@ -181,6 +183,7 @@ Throws:
|
|||||||
*/
|
*/
|
||||||
void PaymentManagementService::generateInvoice(ServiceBooking* booking)
|
void PaymentManagementService::generateInvoice(ServiceBooking* booking)
|
||||||
{
|
{
|
||||||
|
DataStoreLockGuard lock(m_dataStore);
|
||||||
if (!booking)
|
if (!booking)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Invoice generation failed: booking is null.");
|
throw std::runtime_error("Invoice generation failed: booking is null.");
|
||||||
@@ -190,10 +193,10 @@ void PaymentManagementService::generateInvoice(ServiceBooking* booking)
|
|||||||
std::string bookingID = booking->getId();
|
std::string bookingID = booking->getId();
|
||||||
util::Map<std::string, Service*> servicesInTheBookedService = booking->getServices();
|
util::Map<std::string, Service*> servicesInTheBookedService = booking->getServices();
|
||||||
util::Map<std::string, InventoryItem*> completeInventoryItemMapOfBooking;
|
util::Map<std::string, InventoryItem*> completeInventoryItemMapOfBooking;
|
||||||
util::Map<std::string, JobCard*> currentJobCards = m_dataStore.getJobCards();
|
auto& currentTrackedJobCards = m_dataStore.getJobCards();
|
||||||
for (int iterator = 0; iterator < currentJobCards.getSize(); iterator++)
|
for (int iterator = 0; iterator < currentTrackedJobCards.getSize(); iterator++)
|
||||||
{
|
{
|
||||||
JobCard* currentJobCard = currentJobCards.getValueAt(iterator);
|
JobCard* currentJobCard = currentTrackedJobCards.getValueAt(iterator).data;
|
||||||
util::ServiceJobStatus currentJobCardStatus = currentJobCard->getStatus();
|
util::ServiceJobStatus currentJobCardStatus = currentJobCard->getStatus();
|
||||||
if (currentJobCard->getBookingId() == bookingID && currentJobCardStatus != util::ServiceJobStatus::CANCELLED && currentJobCardStatus != util::ServiceJobStatus::COMPLETED)
|
if (currentJobCard->getBookingId() == bookingID && currentJobCardStatus != util::ServiceJobStatus::CANCELLED && currentJobCardStatus != util::ServiceJobStatus::COMPLETED)
|
||||||
{
|
{
|
||||||
@@ -213,8 +216,9 @@ void PaymentManagementService::generateInvoice(ServiceBooking* booking)
|
|||||||
totalServiceCost = totalLaborCost + totalPartsCost;
|
totalServiceCost = totalLaborCost + totalPartsCost;
|
||||||
totalServiceCost -= (totalServiceCost * (discountPercentage / 100));
|
totalServiceCost -= (totalServiceCost * (discountPercentage / 100));
|
||||||
Invoice* invoice = Factory::getObject<Invoice>(bookingID, booking, util::Timestamp(), totalLaborCost, completeInventoryItemMapOfBooking, totalPartsCost, discountPercentage, totalServiceCost, util::Timestamp(), util::PaymentMode::NOTSET, util::PaymentStatus::PENDING);
|
Invoice* invoice = Factory::getObject<Invoice>(bookingID, booking, util::Timestamp(), totalLaborCost, completeInventoryItemMapOfBooking, totalPartsCost, discountPercentage, totalServiceCost, util::Timestamp(), util::PaymentMode::NOTSET, util::PaymentStatus::PENDING);
|
||||||
util::Map<std::string, Invoice*>& currentInvoices = m_dataStore.getInvoices();
|
auto& currentTrackedInvoices = m_dataStore.getInvoices();
|
||||||
currentInvoices.insert(invoice->getId(), invoice);
|
currentTrackedInvoices.insert(invoice->getId(), util::createNewRecord(invoice));
|
||||||
|
m_dataStore.saveInvoices();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -227,11 +231,12 @@ Returns:
|
|||||||
*/
|
*/
|
||||||
util::Map<std::string, Invoice*> PaymentManagementService::getInvoices(const std::string& customerID)
|
util::Map<std::string, Invoice*> PaymentManagementService::getInvoices(const std::string& customerID)
|
||||||
{
|
{
|
||||||
util::Map<std::string, Invoice*>& currentInvoices = m_dataStore.getInvoices();
|
DataStoreLockGuard lock(m_dataStore);
|
||||||
|
auto& currentTrackedInvoices = m_dataStore.getInvoices();
|
||||||
util::Map<std::string, Invoice*> currentUserInvoices;
|
util::Map<std::string, Invoice*> currentUserInvoices;
|
||||||
for (int iterator = 0; iterator < currentInvoices.getSize(); iterator++)
|
for (int iterator = 0; iterator < currentTrackedInvoices.getSize(); iterator++)
|
||||||
{
|
{
|
||||||
Invoice* currentInvoice = currentInvoices.getValueAt(iterator);
|
Invoice* currentInvoice = currentTrackedInvoices.getValueAt(iterator).data;
|
||||||
if (currentInvoice->getBooking()->getCustomerId() == customerID)
|
if (currentInvoice->getBooking()->getCustomerId() == customerID)
|
||||||
{
|
{
|
||||||
currentUserInvoices.insert(currentInvoice->getId(), currentInvoice);
|
currentUserInvoices.insert(currentInvoice->getId(), currentInvoice);
|
||||||
@@ -254,11 +259,13 @@ Throws:
|
|||||||
*/
|
*/
|
||||||
void PaymentManagementService::completePayment(const std::string& invoiceID, util::PaymentMode paymentMode)
|
void PaymentManagementService::completePayment(const std::string& invoiceID, util::PaymentMode paymentMode)
|
||||||
{
|
{
|
||||||
auto& currentInvoices = m_dataStore.getInvoices();
|
DataStoreLockGuard lock(m_dataStore);
|
||||||
int invoiceIndex = currentInvoices.find(invoiceID);
|
auto& currentTrackedInvoices = m_dataStore.getInvoices();
|
||||||
|
int invoiceIndex = currentTrackedInvoices.find(invoiceID);
|
||||||
if (invoiceIndex != -1)
|
if (invoiceIndex != -1)
|
||||||
{
|
{
|
||||||
Invoice* invoice = currentInvoices.getValueAt(invoiceIndex);
|
auto& trackedInvoice = currentTrackedInvoices.getValueAt(invoiceIndex);
|
||||||
|
Invoice* invoice = trackedInvoice.data;
|
||||||
if (invoice && invoice->getStatus() != util::PaymentStatus::PAID)
|
if (invoice && invoice->getStatus() != util::PaymentStatus::PAID)
|
||||||
{
|
{
|
||||||
User* currentUser = invoice->getBooking()->getCustomer();
|
User* currentUser = invoice->getBooking()->getCustomer();
|
||||||
@@ -269,12 +276,14 @@ void PaymentManagementService::completePayment(const std::string& invoiceID, uti
|
|||||||
title = "Payment successful";
|
title = "Payment successful";
|
||||||
message = "Payment successful for Invoice ID " + invoiceID;
|
message = "Payment successful for Invoice ID " + invoiceID;
|
||||||
sendNotification(currentUser, title, message);
|
sendNotification(currentUser, title, message);
|
||||||
|
trackedInvoice.state = RecordState::MODIFIED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Payment failed: invalid invoice ID.");
|
throw std::runtime_error("Payment failed: invalid invoice ID.");
|
||||||
}
|
}
|
||||||
|
m_dataStore.saveInvoices();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -283,11 +292,14 @@ Description: Provides access to all invoices stored in the data store.
|
|||||||
Parameters:
|
Parameters:
|
||||||
- none
|
- none
|
||||||
Returns:
|
Returns:
|
||||||
- util::Map<std::string, Invoice*>&: Map of invoice IDs to invoice objects
|
- util::Map<std::string, Invoice*>: Map of invoice IDs to invoice objects
|
||||||
*/
|
*/
|
||||||
util::Map<std::string, Invoice*>& PaymentManagementService::getAllInvoices()
|
util::Map<std::string, Invoice*> PaymentManagementService::getAllInvoices()
|
||||||
{
|
{
|
||||||
return m_dataStore.getInvoices();
|
DataStoreLockGuard lock(m_dataStore);
|
||||||
|
util::Map<std::string, Invoice*> invoices;
|
||||||
|
invoices = util::getObjects(m_dataStore.getInvoices());
|
||||||
|
return invoices;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -303,20 +315,24 @@ Throws:
|
|||||||
*/
|
*/
|
||||||
void PaymentManagementService::confirmPayment(const std::string& invoiceID)
|
void PaymentManagementService::confirmPayment(const std::string& invoiceID)
|
||||||
{
|
{
|
||||||
auto& currentInvoices = m_dataStore.getInvoices();
|
DataStoreLockGuard lock(m_dataStore);
|
||||||
int invoiceIndex = currentInvoices.find(invoiceID);
|
auto& currentTrackedInvoices = m_dataStore.getInvoices();
|
||||||
|
int invoiceIndex = currentTrackedInvoices.find(invoiceID);
|
||||||
if (invoiceIndex == -1)
|
if (invoiceIndex == -1)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Payment confirmation failed: invalid invoice ID.");
|
throw std::runtime_error("Payment confirmation failed: invalid invoice ID.");
|
||||||
}
|
}
|
||||||
Invoice* invoice = currentInvoices.getValueAt(invoiceIndex);
|
auto& trackedInvoice = currentTrackedInvoices.getValueAt(invoiceIndex);
|
||||||
|
Invoice* invoice = trackedInvoice.data;
|
||||||
if (!invoice || invoice->getStatus() != util::PaymentStatus::PAID)
|
if (!invoice || invoice->getStatus() != util::PaymentStatus::PAID)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Payment confirmation failed: invoice is not awaiting confirmation.");
|
throw std::runtime_error("Payment confirmation failed: invoice is not awaiting confirmation.");
|
||||||
}
|
}
|
||||||
User* currentUser = invoice->getBooking()->getCustomer();
|
User* currentUser = invoice->getBooking()->getCustomer();
|
||||||
invoice->setStatus(util::PaymentStatus::COMPLETED);
|
invoice->setStatus(util::PaymentStatus::COMPLETED);
|
||||||
|
trackedInvoice.state = RecordState::MODIFIED;
|
||||||
std::string title = "Payment Confirmed";
|
std::string title = "Payment Confirmed";
|
||||||
std::string message = "Payment Confirmed for Invoice ID " + invoiceID;
|
std::string message = "Payment Confirmed for Invoice ID " + invoiceID;
|
||||||
sendNotification(currentUser, title, message);
|
sendNotification(currentUser, title, message);
|
||||||
|
m_dataStore.saveInvoices();
|
||||||
}
|
}
|
||||||
+1
-1
@@ -27,7 +27,7 @@ public:
|
|||||||
void generateInvoice(ServiceBooking* booking);
|
void generateInvoice(ServiceBooking* booking);
|
||||||
util::Map<std::string, Invoice*> getInvoices(const std::string& customerID);
|
util::Map<std::string, Invoice*> getInvoices(const std::string& customerID);
|
||||||
void completePayment(const std::string& invoiceID, util::PaymentMode paymentMode);
|
void completePayment(const std::string& invoiceID, util::PaymentMode paymentMode);
|
||||||
util::Map<std::string, Invoice*>& getAllInvoices();
|
util::Map<std::string, Invoice*> getAllInvoices();
|
||||||
void confirmPayment(const std::string& invoiceID);
|
void confirmPayment(const std::string& invoiceID);
|
||||||
void sendPaymentReminders();
|
void sendPaymentReminders();
|
||||||
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;
|
||||||
|
|||||||
Reference in New Issue
Block a user