Implement delivery assignment flow, restaurant order handling, and new controller helpers
- Add new Controller helper getDeliveryStatusString() - Add new Controller helper pickAssignmentFromDeliveryAssignments() - Implement controller listRestaurantOrders() - Implement controller markOrderReady() - Add order to restaurant when customer places order - Add m_assignments attribute to Controller - Implement controller listDeliveryAssignments() - Implement controller acceptDeliveryAssignments() - Implement controller confirmDeliveryAssignments()
This commit is contained in:
@@ -15,6 +15,9 @@ Date: 19-02-2026
|
|||||||
#include "Customer.h"
|
#include "Customer.h"
|
||||||
#include "DeliveryPartner.h"
|
#include "DeliveryPartner.h"
|
||||||
#include "Restaurant.h"
|
#include "Restaurant.h"
|
||||||
|
#include "MenuItem.h"
|
||||||
|
#include "Order.h"
|
||||||
|
#include "DeliveryAssignment.h"
|
||||||
#include "inputHelper.h"
|
#include "inputHelper.h"
|
||||||
#include "outputHelper.h"
|
#include "outputHelper.h"
|
||||||
|
|
||||||
@@ -161,6 +164,65 @@ static orders::iterator pickOrderFromOrders(orders& userOrders)
|
|||||||
return orderIterator;
|
return orderIterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string getDeliveryStatusString(const DeliveryStatus& deliveryStatus)
|
||||||
|
{
|
||||||
|
switch (deliveryStatus)
|
||||||
|
{
|
||||||
|
case DeliveryStatus::CREATED:
|
||||||
|
return "Created";
|
||||||
|
case DeliveryStatus::ACCEPTED:
|
||||||
|
return "Accepted";
|
||||||
|
case DeliveryStatus::DELIVERED:
|
||||||
|
return "Delivered";
|
||||||
|
default:
|
||||||
|
return "Unkown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static deliveryAssignments::iterator pickAssignmentFromDeliveryAssignments(deliveryAssignments& assignments, const users& allUsers)
|
||||||
|
{
|
||||||
|
util::clear();
|
||||||
|
std::cout << "Pick a Delivery Assignment\n";
|
||||||
|
int deliveryIndex = 1, deliveryChoiceIndex;
|
||||||
|
if (assignments.empty())
|
||||||
|
{
|
||||||
|
std::cout << "No Delivery Assignments available at the moment!\n";
|
||||||
|
return assignments.end();
|
||||||
|
}
|
||||||
|
std::cout << std::left << std::setw(8) << "Index"
|
||||||
|
<< std::left << std::setw(5) << "ID"
|
||||||
|
<< std::left << std::setw(12) << "Order ID"
|
||||||
|
<< std::left << std::setw(22) << "Delivery Status"
|
||||||
|
<< std::left << std::setw(30) << "Address"
|
||||||
|
<< "\n";
|
||||||
|
for (auto& assignment : assignments)
|
||||||
|
{
|
||||||
|
Order& order = assignment.second->getOrder();
|
||||||
|
users::const_iterator customer = allUsers.find(order.getCustomerUsername());
|
||||||
|
if (customer == allUsers.end())
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Invalid state: Delivery Assignment has no associated Customer.");
|
||||||
|
}
|
||||||
|
std::cout << std::left << std::setw(8) << deliveryIndex
|
||||||
|
<< std::left << std::setw(5) << assignment.second->getId()
|
||||||
|
<< std::left << std::setw(12) << order.getId()
|
||||||
|
<< std::left << std::setw(22) << getDeliveryStatusString(assignment.second->getStatus())
|
||||||
|
<< std::left << std::setw(30) << customer->second->getAddress()
|
||||||
|
<< "\n";
|
||||||
|
deliveryIndex++;
|
||||||
|
}
|
||||||
|
std::cout << "\nSelect Index: ";
|
||||||
|
util::readValue<int>(deliveryChoiceIndex);
|
||||||
|
deliveryChoiceIndex--;
|
||||||
|
if (deliveryChoiceIndex < 0 || deliveryChoiceIndex >= assignments.size())
|
||||||
|
{
|
||||||
|
return assignments.end();
|
||||||
|
}
|
||||||
|
deliveryAssignments::iterator assignmentIterator = assignments.begin();
|
||||||
|
std::advance(assignmentIterator, deliveryChoiceIndex);
|
||||||
|
return assignmentIterator;
|
||||||
|
}
|
||||||
|
|
||||||
void FoodDeliveryController::run()
|
void FoodDeliveryController::run()
|
||||||
{
|
{
|
||||||
bool isMenuActive = true;
|
bool isMenuActive = true;
|
||||||
@@ -393,12 +455,118 @@ void FoodDeliveryController::updateRestaurantStatus() const
|
|||||||
|
|
||||||
void FoodDeliveryController::listRestaurantOrders() const
|
void FoodDeliveryController::listRestaurantOrders() const
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
util::clear();
|
||||||
|
if (!checkAccess(m_authenticatedUser, "RestaurantOwner"))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
RestaurantOwner& restaurantOwner = *(std::dynamic_pointer_cast<RestaurantOwner>(m_authenticatedUser));
|
||||||
|
restaurants::iterator restaurantIterator = pickRestaurantFromRestaurants(restaurantOwner.getRestaurants());
|
||||||
|
if (restaurantIterator != restaurantOwner.getRestaurants().end())
|
||||||
|
{
|
||||||
|
orders& restaurantOrders = restaurantIterator->second->getOrders();
|
||||||
|
if (restaurantOrders.empty())
|
||||||
|
{
|
||||||
|
std::cout << "Restaurant " << restaurantIterator->second->getName() << " has no orders!\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
orders::iterator orderIterator = pickOrderFromOrders(restaurantOrders);
|
||||||
|
if (orderIterator != restaurantOrders.end())
|
||||||
|
{
|
||||||
|
util::clear();
|
||||||
|
items& orderItems = orderIterator->second->getItems();
|
||||||
|
if (orderItems.empty())
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Order has no items!");
|
||||||
|
}
|
||||||
|
std::cout << "Order " << orderIterator->second->getId() << "\n";
|
||||||
|
std::cout << std::left << std::setw(25) << "Menu Item"
|
||||||
|
<< std::left << std::setw(10) << "Price"
|
||||||
|
<< std::left << std::setw(10) << "Quantity"
|
||||||
|
<< std::left << std::setw(10) << "Total Cost"
|
||||||
|
<< "\n";
|
||||||
|
for (auto& item : orderItems)
|
||||||
|
{
|
||||||
|
MenuItem& menuItem = item->getMenuItem();
|
||||||
|
std::cout << std::left << std::setw(25) << menuItem.getName()
|
||||||
|
<< std::left << std::setw(10) << menuItem.getPrice()
|
||||||
|
<< std::left << std::setw(10) << item->getQuantity()
|
||||||
|
<< std::left << std::setw(10) << menuItem.getPrice() * item->getQuantity()
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
std::cout << "\nNet Cost : " << orderIterator->second->getTotal() << "\n";
|
||||||
|
std::cout << "Status : " << getOrderStatusString(orderIterator->second->getStatus()) << "\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Invalid Index. Cannot display Restaurant Orders\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!restaurantOwner.getRestaurants().empty())
|
||||||
|
{
|
||||||
|
std::cout << "Invalid Index. Cannot display Restaurant Orders\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
std::cout << "Exception: " << e.what() << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FoodDeliveryController::markOrderReady()
|
void FoodDeliveryController::markOrderReady()
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
util::clear();
|
||||||
|
if (!checkAccess(m_authenticatedUser, "RestaurantOwner"))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
RestaurantOwner& restaurantOwner = *(std::dynamic_pointer_cast<RestaurantOwner>(m_authenticatedUser));
|
||||||
|
restaurants::iterator restaurantIterator = pickRestaurantFromRestaurants(restaurantOwner.getRestaurants());
|
||||||
|
if (restaurantIterator != restaurantOwner.getRestaurants().end())
|
||||||
|
{
|
||||||
|
orders& restaurantOrders = restaurantIterator->second->getOrders();
|
||||||
|
if (restaurantOrders.empty())
|
||||||
|
{
|
||||||
|
std::cout << "Restaurant " << restaurantIterator->second->getName() << " has no orders!\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
orders::iterator orderIterator = pickOrderFromOrders(restaurantOrders);
|
||||||
|
if (orderIterator != restaurantOrders.end())
|
||||||
|
{
|
||||||
|
OrderStatus orderStatus = orderIterator->second->getStatus();
|
||||||
|
if (orderStatus == OrderStatus::CREATED)
|
||||||
|
{
|
||||||
|
orderIterator->second->setStatus(OrderStatus::READYFORPICKUP);
|
||||||
|
std::shared_ptr<DeliveryAssignment> deliveryAssignment = std::make_shared<DeliveryAssignment>(*orderIterator->second);
|
||||||
|
m_assignments[deliveryAssignment->getId()] = deliveryAssignment;
|
||||||
|
std::cout << "Order has been marked ready for pickup\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Cannot mark order ready for pickup. Order has already been cancelled, is in transit, or is already marked ready for pickup, or has been delivered!\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Invalid Index. Cannot mark order ready for pickup!\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!restaurantOwner.getRestaurants().empty())
|
||||||
|
{
|
||||||
|
std::cout << "Invalid Index. Cannot mark order ready for pickup!\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
std::cout << "Exception: " << e.what() << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FoodDeliveryController::listMenuItems() const
|
void FoodDeliveryController::listMenuItems() const
|
||||||
@@ -651,6 +819,7 @@ void FoodDeliveryController::placeOrder()
|
|||||||
if (order && !order->getItems().empty())
|
if (order && !order->getItems().empty())
|
||||||
{
|
{
|
||||||
customer->addOrder(order);
|
customer->addOrder(order);
|
||||||
|
restaurantIterator->second->addOrder(order);
|
||||||
std::cout << "Order with ID " << order->getId() << " has been placed successfully\n";
|
std::cout << "Order with ID " << order->getId() << " has been placed successfully\n";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -718,17 +887,141 @@ void FoodDeliveryController::cancelOrder() const
|
|||||||
|
|
||||||
void FoodDeliveryController::listDeliveryAssignments()
|
void FoodDeliveryController::listDeliveryAssignments()
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
util::clear();
|
||||||
|
if (!checkAccess(m_authenticatedUser, "DeliveryPartner"))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto deliveryPartner = std::dynamic_pointer_cast<DeliveryPartner>(m_authenticatedUser);
|
||||||
|
if (!deliveryPartner)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Cannot accept Delivery Assignment. Failed to verify access!");
|
||||||
|
}
|
||||||
|
deliveryAssignments& assignments = deliveryPartner->getAssignedDeliveries();
|
||||||
|
if (assignments.empty())
|
||||||
|
{
|
||||||
|
std::cout << "You haven't accepted any Delivery Assignments!\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::cout << std::left << std::setw(5) << "ID"
|
||||||
|
<< std::left << std::setw(12) << "Order ID"
|
||||||
|
<< std::left << std::setw(22) << "Delivery Status"
|
||||||
|
<< std::left << std::setw(30) << "Address"
|
||||||
|
<< "\n";
|
||||||
|
for (auto& assignment : assignments)
|
||||||
|
{
|
||||||
|
Order& order = assignment.second->getOrder();
|
||||||
|
users::const_iterator customer = m_users.find(order.getCustomerUsername());
|
||||||
|
if (customer == m_users.end())
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Invalid state: Delivery Assignment has no associated Customer.");
|
||||||
|
}
|
||||||
|
std::cout << std::left << std::setw(5) << assignment.second->getId()
|
||||||
|
<< std::left << std::setw(12) << order.getId()
|
||||||
|
<< std::left << std::setw(22) << getDeliveryStatusString(assignment.second->getStatus())
|
||||||
|
<< std::left << std::setw(30) << customer->second->getAddress()
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
std::cout << "Exception: " << e.what() << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FoodDeliveryController::acceptDeliveryAssignment()
|
void FoodDeliveryController::acceptDeliveryAssignment()
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
util::clear();
|
||||||
|
if (!checkAccess(m_authenticatedUser, "DeliveryPartner"))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto deliveryPartner = std::dynamic_pointer_cast<DeliveryPartner>(m_authenticatedUser);
|
||||||
|
if (!deliveryPartner)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Cannot accept Delivery Assignment. Failed to verify access!");
|
||||||
|
}
|
||||||
|
if (m_assignments.empty())
|
||||||
|
{
|
||||||
|
std::cout << "No Delivery Assignments available at the moment!\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
deliveryAssignments::iterator assignmentIterator = pickAssignmentFromDeliveryAssignments(m_assignments, m_users);
|
||||||
|
if (assignmentIterator != m_assignments.end())
|
||||||
|
{
|
||||||
|
DeliveryStatus deliveryStatus = assignmentIterator->second->getStatus();
|
||||||
|
if (deliveryStatus == DeliveryStatus::CREATED)
|
||||||
|
{
|
||||||
|
assignmentIterator->second->setStatus(DeliveryStatus::ACCEPTED);
|
||||||
|
assignmentIterator->second->getOrder().setStatus(OrderStatus::OUTFORDELIVERY);
|
||||||
|
deliveryPartner->acceptDeliveryAssignment(assignmentIterator->second);
|
||||||
|
std::cout << "Delivery Assignment " << assignmentIterator->second->getId() << " has been accepted successfully!\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Delivery Assignment " << assignmentIterator->second->getId() << " cannot be accepted as it is already accepted, or delivered!\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Invalid Index. Cannot accept Delivery Assignment!\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
std::cout << "Exception: " << e.what() << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FoodDeliveryController::confirmDeliveryAssignment()
|
void FoodDeliveryController::confirmDeliveryAssignment()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
util::clear();
|
||||||
|
if (!checkAccess(m_authenticatedUser, "DeliveryPartner"))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto deliveryPartner = std::dynamic_pointer_cast<DeliveryPartner>(m_authenticatedUser);
|
||||||
|
if (!deliveryPartner)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Cannot confirm Delivery Assignment. Failed to verify access!");
|
||||||
|
}
|
||||||
|
deliveryAssignments& assignments = deliveryPartner->getAssignedDeliveries();
|
||||||
|
if (assignments.empty())
|
||||||
|
{
|
||||||
|
std::cout << "You haven't accepted any Delivery Assignments!\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
deliveryAssignments::iterator assignmentIterator = pickAssignmentFromDeliveryAssignments(assignments, m_users);
|
||||||
|
if (assignmentIterator != assignments.end())
|
||||||
|
{
|
||||||
|
DeliveryStatus deliveryStatus = assignmentIterator->second->getStatus();
|
||||||
|
if (deliveryStatus == DeliveryStatus::ACCEPTED)
|
||||||
|
{
|
||||||
|
assignmentIterator->second->setStatus(DeliveryStatus::DELIVERED);
|
||||||
|
assignmentIterator->second->getOrder().setStatus(OrderStatus::DELIVERED);
|
||||||
|
std::cout << "Delivery Assignment " << assignmentIterator->second->getId() << " has been completed successfully!\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Delivery Assignment " << assignmentIterator->second->getId() << " cannot be confirmed as it has not been accepted yet, or has already been delivered!\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Invalid Index. Cannot confirm Delivery Assignment!\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
std::cout << "Exception: " << e.what() << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FoodDeliveryController::viewProfile() const
|
void FoodDeliveryController::viewProfile() const
|
||||||
|
|||||||
@@ -14,12 +14,14 @@ class Restaurant;
|
|||||||
class MenuItem;
|
class MenuItem;
|
||||||
class Item;
|
class Item;
|
||||||
class Order;
|
class Order;
|
||||||
|
class DeliveryAssignment;
|
||||||
|
|
||||||
using users = std::map<std::string, std::shared_ptr<User>>;
|
using users = std::map<std::string, std::shared_ptr<User>>;
|
||||||
using restaurants = std::map<int, std::shared_ptr<Restaurant>>;
|
using restaurants = std::map<int, std::shared_ptr<Restaurant>>;
|
||||||
using menuItems = std::map<int, std::shared_ptr<MenuItem>>;
|
using menuItems = std::map<int, std::shared_ptr<MenuItem>>;
|
||||||
using items = std::vector<std::shared_ptr<Item>>;
|
using items = std::vector<std::shared_ptr<Item>>;
|
||||||
using orders = std::map<int, std::shared_ptr<Order>>;
|
using orders = std::map<int, std::shared_ptr<Order>>;
|
||||||
|
using deliveryAssignments = std::map<int, std::shared_ptr<DeliveryAssignment>>;
|
||||||
|
|
||||||
class FoodDeliveryController
|
class FoodDeliveryController
|
||||||
{
|
{
|
||||||
@@ -27,6 +29,7 @@ private:
|
|||||||
users m_users;
|
users m_users;
|
||||||
restaurants m_restaurants;
|
restaurants m_restaurants;
|
||||||
orders m_orders;
|
orders m_orders;
|
||||||
|
deliveryAssignments m_assignments;
|
||||||
std::shared_ptr<User> m_authenticatedUser;
|
std::shared_ptr<User> m_authenticatedUser;
|
||||||
public:
|
public:
|
||||||
void run();
|
void run();
|
||||||
|
|||||||
Reference in New Issue
Block a user