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 : /proc/self/root/var/www/laciasmara.com/public_html/shop/application/controllers/admin/ |
Upload File : |
<?php if (!defined('BASEPATH')) exit('No direct script access allowed'); class Products extends Admin_Controller { function __construct() { parent::__construct(); $this->load->model('product_m'); $this->load->model('category_m'); $this->load->model('configuration_m'); $this->load->model('brand_m'); $this->load->model('warehouse_m'); $this->load->model('product_attributes_m'); $this->load->helper('form'); } function index() { $data['userdata'] = $this->session->userdata(); $data['categories'] = $this->category_m->all_categories(); $data['brands'] = $this->brand_m->get_all_brands(); $data['title'] = 'Pengaturan Produk | Laciasmara'; $data['total_products'] = $this->product_m->count_products(); $data['active_products'] = $this->product_m->count_products(1); $data['inactive_products'] = $this->product_m->count_products(0); $this->load->view('admin_new/layouts/header', $data); $this->load->view('admin_new/products/manage_product'); $this->load->view('admin_new/layouts/footer'); } // Pages // Manage Product function manage() { $data['userdata'] = $this->session->userdata(); $data['categories'] = $this->category_m->all_categories(); $data['brands'] = $this->brand_m->get_all_brands(); $data['title'] = 'Pengaturan Produk | Laciasmara'; $data['total_products'] = $this->product_m->count_products(); $data['active_products'] = $this->product_m->count_products(1); $data['inactive_products'] = $this->product_m->count_products(0); $this->load->view('admin_new/layouts/header', $data); $this->load->view('admin_new/products/manage_product'); $this->load->view('admin_new/layouts/footer'); } // Add Product Page function add_product() { $data['userdata'] = $this->session->userdata(); $data['title'] = 'Tambah Produk | Laciasmara'; $data['brands'] = $this->brand_m->get_all_brands(); $data['categories'] = $this->category_m->all_categories(); $data['products'] = $this->product_m->all_products(); $data['productAttributes'] = $this->product_m->get_all_attributes(); $data['shippingMethods'] = $this->product_m->get_all_shipping_methods(); $this->load->view('admin_new/layouts/header', $data); $this->load->view('admin_new/products/add_product'); $this->load->view('admin_new/layouts/footer'); } // Edit Product Page public function edit_product($id_product = NULL) { if (!$id_product) { redirect('admin/products/manage-product'); } $data['userdata'] = $this->session->userdata(); $data['title'] = 'Ubah Produk | Laciasmara'; $data['brands'] = $this->brand_m->get_all_brands(); $data['categories'] = $this->category_m->all_categories(); $data['products'] = $this->product_m->all_products(); $data['productAttributes'] = $this->product_m->get_all_attributes(); $data['shippingMethods'] = $this->product_m->get_all_shipping_methods(); // Fetch data produk yang mau di ubah $data['product'] = $this->product_m->fetch_product_by_id($id_product); // Selected Category $product_categories = $this->product_m->fetch_product_categories($id_product); // Convert ke array, biar lebih gampang dipake $data['product_categories'] = array_map(function ($cat) { return $cat->id_category; }, $product_categories); // Selected Shipping Method $shipping_method = $this->product_m->fetch_product_shipping_methods($id_product); $data['shipping_methods'] = array_map(function ($ship) { return $ship->shipment_method_id; }, $shipping_method); // Product Reccomendation if ($data['product']->product_suggest) { $data['product_suggestions'] = explode(',', $data['product']->product_suggest); } else { $data['product_suggestions'] = []; } // Variant $data['product_variants'] = $this->product_m->fetch_product_variants($id_product); if (!$data['product']) { redirect('admin/products/manage-product'); } $this->load->view('admin_new/layouts/header', $data); $this->load->view('admin_new/products/edit_product'); $this->load->view('admin_new/layouts/footer'); } public function product_image($id_product = NULL) { if (!$id_product) { redirect('admin/products/manage-product'); } $product = $this->db->get_where('products', ['id_products' => $id_product])->row_array(); $product_name = $product ? $product['title'] : ''; $data['userdata'] = $this->session->userdata(); $data['title'] = 'Gambar Produk | Laciasmara'; $product_details = $this->product_m->fetch_product_details_by_id($id_product); $data['product_details'] = $product_details; $data['id_product'] = $id_product; $data['product_name'] = $product_name; $product_details_ids = array_column($product_details, 'id'); $product_images = $this->product_m->fetch_product_images_by_id_details($product_details_ids); $data['product_images'] = $product_images; $this->load->view('admin_new/layouts/header', $data); $this->load->view('admin_new/products/image_product'); $this->load->view('admin_new/layouts/footer'); } public function store_image($id_product) { $config['upload_path'] = './uploads/product/'; $config['allowed_types'] = 'jpg|jpeg|png|gif|webp'; $config['max_size'] = 1024; // 1MB $config['encrypt_name'] = TRUE; if (!is_dir($config['upload_path'])) { mkdir($config['upload_path'], 0777, TRUE); } $product = $this->db->get_where('products', ['id_products' => $id_product])->row_array(); $product_name = $product ? $product['title'] : ''; $this->load->library('upload', $config); $this->db->trans_begin(); try { $product_images = $_FILES['product_images'] ?? []; $deleted_images = $this->input->post('delete_images'); $existing_images = $this->input->post('existing_images'); // Ambil existing images dari form // **Step 1: Update Priority dari Existing Images** if (!empty($existing_images)) { foreach ($existing_images as $product_details_id => $images) { foreach ($images as $index => $image_id) { $this->db->where('id', $image_id); $this->db->update('product_images', [ 'title' => $product_name, // Tambahkan title 'title_en' => $product_name, // Tambahkan title_en 'alt' => $product_name, 'priority' => $index + 1, // Update priority sesuai index yang dikirim 'updated_at' => date('Y-m-d H:i:s') ]); } } } // **Step 2: Hapus Gambar Jika Ada Data delete_images[]** if (!empty($deleted_images)) { foreach ($deleted_images as $image_id) { $image = $this->db->get_where('product_images', ['id' => $image_id])->row_array(); if ($image) { $image_path = './uploads/product/' . $image['image']; if (file_exists($image_path)) { unlink($image_path); } $this->db->where('id', $image_id); $this->db->delete('product_images'); } } } // **Step 3: Proses Upload Gambar Baru** foreach ($product_images['name'] as $product_details_id => $images) { foreach ($images as $index => $file_name) { if (!empty($file_name)) { $_FILES['image']['name'] = $file_name; $_FILES['image']['type'] = $product_images['type'][$product_details_id][$index]; $_FILES['image']['tmp_name'] = $product_images['tmp_name'][$product_details_id][$index]; $_FILES['image']['error'] = $product_images['error'][$product_details_id][$index]; $_FILES['image']['size'] = $product_images['size'][$product_details_id][$index]; if ($this->upload->do_upload('image')) { $upload_data = $this->upload->data(); $image_name = $upload_data['file_name']; $this->db->insert('product_images', [ 'product_id' => $id_product, 'product_details_id' => $product_details_id, 'image' => $image_name, 'title' => $product_name, // Tambahkan title 'title_en' => $product_name, // Tambahkan title_en 'alt' => $product_name, 'priority' => $index + 1, // Priority sesuai index 'status' => 1, 'created_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s') ]); } else { throw new Exception($this->upload->display_errors('', '')); } } } } if ($this->db->trans_status() === FALSE) { throw new Exception('Database error.'); } $this->db->trans_commit(); $this->session->set_flashdata('message', 'Gambar produk berhasil diperbarui.'); $this->session->set_flashdata('message_type', 'success'); } catch (Exception $e) { $this->db->trans_rollback(); $this->session->set_flashdata('message', 'Gagal memperbarui gambar produk: ' . $e->getMessage()); $this->session->set_flashdata('message_type', 'error'); } redirect('admin/products/product-image/' . $id_product); } // Manage Variant function manage_variant() { $data['userdata'] = $this->session->userdata(); $data['title'] = 'Pengaturan Varian | Laciasmara'; $attributes = $this->product_m->get_all_attributes(); foreach ($attributes as &$attribute) { $values = $this->product_m->get_attribute_values($attribute->id); $attribute->value_count = count($values); // Simpan jumlah opsi $attribute->product_count = $this->product_m->count_products_by_attribute($attribute->id); } $data['product_attributes'] = $attributes; $this->load->view('admin_new/layouts/header', $data); $this->load->view('admin_new/variants/variant_product'); $this->load->view('admin_new/layouts/footer'); } // Add Variant Page function add_variant() { $data['userdata'] = $this->session->userdata(); $data['title'] = 'Tambah Varian | Laciasmara'; $this->load->view('admin_new/layouts/header', $data); $this->load->view('admin_new/variants/add_variant'); $this->load->view('admin_new/layouts/footer'); } // Edit Variant public function edit_variant($id_variant = NULL) { if (!$id_variant) { redirect('admin/products/variant-product'); } $data['userdata'] = $this->session->userdata(); $data['title'] = 'Ubah Produk | Laciasmara'; // Fetch data produk yang mau di ubah $data['product_attribute'] = $this->product_m->fetch_variant_by_id($id_variant); if (!$data['product_attribute']) { $this->session->set_flashdata('message', 'Atribut tidak ditemukan.'); $this->session->set_flashdata('message_type', 'error'); redirect('admin/products/variant-product'); } $this->load->view('admin_new/layouts/header', $data); $this->load->view('admin_new/variants/edit_variant'); $this->load->view('admin_new/layouts/footer'); } public function manage_variant_options($id_attribute = NULL) { if (!$id_attribute) { redirect('admin/products/variant-product'); } $data['userdata'] = $this->session->userdata(); $data['title'] = 'Ubah Opsi Atribut | Laciasmara'; $data['attribute_values'] = $this->product_m->get_attribute_values($id_attribute); $data['product_attribute'] = $this->product_m->fetch_variant_by_id($id_attribute); // if (!$data['attribute_values']) { // $this->session->set_flashdata('message', 'Opsi Atribut tidak ditemukan.'); // $this->session->set_flashdata('message_type', 'error'); // redirect('admin/products/variant-product'); // } $this->load->view('admin_new/layouts/header', $data); $this->load->view('admin_new/variants/edit_variant_values'); $this->load->view('admin_new/layouts/footer'); } // Stock function stock() { $data['userdata'] = $this->session->userdata(); $data['categories'] = $this->category_m->all_categories(); $data['brands'] = $this->brand_m->get_all_brands(); $data['warehouses'] = $this->warehouse_m->fetch_all_warehouses(); $data['title'] = 'Stok Produk | Laciasmara'; $data['total_products'] = $this->product_m->count_products(); $data['active_products'] = $this->product_m->count_products(1); $data['inactive_products'] = $this->product_m->count_products(0); $this->load->view('admin_new/layouts/header', $data); $this->load->view('admin_new/products/stock_product'); $this->load->view('admin_new/layouts/footer'); } function transfer_stock() { $data['userdata'] = $this->session->userdata(); $data['warehouses'] = $this->warehouse_m->fetch_all_warehouses(); $data['products'] = []; $data['shippingMethods'] = $this->product_m->get_all_shipping_methods(); $data['title'] = 'Transfer Stok | Laciasmara'; $this->load->view('admin_new/layouts/header', $data); $this->load->view('admin_new/products/transfer_stock'); $this->load->view('admin_new/layouts/footer'); } function list_transfer_stock() { $data['userdata'] = $this->session->userdata(); $data['warehouses'] = $this->warehouse_m->fetch_all_warehouses(); $data['products'] = []; $data['shippingMethods'] = $this->product_m->get_all_shipping_methods(); $data['title'] = 'Daftar Transfer Stok | Laciasmara'; $this->load->view('admin_new/layouts/header', $data); $this->load->view('admin_new/products/list_transfer_stock'); $this->load->view('admin_new/layouts/footer'); } function get_warehouse_products() { $warehouse_id = $this->input->post('warehouse_id'); if (!$warehouse_id) { echo json_encode(['error' => 'Warehouse ID is required']); return; } $products = $this->product_m->get_products_by_warehouse($warehouse_id); echo json_encode($products); } // Data // Fetch Product Data public function get_products() { // Ambil parameter GET dengan validasi dasar $tab = $this->input->get('tab', true); $isEmptyStockOnly = filter_var($this->input->get('isEmptyStockOnly', true), FILTER_VALIDATE_BOOLEAN); $isLowStock = filter_var($this->input->get('isLowStock', true), FILTER_VALIDATE_BOOLEAN); $isNewProduct = filter_var($this->input->get('isNewProduct', true), FILTER_VALIDATE_BOOLEAN); $isDiscounted = filter_var($this->input->get('isDiscounted', true), FILTER_VALIDATE_BOOLEAN); $isBestSelling = filter_var($this->input->get('isBestSelling', true), FILTER_VALIDATE_BOOLEAN); $brandId = $this->input->get('merk', true); $categoryId = $this->input->get('kategori', true); $sort = $this->input->get('sort', true); $searchTerm = $this->input->get('search', true); // Query utama untuk mendapatkan produk $this->db->select(' p.title, p.alias, p.product_status, p.id_products, p.created_at, p.updated_at, pd.id as product_detail_id, MIN(pd.price) as min_price, MAX(pd.price) as max_price, CASE WHEN COUNT(pd.id) > 1 THEN "-" ELSE MAX(pd.sku) END as sku, pi.image as image, s.stock as total_stock, b.brand as brand_title, COALESCE(od_count.total_sold, 0) as total_sold '); $this->db->from('products p'); $this->db->join('product_details pd', 'pd.product_id = p.id_products', 'left'); $this->db->join('stock s', 'pd.id = s.id_product_detail AND s.warehouse_id = 1', 'left'); $this->db->join('brands b', 'p.brand_id = b.id_brands', 'left'); $this->db->join('product_images pi', 'pi.product_details_id = pd.id AND pi.priority = 1 AND pi.status = 1', 'left'); $this->db->join('category_product cp', 'cp.id_product = p.id_products', 'left'); $this->db->join('( SELECT od.product_id, COUNT(*) as total_sold FROM orders_detail od JOIN orders o ON od.orders_id = o.id_orders WHERE o.payment_status = 5 GROUP BY od.product_id ) as od_count', 'p.id_products = od_count.product_id', 'left'); $this->db->where('p.deleted_at', null); if ($tab === 'active') { $this->db->where('p.product_status', '1'); } elseif ($tab === 'inactive') { $this->db->where('p.product_status', '0'); } // 1. **Filter untuk produk dengan stok kosong** if ($isEmptyStockOnly) { $this->db->having('total_stock = 0'); } // 2. **Filter untuk produk dengan stok rendah (≤ 5)** if ($isLowStock) { $this->db->having('total_stock > 0 AND total_stock < 5'); } // 3. **Filter untuk produk baru (dalam 30 hari terakhir)** if ($isNewProduct) { $this->db->where("p.created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)"); } // 4. **Filter untuk produk dengan diskon (discounted_price > 0)** if ($isDiscounted) { $this->db->where("p.id_products IN ( SELECT pd.product_id FROM product_details pd WHERE pd.discounted_price > 0 )"); } // 5. **Filter untuk produk terlaris (paling banyak dibeli di orders_detail)** if ($isBestSelling) { $this->db->join("( SELECT od.product_id FROM orders_detail od JOIN orders o ON od.orders_id = o.id_orders WHERE o.payment_status = 5 GROUP BY od.product_id ORDER BY COUNT(*) DESC LIMIT 10 ) AS best_selling", "p.id_products = best_selling.product_id"); } // Brand if (!empty($brandId)) { $this->db->where('p.brand_id', $brandId); } // Category if (!empty($categoryId)) { $this->db->where('cp.id_category', $categoryId); } if (!empty($searchTerm)) { $this->db->group_start(); $this->db->like('p.title', $searchTerm); $this->db->or_like('pd.sku', $searchTerm); $this->db->or_like('b.brand', $searchTerm); $this->db->or_like('p.id_products', $searchTerm); $this->db->or_like('pd.id', $searchTerm); $this->db->group_end(); } // Sort switch ($sort) { case 'baru': $this->db->order_by('created_at', 'DESC'); break; case 'baru-diubah': $this->db->order_by('updated_at', 'DESC'); break; case 'terlaris': $this->db->order_by('total_sold', 'DESC'); break; case 'kurang-diminati': $this->db->order_by('total_sold', 'ASC'); break; case 'harga-tertinggi': $this->db->order_by('max_price', 'DESC'); break; case 'harga-terendah': $this->db->order_by('min_price', 'ASC'); break; case 'nama-az': $this->db->order_by('p.title', 'ASC'); break; case 'nama-za': $this->db->order_by('p.title', 'DESC'); break; case 'stok-terbanyak': $this->db->order_by('total_stock', 'DESC'); break; case 'stok-tersedikit': $this->db->order_by('total_stock', 'ASC'); break; } $this->db->group_by('p.id_products'); $query = $this->db->get(); $all_products = $query->result(); // Post-processing foreach ($all_products as $product) { // Process price range if (!empty($product->min_price) && !empty($product->max_price)) { $product->price = ($product->min_price == $product->max_price) ? $product->min_price : $product->min_price . ' - ' . $product->max_price; } else { $product->price = 'N/A'; } unset($product->min_price, $product->max_price); // Ambil detail produk dengan variannya $this->db->select(' pd.id as product_detail_id, pd.sku, pd.price, COALESCE(s.stock, 0) as stock, pd.discounted_price, GROUP_CONCAT( CONCAT_WS(": ", pa.product_attribute, pad.attribute_detail) SEPARATOR ", " ) as variants, pa.product_attribute as attribute, pad.attribute_detail as attribute_detail '); $this->db->from('product_details pd'); $this->db->join('product_combination pc', 'pc.product_details_id = pd.id', 'left'); $this->db->join('product_attributes pa', 'pc.attribute_id = pa.id', 'left'); $this->db->join('product_attributes_detail pad', 'pc.attribute_detail_id = pad.id', 'left'); $this->db->join('stock s', 'pd.id = s.id_product_detail', 'left'); $this->db->where('pd.product_id', $product->id_products); $this->db->group_by('pd.id'); $this->db->order_by('pd.id', 'ASC'); $variants_query = $this->db->get(); $product->variants = $variants_query->result(); // unset($product->id_products); } echo json_encode($all_products); } // Fetch Attribute Options Data public function get_attribute_options() { $attribute_id = $this->input->get('attribute_id'); if (!$attribute_id) { echo json_encode([]); return; } $options = $this->product_m->get_attribute_options($attribute_id); echo json_encode($options); } // Update attribute priority public function update_attribute_priority() { // Ambil data yang dikirim dari FormData $order = $this->input->post('order'); if (!empty($order)) { foreach ($order as $item) { $this->db->where('id', $item['id']) ->update('product_attributes', ['priority' => $item['priority']]); } // Kirim response dengan CSRF token baru echo json_encode([ 'message' => 'Priority updated successfully', 'csrf_token' => $this->security->get_csrf_hash() ]); } else { echo json_encode([ 'message' => 'No data received', 'csrf_token' => $this->security->get_csrf_hash() ]); } } // Update attribute value public function update_attribute_value_priority() { // Ambil data yang dikirim dari FormData $order = $this->input->post('order'); if (!empty($order)) { foreach ($order as $item) { $this->db->where('id', $item['id']) ->update('product_attributes_detail', ['priority' => $item['priority']]); } // Kirim response dengan CSRF token baru echo json_encode([ 'message' => 'Priority updated successfully', 'csrf_token' => $this->security->get_csrf_hash() ]); } else { echo json_encode([ 'message' => 'No data received', 'csrf_token' => $this->security->get_csrf_hash() ]); } } // Update Price public function updatePrice() { if (!$this->input->is_ajax_request()) { show_error('No direct script access allowed', 403); return; } // Ambil data dari POST $product_detail_id = $this->input->post('product_detail_id'); $price = intval($this->input->post('price')); // Update harga produk $this->db->where('id', $product_detail_id); $update = $this->db->update('product_details', ['price' => $price]); echo json_encode(["success" => $update]); } // Update Stock public function updateStock() { // Cek apakah ini AJAX request if (!$this->input->is_ajax_request()) { show_error('No direct script access allowed', 403); return; } // Ambil data dari POST $product_detail_id = $this->input->post('product_detail_id'); $stock = intval($this->input->post('stock')); // Update stok produk di warehouse_id = 1 $this->db->where('id_product_detail', $product_detail_id); $this->db->where('warehouse_id', 1); // Pastikan hanya mengupdate di warehouse_id = 1 $update = $this->db->update('stock', ['stock' => $stock]); // Cek apakah update berhasil if ($update) { echo json_encode(["success" => true, "message" => "Stock updated successfully"]); } else { echo json_encode(["success" => false, "message" => "Failed to update stock"]); } } // Update Stock in stock page public function update_stock() { // Cek apakah ini AJAX request if (!$this->input->is_ajax_request()) { show_error('No direct script access allowed', 403); return; } // Ambil data dari POST $product_detail_id = $this->input->post('product_detail_id'); $warehouse_id = $this->input->post('warehouse_id'); $stock_type = $this->input->post('stock_type'); // stock, stock_keep, stock_reject, stock_sample $action = $this->input->post('action'); // add or subtract $amount = intval($this->input->post('amount')); $note = $this->input->post('note'); $user_name = $this->session->userdata('name'); // Validasi input if ( empty($product_detail_id) || empty($warehouse_id) || empty($stock_type) || empty($action) || $amount <= 0 || empty($note) ) { echo json_encode(["success" => false, "message" => "Data tidak lengkap"]); return; } // Get current stock information $this->db->select('id, id_product, stock, stock_keep, stock_reject, stock_sample'); $this->db->where('id_product_detail', $product_detail_id); $this->db->where('warehouse_id', $warehouse_id); $current_stock = $this->db->get('stock')->row(); if (!$current_stock) { echo json_encode(["success" => false, "message" => "Data stok tidak ditemukan"]); return; } // Proses update berdasarkan jenis stok dan aksi $old_value = 0; $new_value = 0; $update_data = []; $movement_table = 'stock_movement'; // Tabel default try { $this->db->trans_start(); // Mulai transaksi database switch ($stock_type) { case 'stock': $old_value = intval($current_stock->stock); $new_value = ($action === 'add') ? $old_value + $amount : $old_value - $amount; // Cek jika stok akan menjadi negatif if ($new_value < 0) { echo json_encode(["success" => false, "message" => "Stok tidak cukup"]); return; } $update_data['stock'] = $new_value; $movement_table = 'stock_movement'; break; case 'stock_keep': $old_value = intval($current_stock->stock_keep); $new_value = ($action === 'add') ? $old_value + $amount : $old_value - $amount; // Cek jika stok akan menjadi negatif if ($new_value < 0) { echo json_encode(["success" => false, "message" => "Stok keep tidak cukup"]); return; } $update_data['stock_keep'] = $new_value; $movement_table = 'stock_movement_keep'; break; case 'stock_reject': $old_value = intval($current_stock->stock_reject); $new_value = ($action === 'add') ? $old_value + $amount : $old_value - $amount; // Cek jika stok akan menjadi negatif if ($new_value < 0) { echo json_encode(["success" => false, "message" => "Stok reject tidak cukup"]); return; } $update_data['stock_reject'] = $new_value; $movement_table = 'stock_movement_reject'; break; case 'stock_sample': $old_value = intval($current_stock->stock_sample); $new_value = ($action === 'add') ? $old_value + $amount : $old_value - $amount; // Cek jika stok akan menjadi negatif if ($new_value < 0) { echo json_encode(["success" => false, "message" => "Stok sample tidak cukup"]); return; } $update_data['stock_sample'] = $new_value; $movement_table = 'stock_movement_sample'; break; default: echo json_encode(["success" => false, "message" => "Tipe stok tidak valid"]); return; } // Update stok di database $this->db->where('id_product_detail', $product_detail_id); $this->db->where('warehouse_id', $warehouse_id); $update = $this->db->update('stock', $update_data); if (!$update) { $this->db->trans_rollback(); echo json_encode(["success" => false, "message" => "Gagal mengupdate stok"]); return; } // Catat pergerakan stok ke tabel yang sesuai $type = ($action === 'add') ? '+' : '-'; $stock_movement = [ 'stock_id' => $current_stock->id, 'type' => $type, 'stock_change' => $amount, 'remark' => $note, 'total' => $new_value, 'name' => $user_name, 'stock_type' => $stock_type ]; $movement_insert = $this->db->insert($movement_table, $stock_movement); if (!$movement_insert) { $this->db->trans_rollback(); echo json_encode(["success" => false, "message" => "Gagal mencatat pergerakan stok"]); return; } $this->db->trans_commit(); // Commit transaksi jika semua berhasil // Return response sukses echo json_encode([ "success" => true, "message" => "Stok berhasil diperbarui", "csrf_token" => $this->security->get_csrf_hash(), "data" => [ "old_value" => $old_value, "new_value" => $new_value, "difference" => $amount, "action" => $action, "stock_type" => $stock_type ] ]); } catch (Exception $e) { $this->db->trans_rollback(); log_message('error', 'Update Stock Error: ' . $e->getMessage()); echo json_encode(["success" => false, "message" => "Terjadi kesalahan: " . $e->getMessage()]); } } /** * Get stock mutation data based on stock type * * @return json */ public function get_mutation_data() { // Cek apakah ini AJAX request if (!$this->input->is_ajax_request()) { show_error('No direct script access allowed', 403); return; } // Ambil parameter yang dikirim $product_detail_id = $this->input->post('product_detail_id') ?? null; $warehouse_id = $this->input->post('warehouse_id') ?? null; $stock_type = $this->input->post('stock_type') ?? null; // Validasi parameter if (empty($product_detail_id) || empty($warehouse_id)) { echo json_encode([ 'status' => 'error', 'message' => 'Parameter tidak lengkap' ]); return; } try { // Dapatkan stock_id dari tabel stock $this->db->select('id'); $this->db->where('id_product_detail', $product_detail_id); $this->db->where('warehouse_id', $warehouse_id); $stock_query = $this->db->get('stock'); if ($stock_query->num_rows() == 0) { echo json_encode([ 'status' => 'error', 'message' => 'Data stok tidak ditemukan' ]); return; } $stock_id = $stock_query->row()->id; // Tentukan tabel yang akan digunakan berdasarkan jenis stok $table_name = ''; switch ($stock_type) { case 'stock': $table_name = 'stock_movement'; break; case 'stock_keep': $table_name = 'stock_movement_keep'; break; case 'stock_reject': $table_name = 'stock_movement_reject'; break; case 'stock_sample': $table_name = 'stock_movement_sample'; break; default: echo json_encode([ 'status' => 'error', 'message' => 'Tipe stok tidak valid' ]); return; } // Query untuk mengambil data mutasi stok $this->db->select(' id, stock_id, type, stock_change as amount, total as total_stock, remark as notes, name as admin_name, datetime, stock_type '); $this->db->where('stock_id', $stock_id); $this->db->order_by('datetime', 'DESC'); $mutations = $this->db->get($table_name)->result_array(); // Tambahkan informasi waktu untuk setiap data foreach ($mutations as &$mutation) { if (isset($mutation['datetime']) && $mutation['datetime'] !== null && $mutation['datetime'] !== '') { try { $date = new DateTime($mutation['datetime']); $mutation['datetime'] = $date->format('Y-m-d H:i:s'); } catch (Exception $e) { $mutation['datetime'] = '-'; } } else { // Jika datetime kosong atau null, berikan nilai default $mutation['datetime'] = '-'; } // Map tipe mutasi untuk tampilan yang lebih baik if (isset($mutation['type'])) { if ($mutation['type'] === '+') { $mutation['type'] = 'add'; } else if ($mutation['type'] === '-') { $mutation['type'] = 'subtract'; } } } // Return data dalam format JSON echo json_encode([ 'status' => 'success', 'message' => 'Data berhasil diambil', 'data' => $mutations, 'csrf_token' => $this->security->get_csrf_hash() ]); } catch (Exception $e) { log_message('error', 'Get Stock Mutation Error: ' . $e->getMessage()); echo json_encode([ 'status' => 'error', 'message' => 'Terjadi kesalahan: ' . $e->getMessage() ]); } } // Update Status public function updateStatus() { if (!$this->input->is_ajax_request()) { show_error('No direct script access allowed', 403); return; } // Ambil data dari POST $product_id = $this->input->post('product_id'); $new_status = $this->input->post('new_status'); // Update harga produk $this->db->where('id_products', $product_id); $update = $this->db->update('products', ['product_status' => $new_status]); echo json_encode(["success" => $update]); } // Delete Product public function delete_product($id) { if (!$id || !is_numeric($id)) { echo json_encode(["success" => false, "message" => "ID produk tidak valid."]); return; } $this->db->where('id_products', $id); $this->db->where('deleted_at', null); $product = $this->db->get('products')->row(); if (!$product) { echo json_encode(["success" => false, "message" => "Produk tidak ditemukan atau sudah dihapus."]); return; } $this->db->where('id_products', $id); $updateSuccess = $this->db->update('products', ['deleted_at' => date('Y-m-d H:i:s')]); if ($updateSuccess) { echo json_encode(["success" => true, "message" => "Produk berhasil dihapus."]); } else { echo json_encode(["success" => false, "message" => "Gagal menghapus produk, coba lagi nanti."]); } } // Delete Attribute public function delete_attribute($id) { // Validasi ID atribut if (!$id || !is_numeric($id)) { echo json_encode(["success" => false, "message" => "ID atribut tidak valid."]); return; } // Memeriksa apakah atribut ada $attribute = $this->db->where('id', $id)->get('product_attributes')->row(); if (!$attribute) { echo json_encode(["success" => false, "message" => "Atribut tidak ditemukan."]); return; } // Hapus atribut $this->db->where('id', $id); $deleteSuccess = $this->db->delete('product_attributes'); if ($deleteSuccess) { echo json_encode([ "success" => true, "message" => "Atribut berhasil dihapus.", "csrf_token" => $this->security->get_csrf_hash() // Perbarui CSRF token ]); } else { echo json_encode([ "success" => false, "message" => "Gagal menghapus atribut, coba lagi nanti.", "csrf_token" => $this->security->get_csrf_hash() ]); } } // Delete Attribute public function delete_attribute_value($id) { // Validasi ID atribut if (!$id || !is_numeric($id)) { echo json_encode(["success" => false, "message" => "ID atribut tidak valid."]); return; } // Ambil data yang akan dihapus $attribute = $this->db->where('id', $id)->get('product_attributes_detail')->row(); if (!$attribute) { echo json_encode(["success" => false, "message" => "Opsi atribut tidak ditemukan."]); return; } $product_attribute_id = $attribute->product_attribute_id; // Hapus atribut $this->db->where('id', $id); $deleteSuccess = $this->db->delete('product_attributes_detail'); if ($deleteSuccess) { // Ambil semua ID dalam urutan yang benar setelah penghapusan $query = $this->db->select('id') ->where('product_attribute_id', $product_attribute_id) ->order_by('priority', 'ASC') ->get('product_attributes_detail'); $attributes = $query->result(); $newPriority = 1; // Update priority satu per satu foreach ($attributes as $attr) { $this->db->where('id', $attr->id) ->update('product_attributes_detail', ['priority' => $newPriority]); $newPriority++; } echo json_encode([ "success" => true, "message" => "Opsi Atribut berhasil dihapus dan priority telah diperbarui.", "csrf_token" => $this->security->get_csrf_hash() ]); } else { echo json_encode([ "success" => false, "message" => "Gagal menghapus opsi atribut, coba lagi nanti.", "csrf_token" => $this->security->get_csrf_hash() ]); } } // Process Add Product public function store() { // Ambil data dari POST $data = $this->input->post(); // Format alias dari product name $alias = preg_replace('/[^a-zA-Z0-9\s]/', '', $data['productName']); // Remove special characters $alias = preg_replace('/\s+/', ' ', $alias); // Replace multiple spaces with a single space $alias = str_replace(' ', '-', $alias); // Replace spaces with hyphens $alias = strtolower($alias); // Check if the 'restock' checkbox is set (checked), otherwise set default value to '0' $restock = isset($data['restock']) && $data['restock'] == '1' ? 'yes' : 'no'; // Siapkan data untuk table products $product_data = [ 'title' => $data['productName'], 'alias' => $alias, 'brand_id' => (int)$data['brand'], 'product_status' => isset($data['status']) ? (string)$data['status'] : '0', 'description' => $data['short_desc_id'], 'description_en' => $data['short_desc_en'], 'long_description' => $data['full_desc_id'], 'long_description_en' => $data['full_desc_en'], 'meta_description' => $data['seoMetaDescription'], 'meta_title' => $data['seoTitle'], 'restock' => $restock, 'media_file_link' => $data['linkMedia'] ? $data['linkMedia'] : null, 'product_video_link' => $data['productVideo'] ? $data['productVideo'] : null, 'product_guide_link' => $data['guideVideo'] ? $data['guideVideo'] : null, 'product_suggest' => isset($data['productRecommendation']) && is_array($data['productRecommendation']) ? implode(',', array_map('intval', $data['productRecommendation'])) : null, 'created_at' => date('Y-m-d H:i:s') ]; // Begin transaction $this->db->trans_begin(); try { // Insert product $this->db->insert('products', $product_data); $product_id = $this->db->insert_id(); // Insert categories $category_data = []; if (!empty($data['categories']) && is_array($data['categories'])) { foreach ($data['categories'] as $category_id) { $category_data[] = [ 'id_product' => $product_id, 'id_category' => $category_id ]; } if (!empty($category_data)) { $this->db->insert_batch('category_product', $category_data); } } // Insert shipping methods $shipping_data = []; if (!empty($data['shippingMethod']) && is_array($data['shippingMethod'])) { foreach ($data['shippingMethod'] as $shipment_id) { $shipping_data[] = [ 'product_id' => $product_id, 'shipment_method_id' => $shipment_id ]; } if (!empty($shipping_data)) { $this->db->insert_batch('shipment_method_product', $shipping_data); } } // Process variants if (isset($data['selected_variant_data']) && isset($data['selected_variant'])) { $selected_variant_data = json_decode($data['selected_variant_data'], true); $selected_variants = explode(',', $data['selected_variant']); foreach ($selected_variant_data as $index => $variant) { // Insert product details $product_details_data = [ 'product_id' => $product_id, 'sku' => $variant['sku'], 'weight' => $variant['berat'], 'price' => $variant['harga'], 'length' => $variant['panjang'], 'width' => $variant['lebar'], 'height' => $variant['tinggi'], 'is_indent' => 'no' // default value, adjust if needed ]; $this->db->insert('product_details', $product_details_data); $product_details_id = $this->db->insert_id(); // Insert product combination $product_combination_data = [ 'product_id' => $product_id, 'product_details_id' => $product_details_id, 'attribute_id' => $data['variant_type'], 'attribute_detail_id' => $variant['variant_id'] ]; $this->db->insert('product_combination', $product_combination_data); // Insert stock data for each variant $stock_data = [ 'id_product' => $product_id, 'id_product_detail' => $product_details_id, 'warehouse_id' => 1, // assuming warehouse_id is 1 'stock' => $data['variant_stock'][$index], // getting the stock value from variant_stock array 'stock_keep' => 0, // Set default values as needed 'stock_reject' => 0 // Set default values as needed ]; $this->db->insert('stock', $stock_data); } } else { // Handle the case where the selected_variant_data is not a valid JSON string or empty echo "Invalid or empty selected_variant_data."; } // Commit transaction if ($this->db->trans_status() === FALSE) { throw new Exception('Transaction failed'); } $this->db->trans_commit(); $this->session->set_flashdata('message', 'Product successfully added'); $this->session->set_flashdata('message_type', 'success'); // Redirect to manage-product page redirect('admin/products/manage-product'); } catch (Exception $e) { // Rollback transaction if failed $this->db->trans_rollback(); $this->session->set_flashdata('message', 'Failed to add product: ' . $e->getMessage()); $this->session->set_flashdata('message_type', 'error'); // Redirect to manage-product page redirect('admin/products/add-product'); } } // Store Variant public function store_variant() { // Ambil data dari POST $data = $this->input->post(); // Validasi input (Pastikan nama atribut tidak kosong) if (empty($data['idAttributeName']) || empty($data['enAttributeName'])) { $this->session->set_flashdata('message', 'Nama atribut dalam dua bahasa wajib diisi.'); $this->session->set_flashdata('message_type', 'error'); redirect('admin/products/add-variant'); return; } // Sanitasi input $idAttributeName = htmlspecialchars($data['idAttributeName']); $enAttributeName = htmlspecialchars($data['enAttributeName']); // Periksa apakah atribut sudah ada dalam database $this->db->where('product_attribute', $idAttributeName); $this->db->or_where('product_attribute_en', $enAttributeName); $query = $this->db->get('product_attributes'); if ($query->num_rows() > 0) { // Jika sudah ada, kirim pesan error $this->session->set_flashdata('message', 'Nama atribut sudah digunakan. Coba pakai nama yang lain.'); $this->session->set_flashdata('message_type', 'error'); redirect('admin/products/add-variant'); return; } // Tentukan apakah atribut ini warna atau tidak $is_color = isset($data['isColor']) && $data['isColor'] == '1' ? 'yes' : 'no'; // Ambil nilai priority terakhir $this->db->select_max('priority'); $query = $this->db->get('product_attributes'); $row = $query->row(); // Jika ada hasil, tambahkan +1, jika tidak, mulai dari 1 $priority = $row ? ($row->priority + 1) : 1; // Siapkan data untuk dimasukkan ke tabel `product_attributes` $attribute_data = [ 'product_attribute' => $idAttributeName, 'product_attribute_en' => $enAttributeName, 'is_color' => $is_color, 'priority' => $priority ]; // Mulai transaksi $this->db->trans_begin(); try { // Simpan data ke tabel `product_attributes` $this->db->insert('product_attributes', $attribute_data); // Commit transaksi if ($this->db->trans_status() === FALSE) { throw new Exception('Gagal menyimpan atribut.'); } $this->db->trans_commit(); // Redirect dengan pesan sukses $this->session->set_flashdata('message', 'Atribut berhasil ditambahkan.'); $this->session->set_flashdata('message_type', 'success'); redirect('admin/products/variant-product'); } catch (Exception $e) { // Rollback transaksi jika terjadi kesalahan $this->db->trans_rollback(); $this->session->set_flashdata('message', 'Gagal menambahkan atribut: ' . $e->getMessage()); $this->session->set_flashdata('message_type', 'error'); redirect('admin/products/add-variant'); } } // Store Variant Value public function store_variant_value() { $this->output->set_content_type('application/json'); // Validasi input $product_attribute_id = $this->input->post("product_attribute_id"); $attribute_detail = $this->input->post("attribute_detail"); $attribute_detail_en = $this->input->post("attribute_detail_en"); $color_hex = $this->input->post("color_hex"); if (empty($product_attribute_id) || empty($attribute_detail) || empty($attribute_detail_en)) { echo json_encode(["success" => false, "message" => "Data tidak lengkap!"]); return; } // Ambil priority terakhir dari product_attribute_id ini $this->db->select_max("priority"); $this->db->where("product_attribute_id", $product_attribute_id); $query = $this->db->get("product_attributes_detail"); $row = $query->row(); $priority = ($row && $row->priority !== null) ? $row->priority + 1 : 1; // Data yang akan dimasukkan ke database $insertData = [ "product_attribute_id" => $product_attribute_id, "attribute_detail" => htmlspecialchars($attribute_detail), "attribute_detail_en" => htmlspecialchars($attribute_detail_en), "color_hex" => $color_hex ? htmlspecialchars($color_hex) : null, "priority" => $priority ]; // Simpan ke database if ($this->db->insert("product_attributes_detail", $insertData)) { echo json_encode(["success" => true, "message" => "Data berhasil disimpan"]); } else { echo json_encode(["success" => false, "message" => "Gagal menyimpan data"]); } } // Process Update Product public function update($id_products) { // Pastikan produk ada sebelum melakukan update $product_exists = $this->db->get_where('products', ['id_products' => $id_products])->row(); if (!$product_exists) { $this->session->set_flashdata('message', 'Product not found.'); $this->session->set_flashdata('message_type', 'error'); redirect('admin/products/manage-product'); return; } // Ambil data dari POST dan sanitasi $data = $this->input->post(); if (!isset($data['productName'])) { $this->session->set_flashdata('message', 'Product name is required.'); $this->session->set_flashdata('message_type', 'error'); redirect('admin/products/edit_product/' . $id_products); return; } $alias = strtolower(trim(preg_replace('/[^a-zA-Z0-9]+/', '-', $data['productName']), '-')); $restock = isset($data['restock']) && $data['restock'] == '1' ? 'yes' : 'no'; $product_data = [ 'title' => $data['productName'], 'alias' => $alias, 'brand_id' => isset($data['brand']) ? (int)$data['brand'] : null, 'product_status' => isset($data['status']) ? (string)$data['status'] : '0', 'description' => $data['short_desc_id'], 'description_en' => $data['short_desc_en'], 'long_description' => $data['full_desc_id'], 'long_description_en' => $data['full_desc_en'], 'meta_description' => $data['seoMetaDescription'], 'meta_title' => $data['seoTitle'], 'restock' => $restock, 'media_file_link' => !empty($data['linkMedia']) ? $data['linkMedia'] : null, 'product_video_link' => !empty($data['productVideo']) ? $data['productVideo'] : null, 'product_guide_link' => !empty($data['guideVideo']) ? $data['guideVideo'] : null, 'product_suggest' => isset($data['productRecommendation']) && is_array($data['productRecommendation']) ? implode(',', array_map('intval', $data['productRecommendation'])) : null, 'updated_at' => date('Y-m-d H:i:s') ]; $this->db->trans_begin(); try { // Update produk $this->db->where('id_products', $id_products); $this->db->update('products', $product_data); // **Update Kategori Produk** if (!empty($data['categories']) && is_array($data['categories'])) { $this->db->delete('category_product', ['id_product' => $id_products]); $category_data = array_map(function ($category_id) use ($id_products) { return ['id_product' => $id_products, 'id_category' => $category_id]; }, $data['categories']); $this->db->insert_batch('category_product', $category_data); } // **Update Metode Pengiriman** if (!empty($data['shippingMethod']) && is_array($data['shippingMethod'])) { $this->db->delete('shipment_method_product', ['product_id' => $id_products]); $shipping_data = array_map(function ($shipment_id) use ($id_products) { return ['product_id' => $id_products, 'shipment_method_id' => $shipment_id]; }, $data['shippingMethod']); $this->db->insert_batch('shipment_method_product', $shipping_data); } // **Update Variasi Produk** if (isset($data['selected_variant_data']) && isset($data['selected_variant'])) { $selected_variant_data = json_decode($data['selected_variant_data'], true); $variant_ids = array_column($selected_variant_data, 'variant_id'); // Dapatkan data variasi yang ada $existing_variants = $this->db->get_where('product_combination', [ 'product_id' => $id_products ])->result_array(); $existing_variant_details = []; foreach ($existing_variants as $variant) { $existing_variant_details[$variant['attribute_detail_id']] = $variant['product_details_id']; } // Hapus variasi yang tidak ada lagi dalam data baru $variants_to_keep = $variant_ids; $variants_to_remove = array_diff(array_keys($existing_variant_details), $variants_to_keep); if (!empty($variants_to_remove)) { foreach ($variants_to_remove as $variant_id) { $product_details_id = $existing_variant_details[$variant_id]; // Hapus stok untuk variasi yang dihapus $this->db->delete('stock', [ 'id_product' => $id_products, 'id_product_detail' => $product_details_id ]); // Hapus kombinasi produk untuk variasi yang dihapus $this->db->delete('product_combination', [ 'product_id' => $id_products, 'attribute_detail_id' => $variant_id ]); // Hapus detail produk untuk variasi yang dihapus $this->db->delete('product_details', [ 'id' => $product_details_id ]); } } // Update atau tambahkan variasi baru foreach ($selected_variant_data as $index => $variant) { $variant_id = (int)$variant['variant_id']; if (isset($existing_variant_details[$variant_id])) { // Update variasi yang sudah ada $product_details_id = $existing_variant_details[$variant_id]; $product_details_data = [ 'sku' => htmlspecialchars($variant['sku']), 'weight' => (float)$variant['berat'], 'price' => (float)$variant['harga'], 'length' => (float)$variant['panjang'], 'width' => (float)$variant['lebar'], 'height' => (float)$variant['tinggi'], 'is_indent' => 'no' ]; $this->db->where('id', $product_details_id); $this->db->update('product_details', $product_details_data); // Update stok jika ada if (isset($data['variant_stock'][$index])) { $stock_exists = $this->db->get_where('stock', [ 'id_product' => $id_products, 'id_product_detail' => $product_details_id ])->row(); $stock_data = [ 'stock' => (int)$data['variant_stock'][$index] ]; if ($stock_exists) { $this->db->where('id_product', $id_products); $this->db->where('id_product_detail', $product_details_id); $this->db->update('stock', $stock_data); } else { $stock_data['id_product'] = $id_products; $stock_data['id_product_detail'] = $product_details_id; $stock_data['warehouse_id'] = 1; $stock_data['stock_keep'] = 0; $stock_data['stock_reject'] = 0; $this->db->insert('stock', $stock_data); } } } else { // Tambahkan variasi baru $product_details_data = [ 'product_id' => $id_products, 'sku' => htmlspecialchars($variant['sku']), 'weight' => (float)$variant['berat'], 'price' => (float)$variant['harga'], 'length' => (float)$variant['panjang'], 'width' => (float)$variant['lebar'], 'height' => (float)$variant['tinggi'], 'is_indent' => 'no' ]; $this->db->insert('product_details', $product_details_data); $product_details_id = $this->db->insert_id(); $product_combination_data = [ 'product_id' => $id_products, 'product_details_id' => $product_details_id, 'attribute_id' => isset($data['variant_type']) ? (int)$data['variant_type'] : null, 'attribute_detail_id' => $variant_id ]; $this->db->insert('product_combination', $product_combination_data); if (isset($data['variant_stock'][$index])) { $stock_data = [ 'id_product' => $id_products, 'id_product_detail' => $product_details_id, 'warehouse_id' => 1, 'stock' => (int)$data['variant_stock'][$index], 'stock_keep' => 0, 'stock_reject' => 0 ]; $this->db->insert('stock', $stock_data); } } } } if ($this->db->trans_status() === FALSE) { throw new Exception('Transaction failed.'); } $this->db->trans_commit(); $this->session->set_flashdata('message', 'Product successfully updated.'); $this->session->set_flashdata('message_type', 'success'); redirect('admin/products/manage-product'); } catch (Exception $e) { $this->db->trans_rollback(); $this->session->set_flashdata('message', 'Failed to update product: ' . $e->getMessage()); $this->session->set_flashdata('message_type', 'error'); redirect('admin/products/edit_product/' . $id_products); } } // Update Atribut public function update_attribute($id_attribute) { // Ambil data dari form $data = $this->input->post(); // Periksa apakah 'isColor' di-check, jika ya maka 'yes', jika tidak maka 'no' $is_color = isset($data['isColor']) && $data['isColor'] == '1' ? 'yes' : 'no'; // Siapkan data untuk update atribut $attribute_data = [ 'product_attribute' => htmlspecialchars($data['idAttributeName']), 'product_attribute_en' => htmlspecialchars($data['enAttributeName']), 'is_color' => $is_color, ]; // Mulai transaksi database $this->db->trans_begin(); try { // Update atribut berdasarkan ID $this->db->where('id', $id_attribute); $this->db->update('product_attributes', $attribute_data); // Commit transaksi jika berhasil if ($this->db->trans_status() === FALSE) { throw new Exception('Transaction failed'); } $this->db->trans_commit(); // Set flash message sukses $this->session->set_flashdata('message', 'Atribut berhasil diperbarui'); $this->session->set_flashdata('message_type', 'success'); // Redirect ke halaman manajemen atribut redirect('admin/products/variant-product'); } catch (Exception $e) { // Rollback transaksi jika gagal $this->db->trans_rollback(); // Set flash message error $this->session->set_flashdata('message', 'Gagal memperbarui atribut: ' . $e->getMessage()); $this->session->set_flashdata('message_type', 'error'); // Redirect kembali ke halaman edit atribut redirect('admin/products/edit-attribute/' . $id_attribute); } } public function update_attribute_values($id) { // Pastikan request adalah AJAX if (!$this->input->is_ajax_request()) { show_error('No direct script access allowed', 403); } // Ambil data dari form input $data = $this->input->post(); $response = ['success' => false, 'message' => 'Gagal memperbarui data.']; // Pastikan ID valid if (!is_numeric($id) || empty($data)) { echo json_encode($response); return; } // Siapkan data yang akan diperbarui $update_data = []; if (isset($data['attribute_detail'])) { $update_data['attribute_detail'] = htmlspecialchars($data['attribute_detail']); } if (isset($data['attribute_detail_en'])) { $update_data['attribute_detail_en'] = htmlspecialchars($data['attribute_detail_en']); } if (isset($data['color_hex'])) { $update_data['color_hex'] = htmlspecialchars($data['color_hex']); } // Periksa apakah ada data untuk diupdate if (empty($update_data)) { echo json_encode($response); return; } // Mulai transaksi database $this->db->trans_begin(); try { // Update atribut berdasarkan ID $this->db->where('id', $id); $this->db->update('product_attributes_detail', $update_data); // Commit transaksi jika berhasil if ($this->db->trans_status() === FALSE) { throw new Exception('Gagal memperbarui atribut.'); } $this->db->trans_commit(); // Update CSRF token untuk keamanan $new_csrf = $this->security->get_csrf_hash(); // Respon sukses $response = [ 'success' => true, 'message' => 'Data berhasil diperbarui.', 'csrf_hash' => $new_csrf ]; } catch (Exception $e) { // Rollback transaksi jika terjadi kesalahan $this->db->trans_rollback(); $response['message'] = $e->getMessage(); } // Kirim response dalam format JSON echo json_encode($response); } /** * Metode untuk menghapus produk secara massal * Menerima array ID produk dari frontend via AJAX * * @return JSON response */ public function bulk_delete() { // Cek apakah request adalah AJAX if (!$this->input->is_ajax_request()) { show_404(); } // Ambil data product_ids dari request $product_ids = $this->input->post('product_ids'); // Validasi input if (empty($product_ids) || !is_array($product_ids)) { // Kembalikan response error $response = array( 'success' => false, 'message' => 'Data produk tidak valid', 'product_ids' => $product_ids ); $this->output->set_content_type('application/json')->set_output(json_encode($response)); return; } // Filter array untuk memastikan hanya nilai integer yang valid $product_ids = array_filter($product_ids, function ($id) { return is_numeric($id) && $id > 0; }); // Periksa apakah masih ada produk yang akan dihapus setelah validasi if (empty($product_ids)) { $response = array( 'success' => false, 'message' => 'Tidak ada produk valid untuk dihapus' ); $this->output->set_content_type('application/json')->set_output(json_encode($response)); return; } // Jalankan proses bulk delete melalui model $result = $this->product_m->bulk_delete_products($product_ids); // Kembalikan response $response = array( 'success' => $result, 'message' => $result ? 'Produk berhasil dihapus' : 'Gagal menghapus produk' ); $this->output->set_content_type('application/json')->set_output(json_encode($response)); } function delete_special_discount($id) { //check if id exist. If not exist, show 404. $count = $this->product_m->count_exist_special_discount($id); if ($count == 0) { //page not exist show_404(); } $user_id = $this->session->userdata('admin')['id']; // Query untuk mengambil title dari tabel product $this->db->select('title'); $this->db->from('special_discount'); $this->db->where('id_discount', $id); $query_product = $this->db->get(); $product_data = $query_product->row(); // Buat string "title/SKU" if ($product_data) { $activity = 'User menghapus special discount (' . $product_data->title . ')'; } else { // Handle jika data produk atau detail produk tidak ditemukan $activity = 'User menghapus special discount (' . $id . ')'; } log_activity($user_id, $activity); $this->product_m->delete_special_discount($id); $this->session->set_flashdata('success', '<br><p style="background:green; color:white; padding:5px; font-weight:bold;">Discount berhasil dihapus</p>'); redirect('admin/products/specialdiscount'); } }