customers = new Customer(); $this->voucher_points = new VoucherPoints(); $this->customer_voucher_list = new CustomerVoucherList(); $this->promo_codes = new PromoCode(); $this->promo_settings = new PromoSetting(); $this->carts = new Carts(); $this->calculate_service = service('calculateService'); $this->promo_service = service('promoService'); $this->voucher_service = service('voucherService'); $this->menuItem = new MenuItems(); $this->menuItemCategories = new MenuItemCategories(); } public function claim() { // echo(123);exit; $body = $this->request->getJSON(true) ?? $this->request->getPost(); $customerId = (int) ($body['customer_id'] ?? 0); $voucherId = (int) ($body['voucher_id'] ?? 0); if ($customerId <= 0 || $voucherId <= 0) { return $this->respond(['status' => 400, 'message' => 'Missing customer_id or voucher_id'], 400); } $voucherModel = $this->voucher_points; $custPtsModel = new CustomerPoint(); $custVoucherMod = new CustomerVoucherList(); $voucher = $voucherModel ->where('id', $voucherId) ->where('voucher_status', 'active') ->first(); if (!$voucher) { return $this->respond(['status' => 404, 'message' => 'Voucher not found or inactive'], 404); } if (!empty($voucher['voucher_total_count']) && !empty($voucher['voucher_redeem_count'])) { if ((int)$voucher['voucher_redeem_count'] >= (int)$voucher['voucher_total_count']) { return $this->respond(['status' => 400, 'message' => 'Voucher is out of stock'], 400); } } if (!empty($voucher['voucher_count_customer'])) { $taken = $custVoucherMod->where([ 'customer_id' => $customerId, 'promo_setting_id' => $voucher['promo_setting_id'] ?? null, ])->where('voucher_status !=', 'trash')->countAllResults(); if ($taken >= (int)$voucher['voucher_count_customer']) { return $this->respond(['status' => 400, 'message' => 'You have reached the redeem limit for this voucher'], 400); } } $today = date('Y-m-d'); if (!empty($voucher['voucher_expired_date']) && $today > $voucher['voucher_expired_date']) { return $this->respond(['status' => 400, 'message' => 'Voucher already expired'], 400); } $lastLedger = $custPtsModel->where('customer_id', $customerId) ->orderBy('id', 'DESC')->first(); $currentBalance = $lastLedger ? (float)$lastLedger['balance'] : 0.0; $costPoints = (float) ($voucher['voucher_point_redeem'] ?? 0); if ($costPoints <= 0) { return $this->respond(['status' => 400, 'message' => 'Voucher point cost is invalid'], 400); } if ($currentBalance < $costPoints) { return $this->respond(['status' => 400, 'message' => 'Insufficient points'], 400); } $custVoucherExpiry = null; $type = strtolower(trim($voucher['voucher_expiry_type'] ?? '')); $value = trim($voucher['voucher_expiry_value'] ?? ''); if ($type === 'date' && !empty($voucher['voucher_expired_date'])) { $custVoucherExpiry = $voucher['voucher_expired_date']; } elseif ($type === 'fixed' || $type === 'days') { $days = (int)$value; $custVoucherExpiry = date('Y-m-d', strtotime("+{$days} days")); } else { $custVoucherExpiry = !empty($voucher['voucher_expired_date']) ? $voucher['voucher_expired_date'] : null; } $already = $custVoucherMod->where([ 'customer_id' => $customerId, 'promo_setting_id' => $voucher['promo_setting_id'] ?? null, 'voucher_status' => 'active', ])->first(); if ($already) { return $this->respond(['status' => 200, 'message' => 'Voucher already redeemed for this customer', 'data' => $already]); } $db = \Config\Database::connect(); $db->transStart(); $voucherCode = strtoupper('V' . $voucherId . '-' . bin2hex(random_bytes(3))); $custVoucherId = $custVoucherMod->insert([ 'promo_setting_id' => $voucher['promo_setting_id'] ?? null, 'customer_id' => $customerId, 'voucher_order_id' => 0, 'voucher_topup_id' => 0, 'voucher_code' => $voucherCode, 'voucher_expiry_date'=> $custVoucherExpiry, 'voucher_status' => 'active', ], true); $newBalance = $currentBalance - $costPoints; $ledgerId = $custPtsModel->insert([ 'customer_id' => $customerId, 'related_id' => $voucherId, 'related_type'=> 'voucher', 'action' => 'redeem_voucher', 'current' => $currentBalance, 'in' => 0, 'out' => $costPoints, 'balance' => $newBalance, 'remark' => sprintf('Redeemed voucher "%s" (ID %d, code %s)', $voucher['voucher_name'] ?? '', $voucherId, $voucherCode), ], true); $this->customers->update($customerId, [ 'customer_point' => $newBalance ]); $voucherModel->where('id', $voucherId)->set('voucher_redeem_count', 'voucher_redeem_count + 1', false)->update(); $db->transComplete(); if ($db->transStatus() === false) { return $this->respond(['status' => 500, 'message' => 'Failed to redeem voucher'], 500); } return $this->respond([ 'status' => 200, 'message' => 'Voucher redeemed successfully', 'data' => [ 'customer_voucher_id' => $custVoucherId, 'ledger_id' => $ledgerId, 'voucher_code' => $voucherCode, 'new_balance' => $newBalance, 'voucher_expiry_date' => $custVoucherExpiry, ], ]); } public function index() { // echo(123123);exit; log_message('info', 'Voucher index accessed'); $voucherName = $this->request->getGet('voucher_name'); $dateFrom = $this->request->getGet('date_from'); $dateTo = $this->request->getGet('date_to'); $builder = $this->voucher_points->builder(); $builder->where('voucher_status !=', 'trash'); if ($voucherName) { $builder->like('voucher_name', $voucherName); } if ($dateFrom && $dateTo) { $builder->where('voucher_expired_date >=', $dateFrom); $builder->where('voucher_expired_date <=', $dateTo); } // ✅ Print the generated SQL // echo $builder->getCompiledSelect(); // exit; // All transactions $voucherSettings = $builder->get()->getResult(); if (empty($voucherSettings)) { return $this->respond(["status" => 400, "message" => "No Voucher Found", "data" => []]); } return $this->respond(["status" => 200, "message" => "Successfully retrive data!", "data" => $voucherSettings]); } public function show($id = null) { $voucherSettings = $this->voucher_points->find($id); if (empty($voucherSettings)) { return $this->fail("No voucher settings found.", 400); } $voucherSettingData = []; if ($voucherSettings) { $voucherSettingData[] = [ 'id' => $voucherSettings['id'], 'voucher_name' => $voucherSettings['voucher_name'], 'voucher_total_count' => $voucherSettings['voucher_total_count'], 'voucher_redeem_count' => $voucherSettings['voucher_redeem_count'], 'voucher_count_customer' => $voucherSettings['voucher_count_customer'], 'voucher_expiry_type' => $voucherSettings['voucher_expiry_type'], 'voucher_expiry_value' => $voucherSettings['voucher_expiry_value'], 'voucher_expired_date' => $voucherSettings['voucher_expired_date'], 'voucher_point_redeem' => $voucherSettings['voucher_point_redeem'], 'promo_setting_id'=> $voucherSettings['promo_setting_id'], 'voucher_details'=> $voucherSettings['voucher_details'], 'voucher_tnc'=> $voucherSettings['voucher_tnc'], 'voucher_status'=> $voucherSettings['voucher_status'], 'voucher_image_url'=> getImagePath('vouchers', $voucherSettings['voucher_image']), ]; } return $this->respond(["status" => 200, "message" => "Successfully retrive data!", "data" => $voucherSettingData]); } public function voucherList($customer_id) { if(empty($customer_id)) { return $this->respond(['status' => 400, 'result' => 'Customer ID is empty.']); } $customer = $this->customers->find($customer_id); if(empty($customer)) { return $this->respond(['status' => 400, 'result' => 'Customer data not found.']); } $customer_voucher_list = $this->customer_voucher_list ->select('customer_voucher_list.*, promo_settings.description') ->join('promo_settings', 'promo_settings.id = customer_voucher_list.promo_setting_id') ->where('customer_voucher_list.customer_id', $customer_id) ->findAll(); return $this->respond(['status' => 200, 'message' =>'Customer voucher list retrieved sucessfully!', 'data' => $customer_voucher_list]); } public function redeemVoucher($customer_id) { if(empty($customer_id)) { return $this->respond(['status' => 400, 'result' => 'Customer ID is empty.']); } $customer = $this->customers->find($customer_id); if(empty($customer)) { return $this->respond(['status' => 400, 'result' => 'Customer data not found.']); } $validation = $this->validate([ 'order_type' => 'required', 'promo_code' => 'permit_empty', 'voucher_id' => 'permit_empty', 'cart_id' => 'required', 'outlet_id' => 'required', ]); if (!$validation) { return $this->failValidationErrors($this->validator->getErrors()); } $promo_code = $this->request->getVar('promo_code'); $voucher_id = $this->request->getVar('voucher_id'); $cart_id = $this->request->getVar('cart_id'); $outlet_id = $this->request->getVar('outlet_id'); $order_type = $this->request->getVar('order_type'); if(empty($promo_code) && empty($voucher_id)) { return $this->respond(['status' => 400, 'result' => 'Voucher code or voucher id is empty.']); } $getCart = $this->carts->where('customer_id', $customer_id)->where('outlet_id', $outlet_id)->where('status', 'active')->find($cart_id); if(empty($getCart)) { return $this->respond(['status' => 400, 'result' => 'Unable to find your cart.']); } if($getCart['promo_code_id'] > 0 || $getCart['customer_voucher_list_id'] > 0) { $getCart['promo_code_id'] = 0; $getCart['customer_voucher_list_id'] = 0; $this->carts->update($cart_id, $getCart); } $free_items = []; if(!empty($promo_code)) { // promo code $promo = $this->promo_codes->select('promo_codes.*, promo_settings.promo_setting') ->where('promo_codes.code', $promo_code) ->join('promo_settings', 'promo_settings.id = promo_codes.promo_setting_id') ->orderBy('promo_codes.id', 'DESC')->first(); if(empty($promo)) { return $this->respond(['status' => 400, 'result' => 'Code not found.']); } $promoSettingData = json_decode($promo['promo_setting'], true); $promo_setting = $promoSettingData['Promo']; // print_r($promo);exit; //check promo availability $check_promo = $this->promo_service->checkPromoAvailability($promo['id'], $order_type, $customer_id); //promo unavailable if(isset($check_promo['status']) && $check_promo['status'] == 400) { return $this->respond($check_promo); } if($promo_setting['promo_type'] == 'free_item'){ $free_items = []; $isIncluded = true; if($promo_setting['filter_type'] == 'item'){ foreach($promo_setting['free_item'] as $free_item_id){ $menu_item = $this->menuItem ->select('menu_items.id, menu_items.title, menu_images.image_url, menu_images.image_url_compressed') ->join('menu_images', 'menu_images.menu_item_id = menu_items.id', 'left') ->where('menu_items.status', 'active') ->find($free_item_id); if($menu_item){ $free_items[] = [ 'id' => $menu_item['id'], 'title' => $menu_item['title'], 'image_url' => getMenuImage($menu_item['id']), // 'image_url_compressed' => getMenuImage($menu_item['id']) ]; } } } if($promo_setting['filter_type'] == 'category'){ foreach($promo_setting['free_item'] as $free_item_id){ $menu_items = $this->menuItemCategories ->select('menu_items.id, menu_items.title, menu_item_categories.category_id') ->join('menu_items', 'menu_items.id = menu_item_categories.menu_item_id') ->where('menu_item_categories.category_id', $free_item_id) ->where('menu_items.status', 'active') ->findAll(); if($menu_items){ foreach($menu_items as $item){ $menu_item = $this->menuItem ->select('menu_items.id, menu_items.title, menu_images.image_url, menu_images.image_url_compressed') ->join('menu_images', 'menu_images.menu_item_id = menu_items.id', 'left') ->where('menu_items.status', 'active') ->find($item['id']); if($menu_item){ $free_items[$item['category_id']][] = [ 'id' => $menu_item['id'], 'category_id' => $item['category_id'], 'title' => $menu_item['title'], 'image_url' => getMenuImage($menu_item['id']), // 'image_url_compressed' => getMenuImage($menu_item['id']) ]; } } } } } $afterPromo['free_item_list'] = $free_items; } //promo available $this->carts->update($cart_id, ['promo_code_id' => $promo['id'], 'customer_voucher_list_id' => 0]); // $applyPromoCode = $this->calculate_service->calculateCartTotals($cart_id, $outlet_id, null, null, null, null, null, null, 'promo'); } else if(!empty($voucher_id)){ // use voucher // please add in voucher_expiry_date $customer_voucher = $this->customer_voucher_list ->select('customer_voucher_list.*, promo_settings.promo_setting') ->join('promo_settings', 'promo_settings.id = customer_voucher_list.promo_setting_id') ->where('customer_voucher_list.id', $voucher_id) ->first(); if(empty($customer_voucher)){ return $this->respond(['status' => 400, 'result' => 'Voucher not found.']); } $promoSettingData = json_decode($customer_voucher['promo_setting'], true); $promo_setting = $promoSettingData['Promo']; // print_r($promo);exit; //check voucher availability $check_voucher = $this->voucher_service->checkVoucherAvailability($customer_voucher['id'], $order_type, $customer_id); //voucher unavailable if(isset($check_voucher['status']) && $check_voucher['status'] == 400) { return $this->respond($check_voucher); } $free_items = []; if($promo_setting['promo_type'] == 'free_item'){ $isIncluded = true; if($promo_setting['filter_type'] == 'item'){ foreach($promo_setting['free_item'] as $free_item_id){ $menu_item = $this->menuItem ->select('menu_items.id, menu_items.title, menu_images.image_url, menu_images.image_url_compressed') ->join('menu_images', 'menu_images.menu_item_id = menu_items.id', 'left') ->where('menu_items.status', 'active') ->find($free_item_id); if($menu_item){ $free_items[] = [ 'id' => $menu_item['id'], 'title' => $menu_item['title'], 'image_url' => getMenuImage($menu_item['id']), // 'image_url_compressed' => getMenuImage($menu_item['id']) ]; } } } if($promo_setting['filter_type'] == 'category'){ foreach($promo_setting['free_item'] as $free_item_id){ $menu_items = $this->menuItemCategories ->select('menu_items.id, menu_items.title, menu_item_categories.category_id') ->join('menu_items', 'menu_items.id = menu_item_categories.menu_item_id') ->where('menu_item_categories.category_id', $free_item_id) ->where('menu_items.status', 'active') ->findAll(); if($menu_items){ foreach($menu_items as $item){ $menu_item = $this->menuItem ->select('menu_items.id, menu_items.title, menu_images.image_url, menu_images.image_url_compressed') ->join('menu_images', 'menu_images.menu_item_id = menu_items.id', 'left') ->where('menu_items.status', 'active') ->find($item['id']); if($menu_item){ $free_items[$item['category_id']][] = [ 'id' => $menu_item['id'], 'category_id' => $item['category_id'], 'title' => $menu_item['title'], 'image_url' => getMenuImage($menu_item['id']), // 'image_url_compressed' => getMenuImage($menu_item['id']) ]; } } } } } } //voucher available $this->carts->update($cart_id, ['customer_voucher_list_id' => $customer_voucher['id'], 'promo_code_id' => 0]); // $applyPromoCode = $this->calculate_service->calculateCartTotals($cart_id, $outlet_id, null, null, null, null, null, null, 'voucher'); } return $this->respond(['status' => 200, 'result' => 'Voucher applied successfully.', 'data' => $free_items]); } public function removeVoucher($customer_id) { $cart_id = $this->request->getVar('cart_id'); if(empty($cart_id)){ return $this->respond(['status' => 400, 'result' => 'Cart id is empty.']); } $getCart = $this->carts->where('customer_id', $customer_id)->where('status', 'active')->find($cart_id); if(empty($getCart)) { return $this->respond(['status' => 400, 'result' => 'Unable to find your cart.']); } $this->calculate_service->resetVoucher($cart_id); return $this->respond(['status' => 200, 'result' => 'Voucher removed successfully.']); } }