initial project
This commit is contained in:
@@ -0,0 +1,508 @@
|
||||
<?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.']);
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user