601 lines
27 KiB
PHP
601 lines
27 KiB
PHP
<?php
|
|
|
|
namespace App\Controllers\Frontend;
|
|
|
|
use App\Models\CartItemOptions;
|
|
use App\Models\CartItems;
|
|
use App\Models\Carts;
|
|
use App\Models\MenuItemOptionsGroups;
|
|
use App\Models\MenuItems;
|
|
use App\Models\MenuItemVariations;
|
|
use App\Models\Options;
|
|
use App\Models\OptionsGroups;
|
|
use App\Models\Outlet;
|
|
use App\Models\OutletMenus;
|
|
use App\Models\VariationOptionsGroups;
|
|
use CodeIgniter\Database\Config;
|
|
use CodeIgniter\HTTP\ResponseInterface;
|
|
use CodeIgniter\RESTful\ResourceController;
|
|
use App\Services\CartService;
|
|
|
|
class CartController extends ResourceController
|
|
{
|
|
private $carts;
|
|
private $cart_items;
|
|
private $cart_item_options;
|
|
private $menu_items;
|
|
private $menu_item_options_groups;
|
|
private $option_groups;
|
|
private $options;
|
|
private $menu_item_variations;
|
|
private $variation_options_groups;
|
|
private $outlet_menus;
|
|
private $outlet;
|
|
private $db;
|
|
private $cart_service;
|
|
private $calculate_service;
|
|
private $promo_service;
|
|
private $voucher_service;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->carts = new Carts();
|
|
$this->cart_items = new CartItems();
|
|
$this->cart_item_options = new CartItemOptions();
|
|
$this->menu_items = new MenuItems();
|
|
$this->menu_item_options_groups = new MenuItemOptionsGroups();
|
|
$this->option_groups = new OptionsGroups();
|
|
$this->options = new Options();
|
|
$this->menu_item_variations = new MenuItemVariations();
|
|
$this->variation_options_groups = new VariationOptionsGroups();
|
|
$this->outlet_menus = new OutletMenus();
|
|
$this->outlet = new Outlet();
|
|
$this->db = Config::connect();
|
|
$this->cart_service = service('cartService');
|
|
$this->calculate_service = service('calculateService');
|
|
$this->promo_service = service('promoService');
|
|
$this->voucher_service = service('voucherService');
|
|
}
|
|
|
|
public function checkPwp($cart_id)
|
|
{
|
|
$cart = $this->carts->find($cart_id);
|
|
if (!$cart) {
|
|
return ['status' => 400, 'result' => 'Cart not found.'];
|
|
}
|
|
|
|
$cart_items = $this->cart_items
|
|
->where('cart_id', $cart_id)
|
|
->findAll();
|
|
|
|
if (empty($cart_items)) {
|
|
return ['status' => 200, 'result' => []];
|
|
}
|
|
|
|
$cart_item_ids = array_column($cart_items, 'menu_item_id');
|
|
|
|
$pwp_promos = $this->db->table('pwp')
|
|
->where('deleted_at', null)
|
|
->get()
|
|
->getResultArray();
|
|
|
|
$eligible_pwps = [];
|
|
|
|
foreach ($pwp_promos as $promo) {
|
|
$requiredIds = explode(',', $promo['selected_item']);
|
|
$pwpIds = explode(',', $promo['pwp_item_id']);
|
|
|
|
$hasQualifier = count(array_intersect($cart_item_ids, $requiredIds)) > 0;
|
|
|
|
if ($hasQualifier) {
|
|
foreach ($pwpIds as $pid) {
|
|
$menu_item = $this->menu_items->find($pid);
|
|
if (!$menu_item) continue;
|
|
|
|
$eligible_pwps[] = [
|
|
'pwp_id' => $promo['id'],
|
|
'pwp_item' => [
|
|
'id' => $menu_item['id'],
|
|
'title' => $menu_item['title'],
|
|
'original_price' => $menu_item['price'],
|
|
'pwp_price' => $promo['amount'],
|
|
],
|
|
'requires' => $requiredIds,
|
|
'requirement' => [
|
|
'type' => $promo['amount_type'],
|
|
'value' => $promo['order_index']
|
|
]
|
|
];
|
|
}
|
|
}
|
|
}
|
|
|
|
return ['status' => 200, 'result' => $eligible_pwps];
|
|
}
|
|
|
|
public function getCartDetail()
|
|
{
|
|
// echo(123);exit;
|
|
|
|
$validation = $this->validate([
|
|
'customer_id' => 'required|numeric',
|
|
'outlet_id' => 'required|numeric',
|
|
'selected_date' => 'permit_empty|string',
|
|
'selected_time' => 'permit_empty|string',
|
|
'latitude' => 'permit_empty|string',
|
|
'longitude' => 'permit_empty|string',
|
|
'order_type' => 'permit_empty|string',
|
|
'address' => 'permit_empty|string',
|
|
]);
|
|
|
|
if (!$validation) {
|
|
return $this->failValidationErrors($this->validator->getErrors());
|
|
}
|
|
|
|
$customer_id = $this->request->getVar('customer_id');
|
|
$outlet_id = $this->request->getVar('outlet_id');
|
|
$selected_date = $this->request->getVar('selected_date') ?? date('Y-m-d');
|
|
$selected_time = $this->request->getVar('selected_time') ?? date('H:i');
|
|
$latitude = $this->request->getVar('latitude');
|
|
$longitude = $this->request->getVar('longitude');
|
|
$order_type = strtolower(str_replace('-', '', $this->request->getVar('order_type')));
|
|
$address = $this->request->getVar('address');
|
|
|
|
$outlet = $this->outlet->where('id', $outlet_id)->first();
|
|
if (!$outlet) {
|
|
return $this->respond(['status' => 405, 'message' => 'Outlet not found'], 400);
|
|
}
|
|
$outlet['serve_method'] = strtolower(str_replace('-', '', $outlet['serve_method']));
|
|
//check order type
|
|
$serve_method = explode(',', $outlet['serve_method']);
|
|
if ($outlet['status'] == 'inactive' || $outlet['deleted_at'] != null || !in_array($order_type, $serve_method)) {
|
|
return $this->respond(['status' => 405, 'message' => 'Outlet not available for this order type'], 400);
|
|
}
|
|
|
|
|
|
$cart = $this->carts->where('customer_id', $customer_id)
|
|
->where('outlet_id', $outlet_id)
|
|
->where('status', 'active')
|
|
->where('deleted_at', null)
|
|
->orderBy('id', 'DESC')
|
|
->first();
|
|
|
|
if (!$cart) {
|
|
return $this->respond("No active cart found for this customer.", 200);
|
|
}
|
|
|
|
$promo_or_voucher = null;
|
|
|
|
if ($cart['promo_code_id'] > 0) {
|
|
$check_promo = $this->promo_service->checkPromoAvailability($cart['promo_code_id'], $order_type, $customer_id);
|
|
if (isset($check_promo['status']) && $check_promo['status'] == 400) {
|
|
$this->calculate_service->resetVoucher($cart['id']);
|
|
return $this->respond($check_promo);
|
|
}
|
|
$promo_or_voucher = 'promo';
|
|
}
|
|
|
|
if ($cart['customer_voucher_list_id'] > 0) {
|
|
$check_voucher = $this->voucher_service->checkVoucherAvailability($cart['customer_voucher_list_id'], $order_type, $customer_id);
|
|
if (isset($check_voucher['status']) && $check_voucher['status'] == 400) {
|
|
$this->calculate_service->resetVoucher($cart['id']);
|
|
return $this->respond($check_voucher);
|
|
}
|
|
$promo_or_voucher = 'voucher';
|
|
}
|
|
|
|
|
|
|
|
$cart_total_detail = $this->calculate_service->calculateCartTotals($cart['id'], $cart['outlet_id'], $selected_date, $selected_time, $latitude, $longitude, $order_type, $address, $promo_or_voucher);
|
|
// print_r($cart_total_detail);
|
|
// exit;
|
|
if (isset($cart_total_detail['status']) && $cart_total_detail['status'] == 400) {
|
|
$response = [
|
|
'status' => 400,
|
|
'message' => $cart_total_detail['result']
|
|
];
|
|
return $this->respond($response, 400);
|
|
}
|
|
|
|
$cart_total_detail = $cart_total_detail['data'];
|
|
// $pwp_check = $this->checkPwp($cart['id']);
|
|
// $eligible_pwps = ($pwp_check['status'] === 200) ? $pwp_check['result'] : [];
|
|
|
|
unset($cart_total_detail['invalid_items']);
|
|
|
|
return $this->respond([
|
|
'status' => 200,
|
|
'message' => 'Cart retrieved successfully.',
|
|
'data' => $cart_total_detail,
|
|
// 'eligible_pwps' => $eligible_pwps
|
|
]);
|
|
}
|
|
|
|
public function addCart()
|
|
{
|
|
|
|
$validation = $this->validate([
|
|
'customer_id' => 'required|numeric',
|
|
'outlet_id' => 'required|numeric',
|
|
'menu_item_id' => 'required|numeric',
|
|
'quantity' => 'required|numeric',
|
|
'variation_id' => 'permit_empty|numeric',
|
|
'option' => 'permit_empty',
|
|
'is_free_item' => 'permit_empty',
|
|
'is_pwp' => 'permit_empty',
|
|
]);
|
|
|
|
if (!$validation) {
|
|
return $this->failValidationErrors($this->validator->getErrors());
|
|
}
|
|
|
|
$customer_id = $this->request->getVar('customer_id');
|
|
$outlet_id = $this->request->getVar('outlet_id');
|
|
$menu_item_id = $this->request->getVar('menu_item_id');
|
|
$variation_id = $this->request->getVar('variation_id') ?? 0;
|
|
$option_group = $this->request->getVar('option');
|
|
$quantity = $this->request->getVar('quantity');
|
|
|
|
$is_free_item_type = $this->request->getVar('is_free_item') == true ? 'free_item' : null;
|
|
$is_pwp_type = $this->request->getVar('is_pwp') == true ? 'pwp' : null;
|
|
|
|
$type = $is_free_item_type ?? $is_pwp_type;
|
|
// print_r($this->request->getVar('is_free_item') == true ? 'free_item' : null);exit;
|
|
// Check if existing cart
|
|
$existing_cart = $this->carts
|
|
->where('customer_id', $customer_id)
|
|
->where('outlet_id', $outlet_id)
|
|
->where('status', 'active')
|
|
->first();
|
|
|
|
$addCart = $this->cart_service->addCartItem($customer_id, $outlet_id, $existing_cart, $menu_item_id, $variation_id, $option_group, $quantity, $type);
|
|
|
|
return $this->respond($addCart);
|
|
}
|
|
|
|
public function updateCart()
|
|
{
|
|
$validation = $this->validate([
|
|
'customer_id' => 'required|numeric',
|
|
'outlet_id' => 'required|numeric',
|
|
'action' => 'required|numeric',
|
|
]);
|
|
|
|
if (!$validation) {
|
|
return $this->failValidationErrors($this->validator->getErrors());
|
|
}
|
|
|
|
$customer_id = $this->request->getVar('customer_id');
|
|
$outlet_id = $this->request->getVar('outlet_id');
|
|
$action = $this->request->getVar('action');
|
|
$cart_item_id = $this->request->getVar('cart_item_id');
|
|
$quantity = $this->request->getVar('quantity');
|
|
$variation_id = $this->request->getVar('variation_id');
|
|
$option_group = $this->request->getVar('option');
|
|
|
|
$cart = $this->carts->where('customer_id', $customer_id)
|
|
->where('outlet_id', $outlet_id)
|
|
->where('status', 'active')
|
|
->first();
|
|
|
|
if (!$cart) {
|
|
return $this->fail('Cart not found', 400);
|
|
}
|
|
|
|
$this->db->transStart();
|
|
|
|
try {
|
|
|
|
switch ($action) {
|
|
case 1: // Update quantity
|
|
$cart_item = $this->cart_items->find($cart_item_id);
|
|
|
|
if (!$cart_item || $cart_item['cart_id'] != $cart['id']) {
|
|
return $this->fail('Cart item not found', 400);
|
|
}
|
|
|
|
$data = [
|
|
'unit_price' => $cart_item['unit_price'],
|
|
'quantity' => $quantity,
|
|
'line_subtotal' => $cart_item['unit_price'] * $quantity
|
|
];
|
|
$this->cart_items->update($cart_item['id'], $data);
|
|
break;
|
|
|
|
case 2: // Update Option
|
|
$cart_item = $this->cart_items->find($cart_item_id);
|
|
if (!$cart_item || $cart_item['cart_id'] != $cart['id']) {
|
|
return $this->fail('Cart item not found', 400);
|
|
}
|
|
|
|
$menu_item_id = $cart_item['menu_item_id'];
|
|
|
|
if (!isset($variation_id)) {
|
|
return $this->fail('No variation found', 400);
|
|
}
|
|
|
|
$required_groups = $this->cart_service->getRequiredOptionGroups($menu_item_id, $variation_id);
|
|
|
|
// Validate that required options are provided
|
|
if (!empty($required_groups)) {
|
|
if (empty($option_group)) {
|
|
return $this->fail('Required options are missing', 400);
|
|
}
|
|
|
|
$provided_group_ids = array_map(function ($opt) {
|
|
return $opt->group_id;
|
|
}, $option_group);
|
|
|
|
foreach ($required_groups as $group) {
|
|
if (!in_array($group['id'], $provided_group_ids)) {
|
|
return $this->fail('Required option group ' . $group['title'] . ' is missing', 400);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($variation_id == 0) {
|
|
$menu_item = $this->menu_items->where('status', 'active')->find($menu_item_id);
|
|
if (empty($menu_item)) {
|
|
return $this->fail("Menu Item not found!", 400);
|
|
}
|
|
|
|
$basePrice = $menu_item['price'];
|
|
|
|
$line_subtotal = $basePrice * $quantity;
|
|
|
|
$update_cart_detail = [
|
|
'variation_id' => 0,
|
|
'title' => $menu_item['title'],
|
|
'unit_price' => $basePrice,
|
|
'quantity' => $quantity,
|
|
'line_subtotal' => $line_subtotal,
|
|
];
|
|
|
|
$this->cart_items->update($cart_item['id'], $update_cart_detail);
|
|
|
|
if (!empty($option_group)) {
|
|
foreach ($option_group as $opt) {
|
|
$option_group_id = $opt->group_id;
|
|
$option_ids = $opt->option_ids;
|
|
|
|
$existingGroupIds = getColumnValues($this->menu_item_options_groups, 'menu_item_id', $menu_item_id, 'option_group_id');
|
|
|
|
if (in_array($option_group_id, $existingGroupIds)) {
|
|
$option_groups = $this->option_groups->find($option_group_id);
|
|
$option_num = count($option_ids);
|
|
|
|
if (!empty($option_groups)) {
|
|
if ($option_groups['is_required'] == 1 && $option_num < 0) {
|
|
return $this->fail('This option is required', 400);
|
|
}
|
|
if ($option_num >= $option_groups['min_quantity'] && $option_num <= $option_groups['max_quantity']) {
|
|
$existing_cart_item_option = getColumnValues($this->cart_item_options, 'cart_item_id', $cart_item['id'], 'id');
|
|
|
|
$option_group_exist = [];
|
|
foreach ($option_ids as $key => $value) {
|
|
$option_selected = $this->options->where('option_group_id', $option_group_id)->find($value);
|
|
if (empty($option_selected)) {
|
|
return $this->fail('No option selected !', 400);
|
|
}
|
|
$option_data = [
|
|
'cart_item_id' => $cart_item['id'],
|
|
'option_id' => $value,
|
|
'option_group_id' => $option_group_id,
|
|
'option_title' => $option_selected['title'],
|
|
'price_adjustment' => $option_selected['price_adjustment']
|
|
];
|
|
|
|
$current_option_existing = $this->cart_item_options->where('cart_item_id', $cart_item['id'])
|
|
->where('option_id', $value)
|
|
->where('option_group_id', $option_group_id)
|
|
->first();
|
|
if ($current_option_existing) {
|
|
$option_group_exist[] = $current_option_existing['id'];
|
|
} else {
|
|
$this->cart_item_options->insert($option_data);
|
|
}
|
|
}
|
|
|
|
foreach ($existing_cart_item_option as $exist_option_id) {
|
|
if (!in_array($exist_option_id, $option_group_exist)) {
|
|
$this->cart_item_options->delete($exist_option_id);
|
|
}
|
|
}
|
|
} else {
|
|
return $this->fail('Please select correct quantity for option!', 400);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
$existing_cart_item_option = getColumnValues($this->cart_item_options, 'cart_item_id', $cart_item['id'], 'id');
|
|
$this->cart_item_options->whereIn('id', $existing_cart_item_option)->delete();
|
|
}
|
|
} else {
|
|
$menu_item = $this->menu_items->where('status', 'active')->find($menu_item_id);
|
|
if (empty($menu_item)) {
|
|
return $this->fail("Menu Item not found!", 400);
|
|
}
|
|
|
|
$menu_variation = $this->menu_item_variations->where('menu_item_id', $menu_item_id)->first();
|
|
$basePrice = $menu_variation['price'];
|
|
|
|
$line_subtotal = $basePrice * $quantity;
|
|
|
|
$update_cart_detail = [
|
|
'variation_id' => $variation_id,
|
|
'title' => $menu_item['title'],
|
|
'unit_price' => $basePrice,
|
|
'quantity' => $quantity,
|
|
'line_subtotal' => $line_subtotal,
|
|
];
|
|
|
|
$this->cart_items->update($cart_item['id'], $update_cart_detail);
|
|
|
|
if (!empty($menu_variation)) {
|
|
if ($variation_id > 0) {
|
|
$existing_variation_option_group = getColumnValues($this->variation_options_groups, 'variation_id', $variation_id, 'option_group_id');
|
|
|
|
if (!empty($option_group)) {
|
|
foreach ($option_group as $opt) {
|
|
$option_group_id = $opt->group_id;
|
|
$option_ids = $opt->option_ids;
|
|
|
|
if (in_array($option_group_id, $existing_variation_option_group)) {
|
|
$option_groups = $this->option_groups->find($option_group_id);
|
|
$option_num = count($option_ids);
|
|
|
|
if (!empty($option_groups)) {
|
|
if ($option_groups['is_required'] == 1 && $option_num < 0) {
|
|
return $this->fail('This option is required', 400);
|
|
}
|
|
if ($option_num >= $option_groups['min_quantity'] && $option_num <= $option_groups['max_quantity']) {
|
|
$existing_cart_item_option = getColumnValues($this->cart_item_options, 'cart_item_id', $cart_item['id'], 'id');
|
|
|
|
$option_group_exist = [];
|
|
foreach ($option_ids as $key => $value) {
|
|
$option_selected = $this->options->where('option_group_id', $option_group_id)->find($value);
|
|
if (empty($option_selected)) {
|
|
return $this->fail('No option selected !', 400);
|
|
}
|
|
$option_data = [
|
|
'cart_item_id' => $cart_item['id'],
|
|
'option_id' => $value,
|
|
'option_group_id' => $option_group_id,
|
|
'option_title' => $option_selected['title'],
|
|
'price_adjustment' => $option_selected['price_adjustment']
|
|
];
|
|
|
|
$current_option_existing = $this->cart_item_options->where('cart_item_id', $cart_item['id'])
|
|
->where('option_id', $value)
|
|
->where('option_group_id', $option_group_id)
|
|
->first();
|
|
if ($current_option_existing) {
|
|
$option_group_exist[] = $current_option_existing['id'];
|
|
} else {
|
|
$this->cart_item_options->insert($option_data);
|
|
}
|
|
}
|
|
|
|
foreach ($existing_cart_item_option as $exist_option_id) {
|
|
if (!in_array($exist_option_id, $option_group_exist)) {
|
|
$this->cart_item_options->delete($exist_option_id);
|
|
}
|
|
}
|
|
} else {
|
|
return $this->fail('Please select correct quantity for option!', 400);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
$existing_cart_item_options = $this->cart_item_options
|
|
->where('cart_item_id', $cart_item['id'])
|
|
->findAll();
|
|
|
|
if (!empty($existing_cart_item_options)) {
|
|
$option_ids = array_column($existing_cart_item_options, 'id');
|
|
$this->cart_item_options->whereIn('id', $option_ids)->delete();
|
|
}
|
|
}
|
|
} else {
|
|
return $this->fail('No variation found!', 400);
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
case 3: // Remove one item
|
|
$cart_item = $this->cart_items->find($cart_item_id);
|
|
// print_r(123123);exit;
|
|
if (!$cart_item || $cart_item['cart_id'] != $cart['id']) {
|
|
return $this->fail('Cart item not found', 400);
|
|
}
|
|
|
|
$this->cart_items->delete($cart_item['id']);
|
|
$this->cart_item_options->where('cart_item_id', $cart_item['id'])->delete();
|
|
break;
|
|
|
|
case 4: // Remove all items
|
|
$all_cart_item = $this->cart_items->where('cart_id', $cart['id'])->findAll();
|
|
foreach ($all_cart_item as $item) {
|
|
$this->cart_item_options->where('cart_item_id', $item['id'])->delete();
|
|
$this->cart_items->delete($item['id']);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return $this->fail('Invalid action', 400);
|
|
break;
|
|
}
|
|
|
|
// $this->calculate_service->calculateCartTotals($cart['id'], $outlet_id);
|
|
|
|
$this->db->transComplete();
|
|
|
|
return $this->respond([
|
|
'status' => 200,
|
|
'message' => 'Cart updated successfully'
|
|
]);
|
|
} catch (\Exception $e) {
|
|
$this->db->transRollback();
|
|
return $this->fail($e->getMessage(), 400);
|
|
}
|
|
}
|
|
|
|
public function deleteCart()
|
|
{
|
|
$validation = $this->validate([
|
|
'customer_id' => 'required|numeric',
|
|
'outlet_id' => 'required|numeric',
|
|
]);
|
|
|
|
if (!$validation) {
|
|
return $this->failValidationErrors($this->validator->getErrors());
|
|
}
|
|
|
|
$customer_id = $this->request->getVar('customer_id');
|
|
$outlet_id = $this->request->getVar('outlet_id');
|
|
|
|
$cart = $this->carts->where('customer_id', $customer_id)
|
|
->where('outlet_id', $outlet_id)
|
|
->where('status', 'active')
|
|
->first();
|
|
|
|
if ($cart) {
|
|
$this->carts->update($cart['id'], ['status' => 'trash']);
|
|
$this->carts->delete($cart['id']);
|
|
$exist_cart_item = getColumnValues($this->cart_items, 'cart_id', $cart['id'], 'id');
|
|
$this->cart_items->where('cart_id', $cart['id'])->delete();
|
|
$this->cart_item_options->whereIn('cart_item_id', $exist_cart_item)->delete();
|
|
return $this->respond([
|
|
'status' => 200,
|
|
'message' => 'Cart delete successfully'
|
|
]);
|
|
} else {
|
|
return $this->fail('Cart not found', 400);
|
|
}
|
|
}
|
|
|
|
public function getCartItemsDetails($cart_item_id = null)
|
|
{
|
|
$cart_item = $this->cart_items->find($cart_item_id);
|
|
if (!$cart_item) {
|
|
return $this->fail('Cart item not found', 400);
|
|
}
|
|
|
|
$cart_item['variation'] = $this->menu_item_variations->find($cart_item['variation_id']);
|
|
$cart_item['options'] = $this->cart_item_options
|
|
->select('cart_item_options.*, options_groups.title as option_group_title')
|
|
->join('options_groups', 'options_groups.id = cart_item_options.option_group_id', 'left')
|
|
->where('cart_item_id', $cart_item_id)
|
|
->findAll();
|
|
|
|
return $this->respond([
|
|
'status' => 200,
|
|
'message' => 'Cart item details retrieved successfully',
|
|
'data' => $cart_item
|
|
]);
|
|
}
|
|
}
|