|
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 : |
<?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';
$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();
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_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' => []
]);
}
}
// 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)
) {
$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;
}
}
}