load->model('PeralatanTeknisi_model', 'ptm'); if (!$this->session->userdata('logged_in')) { redirect('auth'); } } public function index() { $data = [ "active_menu" => "peralatan_teknisi", "teknisi_list" => $this->ptm->get_teknisi_list() ]; $this->load->view('partials/header', $data); $this->load->view('peralatan_teknisi/layout', $data); $this->load->view('partials/footer'); } public function get_data() { $user_id = $this->input->get('user_id'); $status = $this->input->get('status') ?: 'active'; log_message('debug', '[get_data] user_id: ' . var_export($user_id, true) . ', status: ' . $status); $data = $this->ptm->get_barang_dibawa($user_id, $status); log_message('debug', '[get_data] query returned ' . count($data) . ' rows'); $result = []; $no = 1; foreach ($data as $row) { $result[] = [ $no++, htmlspecialchars($row->barcode, ENT_QUOTES, 'UTF-8'), htmlspecialchars($row->nama_barang, ENT_QUOTES, 'UTF-8'), htmlspecialchars($row->serial_number, ENT_QUOTES, 'UTF-8'), ]; } log_message('debug', '[get_data] response: ' . json_encode(['data' => $result])); echo json_encode(['data' => $result]); } public function scan_item() { $barcode = trim($this->input->get('barcode')); if (empty($barcode)) { echo json_encode(['status' => false, 'message' => 'QR Code tidak boleh kosong']); return; } $item = $this->ptm->get_item_by_barcode($barcode); if (!$item) { echo json_encode(['status' => false, 'message' => 'Barcode tidak ditemukan']); return; } $teknisi = $this->ptm->get_current_teknisi($item->barcode); echo json_encode([ 'status' => true, 'message' => 'Barang ditemukan', 'data' => [ 'barcode' => $item->barcode, 'nama_barang' => $item->nama_barang, 'serial_number' => $item->serial_number, 'barcode_id' => $item->barcode_id, 'item_id' => $item->item_id, 'barcode_status' => $item->barcode_status, 'teknisi_id' => $teknisi ? $teknisi->user_id : null, 'teknisi_name' => $teknisi ? $teknisi->full_name : null, 'teknisi_code' => $teknisi ? $teknisi->employee_code : null ] ]); } public function batch_kembalikan() { $barcodes = $this->input->post('barcodes'); if (empty($barcodes) || !is_array($barcodes)) { echo json_encode(['status' => false, 'message' => 'Tidak ada barcode yang dipilih']); return; } $result = $this->ptm->batch_kembalikan($barcodes); echo json_encode($result); } public function batch_dibawa() { $barcodes = $this->input->post('barcodes'); $user_id = (int)$this->input->post('user_id'); if (empty($barcodes) || !is_array($barcodes)) { echo json_encode(['status' => false, 'message' => 'Tidak ada barcode yang dipilih']); return; } if (empty($user_id)) { echo json_encode(['status' => false, 'message' => 'Pilih teknisi terlebih dahulu']); return; } $result = $this->ptm->batch_dibawa($barcodes, $user_id); echo json_encode($result); } public function get_teknisi_table() { $draw = (int)$this->input->get('draw'); $start = (int)$this->input->get('start'); $length = (int)$this->input->get('length'); $search = $this->input->get('search')['value'] ?? ''; $order_col = (int)$this->input->get('order')[0]['column'] ?? 1; $order_dir = $this->input->get('order')[0]['dir'] ?? 'asc'; $data = $this->ptm->get_teknisi_table_data($start, $length, $search, $order_col, $order_dir); $total_filtered = $this->ptm->count_filtered_teknisi($search); $total_all = $this->ptm->count_all_teknisi(); $result = []; $no = $start + 1; foreach ($data as $row) { $item_count = (int)$row->item_count; $item_text = $item_count . ' Item'; $aksi = ' '; $result[] = [ $no++, htmlspecialchars($row->full_name, ENT_QUOTES, 'UTF-8'), htmlspecialchars($row->employee_code, ENT_QUOTES, 'UTF-8'), htmlspecialchars($row->department_name, ENT_QUOTES, 'UTF-8') ?: '-', $item_text, $aksi ]; } echo json_encode([ 'draw' => $draw, 'recordsTotal' => $total_all, 'recordsFiltered' => $total_filtered, 'data' => $result ]); } public function teknisi_detail() { $user_id = (int)$this->input->get('user_id'); if (!$user_id) { echo json_encode(null); return; } $info = $this->ptm->get_teknisi_info($user_id); echo json_encode($info); } public function get_teknisi_items() { $user_id = (int)$this->input->get('user_id'); $draw = (int)$this->input->get('draw'); $start = (int)$this->input->get('start'); $length = (int)$this->input->get('length'); $search = $this->input->get('search')['value'] ?? ''; $order_col = (int)$this->input->get('order')[0]['column'] ?? 2; $order_dir = $this->input->get('order')[0]['dir'] ?? 'asc'; if (!$user_id) { echo json_encode(['draw' => $draw, 'recordsTotal' => 0, 'recordsFiltered' => 0, 'data' => []]); return; } $data = $this->ptm->get_teknisi_items_data($user_id, $start, $length, $search, $order_col, $order_dir); $total_filtered = $this->ptm->count_filtered_teknisi_items($user_id, $search); $total_all = $this->ptm->count_all_teknisi_items($user_id); $result = []; $no = $start + 1; foreach ($data as $row) { $badge = $row->status == 'active' ? 'Dibawa' : '' . htmlspecialchars($row->status, ENT_QUOTES, 'UTF-8') . ''; $result[] = [ $no++, htmlspecialchars($row->barcode, ENT_QUOTES, 'UTF-8'), htmlspecialchars($row->nama_barang, ENT_QUOTES, 'UTF-8'), htmlspecialchars($row->serial_number, ENT_QUOTES, 'UTF-8') ?: '-', htmlspecialchars($row->qty_sisa, ENT_QUOTES, 'UTF-8') ?: '0', $badge ]; } echo json_encode([ 'draw' => $draw, 'recordsTotal' => $total_all, 'recordsFiltered' => $total_filtered, 'data' => $result ]); } public function get_form_barang_bawaan_data() { $user_id = (int)$this->input->get('user_id'); if (!$user_id) { echo json_encode(['status' => false, 'message' => 'ID teknisi tidak valid']); return; } $info = $this->ptm->get_teknisi_info($user_id); if (!$info) { echo json_encode(['status' => false, 'message' => 'Teknisi tidak ditemukan']); return; } $items = $this->ptm->get_teknisi_items_full($user_id); $noFaktur = 'GRJN/K/' . date('d/m/Y'); $tanggal = date('d F Y'); $itemsData = []; $no = 1; foreach ($items as $item) { $itemsData[] = [ 'no' => $no++, 'barcode' => $item->barcode ?? '-', 'nama_barang' => $item->nama_barang ?? '-', 'serial_number' => $item->serial_number ?? '-', 'jumlah' => isset($item->qty_sisa) ? (int)$item->qty_sisa : 1, 'keterangan' => '' ]; } echo json_encode([ 'status' => true, 'data' => [ 'no_faktur' => $noFaktur, 'tanggal' => $tanggal, 'teknisi' => $info->full_name, 'teknisi_id' => $info->id, 'employee_code' => $info->employee_code, 'position_name' => $info->position_name, 'department_name' => $info->department_name, 'total_item' => count($itemsData), 'items' => $itemsData ] ]); } public function generate_pdf_barang_bawaan($user_id = null) { if ($this->session->userdata('role') != 'Admin') { show_error('Akses ditolak', 403); } $user_id = (int)$user_id; if (!$user_id) { show_error('ID teknisi tidak valid', 400); } if (ob_get_length()) { ob_end_clean(); } $info = $this->ptm->get_teknisi_info($user_id); if (!$info) { show_error('Teknisi tidak ditemukan', 404); } $items = $this->ptm->get_teknisi_items_full($user_id); $noFaktur = 'GRJN/K/' . date('d/m/Y'); $tanggal = date('d F Y'); require_once(APPPATH . 'third_party/fpdf/fpdf.php'); require_once(APPPATH . 'libraries/PDF_BarangBawaan.php'); $pdf = new PDF_BarangBawaan('L', 'mm', 'A5'); $pdf->AliasNbPages(); $pdf->SetMargins(5, 5, 5); $pdf->SetAutoPageBreak(true, 10); $pdf->setFormInfo($noFaktur, $tanggal, $info->full_name); $pdf->AddPage('L', 'A5'); $pdf->BarangBawaanTable($items); $pdf->SignatureArea(); $namaFile = 'FORM_BARANG_BAWAAN_' . str_replace(' ', '_', $info->full_name) . '_' . date('Ymd') . '.pdf'; $pdf->Output('I', $namaFile); exit; } public function get_transfer_data() { $data = $this->ptm->get_transfer_data(); $result = []; $no = 1; foreach ($data as $row) { $result[] = [ $no++, htmlspecialchars($row->barcode, ENT_QUOTES, 'UTF-8'), htmlspecialchars($row->nama_barang, ENT_QUOTES, 'UTF-8'), htmlspecialchars(($row->from_code ?? '') . ' - ' . ($row->from_name ?? ''), ENT_QUOTES, 'UTF-8'), htmlspecialchars(($row->to_code ?? '') . ' - ' . ($row->to_name ?? ''), ENT_QUOTES, 'UTF-8'), htmlspecialchars($row->created_at, ENT_QUOTES, 'UTF-8'), 'Selesai' ]; } echo json_encode(['data' => $result]); } public function batch_transfer() { $barcodes = $this->input->post('barcodes'); $from_user_id = (int)$this->input->post('from_user_id'); $to_user_id = (int)$this->input->post('to_user_id'); $technician = $this->ptm->get_teknisi_info($to_user_id); log_message('debug', 'batch_transfer POST: ' . json_encode([ 'barcodes' => $barcodes, 'from_user_id' => $from_user_id, 'to_user_id' => $to_user_id ])); if (empty($barcodes) || !is_array($barcodes)) { echo json_encode(['status' => false, 'message' => 'Tidak ada barcode yang dipilih']); return; } if (empty($from_user_id) || empty($to_user_id)) { echo json_encode(['status' => false, 'message' => 'Pilih teknisi asal dan tujuan']); return; } if ($from_user_id == $to_user_id) { echo json_encode(['status' => false, 'message' => 'Teknisi tujuan tidak boleh sama dengan teknisi asal']); return; } $now = date('Y-m-d H:i:s'); $errors = []; $this->db->trans_start(); foreach ($barcodes as $barcode) { $barcode = trim($barcode); if ($barcode == '') continue; $item = $this->db ->select('it.*, ib.id as barcode_id, tec.full_name as teknisi_name') ->from('item_technician it') ->join('item_barcodes ib', 'ib.barcode = it.barcode', 'left') ->join('k_employees tec', 'tec.id = it.user_id', 'left') ->where('it.barcode', $barcode) ->where('it.status', 'active') ->where('it.user_id', $from_user_id) ->get() ->row(); if (!$item) { $errors[] = "Barcode $barcode tidak ditemukan pada teknisi asal"; continue; } log_message('debug', 'batch_transfer item: ' . json_encode($item)); $this->db ->where('barcode', $item->barcode) ->where('user_id', $from_user_id) ->where('status', 'active') ->update('item_technician', [ 'user_id' => $to_user_id ]); $this->db->insert('item_movements', [ 'item_id' => $item->item_id, 'barcode_id' => $item->barcode_id, 'qty' => 1, 'from_type' => 'technician', 'from_id' => $from_user_id, 'to_type' => 'technician', 'to_id' => $to_user_id, 'movement_type' => 'transfer', 'notes' => 'Transfer Barang dari: ' . $item->teknisi_name . ' ke ' . $technician->full_name, 'created_at' => $now ]); } $this->db->trans_complete(); if ($this->db->trans_status() === FALSE) { $db_error = $this->db->error(); log_message('error', 'batch_transfer gagal: ' . json_encode($db_error)); echo json_encode([ 'status' => false, 'message' => 'Gagal memproses transfer', 'debug' => $db_error['message'] ?? 'Unknown database error' ]); return; } $success_count = count($barcodes) - count($errors); $msg = "$success_count barang berhasil ditransfer"; if (count($errors) > 0) { $msg .= '. ' . implode(', ', $errors); } echo json_encode(['status' => true, 'message' => $msg, 'errors' => $errors]); } public function get_log_data() { $data = $this->ptm->get_log_barang(); $result = []; $no = 1; foreach ($data as $row) { $status_badge = $row->status === 'active' ? 'ACTIVE' : 'INACTIVE'; $result[] = [ $no++, htmlspecialchars($row->teknisi_name ?? '-', ENT_QUOTES, 'UTF-8'), htmlspecialchars($row->item_code ?? '-', ENT_QUOTES, 'UTF-8'), htmlspecialchars($row->barcode, ENT_QUOTES, 'UTF-8'), htmlspecialchars($row->nama_barang ?? '-', ENT_QUOTES, 'UTF-8'), $row->created_at ? date('d/m/Y H:i', strtotime($row->created_at)) : '-', $row->status === 'inactive' && $row->deleted_at ? date('d/m/Y H:i', strtotime($row->deleted_at)) : '-', $status_badge, ]; } echo json_encode(['data' => $result]); } public function log_barang() { $data = [ "active_menu" => "peralatan_teknisi", ]; $this->load->view('partials/header', $data); $this->load->view('peralatan_teknisi/log_barang', $data); $this->load->view('partials/footer'); } }