https://t.me/RX1948
Server : Apache/2.4.18 (Ubuntu)
System : Linux canvaswebdesign 3.13.0-71-generic #114-Ubuntu SMP Tue Dec 1 02:34:22 UTC 2015 x86_64
User : oppastar ( 1041)
PHP Version : 7.0.33-0ubuntu0.16.04.15
Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,
Directory :  /var/www/laciasmara.com/public_html/shop/application/controllers/admin/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /var/www/laciasmara.com/public_html/shop/application/controllers/admin/Customers.php
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');



class Customers extends Admin_Controller

{



	//this property is used for validating existing customer title on call back edit customer

	private $customer_current_id = NULL;



	function __construct()

	{

		parent::__construct();

		$this->load->model('customer_m');

	}



	public function add()

	{



		$data['userdata'] = $this->session->userdata();

		$data['title'] = 'Tambah Pelanggan | Laciasmara';

		$data['provinces'] = $this->getProvinces();



		$this->load->view('admin_new/layouts/header', $data);

		$this->load->view('admin_new/customers/add_customer');

		$this->load->view('admin_new/layouts/footer');

	}



	public function manage()

	{

		$data['userdata'] = $this->session->userdata();

		$data['title'] = 'Daftar Pelanggan | Laciasmara';

		$data['customers'] = $this->customer_m->fetch_all_customers();



		$this->load->view('admin_new/layouts/header', $data);

		$this->load->view('admin_new/customers/manage_customer');

		$this->load->view('admin_new/layouts/footer');

	}



	public function detail($id_customer = NULL)

	{

		if (!$id_customer) {

			redirect('admin/customers/manage');

		}

		$data['userdata'] = $this->session->userdata();

		$data['title'] = 'Detail Pelanggan | Laciasmara';



		// Fetch data order

		$data['customer'] = $this->customer_m->fetch_customer_by_id($id_customer);

		if (!$data['customer']) {

			$this->session->set_flashdata('message', 'Customer ID tidak ditemukan.');

			$this->session->set_flashdata('message_type', 'error');

			redirect('admin/customers/manage');

		}



		$data['customer_addresses'] = $this->customer_m->get_customer_addresses($id_customer);

		// echo "<pre>";

		// print_r($data['customer_addresses']);

		// echo "</pre>";

		// exit();



		$this->load->view('admin_new/layouts/header', $data);

		$this->load->view('admin_new/customers/detail_customer');

		$this->load->view('admin_new/layouts/footer');

	}



	public function create_customer()

	{

		$this->load->model('customer_m');

		$email = $this->input->post('customer_email', true);



		// Cek apakah email atau nomor telepon sudah terdaftar

		$existing_customer = $this->db->where('email', $email)

			->get('customers')

			->row();



		if ($existing_customer) {

			$this->session->set_flashdata('message_type', 'error');

			$this->session->set_flashdata('message', 'Email sudah digunakan, coba pakai email yang lain.');

			redirect(base_url('admin/customers/add'));

			return;

		}



		// Data customer

		$data = [

			'name' => $this->input->post('customer_name', true),

			'email' => $this->input->post('customer_email', true),

			'phone' => $this->input->post('customer_phone', true),

			'birthday' => $this->input->post('customer_birthdate', true),

			'sex_type' => $this->input->post('customer_gender', true),

			'password' => $this->customer_m->hash($this->input->post('customer_password', true)),

			'shipping_country' => 'Indonesia',

			'shipping_phone' => $this->input->post('customer_phone', true),

			'refferal' => $this->input->post('customer_ref', true),

			'status' => 1,

			'current_pointreward' => 0,

			'type' => 'regular',

			'is_first' => 0,

			'source' => 'www.laciasmara.com',

			'country' => 'Indonesia',

			'join_date' => date('Y-m-d H:i:s'),

		];



		// Mulai transaksi

		$this->db->trans_begin();



		// Simpan data ke tabel customers

		$this->db->insert('customers', $data);

		$customer_id = $this->db->insert_id();



		// Ambil dan decode customer_addresses

		$addresses_json = $this->input->post('customer_addresses');

		$addresses = json_decode($addresses_json, true); // decode as associative array



		if ($addresses && is_array($addresses)) {

			foreach ($addresses as $address) {

				$address_data = [

					'customer_id' => $customer_id,

					'label' => $address['label'],

					'recipient_name' => $address['receiverName'],

					'phone' => $address['receiverPhone'],

					'address' => $address['fullAddress'],

					'notes' => $address['notes'] ?? null,

					'latitude' => $address['latitude'] ?? null,

					'longitude' => $address['longitude'] ?? null,

					'province' => $address['province'],

					'city' => $address['city'],

					'district' => $address['district'],

					'subdistrict' => $address['subdistrict'],

					'postal_code' => $address['postalCode'],

					'is_default' => !empty($address['isMainAddress']) ? 1 : 0,

					'created_at' => date('Y-m-d H:i:s'),

					'updated_at' => date('Y-m-d H:i:s'),

				];



				$this->db->insert('customer_addresses', $address_data);

			}

		}



		// Commit atau rollback transaksi

		if ($this->db->trans_status() === FALSE) {

			$this->db->trans_rollback();

			$this->session->set_flashdata('error', 'Gagal menyimpan data customer.');

		} else {

			$this->db->trans_commit();

			$this->session->set_flashdata('success', 'Customer berhasil ditambahkan.');

		}



		redirect('admin/customers/manage');

	}





	public function update_customer()

	{

		$this->load->model('customer_m');

		$customer_id = $this->input->post('customer_id', true);

		$email = $this->input->post('customer_email', true);



		// Cek apakah email sudah digunakan oleh customer lain

		$existing_customer = $this->db->where('email', $email)

			->where('id_customers !=', $customer_id)

			->get('customers')

			->row();



		if ($existing_customer) {

			$this->session->set_flashdata('message_type', 'error');

			$this->session->set_flashdata('message', 'Email sudah digunakan oleh customer lain.');

			redirect(base_url('admin/customers/detail/' . $customer_id));

			return;

		}



		$this->db->trans_start();

		$province_id = (int) $this->input->post('province_id', true);

		$district_id = (int) $this->input->post('district_id', true);

		$subdistrict_id = (int) $this->input->post('subdistrict_id', true);

		$shipping_province = $this->get_province_name($province_id);

		$shipping_district = $this->get_district_name($district_id);

		$shipping_subdistrict = $this->get_subdistrict_name($subdistrict_id);



		try {

			$data = [

				'name' => $this->input->post('customer_name', true),

				'email' => $this->input->post('customer_email', true),

				'phone' => $this->input->post('customer_phone', true),

				'birthday' => $this->input->post('customer_birthdate', true),

				'sex_type' => $this->input->post('customer_gender', true),

				'recipient_name' => $this->input->post('customer_name', true),

				'shipping_name' => $this->input->post('customer_name', true),

				'shipping_address' => $this->input->post('customer_address', true),

				'shipping_id_province' => $province_id,

				'shipping_id_district' => $district_id,

				'shipping_id_subdistrict' => $subdistrict_id,

				'shipping_province' => $shipping_province,

				'shipping_district' => $shipping_district,

				'shipping_subdistrict' => $shipping_subdistrict,

				'shipping_country' => 'Indonesia',

				'shipping_phone' => $this->input->post('customer_phone', true),

				'refferal' => $this->input->post('customer_ref', true),

			];



			// Jika password diisi, update password

			$password = $this->input->post('customer_password', true);

			if (!empty($password)) {

				$data['password'] = $this->customer_m->hash($password);

			}



			// Update data customer berdasarkan ID

			$this->db->where('id_customers', $customer_id);

			$this->db->update('customers', $data);



			if ($this->db->trans_status() === false) {

				throw new Exception('Database error occurred');

			}



			$this->db->trans_commit();



			// Set flashdata dan redirect

			$this->session->set_flashdata('message_type', 'success');

			$this->session->set_flashdata('message', 'Data customer berhasil diperbarui!');

			redirect(base_url('admin/customers/manage'));

		} catch (Exception $e) {

			$this->db->trans_rollback();



			// Set flashdata untuk error dan redirect

			$this->session->set_flashdata('message_type', 'error');

			$this->session->set_flashdata('message', $e->getMessage());

			redirect(base_url('admin/customers/detail/' . $customer_id));

		}

	}



	// Fetch customer data

	public function get_customers()

	{

		$sort = $this->input->get('sort', true);

		$dateFilter = $this->input->get('date_filter', true);

		$startDate = $this->input->get('start_date', true);

		$endDate = $this->input->get('end_date', true);



		$isMale = filter_var($this->input->get('isMale', true), FILTER_VALIDATE_BOOLEAN);

		$isFemale = filter_var($this->input->get('isFemale', true), FILTER_VALIDATE_BOOLEAN);

		$isOther = filter_var($this->input->get('isOther', true), FILTER_VALIDATE_BOOLEAN);



		$bornJan = filter_var($this->input->get('bornJan', true), FILTER_VALIDATE_BOOLEAN);

		$bornFeb = filter_var($this->input->get('bornFeb', true), FILTER_VALIDATE_BOOLEAN);

		$bornMar = filter_var($this->input->get('bornMar', true), FILTER_VALIDATE_BOOLEAN);

		$bornApr = filter_var($this->input->get('bornApr', true), FILTER_VALIDATE_BOOLEAN);

		$bornMay = filter_var($this->input->get('bornMay', true), FILTER_VALIDATE_BOOLEAN);

		$bornJun = filter_var($this->input->get('bornJun', true), FILTER_VALIDATE_BOOLEAN);

		$bornJul = filter_var($this->input->get('bornJul', true), FILTER_VALIDATE_BOOLEAN);

		$bornAug = filter_var($this->input->get('bornAug', true), FILTER_VALIDATE_BOOLEAN);

		$bornSep = filter_var($this->input->get('bornSep', true), FILTER_VALIDATE_BOOLEAN);

		$bornOct = filter_var($this->input->get('bornOct', true), FILTER_VALIDATE_BOOLEAN);

		$bornNov = filter_var($this->input->get('bornNov', true), FILTER_VALIDATE_BOOLEAN);

		$bornDec = filter_var($this->input->get('bornDec', true), FILTER_VALIDATE_BOOLEAN);



		$page = (int) ($this->input->get('page', true) ?? 1);

		$limit = (int) ($this->input->get('limit', true) ?? 10);

		$offset = ($page - 1) * $limit;



		$searchTerm = $this->input->get('search', true);



		// Build main query

		$this->db->select('

			c.id_customers,

			c.name,

			c.title,

			c.sex_type,

			c.email,

			c.birthday,

			c.shipping_address as address,

			c.shipping_phone as phone,

			c.join_date,

			c.shipping_province,

			c.shipping_district,

			c.shipping_subdistrict,

			c.shipping_country,

			c.shipping_postcode,

			c.current_pointreward,

			c.status,

			COUNT(CASE WHEN o.payment_status = 5 THEN o.id_orders ELSE NULL END) as total_orders,

			SUM(CASE WHEN o.payment_status = 5 THEN o.grand_total_amount ELSE 0 END) as total_spent

		');

		$this->db->from('customers c');

		$this->db->join('orders o', 'c.id_customers = o.customer_id', 'left');

		$this->db->where_not_in('c.id_customers', [2615, 815, 2796, 21, 1427, 2283, 2538, 2496, 2768]);

		$this->db->where('(c.reseller_id IS NULL OR c.reseller_id = "")');

		$this->db->where('c.type', 'regular');



		// Filter berdasarkan jenis kelamin

		if ($isMale || $isFemale || $isOther) {

			$sexTypes = [];



			if ($isMale) {

				$sexTypes[] = 'male';

			}

			if ($isFemale) {

				$sexTypes[] = 'female';

			}

			if ($isOther) {

				$sexTypes[] = 'others';

			}



			if (!empty($sexTypes)) {

				$this->db->where_in('c.sex_type', $sexTypes);

			}

		}



		// Filter berdasarkan bulan lahir

		if (

			$bornJan || $bornFeb || $bornMar || $bornApr || $bornMay || $bornJun ||

			$bornJul || $bornAug || $bornSep || $bornOct || $bornNov || $bornDec

		) {



			$months = [];



			if ($bornJan) $months[] = '01';

			if ($bornFeb) $months[] = '02';

			if ($bornMar) $months[] = '03';

			if ($bornApr) $months[] = '04';

			if ($bornMay) $months[] = '05';

			if ($bornJun) $months[] = '06';

			if ($bornJul) $months[] = '07';

			if ($bornAug) $months[] = '08';

			if ($bornSep) $months[] = '09';

			if ($bornOct) $months[] = '10';

			if ($bornNov) $months[] = '11';

			if ($bornDec) $months[] = '12';



			if (!empty($months)) {

				$this->db->group_start();

				foreach ($months as $month) {

					$this->db->or_like('c.birthday', '-' . $month . '-');

				}

				$this->db->group_end();

			}

		}



		// Filter berdasarkan tanggal join

		if ($dateFilter) {

			switch ($dateFilter) {

				case 'today':

					$this->db->where('DATE(c.join_date) = CURDATE()');

					break;

				case 'yesterday':

					$this->db->where('DATE(c.join_date) = DATE_SUB(CURDATE(), INTERVAL 1 DAY)');

					break;

				case 'last7days':

					$this->db->where('c.join_date >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)');

					break;

				case 'last30days':

					$this->db->where('c.join_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)');

					break;

				case 'thisMonth':

					$this->db->where('MONTH(c.join_date) = MONTH(CURDATE()) AND YEAR(c.join_date) = YEAR(CURDATE())');

					break;

				case 'thisYear':

					$this->db->where('YEAR(c.join_date) = YEAR(CURDATE())');

					break;

				case 'custom':

					if ($startDate && $endDate) {

						$startDate = date('Y-m-d', strtotime($startDate));

						$endDate = date('Y-m-d', strtotime($endDate));

						if ($startDate && $endDate) {

							$this->db->where('DATE(c.join_date) >=', $startDate);

							$this->db->where('DATE(c.join_date) <=', $endDate);

						}

					}

					break;

			}

		}



		if (!empty($searchTerm)) {

			$this->db->group_start();

			$this->db->like('c.name', $searchTerm);

			$this->db->like('c.recipient_name', $searchTerm);

			$this->db->or_like('c.sex_type', $searchTerm);

			$this->db->or_like('c.email', $searchTerm);

			$this->db->or_like('c.address', $searchTerm);

			$this->db->or_like('c.shipping_address', $searchTerm);

			$this->db->or_like('c.shipping_province', $searchTerm);

			$this->db->or_like('c.shipping_district', $searchTerm);

			$this->db->or_like('c.shipping_subdistrict', $searchTerm);

			$this->db->or_like('c.shipping_phone', $searchTerm);



			// Untuk bulan lahir, perlu logika ekstra

			// Mari coba pencocokan dengan nama bulan (January, February, dll.)

			$monthMap = [

				'january' => '01',

				'februari' => '02',

				'march' => '03',

				'april' => '04',

				'may' => '05',

				'june' => '06',

				'july' => '07',

				'august' => '08',

				'september' => '09',

				'october' => '10',

				'november' => '11',

				'december' => '12'

			];



			$lowerSearchTerm = strtolower($searchTerm);

			foreach ($monthMap as $monthName => $monthNum) {

				if (strpos($monthName, $lowerSearchTerm) !== false) {

					$this->db->or_like('c.birthday', '-' . $monthNum . '-');

				}

			}



			$this->db->group_end();

		}



		// Group by untuk menghindari duplikasi data customer

		$this->db->group_by('c.id_customers');



		// Apply sorting

		if ($sort) {

			switch ($sort) {

				case 'paling_baru':

					$this->db->order_by('c.join_date', 'DESC');

					break;

				case 'paling_lama':

					$this->db->order_by('c.join_date', 'ASC');

					break;

				case 'royal':

					$this->db->order_by('total_spent', 'DESC');

					break;

				case 'loyal':

					$this->db->order_by('total_orders', 'DESC');

					break;

				default:

					// Default sort by newest

					$this->db->order_by('c.join_date', 'DESC');

			}

		} else {

			// Default sort by newest join date

			$this->db->order_by('c.join_date', 'DESC');

		}



		// Apply pagination

		$this->db->limit($limit, $offset);



		// Execute query

		$query = $this->db->get();

		$all_customers = $query->result();



		// Post-processing data

		foreach ($all_customers as $customer) {

			// Format tanggal

			$customer->join_date_formatted = date('d M Y H:i', strtotime($customer->join_date));



			// Format birthday jika ada

			if (!empty($customer->birthday) && strtotime($customer->birthday)) {

				$customer->birthday_formatted = date('d M Y', strtotime($customer->birthday));

				$customer->birth_month = date('F', strtotime($customer->birthday));



				$birthDate = new DateTime($customer->birthday);

				$today = new DateTime();

				$age = $today->diff($birthDate)->y;

				$customer->age = $age;

			} else {

				$customer->birthday_formatted = 'Not set';

				$customer->birth_month = 'Unknown';

				$customer->age = null;

			}



			// Format sex_type untuk tampilan

			switch ($customer->sex_type) {

				case 'male':

					$customer->sex_type_text = 'Male';

					$customer->sex_type_class = 'bg-blue-100 text-blue-700 px-2 py-1 rounded';

					break;

				case 'female':

					$customer->sex_type_text = 'Female';

					$customer->sex_type_class = 'bg-pink-100 text-pink-700 px-2 py-1 rounded';

					break;

				case 'other':

					$customer->sex_type_text = 'Other';

					$customer->sex_type_class = 'bg-purple-100 text-purple-700 px-2 py-1 rounded';

					break;

				default:

					$customer->sex_type_text = 'Not specified';

					$customer->sex_type_class = 'bg-gray-100 text-gray-700 px-2 py-1 rounded';

			}



			// Format status

			if ($customer->status == 1) {

				$customer->status_text = 'Active';

				$customer->status_class = 'bg-green-100 text-green-700 px-2 py-1 rounded';

			} else {

				$customer->status_text = 'Inactive';

				$customer->status_class = 'bg-red-100 text-red-700 px-2 py-1 rounded';

			}



			// Tambahkan informasi alamat lengkap

			$customer->full_address = trim($customer->address);



			if (!empty($customer->subdistrict)) {

				$customer->full_address .= ', ' . $customer->subdistrict;

			}



			if (!empty($customer->district)) {

				$customer->full_address .= ', ' . $customer->district;

			}



			if (!empty($customer->province)) {

				$customer->full_address .= ', ' . $customer->province;

			}



			if (!empty($customer->country)) {

				$customer->full_address .= ', ' . $customer->country;

			}



			if (!empty($customer->postcode)) {

				$customer->full_address .= ' ' . $customer->postcode;

			}



			// Default jika tidak ada order

			if ($customer->total_orders === null) {

				$customer->total_orders = 0;

				$customer->total_spent = 0;

			}



			// Format total spent

			$customer->total_spent_formatted = 'Rp ' . number_format($customer->total_spent, 0, ',', '.');

		}



		// Get total number of customers (for pagination)

		$this->db->select('COUNT(DISTINCT c.id_customers) as total');

		$this->db->from('customers c');



		// Apply the same filters for counting

		if ($isMale || $isFemale || $isOther) {

			$sexTypes = [];



			if ($isMale) {

				$sexTypes[] = 'male';

			}

			if ($isFemale) {

				$sexTypes[] = 'female';

			}

			if ($isOther) {

				$sexTypes[] = 'other';

			}



			if (!empty($sexTypes)) {

				$this->db->where_in('c.sex_type', $sexTypes);

			}

		}



		// Filter berdasarkan bulan lahir untuk counting

		if (

			$bornJan || $bornFeb || $bornMar || $bornApr || $bornMay || $bornJun ||

			$bornJul || $bornAug || $bornSep || $bornOct || $bornNov || $bornDec

		) {



			$months = [];



			if ($bornJan) $months[] = '01';

			if ($bornFeb) $months[] = '02';

			if ($bornMar) $months[] = '03';

			if ($bornApr) $months[] = '04';

			if ($bornMay) $months[] = '05';

			if ($bornJun) $months[] = '06';

			if ($bornJul) $months[] = '07';

			if ($bornAug) $months[] = '08';

			if ($bornSep) $months[] = '09';

			if ($bornOct) $months[] = '10';

			if ($bornNov) $months[] = '11';

			if ($bornDec) $months[] = '12';



			if (!empty($months)) {

				$this->db->group_start();

				foreach ($months as $month) {

					$this->db->or_like('c.birthday', '-' . $month . '-');

				}

				$this->db->group_end();

			}

		}



		// Filter berdasarkan tanggal join untuk counting

		if ($dateFilter) {

			switch ($dateFilter) {

				case 'today':

					$this->db->where('DATE(c.join_date) = CURDATE()');

					break;

				case 'yesterday':

					$this->db->where('DATE(c.join_date) = DATE_SUB(CURDATE(), INTERVAL 1 DAY)');

					break;

				case 'last7days':

					$this->db->where('c.join_date >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)');

					break;

				case 'last30days':

					$this->db->where('c.join_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)');

					break;

				case 'thisMonth':

					$this->db->where('MONTH(c.join_date) = MONTH(CURDATE()) AND YEAR(c.join_date) = YEAR(CURDATE())');

					break;

				case 'thisYear':

					$this->db->where('YEAR(c.join_date) = YEAR(CURDATE())');

					break;

				case 'custom':

					if ($startDate && $endDate) {

						$startDate = date('Y-m-d', strtotime($startDate));

						$endDate = date('Y-m-d', strtotime($endDate));

						if ($startDate && $endDate) {

							$this->db->where('DATE(c.join_date) >=', $startDate);

							$this->db->where('DATE(c.join_date) <=', $endDate);

						}

					}

					break;

			}

		}



		$count_query = $this->db->get();

		$count_result = $count_query->row();

		$total_customers = $count_result->total;



		// Prepare pagination info

		$total_pages = ceil($total_customers / $limit);



		$pagination = [

			'current_page' => $page,

			'total_pages' => $total_pages,

			'total_records' => $total_customers,

			'limit' => $limit

		];



		foreach ($all_customers as $customer) {

			$customer->_pagination = $pagination;

		}



		// Return JSON response langsung dari all_customers

		echo json_encode($all_customers);

	}



	public function get_province_name($id)

	{

		return $this->db->select('province')

			->where('rajaongkir_province_id', $id)

			->get('indonesia_provinces')

			->row('province');

	}



	public function get_district_name($id)

	{

		return $this->db->select('district')

			->where('rajaongkir_id_district', $id)

			->get('indonesia_districts')

			->row('district');

	}



	public function get_subdistrict_name($id)

	{

		return $this->db->select('subdistrict')

			->where('rajaongkir_id_subdistrict', $id)

			->get('indonesia_subdistricts')

			->row('subdistrict');

	}

	public function getShippingAddress()

	{

		$customer_id = $this->input->get('customer_id');



		$customer = $this->customer_m->fetch_customer_by_id($customer_id);



		if ($customer) {

			echo json_encode([

				'shipping_id_subdistrict' => $customer->shipping_id_subdistrict,

				'shipping_address' => $customer->shipping_address,

				'shipping_subdistrict' => $customer->shipping_subdistrict,

				'shipping_district' => $customer->shipping_district,

				'shipping_province' => $customer->shipping_province,

				'shipping_phone' => $customer->shipping_phone,

				'id_subdistrict' => $customer->id_subdistrict,

				'address' => $customer->address,

				'subdistrict' => $customer->subdistrict,

				'district' => $customer->district,

				'province' => $customer->province,

				'phone' => $customer->phone,

				'email' => $customer->email,

				'name' => $customer->name,

				'id_customers' => $customer->id_customers

			]);

		} else {

			echo json_encode([

				'shipping_address' => ''

			]);

		}

	}



	public function getCustomerAddresses()

	{

		$customer_id = $this->input->get('customer_id');



		// Get customer data

		$customer = $this->customer_m->fetch_customer_by_id($customer_id);



		if ($customer) {

			// Get customer addresses using your new method

			$addresses = $this->customer_m->get_customer_addresses($customer_id);



			if ($addresses && count($addresses) > 0) {

				echo json_encode([

					'success' => true,

					'customer' => [

						'id_customers' => $customer->id_customers,

						'name' => $customer->name,

						'email' => $customer->email

					],

					'addresses' => $addresses

				]);

			} else {

				echo json_encode([

					'success' => false,

					'message' => 'No addresses found',

					'customer' => [

						'id_customers' => $customer->id_customers,

						'name' => $customer->name,

						'email' => $customer->email

					],

					'addresses' => []

				]);

			}

		} else {

			echo json_encode([

				'success' => false,

				'message' => 'Customer not found',

				'addresses' => []

			]);

		}

	}



	private function getProvinces()

	{

		return $this->db->select('rajaongkir_province_id as id, province as name')

			->from('indonesia_provinces')

			->order_by('province', 'ASC')

			->get()

			->result();

	}



	// AJAX For Frontend

	public function getDistricts()

	{

		$this->output->set_content_type('application/json');



		$provinceId = $this->input->post('province_id');



		if (!$provinceId) {

			$response = [

				'status' => 'error',

				'message' => 'Province ID is required',

				'data' => [],

				'csrf_token' => $this->security->get_csrf_hash()

			];

			$this->output->set_output(json_encode($response));

			return;

		}



		$districts = $this->getDistrictsByProvince($provinceId);



		$response = [

			'status' => 'success',

			'message' => 'Districts retrieved successfully',

			'data' => $districts,

			'csrf_token' => $this->security->get_csrf_hash()

		];



		$this->output->set_output(json_encode($response));

	}



	public function getSubdistricts()

	{

		$this->output->set_content_type('application/json');



		$districtId = $this->input->post('district_id');

		if (!$districtId) {

			$response = [

				'status' => 'error',

				'message' => 'District ID is required',

				'data' => [],

				'csrf_token' => $this->security->get_csrf_hash()

			];

			$this->output->set_output(json_encode($response));

			return;

		}



		$subdistricts = $this->getSubdistrictsByDistrict($districtId);



		$response = [

			'status' => 'success',

			'message' => 'Subdistricts retrieved successfully',

			'data' => $subdistricts,

			'csrf_token' => $this->security->get_csrf_hash()

		];



		$this->output->set_output(json_encode($response));

	}



	private function getDistrictsByProvince($provinceId)

	{

		if (!$provinceId) return [];



		return $this->db->select('rajaongkir_id_district as id, district as name')

			->from('indonesia_districts')

			->where('indonesia_id_province', $provinceId)

			->order_by('district', 'ASC')

			->get()

			->result();

	}



	private function getSubdistrictsByDistrict($districtId)

	{

		if (!$districtId) return [];



		return $this->db->select('rajaongkir_id_subdistrict as id, subdistrict as name')

			->from('indonesia_subdistricts')

			->where('indonesia_id_district', $districtId)

			->order_by('subdistrict', 'ASC')

			->get()

			->result();

	}



	public function check_email()

	{

		// Hanya terima POST request

		if ($this->input->method() !== 'post') {

			$this->output

				->set_status_header(405)

				->set_output(json_encode([

					'status' => 'error',

					'message' => 'Method not allowed'

				]));

			return;

		}



		// Cek apakah request dari AJAX

		if (!$this->input->is_ajax_request()) {

			$this->output

				->set_status_header(400)

				->set_output(json_encode([

					'status' => 'error',

					'message' => 'AJAX request required'

				]));

			return;

		}



		try {

			$email = $this->input->post('email');



			if (!$email) {

				$this->output

					->set_status_header(400)

					->set_output(json_encode([

						'status' => 'error',

						'message' => 'Email parameter required'

					]));

				return;

			}



			$email = trim($email);



			// Validasi format email

			if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {

				$this->output

					->set_status_header(400)

					->set_output(json_encode([

						'status' => 'error',

						'message' => 'Invalid email format'

					]));

				return;

			}



			// Cek ke database apakah email sudah ada

			$is_email_exists = $this->_check_email_exists($email);



			// Response

			$response = [

				'status' => 'success',

				'email' => $email,

				'available' => !$is_email_exists,

				'message' => $is_email_exists ? 'Email sudah digunakan' : 'Email tersedia',

				'timestamp' => date('Y-m-d H:i:s')

			];



			$this->output

				->set_status_header(200)

				->set_output(json_encode($response));

		} catch (Exception $e) {

			// Log error

			log_message('error', 'Email check error: ' . $e->getMessage());



			$this->output

				->set_status_header(500)

				->set_output(json_encode([

					'status' => 'error',

					'message' => 'Internal server error'

				]));

		}

	}



	private function _check_email_exists($email)

	{

		$this->db->where('email', $email);

		$query = $this->db->get('customers');



		return $query->num_rows() > 0;

	}



	//this is to list all customers

	public function index()

	{



		/*----FILTER SEARCH PRODUCT--*/

		$this->data['search_by'] = 'by_name';

		if (isset($_POST['search_customer'])) {



			//get product name from form

			$this->data['keyword'] = $this->security->xss_clean($this->input->post('customer'));

			$this->data['search_by'] = $this->security->xss_clean($this->input->post('search_by'));



			$flash_search_by = '';

			//get all customers

			// $this->db->select('*,TIMESTAMPDIFF(YEAR, birthday, CURDATE()) AS age');

			// $this->db->from('customers');

			if ($this->data['search_by'] == 'by_name') {

				$this->db->select('*,TIMESTAMPDIFF(YEAR, birthday, CURDATE()) AS age');

				$this->db->from('customers');

				$this->db->like('name', $this->data['keyword']);

				$flash_search_by = 'Pencarian dengan Nama : ' . $this->data['keyword'];

			} else if ($this->data['search_by'] == 'by_email') {

				$this->db->select('*,TIMESTAMPDIFF(YEAR, birthday, CURDATE()) AS age');

				$this->db->from('customers');

				$this->db->like('email', $this->data['keyword']);

				$flash_search_by = 'Pencarian dengan Email : ' . $this->data['keyword'];

			} else if ($this->data['search_by'] == 'by_gender') {

				$this->db->select('*,TIMESTAMPDIFF(YEAR, birthday, CURDATE()) AS age');

				$this->db->from('customers');

				$this->db->where('sex_type', $this->data['keyword']);

				$flash_search_by = 'Pencarian dengan Gender : ' . $this->data['keyword'];

			} else if ($this->data['search_by'] == 'by_age') {

				$this->db->select('*,TIMESTAMPDIFF(YEAR, birthday, CURDATE()) AS age');

				$this->db->from('customers');

				$this->db->where('TIMESTAMPDIFF(YEAR, birthday, CURDATE()) = ', (int) $this->data['keyword']);

				$flash_search_by = 'Pencarian dengan Umur : ' . $this->data['keyword'];

			} else if ($this->data['search_by'] == 'by_product') {

				$this->db->select('orders_id , orders.customer_id, customers.* ,TIMESTAMPDIFF(YEAR, customers.birthday, CURDATE()) AS age');

				$this->db->from('orders_detail , orders, customers');

				$this->db->where('orders.customer_id = customers.id_customers and orders_detail.orders_id = orders.id_orders');

				$this->db->where('product_id', $this->data['keyword']);

				$flash_search_by = 'Pencarian User yang pernah membeli produk id : ' . $this->data['keyword'];

			} else if ($this->data['search_by'] == 'by_phone') {

				$this->db->select('*,TIMESTAMPDIFF(YEAR, birthday, CURDATE()) AS age');

				$this->db->from('customers');

				$this->db->like('phone', $this->data['keyword']);

				$flash_search_by = 'Pencarian dengan Nomor Telepon : ' . $this->data['keyword'];

			} else if ($this->data['search_by'] == 'by_birth_month') {

				$this->db->select('*, TIMESTAMPDIFF(YEAR, birthday, CURDATE()) AS age');

				$this->db->from('customers');

				$this->db->where('MONTH(birthday)', $this->data['keyword']);

				$flash_search_by = 'Pencarian berdasarkan Bulan Lahir: ' . $this->data['keyword'];

			} else if ($this->data['search_by'] == 'by_birth_year') {

				$this->db->select('*, TIMESTAMPDIFF(YEAR, birthday, CURDATE()) AS age');

				$this->db->from('customers');

				$this->db->where('YEAR(birthday)', $this->data['keyword']);

				$flash_search_by = 'Pencarian berdasarkan Tahun Lahir: ' . $this->data['keyword'];

			}

			$this->db->order_by('join_date', 'DESC');

			$this->data['customers'] = $this->db->get()->result();



			$this->session->set_flashdata('flash_search_by', '<br><p style="background:green; color:white; padding:3px; font-weight:bold;">' . $flash_search_by . '</p>');

		} else {



			$this->load->helper('pagination_helper');

			add_pagination(base_url() . 'admin/customers/index', $this->customer_m->record_count(), 100, 4);



			//fetch all customers

			$this->data['customers'] = $this->customer_m->get_all_customers(100, $this->uri->segment(4));

			$this->data['use_pagination'] = 'yes';

		}



		//load view

		$this->data['subview'] = 'admin/customers/index';

		$this->load->view('admin/templates/header', $this->data_header);

		$this->load->view('admin/_layout_main', $this->data);

		$this->load->view('admin/templates/footer');

	}



	public function search_customer()

	{

		$query = $this->input->get('query');

		$this->db->like('name', $query);

		$this->db->or_like('email', $query);

		$this->db->or_like('birthday', $query);

		$this->db->or_like('sex_type', $query);

		$this->db->or_like('phone', $query);

		$this->db->or_like('address', $query);

		$customers = $this->db->get('customers')->result();



		$result = [];



		foreach ($customers as $customer) {

			$customer->name = !empty($customer->name) ? $customer->name : '';

			$customer->email = !empty($customer->email) ? $customer->email : '';

			$customer->birthday = !empty($customer->birthday) ? $customer->birthday : '';

			$customer->sex_type = !empty($customer->sex_type) ? $customer->sex_type : '';

			$customer->phone = !empty($customer->phone) ? $customer->phone : '';

			$customer->address = !empty($customer->address) ? $customer->address : '';



			if (!empty($customer->birthday) && strtotime($customer->birthday)) {

				try {

					$birthday = new DateTime($customer->birthday);

					$today = new DateTime();

					$age = $today->diff($birthday)->y;

					$customer->age = $age;

				} catch (Exception $e) {



					$customer->age = '';

				}

			} else {

				$customer->age = '';

			}



			$total_purchase = 0;

			$this->db->select('*')

				->from('orders')

				->where('customer_id', $customer->id_customers)

				->group_start()

				->where_in('payment_status', [3, 4, 5])

				->group_end();

			$purchases = $this->db->get()->result();



			foreach ($purchases as $purchase) {

				$grand_total = (($purchase->total_amount - $purchase->redeemed_voucher_amount - $purchase->minus_reward_amount) + ($purchase->shipping_fee - $purchase->free_shipping_fee));

				if ($grand_total > 0) {

					$total_purchase += $grand_total;

				}

			}



			// Add total purchase to the customer data

			$customer->total_purchase = !empty($total_purchase) ? number_format($total_purchase) : 0;



			$result[] = $customer;

		}



		echo json_encode($result);

	}



	public function get_address($address_id)

	{

		// Set JSON response header

		$this->output->set_content_type('application/json');



		try {

			// Validate address ID

			if (!$address_id || !is_numeric($address_id)) {

				$this->output->set_output(json_encode([

					'success' => false,

					'message' => 'ID alamat tidak valid'

				]));

				return;

			}



			// Get address data from database

			$address = $this->customer_m->get_address_by_id($address_id);



			if (!$address) {

				$this->output->set_output(json_encode([

					'success' => false,

					'message' => 'Alamat tidak ditemukan'

				]));

				return;

			}



			// Clean phone number

			if ($address->phone && strpos($address->phone, '+62') === 0) {

				$address->phone = substr($address->phone, 3);

			} elseif ($address->phone && strpos($address->phone, '62') === 0) {

				$address->phone = substr($address->phone, 2);

			}



			// Validate and sanitize coordinates

			$latitude = isset($address->latitude) ? floatval($address->latitude) : null;

			$longitude = isset($address->longitude) ? floatval($address->longitude) : null;



			if (

				empty($latitude) || empty($longitude) ||

				!is_finite($latitude) || !is_finite($longitude) ||

				$latitude < -90 || $latitude > 90 ||

				$longitude < -180 || $longitude > 180

			) {



				log_message('warning', "Invalid coordinates for address ID {$address_id}: lat={$latitude}, lng={$longitude}");



				$address->latitude = -6.229434;

				$address->longitude = 106.853123;

			} else {

				$address->latitude = $latitude;

				$address->longitude = $longitude;

			}



			$this->output->set_output(json_encode([

				'success' => true,

				'address' => $address

			]));

		} catch (Exception $e) {

			log_message('error', 'Error getting address: ' . $e->getMessage());

			$this->output->set_output(json_encode([

				'success' => false,

				'message' => 'Terjadi kesalahan server'

			]));

		}

	}



	public function save_address()

	{

		// Set response header untuk JSON

		$this->output->set_content_type('application/json');



		// Validasi request method

		if ($this->input->server('REQUEST_METHOD') !== 'POST') {

			$response = array(

				'success' => false,

				'message' => 'Method not allowed'

			);

			$this->output->set_output(json_encode($response));

			return;

		}



		// Ambil data dari POST

		$customer_id = $this->input->post('customerId');

		$label = $this->input->post('label');

		$recipient_name = $this->input->post('receiverName');

		$phone = $this->input->post('receiverPhone');

		$address = $this->input->post('fullAddress');

		$notes = $this->input->post('notes');

		$latitude = $this->input->post('latitude');

		$longitude = $this->input->post('longitude');

		$province = $this->input->post('province');

		$city = $this->input->post('city');

		$district_name = $this->input->post('district');

		$subdistrict_name = $this->input->post('subdistrict');

		$postal_code = $this->input->post('postalCode');

		$is_main_address = $this->input->post('isMainAddress') === 'true' ? 1 : 0;



		// Validasi required fields

		if (

			empty($label) || empty($recipient_name) || empty($phone) || empty($address) ||

			empty($city) || empty($district_name) || empty($subdistrict_name) || empty($postal_code)

		) {

			$response = array(

				'success' => false,

				'message' => 'Semua field wajib harus diisi'

			);

			$this->output->set_output(json_encode($response));

			return;

		}



		$district = $this->find_district($district_name);

		$subdistrict = $this->find_subdistrict($subdistrict_name);



		// Start transaction

		$this->db->trans_start();



		// Jika ini adalah alamat utama, set alamat lain menjadi tidak utama

		if ($is_main_address) {

			$this->db->where('customer_id', $customer_id)

				->update('customer_addresses', array('is_default' => 0));

		}



		$lat_value = null;

		$lng_value = null;



		if (!empty($latitude) && is_numeric($latitude) && $latitude != '0') {

			$lat_value = (float) $latitude;

		}



		if (!empty($longitude) && is_numeric($longitude) && $longitude != '0') {

			$lng_value = (float) $longitude;

		}



		// Prepare data untuk insert

		$address_data = array(

			'customer_id' => $customer_id,

			'label' => $label,

			'recipient_name' => $recipient_name,

			'phone' => $phone,

			'address' => $address,

			'notes' => $notes,

			'latitude' => $lat_value,

			'longitude' => $lng_value,

			'province' => $province,

			'city' => $city,

			'district' => $district_name,

			'rajaongkir_district_id' => $district ? $district->rajaongkir_id_district : null,

			'subdistrict' => $subdistrict_name,

			'rajaongkir_subdistrict_id' => $subdistrict ? $subdistrict->rajaongkir_id_subdistrict : null,

			'postal_code' => $postal_code,

			'is_default' => $is_main_address,

			'created_at' => date('Y-m-d H:i:s'),

			'updated_at' => date('Y-m-d H:i:s')

		);



		// Insert data alamat

		$insert_result = $this->db->insert('customer_addresses', $address_data);



		// Complete transaction

		$this->db->trans_complete();



		// Check transaction status

		if ($this->db->trans_status() === FALSE || !$insert_result) {

			$response = array(

				'success' => false,

				'message' => 'Gagal menyimpan alamat. Silakan coba lagi.'

			);

		} else {

			$response = array(

				'success' => true,

				'message' => 'Alamat berhasil disimpan!',

				'address_id' => $this->db->insert_id()

			);

		}



		$this->output->set_output(json_encode($response));

	}



	public function update_address($id = null)

	{

		$this->output->set_content_type('application/json');



		if ($this->input->server('REQUEST_METHOD') !== 'POST') {

			$response = array(

				'success' => false,

				'message' => 'Method not allowed'

			);

			$this->output->set_output(json_encode($response));

			return;

		}



		if (empty($id) || !is_numeric($id)) {

			$response = array(

				'success' => false,

				'message' => 'ID alamat tidak valid'

			);

			$this->output->set_output(json_encode($response));

			return;

		}



		// Ambil data dari POST

		$customer_id = $this->input->post('customerId');

		$label = $this->input->post('label');

		$recipient_name = $this->input->post('receiverName');

		$phone = $this->input->post('receiverPhone');

		$address = $this->input->post('fullAddress');

		$notes = $this->input->post('notes');

		$latitude = $this->input->post('latitude');

		$longitude = $this->input->post('longitude');

		$province = $this->input->post('province');

		$city = $this->input->post('city');

		$district_name = $this->input->post('district');

		$subdistrict_name = $this->input->post('subdistrict');

		$postal_code = $this->input->post('postalCode');

		$is_main_address = $this->input->post('isMainAddress') === 'true' ? 1 : 0;



		// Validasi required fields

		if (

			empty($label) || empty($recipient_name) || empty($phone) || empty($address) ||

			empty($city) || empty($district_name) || empty($subdistrict_name) || empty($postal_code)

		) {

			$response = array(

				'success' => false,

				'message' => 'Semua field wajib harus diisi'

			);

			$this->output->set_output(json_encode($response));

			return;

		}



		$district = $this->find_district($district_name);

		$subdistrict = $this->find_subdistrict($subdistrict_name);



		$lat_value = null;

		$lng_value = null;



		if (!empty($latitude) && is_numeric($latitude) && $latitude != '0') {

			$lat_value = (float) $latitude;

		}



		if (!empty($longitude) && is_numeric($longitude) && $longitude != '0') {

			$lng_value = (float) $longitude;

		}



		// Mulai transaksi

		$this->db->trans_start();



		if ($is_main_address) {

			$this->db->where('customer_id', $customer_id)

				->update('customer_addresses', array('is_default' => 0));

		}



		$address_data = array(

			'label' => $label,

			'recipient_name' => $recipient_name,

			'phone' => $phone,

			'address' => $address,

			'notes' => $notes,

			'latitude' => $lat_value,

			'longitude' => $lng_value,

			'province' => $province,

			'city' => $city,

			'district' => $district_name,

			'rajaongkir_district_id' => $district ? $district->rajaongkir_id_district : null,

			'subdistrict' => $subdistrict_name,

			'rajaongkir_subdistrict_id' => $subdistrict ? $subdistrict->rajaongkir_id_subdistrict : null,

			'postal_code' => $postal_code,

			'is_default' => $is_main_address,

			'updated_at' => date('Y-m-d H:i:s')

		);



		$this->db->where('id', $id);

		$update_result = $this->db->update('customer_addresses', $address_data);



		$this->db->trans_complete();



		if ($this->db->trans_status() === FALSE || !$update_result) {

			$response = array(

				'success' => false,

				'message' => 'Gagal memperbarui alamat. Silakan coba lagi.'

			);

		} else {

			$response = array(

				'success' => true,

				'message' => 'Alamat berhasil diperbarui!',

				'address_id' => $id

			);

		}



		$this->output->set_output(json_encode($response));

	}





	public function set_default_address($id)

	{

		$customer_id = $this->input->post('customer_id');



		// Unset semua alamat default

		$this->customer_m->unset_default($customer_id);



		// Set alamat ini sebagai default

		$result = $this->customer_m->set_default($id, $customer_id);



		if ($result) {

			echo json_encode([

				'status' => 'success',

				'message' => 'Alamat berhasil dipilih'

			]);

		} else {

			echo json_encode([

				'status' => 'error',

				'message' => 'Gagal memilih alamat'

			]);

		}

	}



	private function normalize_region_name($name)

	{

		$name = strtolower(trim($name));



		$name = preg_replace('/^kota\s+/i', '', $name);

		$name = preg_replace('/^kabupaten\s+/i', '', $name);

		$name = preg_replace('/^kec(?:amatan)?\s+/i', '', $name);



		$name = preg_replace('/[^a-zA-Z0-9\s]/', '', $name);

		$name = preg_replace('/\s+/', ' ', $name);



		return trim($name);

	}



	private function generate_search_variations($name)

	{

		$normalized = $this->normalize_region_name($name);

		$variations = array();



		$variations[] = $normalized;



		$variations[] = str_replace(' ', '', $normalized);



		$variations[] = str_replace(' ', '_', $normalized);



		$original_clean = strtolower(trim($name));

		$variations[] = $original_clean;



		$variations = array_unique(array_filter($variations));



		return $variations;

	}



	private function find_district($district_name)

	{

		$variations = $this->generate_search_variations($district_name);



		foreach ($variations as $variation) {

			$safe_variation = $this->db->escape_str($variation);



			$district = $this->db

				->where('LOWER(district)', $safe_variation)

				->get('indonesia_districts')

				->row();



			if ($district) {

				return $district;

			}

		}



		foreach ($variations as $variation) {

			$safe_variation = $this->db->escape_str($variation);



			$this->db->where("LOWER(district) LIKE '%" . $safe_variation . "%'");

			$district = $this->db->get('indonesia_districts')->row();



			if ($district) {

				return $district;

			}



			$this->db->reset_query();

		}



		return null;

	}



	private function find_subdistrict($subdistrict_name)

	{

		$variations = $this->generate_search_variations($subdistrict_name);



		foreach ($variations as $variation) {

			$safe_variation = $this->db->escape_str($variation);



			$subdistrict = $this->db

				->where('LOWER(subdistrict)', $safe_variation)

				->get('indonesia_subdistricts')

				->row();



			if ($subdistrict) {

				return $subdistrict;

			}

		}



		foreach ($variations as $variation) {

			$safe_variation = $this->db->escape_str($variation);



			$this->db->where("LOWER(subdistrict) LIKE '%" . $safe_variation . "%'");

			$subdistrict = $this->db->get('indonesia_subdistricts')->row();



			if ($subdistrict) {

				return $subdistrict;

			}



			$this->db->reset_query();

		}



		return null;

	}



	// delete address by address id

	public function delete_address($id)

	{

		if (!$this->input->is_ajax_request()) {

			show_404();

		}



		$address = $this->customer_m->get_address_by_id($id);

		if (!$address) {

			return $this->output

				->set_content_type('application/json')

				->set_output(json_encode([

					'success' => false,

					'message' => 'Alamat tidak ditemukan.',

				]));

		}



		$customer_id = $address->customer_id;

		$this->customer_m->delete_address($id);



		if ($address->is_default == 1) {

			$new_default = $this->customer_m->get_other_address($customer_id, $id);

			if ($new_default) {

				$this->customer_m->set_default($new_default->id, $customer_id);

			}

		}



		return $this->output

			->set_content_type('application/json')

			->set_output(json_encode([

				'success' => true,

				'message' => 'Alamat berhasil dihapus.'

			]));

	}



	//callback function validation register new email

	public function cek_email($str)

	{



		$num_rows = $this->customer_m->cek_existing_email($str,  $this->customer_current_id);



		if ($num_rows != 0) {

			$this->form_validation->set_message('cek_email', 'Email already exist !');

			return FALSE;

		} else {

			return TRUE;

		}

	}

}


https://t.me/RX1948 - 2025