From 6f12328ed5e33e8f1f61b87e7a6c6c78a58b2a49 Mon Sep 17 00:00:00 2001 From: Joel Thomas <1914@trenser.com> Date: Sat, 21 Feb 2026 13:26:37 +0530 Subject: [PATCH] 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() --- .../FoodDeliveryController.cpp | 301 +++++++++++++++++- .../FoodDeliveryController.h | 3 + 2 files changed, 300 insertions(+), 4 deletions(-) diff --git a/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/FoodDeliveryController.cpp b/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/FoodDeliveryController.cpp index 7734408..a2528cb 100644 --- a/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/FoodDeliveryController.cpp +++ b/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/FoodDeliveryController.cpp @@ -15,6 +15,9 @@ Date: 19-02-2026 #include "Customer.h" #include "DeliveryPartner.h" #include "Restaurant.h" +#include "MenuItem.h" +#include "Order.h" +#include "DeliveryAssignment.h" #include "inputHelper.h" #include "outputHelper.h" @@ -161,6 +164,65 @@ static orders::iterator pickOrderFromOrders(orders& userOrders) 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(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() { bool isMenuActive = true; @@ -393,12 +455,118 @@ void FoodDeliveryController::updateRestaurantStatus() const void FoodDeliveryController::listRestaurantOrders() const { - + try + { + util::clear(); + if (!checkAccess(m_authenticatedUser, "RestaurantOwner")) + { + return; + } + RestaurantOwner& restaurantOwner = *(std::dynamic_pointer_cast(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() { - + try + { + util::clear(); + if (!checkAccess(m_authenticatedUser, "RestaurantOwner")) + { + return; + } + RestaurantOwner& restaurantOwner = *(std::dynamic_pointer_cast(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 = std::make_shared(*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 @@ -651,6 +819,7 @@ void FoodDeliveryController::placeOrder() if (order && !order->getItems().empty()) { customer->addOrder(order); + restaurantIterator->second->addOrder(order); std::cout << "Order with ID " << order->getId() << " has been placed successfully\n"; } else @@ -718,17 +887,141 @@ void FoodDeliveryController::cancelOrder() const void FoodDeliveryController::listDeliveryAssignments() { - + try + { + util::clear(); + if (!checkAccess(m_authenticatedUser, "DeliveryPartner")) + { + return; + } + auto deliveryPartner = std::dynamic_pointer_cast(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() { - + try + { + util::clear(); + if (!checkAccess(m_authenticatedUser, "DeliveryPartner")) + { + return; + } + auto deliveryPartner = std::dynamic_pointer_cast(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() { + try + { + util::clear(); + if (!checkAccess(m_authenticatedUser, "DeliveryPartner")) + { + return; + } + auto deliveryPartner = std::dynamic_pointer_cast(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 diff --git a/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/FoodDeliveryController.h b/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/FoodDeliveryController.h index a23bbdd..b80dbe8 100644 --- a/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/FoodDeliveryController.h +++ b/Trenser.FoodDeliveryApp/Trenser.FoodDeliveryApp/FoodDeliveryController.h @@ -14,12 +14,14 @@ class Restaurant; class MenuItem; class Item; class Order; +class DeliveryAssignment; using users = std::map>; using restaurants = std::map>; using menuItems = std::map>; using items = std::vector>; using orders = std::map>; +using deliveryAssignments = std::map>; class FoodDeliveryController { @@ -27,6 +29,7 @@ private: users m_users; restaurants m_restaurants; orders m_orders; + deliveryAssignments m_assignments; std::shared_ptr m_authenticatedUser; public: void run();