Implement customer order controllers with related model/helper updates

- Implement Controller listCustomerOrders()
- Implement Controller placeOrder()
- Implement Controller cancelOrder()
- Fix Item() constructor
- Add static m_uid to Order to track unique ID
- Add Order Status getter and setter
- Rename pickMenuFromMenuItems() to pickItemFromMenu()
- Add new controller helper pickOrderFromOrders()
- Add new controller helper getOrderStatusString()
This commit is contained in:
Joel Thomas
2026-02-20 17:30:57 +05:30
parent 184ea60c08
commit 27dab16ae1
5 changed files with 272 additions and 18 deletions
@@ -65,7 +65,7 @@ static restaurants::iterator pickRestaurantFromRestaurants(restaurants& ownerRes
return restaurantIterator;
}
static menuItems::iterator pickMenuFromMenuItems(menuItems& restaurantMenuItems)
static menuItems::iterator pickItemFromMenu(menuItems& restaurantMenuItems)
{
util::clear();
int menuItemIndex = 1, menuItemChoiceIndex;
@@ -104,6 +104,63 @@ static menuItems::iterator pickMenuFromMenuItems(menuItems& restaurantMenuItems)
return menuItemIterator;
}
static std::string getOrderStatusString(const OrderStatus& orderStatus)
{
switch (orderStatus)
{
case OrderStatus::CREATED:
return "Created";
case OrderStatus::READYFORPICKUP:
return "Ready For Pickup";
case OrderStatus::OUTFORDELIVERY:
return "Out for Delivery";
case OrderStatus::DELIVERED:
return "Delivered";
case OrderStatus::CANCELLED:
return "Cancelled";
default:
return "Unkown";
}
}
static orders::iterator pickOrderFromOrders(orders& customerOrders)
{
util::clear();
std::cout << "Pick an order\n";
int orderIndex = 1, orderChoiceIndex;
if (customerOrders.empty())
{
std::cout << "You have not placed any orders!\n";
return customerOrders.end();
}
std::cout << std::left << std::setw(8) << "Index"
<< std::left << std::setw(5) << "ID"
<< std::left << std::setw(15) << "Item Count"
<< std::left << std::setw(15) << "Total Amount"
<< std::left << std::setw(15) << "Status"
<< "\n";
for (auto& order : customerOrders)
{
std::cout << std::left << std::setw(8) << orderIndex
<< std::left << std::setw(5) << order.second->getId()
<< std::left << std::setw(15) << order.second->getItems().size()
<< std::left << std::setw(15) << order.second->getTotal()
<< std::left << std::setw(15) << getOrderStatusString(order.second->getStatus())
<< "\n";
orderIndex++;
}
std::cout << "\nSelect Index: ";
util::readValue<int>(orderChoiceIndex);
orderChoiceIndex--;
if (orderChoiceIndex < 0 || orderChoiceIndex >= customerOrders.size())
{
return customerOrders.end();
}
orders::iterator orderIterator = customerOrders.begin();
std::advance(orderIterator, orderChoiceIndex);
return orderIterator;
}
void FoodDeliveryController::run()
{
bool isMenuActive = true;
@@ -441,7 +498,7 @@ void FoodDeliveryController::removeMenuItem() const
if (restaurantIterator != restaurantOwner.getRestaurants().end())
{
menuItems& restaurantMenuItems = restaurantIterator->second->getMenuItems();
menuItems::iterator menuItemIterator = pickMenuFromMenuItems(restaurantMenuItems);
menuItems::iterator menuItemIterator = pickItemFromMenu(restaurantMenuItems);
if (menuItemIterator != restaurantMenuItems.end())
{
restaurantMenuItems.erase(menuItemIterator);
@@ -464,19 +521,200 @@ void FoodDeliveryController::removeMenuItem() const
}
}
void FoodDeliveryController::listCustomerOrders()
void FoodDeliveryController::listCustomerOrders() const
{
try
{
util::clear();
if (!checkAccess(m_authenticatedUser, "Customer"))
{
return;
}
auto customer = std::dynamic_pointer_cast<Customer>(m_authenticatedUser);
if (!customer)
{
throw std::runtime_error("Cannot place order. Failed to verify access!");
}
orders customerOrders = customer->getOrders();
if (customerOrders.empty())
{
std::cout << "You have not placed any orders!\n";
return;
}
orders::iterator orderIterator = pickOrderFromOrders(customerOrders);
if (orderIterator != customerOrders.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 << "Net Cost : " << orderIterator->second->getTotal() << "\n";
std::cout << "Status : " << getOrderStatusString(orderIterator->second->getStatus()) << "\n";
}
else if (!customerOrders.empty())
{
std::cout << "Invalid Index. Cannot display order!\n";
return;
}
}
catch (const std::exception& e)
{
std::cout << "Exception: " << e.what() << std::endl;
}
}
void FoodDeliveryController::placeOrder()
{
try
{
util::clear();
if (!checkAccess(m_authenticatedUser, "Customer"))
{
return;
}
auto customer = std::dynamic_pointer_cast<Customer>(m_authenticatedUser);
if (!customer)
{
throw std::runtime_error("Cannot place order. Failed to verify access!");
}
restaurants::iterator restaurantIterator = pickRestaurantFromRestaurants(m_restaurants);
if (restaurantIterator != m_restaurants.end())
{
bool isMenuActive = true;
menuItems& restaurantMenuItems = restaurantIterator->second->getMenuItems();
if (!restaurantIterator->second->getStatus())
{
std::cout << "Restaurant is closed. Check again later!\n";
return;
}
if (restaurantMenuItems.empty())
{
std::cout << "Operation cancelled. Restaurant has no Menu Items!\n";
return;
}
std::cout << "Creating order\n";
std::shared_ptr<Order> order;
while (isMenuActive)
{
menuItems::iterator menuItemIterator = pickItemFromMenu(restaurantMenuItems);
if (menuItemIterator != restaurantMenuItems.end())
{
int quantity;
char choice;
std::cout << "Enter quantity: ";
util::readValue<int>(quantity);
if (quantity > 0)
{
if (!order)
{
order = std::make_shared<Order>();
}
order->addItem(Item(*(menuItemIterator->second), quantity));
std::cout << menuItemIterator->second->getName() << " with quantity " << quantity << " has been added to your Order\n";
}
else
{
std::cout << "Quantity cannot be zero!\n";
}
std::cout << "Do you want to add more items (Y/N)?: ";
util::readValue<char>(choice);
if (choice != 'Y' && choice != 'y')
{
isMenuActive = false;
}
}
else if (!restaurantMenuItems.empty())
{
std::cout << "Invalid Index. Cannot place order!\n";
return;
}
}
if (order && !order->getItems().empty())
{
customer->addOrder(order);
std::cout << "Order with ID " << order->getId() << " has been placed successfully\n";
}
else
{
std::cout << "Operation cancelled. Cannot place order with zero items!\n";
}
}
else if (!m_restaurants.empty())
{
std::cout << "Invalid Index. Cannot place order!\n";
return;
}
}
catch (const std::exception& e)
{
std::cout << "Exception: " << e.what() << std::endl;
}
}
void FoodDeliveryController::cancelOrder()
void FoodDeliveryController::cancelOrder() const
{
try
{
util::clear();
if (!checkAccess(m_authenticatedUser, "Customer"))
{
return;
}
auto customer = std::dynamic_pointer_cast<Customer>(m_authenticatedUser);
if (!customer)
{
throw std::runtime_error("Cannot place order. Failed to verify access!");
}
orders customerOrders = customer->getOrders();
if (customerOrders.empty())
{
std::cout << "You have not placed any orders!\n";
return;
}
orders::iterator orderIterator = pickOrderFromOrders(customerOrders);
if (orderIterator != customerOrders.end())
{
OrderStatus orderStatus = orderIterator->second->getStatus();
if (orderStatus != OrderStatus::CANCELLED && orderStatus != OrderStatus::DELIVERED) {
orderIterator->second->setStatus(OrderStatus::CANCELLED);
std::cout << "Order " << orderIterator->second->getId() << " has been cancelled successfully!\n";
}
else if (orderStatus == OrderStatus::DELIVERED)
{
std::cout << "Cannot cancel Order " << orderIterator->second->getId() << " as it has already been delivered!\n";
}
else
{
std::cout << "Order " << orderIterator->second->getId() << " has already been cancelled!\n";
}
}
else if (!customerOrders.empty())
{
std::cout << "Invalid Index. Cannot cancel order!\n";
return;
}
}
catch (const std::exception& e)
{
std::cout << "Exception: " << e.what() << std::endl;
}
}
void FoodDeliveryController::listDeliveryAssignments()
@@ -6,21 +6,27 @@ Date: 18-02-2026
#pragma once
#include <string>
#include <memory>
#include <vector>
#include <map>
class User;
class Restaurant;
class MenuItem;
class Item;
class Order;
using users = std::map<std::string, std::shared_ptr<User>>;
using restaurants = std::map<int, std::shared_ptr<Restaurant>>;
using menuItems = std::map<int, std::shared_ptr<MenuItem>>;
using items = std::vector<std::shared_ptr<Item>>;
using orders = std::map<int, std::shared_ptr<Order>>;
class FoodDeliveryController
{
private:
users m_users;
restaurants m_restaurants;
orders m_orders;
std::shared_ptr<User> m_authenticatedUser;
public:
void run();
@@ -34,9 +40,9 @@ public:
void listMenuItems() const;
void addMenuItem() const;
void removeMenuItem() const;
void listCustomerOrders();
void listCustomerOrders() const;
void placeOrder();
void cancelOrder();
void cancelOrder() const;
void listDeliveryAssignments();
void acceptDeliveryAssignment();
void confirmDeliveryAssignment();
@@ -13,8 +13,8 @@ private:
int m_quantity;
public:
Item(MenuItem& item)
: m_item(item), m_quantity(0)
Item(MenuItem& item, int quantity)
: m_item(item), m_quantity(quantity)
{}
int getQuantity() const;
MenuItem& getMenuItem();
@@ -1,5 +1,7 @@
#include "Order.h"
int Order::m_uid = 0;
int Order::getId() const
{
return m_id;
@@ -20,7 +22,17 @@ double Order::getTotal() const
double total = 0;
for (auto& itemPointer : m_items)
{
total += itemPointer->getMenuItem().getPrice();
total += itemPointer->getMenuItem().getPrice() * itemPointer->getQuantity();
}
return total;
}
OrderStatus Order::getStatus() const
{
return m_status;
}
void Order::setStatus(const OrderStatus& orderStatus)
{
m_status = orderStatus;
}
@@ -22,18 +22,14 @@ enum class OrderStatus
class Order
{
private:
static int m_uid;
int m_id;
items m_items;
double m_totalAmount;
OrderStatus m_status;
public:
Order():
m_id(0),
m_totalAmount(0),
m_status(OrderStatus::CREATED)
{}
Order(int id):
m_id(id),
m_id(++m_uid),
m_totalAmount(0),
m_status(OrderStatus::CREATED)
{}
@@ -41,5 +37,7 @@ public:
void addItem(const Item&);
items& getItems();
double getTotal() const;
OrderStatus getStatus() const;
void setStatus(const OrderStatus&);
};