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'; $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; } } }