customerAddressModel = new CustomerAddress(); $this->customerModel = new Customer(); $this->studentCardModel = new StudentCard(); $this->customerTypeModel = new SettingCustomerType(); $this->checkinStreakModel = new CheckinStreak(); $this->logCheckinModel = new LogCustomerCheckin(); $this->checkinRuleModel = new SettingCheckinRule(); $this->customerPointModel = new CustomerPoint(); $this->customerWalletModel = new CustomerWallet(); $this->membershipTierModel = new SettingMembershipTier(); } public function updateProfile($id = null){ helper(['form']); // Check customer exists $customer = $this->customerModel->find($id); if (!$customer) { $response = [ 'status' => 'error', 'message' => "Customer with ID {$id} not found.", 'data' => null ]; return $this->respond($response, 404); } $validationRules = [ 'name' => 'required', 'email' => "required|valid_email|is_unique[customers.email,id,{$id}]", 'birthday' => 'required|valid_date[Y-m-d]', 'password_hash' => 'permit_empty|min_length[6]', 'customer_referral_code' => 'permit_empty|regex_match[/^\d{6}$/]' ]; if (!$this->validate($validationRules)) { $response = [ 'status' => 'error', 'message' => 'Validation failed.', 'data' => $this->validator->getErrors() ]; return $this->respond($response, 422); } $data = [ 'name' => $this->request->getVar('name'), 'email' => $this->request->getVar('email'), 'birthday' => $this->request->getVar('birthday'), 'updated_at' => date('Y-m-d H:i:s'), ]; $passwordHash = $this->request->getVar('password_hash'); if (!empty($passwordHash)) { $data['password_hash'] = md5($passwordHash); } if (empty($customer['customer_type'])) { $defaultTypeName = 'Regular Customer'; $customerType = $this->customerTypeModel ->where('name', $defaultTypeName) ->first(); if (!$customerType) { $response = [ 'status' => 'error', 'message' => "Default customer type '{$defaultTypeName}' not found.", 'data' => null ]; return $this->respond($response, 500); } $data['customer_type'] = $defaultTypeName; } $referralCode = $this->request->getVar('customer_referral_code'); if (!empty($referralCode)) { // Look up referral customer by code $referrer = $this->customerModel ->where('customer_referral_code', $referralCode) ->first(); if ($referrer) { $data['customer_referral_id'] = $referrer['id']; } else { $response = [ 'status' => 'error', 'message' => "Invalid referral code provided.", 'data' => null ]; return $this->respond($response, 422); } } // Handle profile picture upload $profileImage = $this->request->getFile('profile_picture'); if ($profileImage && $profileImage->isValid() && !$profileImage->hasMoved()) { $originalPath = $_SERVER['DOCUMENT_ROOT'] . '/backend/uploads/customers'; $compressedPath = $_SERVER['DOCUMENT_ROOT'] . '/backend/uploads/customers_compressed/'; $baseUrl = 'https://icom.ipsgroup.com.my'; try { $result = save_image_with_compression($profileImage, $originalPath, $compressedPath, 900, 80); // Remove old images if they exist if (!empty($customer['profile_picture'])) { $oldOriginal = $_SERVER['DOCUMENT_ROOT'] . '/backend/' . $customer['profile_picture']; if (file_exists($oldOriginal)) unlink($oldOriginal); // Also remove old compressed version if it exists (adjust field name as needed) if (!empty($customer['profile_picture_compressed'])) { $oldCompressed = $_SERVER['DOCUMENT_ROOT'] . '/backend/' . $customer['profile_picture_compressed']; if (file_exists($oldCompressed)) unlink($oldCompressed); } } $relativeOriginal = str_replace($_SERVER['DOCUMENT_ROOT'].'/backend/', '', $result['original']); $relativeCompressed = str_replace($_SERVER['DOCUMENT_ROOT'].'/backend/', '', $result['compressed']); $data['profile_picture'] = $relativeOriginal; $data['profile_picture_compressed'] = $relativeCompressed; $data['profile_picture_url'] = $baseUrl . "/backend/" . $relativeOriginal; $data['profile_picture_compressed_url'] = $baseUrl . "/backend/" . $relativeCompressed; } catch (\Exception $e) { $response = [ 'status' => 'error', 'message' => 'Failed to upload profile picture: ' . $e->getMessage(), 'data' => null ]; return $this->respond($response, 500); } } if ($this->customerModel->update($id, $data)) { $updatedCustomer = $this->customerModel->find($id); unset($updatedCustomer['password_hash']); $response = [ 'status' => 'success', 'message' => 'Customer profile updated successfully.', 'data' => $updatedCustomer ]; return $this->respond($response, 200); } else { $response = [ 'status' => 'error', 'message' => 'Failed to update profile.', 'data' => null ]; return $this->respond($response, 500); } } public function getCustomerProfile($id= null){ if ($id === null) { $response = [ 'status' => 'error', 'message' => 'Customer ID is required.', 'data' => null ]; return $this->respond($response, 422); } $customer = $this->customerModel ->select(' customers.id, customers.name, customers.email, customers.phone, customers.customer_type, customers.birthday, customers.profile_picture, customers.status, customers.customer_referral_id, customers.customer_referral_code, customers.customer_wallet, customers.customer_point, customers.customer_tier_id, setting_membership_tiers.name AS customer_tier_name, setting_membership_tiers.min_points AS customer_tier_min_points, setting_membership_tiers.color AS customer_tier_color, customers.created_at, ') ->join('setting_membership_tiers', 'setting_membership_tiers.id = customers.customer_tier_id', 'left') ->where('customers.id', $id) ->first(); if (!$customer) { $response = [ 'status' => 'error', 'message' => "Customer with ID {$id} not found.", 'data' => null ]; return $this->respond($response, 404); } // Build full URL for profile picture if it exists if (!empty($customer['profile_picture'])) { $baseUrl = 'https://icom.ipsgroup.com.my'; // Change if dynamic base URL is preferred $customer['profile_picture_url'] = $baseUrl . '/backend/' . $customer['profile_picture']; } else { $customer['profile_picture_url'] = null; } //get customer cumulative point $customer_cumulative_point = $this->customerPointModel->where('customer_id', $id)->where('deleted_at', null)->selectSum('in')->get()->getRow()->in ?? 0; // echo($customer_cumulative_point);exit; //check if customer tier is null if($customer['customer_tier_id'] == null || $customer['customer_tier_id'] == 0 || $customer['customer_tier_min_points'] == null){ // Customer has no tier, get the first available tier $next_tier = $this->membershipTierModel->where('deleted_at', null)->orderBy('min_points', 'ASC')->first(); }else{ // Customer has a tier, get the next higher tier $next_tier = $this->membershipTierModel->where('deleted_at', null) ->where('min_points >', $customer['customer_tier_min_points']) ->orderBy('min_points', 'ASC') ->first(); } // print_r($customer);exit; if($next_tier){ $customer['next_tier'] = $next_tier['name']; $customer['next_tier_min_points'] = $next_tier['min_points']; $customer['point_needed_for_next_tier'] = number_format($next_tier['min_points'] - $customer_cumulative_point, 2); }else{ $customer['next_tier'] = null; $customer['next_tier_min_points'] = null; $customer['point_needed_for_next_tier'] = null; } $customer['current_streak'] = 0; $customer['checkin_today'] = false; $streak = $this->checkinStreakModel->where('customer_id', $id)->orderBy('created_at', 'DESC')->first(); $yesterday = date('Y-m-d', strtotime('-1 day')); $today = date('Y-m-d'); if ($streak) { if ($streak['last_checkin_date'] === $yesterday) { $customer['current_streak'] = $streak['current_streak']; }else if ($streak['last_checkin_date'] === $today) { $customer['current_streak'] = $streak['current_streak']; $customer['checkin_today'] = true; } } $response = [ 'status' => 'success', 'message' => 'Customer retrieved successfully.', 'data' => $customer ]; return $this->respond($response, 200); } public function getCustomerAddresses($customerId = null) { if ($customerId === null) { $response = [ 'status' => 'error', 'message' => 'Customer ID is required.', 'data' => null ]; return $this->respond($response, 422); } $addresses = $this->customerAddressModel->where('customer_id', $customerId)->findAll(); if (empty($addresses)) { $response = [ 'status' => 'error', 'message' => "No addresses found for customer ID {$customerId}.", 'data' => null ]; return $this->respond($response, 404); } $response = [ 'status' => 'success', 'message' => 'Customer addresses retrieved successfully.', 'data' => $addresses ]; return $this->respond($response, 200); } public function getCustomerPoint($customerId) { // Check if customer exists $customer = $this->customerModel->find($customerId); if (!$customer) { $response = [ 'status' => 'error', 'message' => 'Customer not found.', 'data' => null ]; return $this->respond($response, 404); } $dateFrom = $this->request->getGet('date_from'); // optional $dateTo = $this->request->getGet('date_to'); // optional // Build query $builder = $this->customerPointModel ->where('customer_id', $customerId) ->orderBy('created_at', 'desc'); if ($dateFrom) { $builder->where('DATE(created_at) >=', $dateFrom); } if ($dateTo) { $builder->where('DATE(created_at) <=', $dateTo); } $transactions = $builder->findAll(); $response = [ 'status' => 'success', 'message' => empty($transactions) ? 'No data available in the table.' : 'Customer point retrieved successfully.', 'data' => [ 'current_point' => $customer['customer_point'], // from customer table 'transactions' => $transactions ] ]; return $this->respond($response, 200); } public function getCustomerWallet($customerId) { // Check if customer exists $customer = $this->customerModel->find($customerId); if (!$customer) { $response = [ 'status' => 'error', 'message' => 'Customer not found.', 'data' => null ]; return $this->respond($response, 404); } $dateFrom = $this->request->getGet('date_from'); // optional $dateTo = $this->request->getGet('date_to'); // optional // Build query $builder = $this->customerWalletModel ->where('customer_id', $customerId) ->orderBy('created_at', 'desc'); if ($dateFrom) { $builder->where('DATE(created_at) >=', $dateFrom); } if ($dateTo) { $builder->where('DATE(created_at) <=', $dateTo); } $transactions = $builder->findAll(); $response = [ 'status' => 'success', 'message' => empty($transactions) ? 'No data available in the table.' : 'Customer wallet retrieved successfully.', 'data' => [ 'current_wallet' => $customer['customer_wallet'], // from customer table 'transactions' => $transactions ] ]; return $this->respond($response, 200); } public function createCustomerAddress() { helper(['form']); $validationRules = [ 'name' => 'required', 'phone' => 'required', 'address' => 'required', 'unit' => 'permit_empty', 'note' => 'permit_empty', 'longitude' => 'required', 'latitude' => 'required' ]; if (!$this->validate($validationRules)) { $response = [ 'status' => 'error', 'message' => 'Validation failed.', 'data' => $this->validator->getErrors() ]; return $this->respond($response, 422); } $customerId = $this->request->getVar('customer_id'); if (!$customerId) { $response = [ 'status' => 'error', 'message' => 'Customer ID is required.', 'data' => null ]; return $this->respond($response, 422); } // Check if customer exists, is active, and not soft-deleted $customer = $this->customerModel ->where('id', $customerId) ->where('status', 'active') ->where('deleted_at', null) ->first(); if (!$customer) { $response = [ 'status' => 'error', 'message' => "Customer with ID {$customerId} not found or not active.", 'data' => null ]; return $this->respond($response, 404); } // Load the model $customerAddressModel = new CustomerAddress(); // Set all addresses for this customer to is_default = 0 $customerAddressModel ->where('customer_id', $customerId) ->set(['is_default' => 0]) ->update(); $data = [ 'customer_id' => $customerId, 'name' => $this->request->getVar('name'), 'phone' => $this->request->getVar('phone'), 'address' => $this->request->getVar('address'), 'unit' => $this->request->getVar('unit'), 'note' => $this->request->getVar('note'), 'longitude' => $this->request->getVar('longitude'), 'latitude' => $this->request->getVar('latitude'), 'is_default' => 1, // Always true for the newly added 'created_at' => date('Y-m-d H:i:s'), ]; if ($customerAddressModel->insert($data)) { $response = [ 'status' => 'success', 'message' => 'Customer address created successfully.', 'data' => $data ]; return $this->respond($response, 201); } else { $response =[ 'status' => 'error', 'message' => 'Failed to create customer address.', 'data' => null ]; return $this->respond($response, 500); } } public function showCustomerAddress($customerId = null) { if ($customerId === null) { $response = [ 'status' => 'error', 'message' => 'Customer ID is required.', 'data' => null ]; return $this->respond($response, 422); } $address = $this->customerAddressModel->where('customer_id', $customerId)->findAll(); if (!$address) { $response = [ 'status' => 'error', 'message' => "Customer address with ID {$customerId} not found.", 'data' => null ]; return $this->respond($response, 404); } $response = [ 'status' => 'sucess', 'message' => 'Customer address retrieved successfully.', 'data' => $address ]; return $this->respond($response, 200); } public function updateCustomerAddress($id = null) { helper(['form']); if ($id === null) { $response = [ 'status' => 'error', 'message' => 'Address ID is required.', 'data' => null ]; return $this->respond($response, 422); } $address = $this->customerAddressModel->find($id); if (!$address) { $response = [ 'status' => 'error', 'message' => "Customer address with ID {$id} not found.", 'data' => null ]; return $this->respond($response, 404); } // Fetch customer and validate $customerId = $address['customer_id']; $customer = $this->customerModel ->where('id', $customerId) ->where('status', 'active') ->where('deleted_at', null) ->first(); if (!$customer) { $response = [ 'status' => 'error', 'message' => 'Customer not found or inactive.', 'data' => null ]; return $this->respond($response, 404); } $validationRules = [ 'name' => 'required', 'phone' => 'required', 'address' => 'required', 'unit' => 'permit_empty', 'note' => 'permit_empty', 'longitude' => 'required', 'latitude' => 'required', 'is_default'=> 'required|in_list[0,1]' ]; if (!$this->validate($validationRules)) { $response = [ 'status' => 'error', 'message' => 'Validation failed.', 'data' => $this->validator->getErrors() ]; return $this->respond($response, 422); } $data = [ 'name' => $this->request->getVar('name'), 'phone' => $this->request->getVar('phone'), 'address' => $this->request->getVar('address'), 'unit' => $this->request->getVar('unit'), 'note' => $this->request->getVar('note'), 'longitude' => $this->request->getVar('longitude'), 'latitude' => $this->request->getVar('latitude'), 'is_default' => $this->request->getVar('is_default'), 'updated_at' => date('Y-m-d H:i:s') ]; // Handle is_default logic if ($data['is_default'] == 1) { // Set all other addresses of this customer to 0 $this->customerAddressModel ->where('customer_id', $customerId) ->where('id !=', $id) ->set('is_default', 0) ->update(); } if ($this->customerAddressModel->update($id, $data)) { $response = [ 'status' => 'success', 'message' => 'Customer address updated successfully.', 'data' => $data ]; return $this->respond($response, 200); } else { $response = [ 'status' => 'error', 'message' => 'Failed to update customer address.', 'data' => null ]; return $this->respond($response, 500); } } public function deleteCustomerAddress($id = null) { if (!$id) { $response = [ 'status' => 'error', 'message' => 'Customer address ID is required.', 'data' => null ]; return $this->respond($response, 422); } $address = $this->customerAddressModel->find($id); if (!$address) { $response = [ 'status' => 'error', 'message' => "Customer address with ID {$id} not found.", 'data' => null ]; return $this->respond($response, 404); } // Delete the address if ($this->customerAddressModel->delete($id)) { // If deleted address was default, assign default to another one if ($address['is_default'] == 1) { $anotherAddress = $this->customerAddressModel ->where('customer_id', $address['customer_id']) ->where('id !=', $id) ->orderBy('created_at', 'DESC') ->first(); if ($anotherAddress) { $this->customerAddressModel->update($anotherAddress['id'], ['is_default' => 1]); } } $response = [ 'status' => 'success', 'message' => "Customer address with ID {$id} deleted successfully.", 'data' => null ]; return $this->respond($response, 200); } $response = [ 'status' => 'error', 'message' => "Failed to delete customer address.", 'data' => null ]; return $this->respond($response, 500); } public function setDefaultCustomerAddress($id = null) // $id from URL { $customerId = $this->request->getVar('customer_id'); // Validate customer ID input if (!$customerId) { $response = [ 'status' => 'error', 'message' => 'Customer ID is required.', 'data' => null ]; return $this->respond($response, 422); } $customer = $this->customerModel ->where('id', $customerId) ->where('status', 'active') ->where('deleted_at', null) ->first(); if (!$customer) { $response = [ 'status' => 'error', 'message' => 'Customer not found or inactive.', 'data' => null ]; return $this->respond($response, 404); } // 2. Validate address exists AND belongs to the customer $address = $this->customerAddressModel ->where('id', $id) ->where('customer_id', $customerId) // <- this ensures correct linkage ->first(); if (!$address) { $response = [ 'status' => 'error', 'message' => 'Address not found or does not belong to the customer.', 'data' => null ]; return $this->respond($response, 404); } // 3. Set all customer's addresses to is_default = 0 $this->customerAddressModel ->where('customer_id', $customerId) ->set(['is_default' => 0]) ->update(); // 4. Set selected address to is_default = 1 $this->customerAddressModel->update($id, ['is_default' => 1]); $response = [ 'status' => 'success', 'message' => "Address ID {$id} is now the default for customer ID {$customerId}.", 'data' => [ 'address_id' => $id, 'customer_id' => $customerId ] ]; return $this->respond($response,200); } public function getCustomerAddressDetail($id = null) { if ($id === null) { $response = [ 'status' => 'error', 'message' => 'Address ID is required.', 'data' => null ]; return $this->respond($response, 422); } $address = $this->customerAddressModel->find($id); if (!$address) { $response = [ 'status' => 'error', 'message' => "Customer address with ID {$id} not found.", 'data' => null ]; return $this->respond($response, 404); } $response = [ 'status' => 'sucess', 'message' => 'Customer address retrieved successfully.', 'data' => $address ]; return $this->respond($response, 200); } public function submitStudentCard($id = null) { if (empty($id)) { return $this->respond([ 'status' => 'error', 'message' => 'Customer ID is required.', 'data' => null ], 422); } helper(['form']); helper(['image']); $validationRules = [ 'studentName' => 'required', 'studentId' => 'required', 'institution' => 'required', 'graduationDate' => 'required', ]; if (!$this->validate($validationRules)) { return $this->respond([ 'status' => 'error', 'message' => 'Validation failed.', 'data' => $this->validator->getErrors() ], 422); } // Check if customer exists $customer = $this->customerModel ->where('id', $id) ->where('status', 'active') ->where('deleted_at', null) ->first(); if (!$customer) { return $this->respond([ 'status' => 'error', 'message' => "Customer with ID {$id} not found or not active.", 'data' => null ], 404); } // Prepare data for insertion $data = [ 'customer_id' => $id, 'name' => $this->request->getVar('studentName'), 'student_id' => $this->request->getVar('studentId'), 'institution' => $this->request->getVar('institution'), 'graduate_date' => $this->request->getVar('graduationDate'), 'status' => 'pending', 'created_at' => date('Y-m-d H:i:s'), ]; // Handle uploaded image $profilePicture = $this->request->getFile('profile_picture'); if(!$profilePicture) { $response = [ 'status' => 'error', 'message' => 'Student ID picture is required.', 'data' => null ]; return $this->respond($response, 422); } $imagePath = null; $compressedPath = null; if ($profilePicture && $profilePicture->isValid() && !$profilePicture->hasMoved()) { $originalPath = $_SERVER['DOCUMENT_ROOT'] . '/backend/uploads/students'; $compressedDir = $_SERVER['DOCUMENT_ROOT'] . '/backend/uploads/students_compressed'; try { $result = save_image_with_compression($profilePicture, $originalPath, $compressedDir, 900, 80); // You can return relative paths if you want to store them in the DB $imagePath = str_replace($_SERVER['DOCUMENT_ROOT'].'/', '', $result['original']); $compressedPath = str_replace($_SERVER['DOCUMENT_ROOT'].'/', '', $result['compressed']); } catch (\Exception $e) { $response = [ 'status' => 'error', 'message' => 'Student Id picture upload failed: ' . $e->getMessage(), 'data' => null ]; return $this->respond($response, 500); } } if ($imagePath) { $data['student_id_image'] = $imagePath; } if ($this->studentCardModel->insert($data)) { return $this->respond([ 'status' => 'success', 'message' => 'Student Card submitted successfully.', 'data' => $data ], 201); } return $this->respond([ 'status' => 'error', 'message' => 'Failed to submit student card submission.', 'data' => null ], 500); } public function getStudentCardStatus($customer_id = null) { if ($customer_id === null) { return $this->respond([ 'status' => 'error', 'message' => 'Customer ID is required.', 'data' => null ], 422); } // Get the latest student card by created_at for this customer $studentCard = $this->studentCardModel ->where('customer_id', $customer_id) ->orderBy('created_at', 'DESC') ->first(); if (!$studentCard) { return $this->respond([ 'status' => 'error', 'message' => "Student card for Customer ID {$customer_id} not found.", 'data' => null ], 404); } return $this->respond([ 'status' => 'success', 'message' => 'Latest student card retrieved successfully.', 'data' => $studentCard ], 200); } public function customerNextTierInformation($customer_id = null) { if ($customer_id === null) { return $this->respond([ 'status' => 'error', 'message' => 'Customer ID is required.', 'data' => null ], 422); } // Query customer points and next tier info $result = $this->customerModel ->select(' CAST(IFNULL(cp.acc_p, 0) AS UNSIGNED) AS accumulate_points, CAST(next_tier.min_points AS UNSIGNED) AS next_tier_min_points, next_tier.name AS next_tier_name ') ->join( '(SELECT customer_id, SUM(`in`) AS acc_p FROM customer_points GROUP BY customer_id) cp', 'cp.customer_id = customers.id', 'left' ) ->join( '(SELECT t1.id, t1.name, t1.min_points FROM setting_membership_tiers t1) next_tier', 'next_tier.min_points = ( SELECT MIN(t2.min_points) FROM setting_membership_tiers t2 WHERE t2.min_points > IFNULL(cp.acc_p, 0) )', 'left', false ) ->where('customers.id', $customer_id) ->get() ->getRow(); if (!$result) { return $this->respond([ 'status' => 'error', 'message' => "Customer ID {$customer_id} not found.", 'data' => null ], 404); } return $this->respond([ 'status' => 'success', 'message' => 'Customer next tier information retrieved successfully.', 'data' => $result ], 200); } public function checkin($customerId) { $today = date('Y-m-d'); $yesterday = date('Y-m-d', strtotime('-1 day')); //hardcode the date for testing purpose. // $today = '2025-07-09'; // $yesterday = '2025-07-08'; // Validate input if (!$customerId) { $response = [ 'status' => 'error', 'message' => 'Customer ID is required.', 'data' => null ]; return $this->respond($response, 400); } //Check if customer exists $customer = $this->customerModel->find($customerId); if (!$customer) { $response = [ 'status' => 'error', 'message' => 'Customer not found.', 'data' => null ]; return $this->respond($response, 404); } //Prevent multiple check-ins on same day $alreadyChecked = $this->logCheckinModel ->where('customer_id', $customerId) ->where('checkin_date', $today) ->first(); if ($alreadyChecked) { $response = [ 'status' => 'error', 'message' => 'Already checked in today.', 'data' => null ]; return $this->respond($response, 409); } //Get or initialize streak $streak = $this->checkinStreakModel->where('customer_id', $customerId)->first(); if ($streak) { if ($streak['last_checkin_date'] === $yesterday) { $currentStreak = $streak['current_streak'] + 1; } else { $currentStreak = 1; // missed a day, reset streak } $totalCheckin = $streak['total_checkin'] + 1; $this->checkinStreakModel->update($streak['id'], [ 'current_streak' => $currentStreak, 'last_checkin_date' => $today, 'total_checkin' => $totalCheckin, ]); } else { // first time ever $currentStreak = 1; $totalCheckin = 1; $this->checkinStreakModel->insert([ 'customer_id' => $customerId, 'current_streak' => $currentStreak, 'last_checkin_date' => $today, 'total_checkin' => $totalCheckin, ]); } //Log the check-in $this->logCheckinModel->insert([ 'customer_id' => $customerId, 'checkin_date' => $today, 'streak_count' => $currentStreak, ]); //Check for reward rule $rewardGiven = false; $rewardPoint = 0; $rule = $this->checkinRuleModel ->where('checkin_count', $currentStreak) ->first(); if ($rule) { $alreadyRewarded = $this->customerPointModel ->where('customer_id', $customerId) ->where('remark', "Reward for {$currentStreak}-day check-in streak on {$today}.") ->first(); if (!$alreadyRewarded) { $latestPoint = $this->customerPointModel ->where('customer_id', $customerId) ->orderBy('id', 'DESC') ->first(); $previousBalance = $latestPoint ? $latestPoint['balance'] : 0; $rewardPoint = (float) $rule['reward_point']; $newBalance = $previousBalance + $rewardPoint; $this->customerPointModel->insert([ 'customer_id' => $customerId, 'related_id' => '2', 'related_type' => 'checkin_reward', 'action' => 'increase', 'current' => $previousBalance, 'in' => $rewardPoint, 'out' => 0, 'balance' => $newBalance, 'remark' => "Reward for {$currentStreak}-day check-in streak on {$today}.", ]); $this->customerModel->update($customerId, ['customer_point' => $newBalance]); $rewardGiven = true; } } $updatedStreak = $this->checkinStreakModel ->where('customer_id', $customerId) ->first(); $latestPoint = $this->customerPointModel ->where('customer_id', $customerId) ->orderBy('id', 'DESC') ->first(); $data = [ 'reward_given' => $rewardGiven, 'reward_point' => $rewardPoint, 'customer_point' => $latestPoint['balance'], 'current_streak' => $updatedStreak['current_streak'], ]; $response = [ 'status' => 'success', 'message' => 'Check-in successful!', 'data' => $data, ]; return $this->respond($response, 200); } public function referralList($customer_id) { if(empty($customer_id)){ return $this->respond(['status' => 400, 'message' => 'Customer ID is required']); } $customer = $this->customerModel->select('name, created_at')->where('customer_referral_id', $customer_id)->findAll(); return $this->respond(['status' => 200, 'data' => $customer]); } }