509 lines
22 KiB
PHP
509 lines
22 KiB
PHP
<?php
|
|
|
|
namespace App\Controllers\Frontend;
|
|
|
|
use App\Controllers\BaseController;
|
|
use CodeIgniter\API\ResponseTrait;
|
|
use CodeIgniter\HTTP\ResponseInterface;
|
|
use App\Models\Customer;
|
|
use App\Models\CustomerVoucherList;
|
|
use App\Models\PromoCode;
|
|
use App\Models\PromoSetting;
|
|
use App\Models\Carts;
|
|
use App\Models\VoucherPoints;
|
|
use App\Models\MenuItems;
|
|
use App\Models\MenuItemCategories;
|
|
use App\Models\CustomerPoint;
|
|
|
|
|
|
class VoucherController extends BaseController
|
|
{
|
|
use ResponseTrait;
|
|
private $customers;
|
|
private $customer_voucher_list;
|
|
|
|
private $customer_points;
|
|
private $promo_codes;
|
|
private $promo_settings;
|
|
private $carts;
|
|
private $calculate_service;
|
|
private $promo_service;
|
|
private $voucher_service;
|
|
private $menuItem;
|
|
private $menuItemCategories;
|
|
private $voucher_points;
|
|
|
|
|
|
public function __construct()
|
|
{
|
|
$this->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.']);
|
|
|
|
}
|
|
}
|