From 27dab16ae1317b9a9796703a2be3f1770a9437b3 Mon Sep 17 00:00:00 2001 From: Joel Thomas <1914@trenser.com> Date: Fri, 20 Feb 2026 17:30:57 +0530 Subject: [PATCH] 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() --- .../FoodDeliveryController.cpp | 252 +++++++++++++++++- .../FoodDeliveryController.h | 10 +- .../Trenser.FoodDeliveryApp/Item.h | 4 +- .../Trenser.FoodDeliveryApp/Order.cpp | 14 +- .../Trenser.FoodDeliveryApp/Order.h | 10 +- 5 files changed, 272 insertions(+), 18 deletions(-) diff --git a/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/FoodDeliveryController.cpp b/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/FoodDeliveryController.cpp index a7dba74..5a6cd4b 100644 --- a/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/FoodDeliveryController.cpp +++ b/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/FoodDeliveryController.cpp @@ -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(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(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(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; + while (isMenuActive) + { + menuItems::iterator menuItemIterator = pickItemFromMenu(restaurantMenuItems); + if (menuItemIterator != restaurantMenuItems.end()) + { + int quantity; + char choice; + std::cout << "Enter quantity: "; + util::readValue(quantity); + if (quantity > 0) + { + if (!order) + { + order = std::make_shared(); + } + 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(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(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() diff --git a/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/FoodDeliveryController.h b/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/FoodDeliveryController.h index c73272e..5cdb84b 100644 --- a/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/FoodDeliveryController.h +++ b/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/FoodDeliveryController.h @@ -6,21 +6,27 @@ Date: 18-02-2026 #pragma once #include #include +#include #include class User; class Restaurant; class MenuItem; +class Item; +class Order; using users = std::map>; using restaurants = std::map>; using menuItems = std::map>; +using items = std::vector>; +using orders = std::map>; class FoodDeliveryController { private: users m_users; restaurants m_restaurants; + orders m_orders; std::shared_ptr 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(); diff --git a/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/Item.h b/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/Item.h index 209429c..b8b6e53 100644 --- a/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/Item.h +++ b/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/Item.h @@ -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(); diff --git a/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/Order.cpp b/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/Order.cpp index b5fe2e4..fc7ef25 100644 --- a/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/Order.cpp +++ b/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/Order.cpp @@ -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; +} diff --git a/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/Order.h b/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/Order.h index c28431b..182eaf4 100644 --- a/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/Order.h +++ b/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/Order.h @@ -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&); };