diff --git a/src/controllers/Cart.php b/src/controllers/Cart.php index 5f93ec9..aec8d85 100644 --- a/src/controllers/Cart.php +++ b/src/controllers/Cart.php @@ -7,7 +7,6 @@ use Exception; use Steamy\Core\Controller; use Steamy\Core\Utility; -use Steamy\Model\Mailer; use Steamy\Model\Order; use Steamy\Model\OrderProduct; use Steamy\Model\Product; @@ -71,8 +70,6 @@ private function handleInvalidURL(): void private function handleCheckout(): void { - // TODO: write appropriate errors to Cart view instead of sending response code - // check if user is logged in $signed_client = $this->getSignedInClient(); if (!$signed_client) { @@ -110,24 +107,35 @@ private function handleCheckout(): void $new_order->addLineItem($line_item); } - // save order - $success_order = false; + // attempt to save order. An exception will be generated in case of any errors. try { $success_order = $new_order->save(); - http_response_code($success_order ? 201 : 400); } catch (Exception $e) { error_log($e->getMessage()); http_response_code(500); echo json_encode(['error' => $e->getMessage()]); + return; } - // send confirmation email if order was successfully saved - if ($success_order) { - try { - $signed_client->sendOrderConfirmationEmail($new_order); - } catch (Exception $e) { - error_log($e->getMessage()); - } + // if order was unsuccessfully saved without any exceptions generated + if (!$success_order) { + http_response_code(500); + echo json_encode(['error' => "Order could not be saved for an unknown reason."]); + return; + } + + // send confirmation email + try { + $success_mail = $signed_client->sendOrderConfirmationEmail($new_order); + } catch (Exception $e) { + http_response_code(503); + echo json_encode(['error' => "Order was saved but email could not be sent: " . $e->getMessage()]); + return; + } + + if (!$success_mail) { + http_response_code(503); + echo json_encode(['error' => "Order was saved but email could not be sent for an unknown reason."]); } } diff --git a/src/models/Order.php b/src/models/Order.php index 00cef30..1448a12 100644 --- a/src/models/Order.php +++ b/src/models/Order.php @@ -122,12 +122,8 @@ public function save(): bool $update_stock_stm = $conn->prepare($query); foreach ($this->line_items as $line_item) { - if (!empty($line_item->validate())) { - // line item contains invalid attributes - $conn->rollBack(); - $conn = null; - throw new Exception("Invalid line item:" . json_encode($line_item)); - } + // set order ID of line item + $line_item->setOrderID($new_order_id); // fetch product corresponding to line item $product = Product::getByID($line_item->getProductID()); @@ -139,6 +135,9 @@ public function save(): bool throw new Exception("Product with ID " . $line_item->getProductID() . " does not exist"); } + // set true unit price of line item + $line_item->setUnitPrice($product->getPrice()); + // get stock level for current product $stock_level = $store->getProductStock($product->getProductID()); @@ -146,15 +145,39 @@ public function save(): bool // store does not have enough stock $conn->rollBack(); $conn = null; + + $error_message = <<< EOL + Store with ID $this->store_id has insufficient stock ($stock_level) for the following line item: + Product ID = {$line_item->getProductID()} and quantity = {$line_item->getQuantity()}. + EOL; + + throw new Exception($error_message); + } + + // validate line item + $line_item_errors = $line_item->validate(); + if (!empty($line_item_errors)) { + // line item contains invalid attributes + $conn->rollBack(); + $conn = null; + + $line_item_info = json_encode($line_item->toArray()); + $line_item_errors = json_encode($line_item_errors); + + $error_message = <<< EOL + Invalid line item: + $line_item_info + + Errors: + $line_item_errors + EOL; + throw new Exception( - "Store with ID " . $this->store_id - . " has insufficient stock for product " . $line_item->getProductID() + $error_message ); } - // insert into order_product table - $line_item->setOrderID($new_order_id); - $line_item->setUnitPrice($product->getPrice()); + // insert line item into order_product table $success = $insert_line_item_stm->execute($line_item->toArray()); if (!$success) { @@ -192,14 +215,9 @@ public function save(): bool * * @param OrderProduct $orderProduct * @return void - * @throws Exception */ public function addLineItem(OrderProduct $orderProduct): void { - $errors = $orderProduct->validate(); - if (!empty($errors)) { - throw new Exception("Invalid line item: " . json_encode($errors)); - } $this->line_items[] = $orderProduct; } diff --git a/src/models/OrderProduct.php b/src/models/OrderProduct.php index 0048327..2c79e13 100644 --- a/src/models/OrderProduct.php +++ b/src/models/OrderProduct.php @@ -20,6 +20,15 @@ class OrderProduct private int $quantity; private float $unit_price; + /** + * Create a new OrderProduct object + * @param int $product_id + * @param string $cup_size + * @param string $milk_type + * @param int $quantity + * @param float|null $unit_price If not set, the default $unit_price is -1. + * @param int|null $order_id If not set, the default $order_id is -1. + */ public function __construct( int $product_id, string $cup_size,