Perubahan barcode dan inventory
This commit is contained in:
@@ -6,6 +6,10 @@ class Asset extends CI_Controller {
|
||||
public function __construct(){
|
||||
parent::__construct();
|
||||
$this->load->database();
|
||||
|
||||
if (!$this->session->userdata('logged_in')) {
|
||||
redirect('auth');
|
||||
}
|
||||
}
|
||||
|
||||
public function index(){
|
||||
@@ -21,7 +25,7 @@ class Asset extends CI_Controller {
|
||||
->select('assets.*, lokasi_asset.nama as nama_lokasi')
|
||||
->from('assets')
|
||||
->join('lokasi_asset', 'lokasi_asset.id = assets.lokasi_asset_id', 'left')
|
||||
->order_by('assets.id','DESC')
|
||||
->order_by('assets.tanggal_perolehan','DESC')
|
||||
->get()
|
||||
->result();
|
||||
|
||||
@@ -35,6 +39,7 @@ class Asset extends CI_Controller {
|
||||
$d->kode_asset ?? '-',
|
||||
$d->nama_asset,
|
||||
$d->nama_lokasi ?? '-',
|
||||
$d->keterangan ?? '-',
|
||||
number_format($d->nilai_perolehan),
|
||||
$d->masa_manfaat . ' bln',
|
||||
number_format($d->penyusutan_per_bulan),
|
||||
@@ -101,11 +106,12 @@ class Asset extends CI_Controller {
|
||||
'nilai_residu' => $residu,
|
||||
'penyusutan_per_bulan' => $penyusutan,
|
||||
'nilai_buku' => $nilai_perolehan,
|
||||
'sumber' => 'manual',
|
||||
'sumber' => 'pembelian',
|
||||
'account_debit_id' => $account_debit_id,
|
||||
'account_kredit_id' => $account_kredit_id,
|
||||
'lokasi_asset_id' => $lokasi_asset_id,
|
||||
'keterangan' => $keterangan
|
||||
'keterangan' => $keterangan,
|
||||
'qty' => 1
|
||||
];
|
||||
|
||||
$this->db->insert('assets',$data);
|
||||
@@ -142,11 +148,18 @@ class Asset extends CI_Controller {
|
||||
'asset_id' => $asset_id,
|
||||
'tipe' => 'perolehan',
|
||||
'nilai' => $nilai_perolehan,
|
||||
'keterangan' => 'Perolehan manual: '.$keterangan
|
||||
'keterangan' => 'Perolehan manual: '.$keterangan,
|
||||
'tanggal_dibuat' => $tanggal
|
||||
]);
|
||||
|
||||
$this->db->trans_complete();
|
||||
echo json_encode(['status'=>true]);
|
||||
|
||||
if ($this->db->trans_status()) {
|
||||
log_activity('Asset', 'create', 'Menambah asset manual: '.$nama_asset.' (ID: '.$asset_id.')');
|
||||
echo json_encode(['status'=>true]);
|
||||
} else {
|
||||
echo json_encode(['status'=>false]);
|
||||
}
|
||||
}
|
||||
|
||||
// ================= SAVE FROM STOCK =================
|
||||
@@ -157,6 +170,12 @@ class Asset extends CI_Controller {
|
||||
$masa = (int)$this->input->post('s_masa');
|
||||
$residu = preg_replace('/\D/','',$this->input->post('s_residu'));
|
||||
$tanggal = $this->input->post('s_tanggal');
|
||||
$keterangan = $this->input->post('s_keterangan');
|
||||
$barcode_id = $this->input->post('barcode_id');
|
||||
$qty = (int)$this->input->post('qty');
|
||||
if($qty < 1){
|
||||
$qty = 1;
|
||||
}
|
||||
|
||||
$item = $this->db->get_where('items',['id'=>$item_id])->row();
|
||||
|
||||
@@ -165,15 +184,20 @@ class Asset extends CI_Controller {
|
||||
return;
|
||||
}
|
||||
|
||||
if($item->stok < 1){
|
||||
if(!$barcode_id){
|
||||
echo json_encode(['status'=>false,'message'=>'Barcode wajib dipilih']);
|
||||
return;
|
||||
}
|
||||
|
||||
if($item->stok < $qty){
|
||||
echo json_encode(['status'=>false,'message'=>'Stok tidak cukup']);
|
||||
return;
|
||||
}
|
||||
|
||||
$harga = $item->harga_beli;
|
||||
$nama_asset = $item->nama_barang;
|
||||
$nilai_perolehan = $harga;
|
||||
$penyusutan = ($harga - $residu) / ($masa ?: 1);
|
||||
$nilai_perolehan = $harga * $qty;
|
||||
$penyusutan = ($nilai_perolehan - $residu) / ($masa ?: 1);
|
||||
|
||||
$this->db->trans_start();
|
||||
|
||||
@@ -192,10 +216,43 @@ class Asset extends CI_Controller {
|
||||
'sumber' => 'gudang',
|
||||
'account_debit_id' => $account_debit_id,
|
||||
'account_kredit_id' => 21, // Persediaan
|
||||
'lokasi_asset_id' => $lokasi_asset_id
|
||||
'lokasi_asset_id' => $lokasi_asset_id,
|
||||
'keterangan' => $keterangan,
|
||||
'qty' => $qty
|
||||
]);
|
||||
|
||||
$asset_id = $this->db->insert_id();
|
||||
|
||||
// START - Item Movement & item barcodes update status
|
||||
$this->db->where('item_id', $item_id);
|
||||
$this->db->order_by('created_at', 'DESC');
|
||||
$this->db->limit(1);
|
||||
$item_move = $this->db->get('item_movements')->row();
|
||||
|
||||
// get item_barcode
|
||||
$itemBar = $this->db->get_where('item_barcodes', ['id'=>$barcode_id])->row();
|
||||
|
||||
if($itemBar->qty_sisa < $qty) {
|
||||
echo json_encode(['status'=>false, 'message'=>'Stok tidak cukup. Sisa: '.$itemBar->qty_sisa]);
|
||||
$this->db->trans_rollback();
|
||||
return;
|
||||
}
|
||||
|
||||
$total_sisa = $itemBar->qty_sisa - $qty;
|
||||
$status_bar = ($total_sisa == 0) ? 'installed' : 'available';
|
||||
|
||||
$this->db->insert('item_movements',[
|
||||
'item_id' => $item_id,
|
||||
'barcode_id' => $barcode_id,
|
||||
'qty' => $qty,
|
||||
'from_type' => $item_move ? $item_move->to_type : 'warehouse', //enum('supplier','warehouse','technician','customer','invoice','asset')
|
||||
'to_type' => 'asset', //enum('supplier','warehouse','technician','customer','invoice','asset')
|
||||
'movement_type' => 'installation', //enum('purchase','transfer','installation','uninstallation','supplier_return','customer_return','adjustment','sold_out','asset')
|
||||
'notes' => $keterangan,
|
||||
'created_at' => date('Y-m-d H:i:s')
|
||||
]);
|
||||
// Status yang boleh masuk : enum('available','reserved','installed','damaged','lost','returned_supplier','sold_out','asset')
|
||||
$this->db->where('id', $barcode_id)->update('item_barcodes', ['status' => $status_bar, 'qty_sisa' => $total_sisa]);
|
||||
|
||||
// Journal
|
||||
$this->db->insert('journals',[
|
||||
@@ -225,9 +282,9 @@ class Asset extends CI_Controller {
|
||||
'kredit' => $nilai_perolehan
|
||||
]);
|
||||
|
||||
// UPDATE STOK ITEM (kurangi 1)
|
||||
// UPDATE STOK ITEM (kurangi sesuai qty)
|
||||
$this->db->where('id', $item_id)
|
||||
->set('stok', 'stok-1', FALSE)
|
||||
->set('stok', 'stok-'.$qty, FALSE)
|
||||
->update('items');
|
||||
|
||||
// MUTATION DARI GUDANG
|
||||
@@ -235,12 +292,18 @@ class Asset extends CI_Controller {
|
||||
'asset_id' => $asset_id,
|
||||
'tipe' => 'perolehan',
|
||||
'nilai' => $nilai_perolehan,
|
||||
'keterangan' => 'Perolehan dari gudang: '.$nama_asset
|
||||
'keterangan' => 'Perolehan dari gudang: '.$nama_asset,
|
||||
'tanggal_dibuat' => $tanggal
|
||||
]);
|
||||
|
||||
$this->db->trans_complete();
|
||||
|
||||
echo json_encode(['status'=>true]);
|
||||
if ($this->db->trans_status()) {
|
||||
log_activity('Asset', 'create', 'Menambah asset dari gudang: '.$nama_asset.' (ID: '.$asset_id.', Qty: '.$qty.')');
|
||||
echo json_encode(['status'=>true]);
|
||||
} else {
|
||||
echo json_encode(['status'=>false]);
|
||||
}
|
||||
}
|
||||
|
||||
// ================= UPDATE =================
|
||||
@@ -270,7 +333,13 @@ class Asset extends CI_Controller {
|
||||
]);
|
||||
|
||||
$this->db->trans_complete();
|
||||
echo json_encode(['status'=>true]);
|
||||
|
||||
if ($this->db->trans_status()) {
|
||||
log_activity('Asset', 'update', 'Update asset ID: '.$id.' Nama: '.$nama_asset);
|
||||
echo json_encode(['status'=>true]);
|
||||
} else {
|
||||
echo json_encode(['status'=>false]);
|
||||
}
|
||||
}
|
||||
|
||||
// ================= DELETE =================
|
||||
@@ -302,7 +371,13 @@ class Asset extends CI_Controller {
|
||||
]);
|
||||
|
||||
$this->db->trans_complete();
|
||||
echo json_encode(['status'=>true]);
|
||||
|
||||
if ($this->db->trans_status()) {
|
||||
log_activity('Asset', 'delete', 'Hapus asset ID: '.$id.' Alasan: '.$alasan);
|
||||
echo json_encode(['status'=>true]);
|
||||
} else {
|
||||
echo json_encode(['status'=>false]);
|
||||
}
|
||||
}
|
||||
|
||||
// ================= GET DATA SELECT =================
|
||||
@@ -326,11 +401,49 @@ class Asset extends CI_Controller {
|
||||
echo json_encode($data);
|
||||
}
|
||||
|
||||
public function get_items(){
|
||||
$data = $this->db
|
||||
->where('stok > 0')
|
||||
->get('items')
|
||||
->result();
|
||||
public function get_items()
|
||||
{
|
||||
// $data = $this->db
|
||||
// ->select('items.*, kode_barang.*')
|
||||
// ->from('items')
|
||||
// ->join('kode_barang', 'items.kode_id = kode_barang.id', 'left')
|
||||
// ->where('items.stok >', 0)
|
||||
// ->get()
|
||||
// ->result();
|
||||
|
||||
$this->db->select('
|
||||
items.id,
|
||||
items.nama_barang,
|
||||
items.harga_jual,
|
||||
items.harga_beli,
|
||||
items.kode_detail,
|
||||
kode_barang.tracking_type,
|
||||
COALESCE(SUM(
|
||||
stock_logs.qty * IF(stock_logs.tipe="masuk",1,-1)
|
||||
),0) as stok
|
||||
');
|
||||
|
||||
$this->db->where('status', 'active');
|
||||
$this->db->from('items');
|
||||
|
||||
$this->db->join('stock_logs',
|
||||
'stock_logs.item_id = items.id' ,
|
||||
'left');
|
||||
|
||||
$this->db->join('kode_barang',
|
||||
'items.kode_id = kode_barang.id' ,
|
||||
'left');
|
||||
|
||||
// $this->db->where('items.account_id', $account_id);
|
||||
|
||||
$this->db->group_by('items.id');
|
||||
|
||||
// ✅ INI KUNCINYA
|
||||
$this->db->having('stok >', 0);
|
||||
|
||||
|
||||
$data = $this->db->get()->result();
|
||||
|
||||
echo json_encode($data);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@ class Cronjob extends CI_Controller {
|
||||
$this->load->database();
|
||||
|
||||
// ONLY CLI ACCESS
|
||||
if (!$this->input->is_cli_request()) {
|
||||
exit('No direct access allowed');
|
||||
}
|
||||
// if (!$this->input->is_cli_request()) {
|
||||
// exit('No direct access allowed');
|
||||
// }
|
||||
}
|
||||
|
||||
public function generate_insight()
|
||||
@@ -353,4 +353,320 @@ class Cronjob extends CI_Controller {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// =====================================================
|
||||
// CRONJOB AUTO PENYUSUTAN ASSET BULANAN
|
||||
// =====================================================
|
||||
public function depreciation_asset()
|
||||
{
|
||||
$period = date('Y-m');
|
||||
$runDate = date('Y-m-d');
|
||||
$akun_beban_penyusutan = 54;
|
||||
|
||||
$assets = $this->db
|
||||
->select('id, nama_asset, nilai_perolehan, nilai_buku, nilai_residu, penyusutan_per_bulan, masa_manfaat, tanggal_perolehan, akumulasi_penyusutan, account_debit_id')
|
||||
->from('assets')
|
||||
->where('status', 'aktif')
|
||||
->where('nilai_buku > nilai_residu', null, false)
|
||||
->where('penyusutan_per_bulan >', 0)
|
||||
->get()
|
||||
->result();
|
||||
|
||||
$processed = 0;
|
||||
$success = 0;
|
||||
$skipped = 0;
|
||||
$errors = 0;
|
||||
$details = [];
|
||||
|
||||
$this->db->trans_begin();
|
||||
|
||||
try {
|
||||
foreach ($assets as $a) {
|
||||
$processed++;
|
||||
|
||||
$assetDetails = [
|
||||
'asset_id' => (int)$a->id,
|
||||
'asset_name' => $a->nama_asset,
|
||||
'processed_months' => [],
|
||||
'skipped_months' => []
|
||||
];
|
||||
|
||||
$account_parent = $this->db
|
||||
->select('id')
|
||||
->where('parent_id', $a->account_debit_id)
|
||||
->get('accounts')
|
||||
->row();
|
||||
|
||||
if (!$account_parent || empty($account_parent->id)) {
|
||||
$skipped++;
|
||||
$assetDetails['status'] = 'skip';
|
||||
$assetDetails['reason'] = 'account_parent_not_found';
|
||||
$details[] = $assetDetails;
|
||||
continue;
|
||||
}
|
||||
|
||||
$akun_akumulasi_penyusutan = (int)$account_parent->id;
|
||||
|
||||
$mutasiPatokan = $this->db
|
||||
->select('tanggal_dibuat')
|
||||
->from('asset_mutations')
|
||||
->where('asset_id', $a->id)
|
||||
->where_in('tipe', ['perolehan', 'penambahan'])
|
||||
->order_by('tanggal_dibuat', 'DESC')
|
||||
->order_by('id', 'DESC')
|
||||
->limit(1)
|
||||
->get()
|
||||
->row();
|
||||
|
||||
$tanggalPatokan = null;
|
||||
if ($mutasiPatokan && !empty($mutasiPatokan->tanggal_dibuat)) {
|
||||
$tanggalPatokan = $mutasiPatokan->tanggal_dibuat;
|
||||
}
|
||||
|
||||
if (empty($tanggalPatokan)) {
|
||||
$tanggalPatokan = $a->tanggal_perolehan;
|
||||
}
|
||||
|
||||
if (empty($tanggalPatokan)) {
|
||||
$skipped++;
|
||||
$assetDetails['status'] = 'skip';
|
||||
$assetDetails['reason'] = 'tanggal_patokan_tidak_ditemukan';
|
||||
$details[] = $assetDetails;
|
||||
continue;
|
||||
}
|
||||
|
||||
$startMonth = date('Y-m', strtotime(date('Y-m-01', strtotime($tanggalPatokan)) . ' +1 month'));
|
||||
$currentMonth = $period;
|
||||
|
||||
if ($startMonth > $currentMonth) {
|
||||
$skipped++;
|
||||
$assetDetails['status'] = 'skip';
|
||||
$assetDetails['reason'] = 'start_next_month_after_acquisition';
|
||||
$assetDetails['tanggal_patokan'] = $tanggalPatokan;
|
||||
$details[] = $assetDetails;
|
||||
continue;
|
||||
}
|
||||
|
||||
$nilaiPerolehan = (float)$a->nilai_perolehan;
|
||||
$nilaiResidu = (float)$a->nilai_residu;
|
||||
$susutPerBulan = (float)$a->penyusutan_per_bulan;
|
||||
$masaManfaat = (int)$a->masa_manfaat;
|
||||
|
||||
$akumulasiMutasi = $this->db
|
||||
->select('COALESCE(SUM(nilai),0) total', false)
|
||||
->from('asset_mutations')
|
||||
->where('asset_id', $a->id)
|
||||
->where('tipe', 'penyusutan')
|
||||
->get()
|
||||
->row();
|
||||
|
||||
$akumulasiBerjalan = (float)($akumulasiMutasi ? $akumulasiMutasi->total : 0);
|
||||
$nilaiBukuBerjalan = $nilaiPerolehan - $akumulasiBerjalan;
|
||||
|
||||
if ($nilaiBukuBerjalan < $nilaiResidu) {
|
||||
$nilaiBukuBerjalan = $nilaiResidu;
|
||||
$akumulasiBerjalan = $nilaiPerolehan - $nilaiBukuBerjalan;
|
||||
}
|
||||
|
||||
$iterMonth = $startMonth;
|
||||
$assetHasSuccess = false;
|
||||
|
||||
while ($iterMonth <= $currentMonth) {
|
||||
$monthsUsed = 0;
|
||||
$start = new DateTime(date('Y-m-01', strtotime($tanggalPatokan)));
|
||||
$end = new DateTime(date('Y-m-01', strtotime($iterMonth . '-01')));
|
||||
$diff = $start->diff($end);
|
||||
$monthsUsed = ($diff->y * 12) + $diff->m;
|
||||
|
||||
if ($monthsUsed < 0) {
|
||||
$skipped++;
|
||||
$assetDetails['skipped_months'][] = [
|
||||
'period' => $iterMonth,
|
||||
'reason' => 'tanggal_patokan_after_period'
|
||||
];
|
||||
$iterMonth = date('Y-m', strtotime($iterMonth . '-01 +1 month'));
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($masaManfaat > 0 && $monthsUsed >= $masaManfaat) {
|
||||
$skipped++;
|
||||
$assetDetails['skipped_months'][] = [
|
||||
'period' => $iterMonth,
|
||||
'reason' => 'masa_manfaat_finished'
|
||||
];
|
||||
break;
|
||||
}
|
||||
|
||||
$acqDay = (int)date('d', strtotime($tanggalPatokan));
|
||||
$lastDayOfMonth = (int)date('t', strtotime($iterMonth . '-01'));
|
||||
$dueDay = min($acqDay, $lastDayOfMonth);
|
||||
$dueDateThisMonth = $iterMonth . '-' . str_pad($dueDay, 2, '0', STR_PAD_LEFT);
|
||||
|
||||
// Untuk bulan berjalan, tetap hormati due date.
|
||||
// Untuk bulan yang sudah lewat, langsung boleh diproses (catch-up).
|
||||
if ($iterMonth === $currentMonth && strtotime($runDate) < strtotime($dueDateThisMonth)) {
|
||||
$skipped++;
|
||||
$assetDetails['skipped_months'][] = [
|
||||
'period' => $iterMonth,
|
||||
'reason' => 'not_due_date_today',
|
||||
'due_date' => $dueDateThisMonth,
|
||||
'run_date' => $runDate
|
||||
];
|
||||
$iterMonth = date('Y-m', strtotime($iterMonth . '-01 +1 month'));
|
||||
continue;
|
||||
}
|
||||
|
||||
$startDate = $iterMonth . '-01';
|
||||
$endDate = date('Y-m-d', strtotime($startDate . ' +1 month'));
|
||||
|
||||
$already = $this->db
|
||||
->where('asset_id', $a->id)
|
||||
->where('tipe', 'penyusutan')
|
||||
->where('tanggal_dibuat >=', $startDate)
|
||||
->where('tanggal_dibuat <', $endDate)
|
||||
->count_all_results('asset_mutations');
|
||||
|
||||
if ($already > 0) {
|
||||
$skipped++;
|
||||
$assetDetails['skipped_months'][] = [
|
||||
'period' => $iterMonth,
|
||||
'reason' => 'already_depreciated_this_month'
|
||||
];
|
||||
$iterMonth = date('Y-m', strtotime($iterMonth . '-01 +1 month'));
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($nilaiBukuBerjalan <= $nilaiResidu) {
|
||||
$skipped++;
|
||||
$assetDetails['skipped_months'][] = [
|
||||
'period' => $iterMonth,
|
||||
'reason' => 'nothing_to_depreciate'
|
||||
];
|
||||
break;
|
||||
}
|
||||
|
||||
$maxSusut = max(0, $nilaiBukuBerjalan - $nilaiResidu);
|
||||
$susut = min($susutPerBulan, $maxSusut);
|
||||
|
||||
if ($susut <= 0) {
|
||||
$skipped++;
|
||||
$assetDetails['skipped_months'][] = [
|
||||
'period' => $iterMonth,
|
||||
'reason' => 'nothing_to_depreciate'
|
||||
];
|
||||
break;
|
||||
}
|
||||
|
||||
$akumulasiBefore = $akumulasiBerjalan;
|
||||
$nilaiBukuBefore = $nilaiBukuBerjalan;
|
||||
|
||||
$akumulasiBerjalan += $susut;
|
||||
$nilaiBukuBerjalan = $nilaiPerolehan - $akumulasiBerjalan;
|
||||
|
||||
if ($nilaiBukuBerjalan < $nilaiResidu) {
|
||||
$nilaiBukuBerjalan = $nilaiResidu;
|
||||
$akumulasiBerjalan = $nilaiPerolehan - $nilaiBukuBerjalan;
|
||||
}
|
||||
|
||||
$this->db->insert('asset_mutations', [
|
||||
'asset_id' => $a->id,
|
||||
'tipe' => 'penyusutan',
|
||||
'nilai' => $susut,
|
||||
'keterangan' => 'Penyusutan otomatis periode ' . $iterMonth . ' (cronjob)',
|
||||
'tanggal_dibuat' => $dueDateThisMonth
|
||||
]);
|
||||
|
||||
$no_ref = 'DEP-' . date('YmdHis') . '-' . $a->id . '-' . str_replace('-', '', $iterMonth);
|
||||
$this->db->insert('journals', [
|
||||
'tanggal' => $dueDateThisMonth,
|
||||
'no_ref' => $no_ref,
|
||||
'keterangan' => 'Penyusutan Asset ' . $a->nama_asset . ' periode ' . $iterMonth,
|
||||
'ref_type' => 'assets',
|
||||
'ref_id' => $a->id,
|
||||
'created_by' => 1
|
||||
]);
|
||||
|
||||
$jid = $this->db->insert_id();
|
||||
|
||||
$this->db->insert('journal_details', [
|
||||
'journal_id' => $jid,
|
||||
'account_id' => $akun_beban_penyusutan,
|
||||
'debit' => $susut,
|
||||
'kredit' => 0
|
||||
]);
|
||||
|
||||
$this->db->insert('journal_details', [
|
||||
'journal_id' => $jid,
|
||||
'account_id' => $akun_akumulasi_penyusutan,
|
||||
'debit' => 0,
|
||||
'kredit' => $susut
|
||||
]);
|
||||
|
||||
$success++;
|
||||
$assetHasSuccess = true;
|
||||
|
||||
$assetDetails['processed_months'][] = [
|
||||
'period' => $iterMonth,
|
||||
'depreciation' => (float)$susut,
|
||||
'due_date' => $dueDateThisMonth,
|
||||
'akumulasi_before' => (float)$akumulasiBefore,
|
||||
'akumulasi_after' => (float)$akumulasiBerjalan,
|
||||
'nilai_buku_before' => (float)$nilaiBukuBefore,
|
||||
'nilai_buku_after' => (float)$nilaiBukuBerjalan,
|
||||
'journal_no_ref' => $no_ref
|
||||
];
|
||||
|
||||
$iterMonth = date('Y-m', strtotime($iterMonth . '-01 +1 month'));
|
||||
}
|
||||
|
||||
if ($assetHasSuccess) {
|
||||
$this->db->where('id', $a->id)->update('assets', [
|
||||
'akumulasi_penyusutan' => $akumulasiBerjalan,
|
||||
'nilai_buku' => $nilaiBukuBerjalan
|
||||
]);
|
||||
|
||||
$assetDetails['status'] = 'success';
|
||||
$assetDetails['akumulasi_final'] = (float)$akumulasiBerjalan;
|
||||
$assetDetails['nilai_buku_final'] = (float)$nilaiBukuBerjalan;
|
||||
} else {
|
||||
$assetDetails['status'] = 'skip';
|
||||
if (empty($assetDetails['reason'])) {
|
||||
$assetDetails['reason'] = 'no_eligible_month_to_process';
|
||||
}
|
||||
}
|
||||
|
||||
$details[] = $assetDetails;
|
||||
}
|
||||
|
||||
if ($this->db->trans_status() === FALSE) {
|
||||
throw new Exception('Transaction failed');
|
||||
}
|
||||
|
||||
$this->db->trans_commit();
|
||||
|
||||
echo json_encode([
|
||||
'status' => true,
|
||||
'period' => $period,
|
||||
'processed' => $processed,
|
||||
'success' => $success,
|
||||
'skipped' => $skipped,
|
||||
'errors' => $errors,
|
||||
'message' => 'Depreciation cron executed',
|
||||
'details' => $details
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
$this->db->trans_rollback();
|
||||
$errors++;
|
||||
|
||||
echo json_encode([
|
||||
'status' => false,
|
||||
'period' => $period,
|
||||
'processed' => $processed,
|
||||
'success' => $success,
|
||||
'skipped' => $skipped,
|
||||
'errors' => $errors,
|
||||
'message' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -135,6 +135,8 @@ class Customers extends CI_Controller {
|
||||
// =========================
|
||||
public function delete($id)
|
||||
{
|
||||
$customer = $this->dm->setTable('customers')->get_by_id($id);
|
||||
|
||||
$this->dm->setTable('customers')->delete($id);
|
||||
|
||||
// ================= LOG ACTIVITY =================
|
||||
|
||||
@@ -10,6 +10,10 @@ class Employees extends CI_Controller {
|
||||
$this->load->database();
|
||||
$this->load->helper(['url', 'file']);
|
||||
|
||||
if (!$this->session->userdata('logged_in')) {
|
||||
redirect('auth');
|
||||
}
|
||||
|
||||
date_default_timezone_set('Asia/Jakarta');
|
||||
}
|
||||
|
||||
@@ -192,6 +196,14 @@ class Employees extends CI_Controller {
|
||||
$data['photo'] = $photo;
|
||||
|
||||
$this->db->insert('k_employees',$data);
|
||||
$employee_id = $this->db->insert_id();
|
||||
|
||||
log_activity(
|
||||
'employees',
|
||||
'create',
|
||||
'Menambah karyawan: '.$data['full_name'].' (ID: '.$employee_id.')',
|
||||
'success'
|
||||
);
|
||||
|
||||
return $this->json([
|
||||
'status' => true,
|
||||
@@ -247,6 +259,13 @@ class Employees extends CI_Controller {
|
||||
->where('id',$id)
|
||||
->update('k_employees',$data);
|
||||
|
||||
log_activity(
|
||||
'employees',
|
||||
'update',
|
||||
'Update karyawan ID: '.$id.' Nama: '.($data['full_name'] ?? '-'),
|
||||
'success'
|
||||
);
|
||||
|
||||
return $this->json([
|
||||
'status' => true,
|
||||
'message' => 'Berhasil update data'
|
||||
@@ -292,6 +311,13 @@ class Employees extends CI_Controller {
|
||||
'id'=>$id
|
||||
]);
|
||||
|
||||
log_activity(
|
||||
'employees',
|
||||
'delete',
|
||||
'Hapus karyawan ID: '.$id.' Nama: '.($employee->full_name ?? '-'),
|
||||
'success'
|
||||
);
|
||||
|
||||
return $this->json([
|
||||
'status' => true,
|
||||
'message' => 'Berhasil hapus data'
|
||||
|
||||
@@ -27,114 +27,81 @@ class Generateneracasaldo extends CI_Controller {
|
||||
}
|
||||
|
||||
// =========================
|
||||
// HITUNG LABA BERJALAN (REALTIME)
|
||||
// =========================
|
||||
private function get_laba_berjalan()
|
||||
{
|
||||
$this->db->select('
|
||||
accounts.tipe,
|
||||
COALESCE(SUM(journal_details.debit),0) as debit,
|
||||
COALESCE(SUM(journal_details.kredit),0) as kredit
|
||||
');
|
||||
$this->db->from('accounts');
|
||||
$this->db->join('journal_details','journal_details.account_id = accounts.id','LEFT');
|
||||
$this->db->where_in('accounts.tipe',['revenue','expense']);
|
||||
|
||||
$rows = $this->db->get()->result();
|
||||
|
||||
$revenue = 0;
|
||||
$expense = 0;
|
||||
|
||||
foreach ($rows as $r) {
|
||||
if ($r->tipe == 'revenue') {
|
||||
$revenue += ($r->kredit - $r->debit);
|
||||
} else {
|
||||
$expense += ($r->debit - $r->kredit);
|
||||
}
|
||||
}
|
||||
|
||||
return $revenue - $expense;
|
||||
}
|
||||
|
||||
// =========================
|
||||
// AMBIL DATA NERACA SALDO (DIPAKAI BERSAMA OLEH get_data() & generatepdf())
|
||||
// AMBIL DATA NERACA SALDO
|
||||
// DIPAKAI OLEH AJAX & PDF
|
||||
// =========================
|
||||
private function get_neracasaldo_data()
|
||||
{
|
||||
$this->db->select('
|
||||
$tanggal_awal = $this->input->get('tanggal_awal');
|
||||
$tanggal_akhir = $this->input->get('tanggal_akhir');
|
||||
|
||||
$this->db->select("
|
||||
accounts.id,
|
||||
accounts.kode_akun,
|
||||
accounts.nama_akun,
|
||||
accounts.kategori,
|
||||
accounts.tipe,
|
||||
accounts.posisi,
|
||||
COALESCE(SUM(journal_details.debit),0) as debit,
|
||||
COALESCE(SUM(journal_details.kredit),0) as kredit
|
||||
');
|
||||
COALESCE(SUM(journal_details.debit),0) AS debit,
|
||||
COALESCE(SUM(journal_details.kredit),0) AS kredit
|
||||
");
|
||||
|
||||
$this->db->from('accounts');
|
||||
$this->db->join('journal_details','journal_details.account_id = accounts.id','LEFT');
|
||||
|
||||
// OPTIONAL (best practice)
|
||||
$this->db->where('accounts.is_active',1);
|
||||
$this->db->where('accounts.kategori','neraca');
|
||||
// ======================================
|
||||
// FILTER PERIODE
|
||||
// ======================================
|
||||
if (!empty($tanggal_awal) && !empty($tanggal_akhir)) {
|
||||
|
||||
$this->db->group_by('accounts.id');
|
||||
$this->db->order_by('accounts.kode_akun','ASC');
|
||||
$this->db->join(
|
||||
"(SELECT jd.*
|
||||
FROM journal_details jd
|
||||
JOIN journals j ON j.id = jd.journal_id
|
||||
WHERE j.tanggal BETWEEN ".$this->db->escape($tanggal_awal)."
|
||||
AND ".$this->db->escape($tanggal_akhir)."
|
||||
) journal_details",
|
||||
"journal_details.account_id = accounts.id",
|
||||
"left",
|
||||
false
|
||||
);
|
||||
|
||||
$rows = $this->db->get()->result();
|
||||
} else {
|
||||
|
||||
// =========================
|
||||
// HITUNG LABA BERJALAN
|
||||
// =========================
|
||||
$laba = $this->get_laba_berjalan();
|
||||
$this->db->join(
|
||||
'journal_details',
|
||||
'journal_details.account_id = accounts.id',
|
||||
'left'
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
$rows = $this->db
|
||||
->where('accounts.is_active',1)
|
||||
->group_by('accounts.id')
|
||||
->order_by('accounts.kode_akun','ASC')
|
||||
->get()
|
||||
->result();
|
||||
|
||||
$result = [];
|
||||
$total_debit = 0;
|
||||
$total_kredit = 0;
|
||||
|
||||
foreach ($rows as $r) {
|
||||
foreach($rows as $row){
|
||||
|
||||
// ================= SALDO NORMAL
|
||||
if ($r->posisi == 'debit') {
|
||||
$saldo = $r->debit - $r->kredit;
|
||||
} else {
|
||||
$saldo = $r->kredit - $r->debit;
|
||||
}
|
||||
$row->debit = (float)$row->debit;
|
||||
$row->kredit = (float)$row->kredit;
|
||||
|
||||
// ================= OVERRIDE LABA BERJALAN
|
||||
if ($r->kode_akun == '302') {
|
||||
$saldo = $laba;
|
||||
}
|
||||
|
||||
// ================= NORMALISASI KE KOLOM
|
||||
if ($saldo >= 0 AND $r->posisi == 'debit') {
|
||||
$r->saldo_debit = $saldo;
|
||||
$r->saldo_kredit = 0;
|
||||
} else {
|
||||
$r->saldo_debit = 0;
|
||||
$r->saldo_kredit = abs($saldo);
|
||||
}
|
||||
|
||||
$total_debit += $r->saldo_debit;
|
||||
$total_kredit += $r->saldo_kredit;
|
||||
|
||||
$result[] = [
|
||||
'kode' => $r->kode_akun,
|
||||
'nama' => $r->nama_akun,
|
||||
'saldo_debit' => $r->saldo_debit,
|
||||
'saldo_kredit' => $r->saldo_kredit,
|
||||
];
|
||||
$total_debit += $row->debit;
|
||||
$total_kredit += $row->kredit;
|
||||
}
|
||||
|
||||
return [
|
||||
'rows' => $rows,
|
||||
'data' => $result,
|
||||
'total_debit' => $total_debit,
|
||||
'total_kredit' => $total_kredit,
|
||||
'tanggal_awal' => $tanggal_awal,
|
||||
'tanggal_akhir' => $tanggal_akhir,
|
||||
'rows' => $rows,
|
||||
'total_debit' => $total_debit,
|
||||
'total_kredit' => $total_kredit
|
||||
];
|
||||
}
|
||||
|
||||
// =========================
|
||||
// GET DATA NERACA SALDO (JSON, untuk AJAX/datatable)
|
||||
// =========================
|
||||
public function get_data()
|
||||
{
|
||||
$result = $this->get_neracasaldo_data();
|
||||
@@ -142,68 +109,80 @@ class Generateneracasaldo extends CI_Controller {
|
||||
echo json_encode($result['rows']);
|
||||
}
|
||||
|
||||
// =========================
|
||||
// PDF GENERATE — NERACA SALDO
|
||||
// =========================
|
||||
public function generatepdf()
|
||||
{
|
||||
if ($this->session->userdata('role') != 'Admin') {
|
||||
show_error('Akses ditolak', 403);
|
||||
show_error('Akses ditolak',403);
|
||||
}
|
||||
|
||||
if (ob_get_length()) {
|
||||
ob_end_clean();
|
||||
}
|
||||
|
||||
// =============================================================
|
||||
// AMBIL DATA
|
||||
// =============================================================
|
||||
// ==========================================
|
||||
// DATA
|
||||
// ==========================================
|
||||
$neracasaldo = $this->get_neracasaldo_data();
|
||||
|
||||
// =============================================================
|
||||
// DATA PERUSAHAAN
|
||||
// =============================================================
|
||||
// ==========================================
|
||||
// PERUSAHAAN
|
||||
// ==========================================
|
||||
$company = $this->db->get('pengaturan')->row();
|
||||
|
||||
// =============================================================
|
||||
// BUILD STRING PERIODE
|
||||
// =============================================================
|
||||
$periodeStr = 'Per Tanggal : ' . date('d-m-Y');
|
||||
// ==========================================
|
||||
// PERIODE
|
||||
// ==========================================
|
||||
if(!empty($neracasaldo['tanggal_awal']) && !empty($neracasaldo['tanggal_akhir'])){
|
||||
|
||||
// =============================================================
|
||||
// LOAD LIBRARY PDF
|
||||
// =============================================================
|
||||
require_once(APPPATH . 'third_party/fpdf/fpdf.php');
|
||||
require_once(APPPATH . 'libraries/PDF_Neracasaldo.php');
|
||||
$periodeStr = 'Periode : '
|
||||
. date('d-m-Y',strtotime($neracasaldo['tanggal_awal']))
|
||||
.' s/d '
|
||||
. date('d-m-Y',strtotime($neracasaldo['tanggal_akhir']));
|
||||
|
||||
$pdf = new PDF ('P', 'mm', 'A4');
|
||||
$pdf->SetMargins(10, 10, 10);
|
||||
}else{
|
||||
|
||||
$periodeStr = 'Seluruh Periode';
|
||||
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// PDF
|
||||
// ==========================================
|
||||
require_once(APPPATH.'third_party/fpdf/fpdf.php');
|
||||
require_once(APPPATH.'libraries/PDF_Neracasaldo.php');
|
||||
|
||||
$pdf = new PDF('P','mm','A4');
|
||||
$pdf->SetMargins(10,10,10);
|
||||
|
||||
$pdf->setHeaderData(
|
||||
$company->nama_perusahaan,
|
||||
$company->alamat_perusahaan,
|
||||
FCPATH . 'uploads/img/logo-ljn.png'
|
||||
FCPATH.'uploads/img/logo-ljn.png'
|
||||
);
|
||||
|
||||
$pdf->setInfoLaporan($periodeStr);
|
||||
|
||||
$pdf->AddPage('P', 'A4');
|
||||
$pdf->AddPage();
|
||||
|
||||
$pdf->NeracaSaldoTable(
|
||||
$neracasaldo['data'],
|
||||
$neracasaldo['rows'],
|
||||
$neracasaldo['total_debit'],
|
||||
$neracasaldo['total_kredit']
|
||||
);
|
||||
|
||||
$pdf->NeracaSaldoRingkasan(
|
||||
$neracasaldo['total_debit'],
|
||||
$neracasaldo['total_kredit']
|
||||
);
|
||||
$pdf->Pembuat('Tito Ngudiana', 'Finance Department');
|
||||
|
||||
// =============================================================
|
||||
// OUTPUT
|
||||
// =============================================================
|
||||
$filename = 'Neraca_Saldo_' . date('YmdHis') . '.pdf';
|
||||
$pdf->Output('I', $filename);
|
||||
$pdf->Pembuat(
|
||||
$this->session->userdata('nama') ?: 'Administrator',
|
||||
'Finance Department'
|
||||
);
|
||||
|
||||
$filename = 'Neraca_Saldo_'.date('YmdHis').'.pdf';
|
||||
|
||||
$pdf->Output('I',$filename);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
@@ -367,7 +367,9 @@ class Invoices extends CI_Controller {
|
||||
'warehouse_id' => null,
|
||||
'keterangan' => $inv_items->keterangan,
|
||||
'subtotal_asli' => $inv_items->subtotal_asli,
|
||||
'is_cicilan' => $inv_items->is_cicilan
|
||||
'is_cicilan' => $inv_items->is_cicilan,
|
||||
'source_cicilan_id' => $c->id,
|
||||
'total_hpp_barang' => $c->cicilan_hpp_barang
|
||||
];
|
||||
|
||||
$this->db->insert('invoice_details', $insert_data);
|
||||
@@ -476,13 +478,14 @@ class Invoices extends CI_Controller {
|
||||
public function detail($id)
|
||||
{
|
||||
// GET customer_id
|
||||
$row = $this->db->select('customer_id')
|
||||
$row = $this->db->select('customer_id, no_invoice')
|
||||
->where('id',$id)
|
||||
->get('invoices')
|
||||
->row();
|
||||
|
||||
$data['active_menu'] = "invoice_draft";
|
||||
$data['invoice_id'] = $id;
|
||||
$data['no_invoice'] = $row ? $row->no_invoice : null;
|
||||
$data['customer_id'] = $row ? $row->customer_id : null;
|
||||
|
||||
$this->load->view('partials/header', $data);
|
||||
@@ -554,6 +557,7 @@ class Invoices extends CI_Controller {
|
||||
$harga = (float)$this->input->post('harga');
|
||||
$account_id = $this->input->post('account_id');
|
||||
$warehouse_id = $this->input->post('warehouse_id');
|
||||
$barcode_id = $this->input->post('barcode_id');
|
||||
|
||||
$total_harga = $qty * $harga;
|
||||
$total_hpp = 0;
|
||||
@@ -561,7 +565,9 @@ class Invoices extends CI_Controller {
|
||||
// jika di bayar cicilan
|
||||
$is_cicilan = $this->input->post('is_cicilan') ?? null;
|
||||
$tenor = (int)$this->input->post('tenor') ?? 0;
|
||||
|
||||
|
||||
// ambil invoice Detail
|
||||
$invoice = $this->db->get_where('invoices', ['id' => $invoice_id])->row();
|
||||
// =========================
|
||||
// VALIDASI & AMBIL ITEM
|
||||
// =========================
|
||||
@@ -576,12 +582,44 @@ class Invoices extends CI_Controller {
|
||||
$nama_item = $item->nama_barang;
|
||||
|
||||
// cek stok
|
||||
$stok = $this->get_stok($item_id);
|
||||
if($stok < $qty){
|
||||
echo json_encode(['status'=>false, 'message'=>'Stok tidak cukup. Sisa: '.$stok]);
|
||||
// $stok = $this->get_stok($item_id);
|
||||
// if($stok < $qty){
|
||||
// echo json_encode(['status'=>false, 'message'=>'Stok tidak cukup. Sisa: '.$stok]);
|
||||
// $this->db->trans_rollback();
|
||||
// return;
|
||||
// }
|
||||
|
||||
// START - Item Movement & item barcodes update status
|
||||
$this->db->where('item_id', $item_id);
|
||||
$this->db->order_by('created_at', 'DESC');
|
||||
$this->db->limit(1);
|
||||
$item_move = $this->db->get('item_movements')->row();
|
||||
|
||||
// get item_barcode
|
||||
$itemBar = $this->db->get_where('item_barcodes', ['id'=>$barcode_id])->row();
|
||||
|
||||
if($itemBar->qty_sisa < $qty) {
|
||||
echo json_encode(['status'=>false, 'message'=>'Stok tidak cukup. Sisa: '.$itemBar->qty_sisa]);
|
||||
$this->db->trans_rollback();
|
||||
return;
|
||||
}
|
||||
|
||||
$total_sisa = $itemBar->qty_sisa - $qty;
|
||||
$status_bar = ($total_sisa == 0) ? 'sold_out' : 'available';
|
||||
|
||||
$this->db->insert('item_movements',[
|
||||
'item_id' => $item_id,
|
||||
'barcode_id' => $barcode_id,
|
||||
'qty' => $qty,
|
||||
'from_type' => $item_move->to_type, //enum('supplier','warehouse','technician','customer','invoice')
|
||||
'to_type' => 'invoice', //enum('supplier','warehouse','technician','customer','invoice')
|
||||
'movement_type' => 'sold_out', //enum('purchase','transfer','installation','uninstallation','supplier_return','customer_return','adjustment','sold_out')
|
||||
'notes' => 'Barang terjual ke INV : ' . $invoice->no_invoice,
|
||||
'created_at' => date('Y-m-d H:i:s')
|
||||
]);
|
||||
|
||||
$this->db->where('id', $barcode_id)->update('item_barcodes', ['status' => $status_bar, 'qty_sisa' => $total_sisa]);
|
||||
// END - Item Movement & item barcodes update status
|
||||
|
||||
$total_hpp = $qty * $item->harga_beli;
|
||||
}
|
||||
@@ -600,6 +638,9 @@ class Invoices extends CI_Controller {
|
||||
|
||||
// harga per cicilan
|
||||
$harga_cicilan = round($total_harga / $tenor);
|
||||
|
||||
//ngatur HPP Cicilan
|
||||
$total_hpp = round($total_hpp / $tenor);
|
||||
|
||||
$harga_simpan = $harga_cicilan;
|
||||
$subtotal_simpan = $harga_cicilan;
|
||||
@@ -624,7 +665,8 @@ class Invoices extends CI_Controller {
|
||||
'keterangan' => $this->input->post('keterangan'),
|
||||
'subtotal_asli' => $harga_asli,
|
||||
'is_cicilan' => $is_cicilan ? 1 : 0,
|
||||
'total_hpp_barang' => $total_hpp
|
||||
'total_hpp_barang' => $total_hpp,
|
||||
'barcode_id' => $barcode_id
|
||||
];
|
||||
|
||||
$this->db->insert('invoice_details', $insert_data);
|
||||
@@ -639,8 +681,6 @@ class Invoices extends CI_Controller {
|
||||
|
||||
$this->update_total($invoice_id);
|
||||
|
||||
// ambil customer dari invoice
|
||||
$invoice = $this->db->get_where('invoices', ['id' => $invoice_id])->row();
|
||||
|
||||
if ($is_cicilan && $tenor > 0) {
|
||||
|
||||
@@ -653,6 +693,7 @@ class Invoices extends CI_Controller {
|
||||
$tenor,
|
||||
$tanggal,
|
||||
$account_id,
|
||||
$total_hpp,
|
||||
$item_id ?: null
|
||||
);
|
||||
}
|
||||
@@ -675,105 +716,108 @@ class Invoices extends CI_Controller {
|
||||
}
|
||||
}
|
||||
|
||||
// =========================
|
||||
// UPDATE ITEM - RESPONSE KONSISTEN
|
||||
// =========================
|
||||
public function update_item()
|
||||
{
|
||||
$this->db->trans_begin();
|
||||
// // =========================
|
||||
// // UPDATE ITEM - RESPONSE KONSISTEN
|
||||
// // =========================
|
||||
// public function update_item()
|
||||
// {
|
||||
// $this->db->trans_begin();
|
||||
|
||||
$id = $this->input->post('id');
|
||||
$old = $this->db->get_where('invoice_details', ['id'=>$id])->row();
|
||||
// $id = $this->input->post('id');
|
||||
// $old = $this->db->get_where('invoice_details', ['id'=>$id])->row();
|
||||
|
||||
if(!$old){
|
||||
echo json_encode(['status'=>false, 'message'=>'Item tidak ditemukan']);
|
||||
return;
|
||||
}
|
||||
// if(!$old){
|
||||
// echo json_encode(['status'=>false, 'message'=>'Item tidak ditemukan']);
|
||||
// return;
|
||||
// }
|
||||
|
||||
$cek = $this->db->get_where('invoice_installments', [
|
||||
'invoice_detail_id' => $id
|
||||
])->num_rows();
|
||||
// $cek = $this->db->get_where('invoice_installments', [
|
||||
// 'invoice_detail_id' => $id
|
||||
// ])->num_rows();
|
||||
|
||||
if ($cek > 0) {
|
||||
echo json_encode([
|
||||
'status' => false,
|
||||
'message' => 'Item cicilan tidak bisa diubah. Hapus dan buat ulang.'
|
||||
]);
|
||||
return;
|
||||
}
|
||||
// if ($cek > 0) {
|
||||
// echo json_encode([
|
||||
// 'status' => false,
|
||||
// 'message' => 'Item cicilan tidak bisa diubah. Hapus dan buat ulang.'
|
||||
// ]);
|
||||
// return;
|
||||
// }
|
||||
|
||||
// 🔥 REVERSE DATA LAMA
|
||||
$this->delete_jurnal_item($id);
|
||||
$this->delete_stok_item($id);
|
||||
// // 🔥 REVERSE DATA LAMA
|
||||
// $this->delete_jurnal_item($id);
|
||||
// $this->delete_stok_item($id);
|
||||
|
||||
// DATA BARU
|
||||
$item_id = $this->input->post('item_id');
|
||||
$nama_item = $this->input->post('nama_item');
|
||||
$tanggal = $this->input->post('tanggal');
|
||||
// // DATA BARU
|
||||
// $item_id = $this->input->post('item_id');
|
||||
// $nama_item = $this->input->post('nama_item');
|
||||
// $tanggal = $this->input->post('tanggal');
|
||||
|
||||
$total_hpp = 0;
|
||||
// $total_hpp = 0;
|
||||
|
||||
if($item_id){
|
||||
$item = $this->db->get_where('items', ['id'=>$item_id])->row();
|
||||
if($item){
|
||||
$nama_item = $item->nama_barang;
|
||||
$stok = $this->get_stok($item_id);
|
||||
$qty = (float)$this->input->post('qty');
|
||||
$total_hpp = $this->input->post('qty') * $item->harga_beli;
|
||||
if($stok < $qty){
|
||||
echo json_encode(['status'=>false, 'message'=>'Stok tidak cukup']);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if($item_id){
|
||||
// $item = $this->db->get_where('items', ['id'=>$item_id])->row();
|
||||
// if($item){
|
||||
// $nama_item = $item->nama_barang;
|
||||
// $stok = $this->get_stok($item_id);
|
||||
// $qty = (float)$this->input->post('qty');
|
||||
// $total_hpp = $this->input->post('qty') * $item->harga_beli;
|
||||
// if($stok < $qty){
|
||||
// echo json_encode(['status'=>false, 'message'=>'Stok tidak cukup']);
|
||||
// return;
|
||||
// }
|
||||
|
||||
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
$qty = (float)$this->input->post('qty');
|
||||
$harga = (float)$this->input->post('harga');
|
||||
// $qty = (float)$this->input->post('qty');
|
||||
// $harga = (float)$this->input->post('harga');
|
||||
|
||||
// UPDATE
|
||||
$update_data = [
|
||||
'tanggal' => $tanggal,
|
||||
'account_id' => $this->input->post('account_id'),
|
||||
'items_id' => $item_id ?: null,
|
||||
'nama_item' => $nama_item,
|
||||
'qty' => $qty,
|
||||
'harga' => $harga,
|
||||
'subtotal' => $qty * $harga,
|
||||
'warehouse_id' => $this->input->post('warehouse_id'),
|
||||
'keterangan' => $this->input->post('keterangan'),
|
||||
'total_hpp_barang' => $total_hpp
|
||||
];
|
||||
// // UPDATE
|
||||
// $update_data = [
|
||||
// 'tanggal' => $tanggal,
|
||||
// 'account_id' => $this->input->post('account_id'),
|
||||
// 'items_id' => $item_id ?: null,
|
||||
// 'nama_item' => $nama_item,
|
||||
// 'qty' => $qty,
|
||||
// 'harga' => $harga,
|
||||
// 'subtotal' => $qty * $harga,
|
||||
// 'warehouse_id' => $this->input->post('warehouse_id'),
|
||||
// 'keterangan' => $this->input->post('keterangan'),
|
||||
// 'total_hpp_barang' => $total_hpp
|
||||
// ];
|
||||
|
||||
$this->db->where('id', $id)->update('invoice_details', $update_data);
|
||||
// $this->db->where('id', $id)->update('invoice_details', $update_data);
|
||||
|
||||
// GENERATE ULANG
|
||||
if($this->input->post('account_id') != 70) {
|
||||
$this->generate_jurnal_item($id);
|
||||
}
|
||||
$this->update_total($old->invoice_id);
|
||||
// // GENERATE ULANG
|
||||
// if($this->input->post('account_id') != 70) {
|
||||
// $this->generate_jurnal_item($id);
|
||||
// }
|
||||
// $this->update_total($old->invoice_id);
|
||||
|
||||
// ✅ RESPONSE KONSISTEN DENGAN JS
|
||||
if ($this->db->trans_status() === FALSE){
|
||||
$this->db->trans_rollback();
|
||||
echo json_encode(['status'=>false, 'message'=>'Update gagal']);
|
||||
} else {
|
||||
$this->db->trans_commit();
|
||||
// // ✅ RESPONSE KONSISTEN DENGAN JS
|
||||
// if ($this->db->trans_status() === FALSE){
|
||||
// $this->db->trans_rollback();
|
||||
// echo json_encode(['status'=>false, 'message'=>'Update gagal']);
|
||||
// } else {
|
||||
// $this->db->trans_commit();
|
||||
|
||||
log_activity(
|
||||
'invoice',
|
||||
'update_item',
|
||||
'Update item invoice detail ID ' . $id,
|
||||
'success'
|
||||
);
|
||||
// log_activity(
|
||||
// 'invoice',
|
||||
// 'update_item',
|
||||
// 'Update item invoice detail ID ' . $id,
|
||||
// 'success'
|
||||
// );
|
||||
|
||||
echo json_encode(['status'=>true, 'message'=>'Item berhasil diupdate']);
|
||||
}
|
||||
}
|
||||
// echo json_encode(['status'=>true, 'message'=>'Item berhasil diupdate']);
|
||||
// }
|
||||
// }
|
||||
|
||||
// =========================
|
||||
// DELETE ITEM - RESPONSE KONSISTEN
|
||||
// =========================
|
||||
public function delete_item($id)
|
||||
public function delete_item($id, $no_invoice)
|
||||
{
|
||||
$this->db->trans_begin();
|
||||
|
||||
@@ -792,6 +836,36 @@ class Invoices extends CI_Controller {
|
||||
$this->delete_stok_item($id);
|
||||
$this->db->delete('invoice_details', ['id'=>$id]);
|
||||
$this->update_total($d->invoice_id);
|
||||
|
||||
|
||||
if ($d->items_id AND $d->is_cicilan != 1) {
|
||||
// START - Item Movement & item barcodes update status
|
||||
$this->db->where('item_id', $d->items_id);
|
||||
$this->db->order_by('created_at', 'DESC');
|
||||
$this->db->limit(1);
|
||||
$item_move = $this->db->get('item_movements')->row();
|
||||
|
||||
// get item_barcode
|
||||
$itemBar = $this->db->get_where('item_barcodes', ['id'=>$d->barcode_id])->row();
|
||||
|
||||
$total_sisa = $itemBar->qty_sisa + $d->qty;
|
||||
$status_bar = ($total_sisa == 0) ? 'sold_out' : 'available';
|
||||
|
||||
$this->db->insert('item_movements',[
|
||||
'item_id' => $d->items_id,
|
||||
'barcode_id' => $d->barcode_id,
|
||||
'qty' => $d->qty,
|
||||
'from_type' => $item_move->to_type, //enum('supplier','warehouse','technician','customer','invoice')
|
||||
'to_type' => 'warehouse', //enum('supplier','warehouse','technician','customer','invoice')
|
||||
'movement_type' => 'purchase', //enum('purchase','transfer','installation','uninstallation','supplier_return','customer_return','adjustment','sold_out')
|
||||
'notes' => 'Barang di kembalikan ke gudang dari : ' . $no_invoice,
|
||||
'created_at' => date('Y-m-d H:i:s')
|
||||
]);
|
||||
|
||||
// $this->db->where('id', $d->barcode_id)->update('item_barcodes', ['status' => 'available']);
|
||||
$this->db->where('id', $d->barcode_id)->update('item_barcodes', ['status' => $status_bar, 'qty_sisa' => $total_sisa]);
|
||||
// END - Item Movement & item barcodes update status
|
||||
}
|
||||
|
||||
// ✅ RESPONSE KONSISTEN DENGAN JS
|
||||
if ($this->db->trans_status() === FALSE){
|
||||
@@ -1223,7 +1297,7 @@ class Invoices extends CI_Controller {
|
||||
}
|
||||
|
||||
|
||||
private function generate_installments($invoice_id, $detail_id, $customer_id, $total, $tenor, $start_date, $account_id, $item_id = null)
|
||||
private function generate_installments($invoice_id, $detail_id, $customer_id, $total, $tenor, $start_date, $account_id, $total_hpp, $item_id = null)
|
||||
{
|
||||
$nominal = round($total / $tenor);
|
||||
$sisa = $total - ($nominal * $tenor);
|
||||
@@ -1250,6 +1324,7 @@ class Invoices extends CI_Controller {
|
||||
'nominal' => $nilai,
|
||||
'account_id' => $account_id,
|
||||
'item_id' => $item_id ?: null,
|
||||
'cicilan_hpp_barang' => $total_hpp,
|
||||
'status' => 'unpaid',
|
||||
'is_billed' => $is_billed
|
||||
]);
|
||||
@@ -1336,7 +1411,8 @@ class Invoices extends CI_Controller {
|
||||
'keterangan' => $inv_items->keterangan,
|
||||
'subtotal_asli' => $inv_items->subtotal_asli,
|
||||
'is_cicilan' => $inv_items->is_cicilan,
|
||||
'source_cicilan_id' => $cicilan->id
|
||||
'source_cicilan_id' => $cicilan->id,
|
||||
'total_hpp_barang' => $cicilan->cicilan_hpp_barang
|
||||
]);
|
||||
|
||||
// =========================
|
||||
@@ -1498,6 +1574,7 @@ public function bayar()
|
||||
invoice_details.recognized_amount,
|
||||
invoice_details.total_hpp_barang,
|
||||
invoice_details.recognized_hpp,
|
||||
invoice_details.is_cicilan,
|
||||
accounts.priority
|
||||
')
|
||||
->from('invoice_details')
|
||||
|
||||
+461
-159
@@ -40,6 +40,98 @@ class Items extends CI_Controller {
|
||||
$this->load->view('partials/footer');
|
||||
}
|
||||
|
||||
public function item_barcodes_history()
|
||||
{
|
||||
$data = [
|
||||
"active_menu" => "item_historys"
|
||||
];
|
||||
|
||||
$this->load->view('partials/header', $data);
|
||||
$this->load->view('items/item_historys', $data);
|
||||
$this->load->view('partials/footer');
|
||||
}
|
||||
|
||||
public function scan_history()
|
||||
{
|
||||
$barcode = trim($this->input->post('barcode'));
|
||||
|
||||
if(empty($barcode)){
|
||||
echo json_encode([
|
||||
'status'=>false,
|
||||
'message'=>'QR ID tidak boleh kosong'
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
$item = $this->db
|
||||
->select("
|
||||
item_barcodes.id,
|
||||
item_barcodes.barcode,
|
||||
item_barcodes.serial_number,
|
||||
item_barcodes.status,
|
||||
item_barcodes.qty_awal,
|
||||
item_barcodes.qty_sisa,
|
||||
items.nama_barang,
|
||||
items.kode_detail
|
||||
")
|
||||
->from('item_barcodes')
|
||||
->join('items','items.id=item_barcodes.item_id')
|
||||
->where('item_barcodes.barcode',$barcode)
|
||||
->or_where('item_barcodes.serial_number',$barcode)
|
||||
->get()
|
||||
->row();
|
||||
|
||||
if(!$item){
|
||||
|
||||
echo json_encode([
|
||||
'status'=>false,
|
||||
'message'=>'Barcode tidak ditemukan.'
|
||||
]);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
$history = $this->db
|
||||
->select("
|
||||
item_movements.*,
|
||||
w1.nama as from_warehouse,
|
||||
w2.nama as to_warehouse
|
||||
")
|
||||
->from('item_movements')
|
||||
|
||||
->join(
|
||||
'warehouses w1',
|
||||
'w1.id=item_movements.from_id AND item_movements.from_type="warehouse"',
|
||||
'left'
|
||||
)
|
||||
|
||||
->join(
|
||||
'warehouses w2',
|
||||
'w2.id=item_movements.to_id AND item_movements.to_type="warehouse"',
|
||||
'left'
|
||||
)
|
||||
|
||||
->where('barcode_id',$item->id)
|
||||
|
||||
->order_by('created_at','DESC')
|
||||
|
||||
->get()
|
||||
|
||||
->result();
|
||||
|
||||
echo json_encode([
|
||||
|
||||
'status'=>true,
|
||||
|
||||
'item'=>$item,
|
||||
|
||||
'history'=>$history
|
||||
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
public function load_data_barcode($item_id)
|
||||
{
|
||||
$item = $this->db
|
||||
@@ -294,92 +386,103 @@ class Items extends CI_Controller {
|
||||
$this->load_data_barcode($barcode->item_id);
|
||||
}
|
||||
|
||||
public function get_barcode_item()
|
||||
{
|
||||
$barcode = trim($this->input->post('barcode'));
|
||||
public function get_barcode_item()
|
||||
{
|
||||
$barcode = trim($this->input->post('barcode'));
|
||||
|
||||
if ($barcode == '') {
|
||||
echo json_encode([
|
||||
'status' => false,
|
||||
'message' => 'Barcode kosong.'
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
$row = $this->db
|
||||
->select('
|
||||
ib.id AS barcode_id,
|
||||
ib.barcode,
|
||||
ib.serial_number,
|
||||
i.id AS item_id,
|
||||
i.kode_detail,
|
||||
i.nama_barang,
|
||||
i.status,
|
||||
i.harga_beli,
|
||||
i.harga_jual
|
||||
')
|
||||
->from('item_barcodes ib')
|
||||
->join('items i', 'i.id = ib.item_id')
|
||||
->where('ib.qty_sisa !=', 0)
|
||||
->where('i.status', 'active')
|
||||
->group_start()
|
||||
->where('ib.barcode', $barcode)
|
||||
->or_like('i.nama_barang', $barcode, 'both')
|
||||
->or_like('ib.serial_number', $barcode, 'both')
|
||||
->group_end()
|
||||
->limit(15)
|
||||
->get()
|
||||
->result();
|
||||
|
||||
if(!$row){
|
||||
echo json_encode([
|
||||
'status'=>false,
|
||||
'message'=>'Barcode tidak ditemukan.',
|
||||
'barcode' => $barcode
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($barcode == '') {
|
||||
echo json_encode([
|
||||
'status' => false,
|
||||
'message' => 'Barcode kosong.'
|
||||
'status'=>true,
|
||||
'data'=>$row
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
$row = $this->db
|
||||
->select('
|
||||
ib.id AS barcode_id,
|
||||
ib.barcode,
|
||||
ib.serial_number,
|
||||
i.id AS item_id,
|
||||
i.kode_detail,
|
||||
i.nama_barang,
|
||||
i.status,
|
||||
i.harga_beli,
|
||||
i.harga_jual
|
||||
')
|
||||
->from('item_barcodes ib')
|
||||
->join('items i','i.id=ib.item_id')
|
||||
->where('ib.barcode',$barcode)
|
||||
->get()
|
||||
->row();
|
||||
public function get_list_barcode_id($item_id)
|
||||
{
|
||||
// $item_id = trim($this->input->post('item_id'));
|
||||
|
||||
if(!$row){
|
||||
echo json_encode([
|
||||
'status'=>false,
|
||||
'message'=>'Barcode tidak ditemukan.'
|
||||
]);
|
||||
return;
|
||||
if ($item_id == '') {
|
||||
echo json_encode([
|
||||
'status' => false,
|
||||
'message' => 'Item belum dipilih'
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
$row = $this->db
|
||||
->select('
|
||||
ib.id AS barcode_id,
|
||||
ib.barcode,
|
||||
ib.serial_number,
|
||||
ib.qty_awal,
|
||||
ib.qty_sisa,
|
||||
i.id AS item_id,
|
||||
i.kode_detail,
|
||||
i.nama_barang,
|
||||
i.status,
|
||||
i.harga_beli,
|
||||
i.harga_jual
|
||||
')
|
||||
->from('item_barcodes ib')
|
||||
->join('items i','i.id=ib.item_id')
|
||||
->where('ib.item_id',$item_id)
|
||||
->where('ib.qty_sisa !=', 0)
|
||||
->where_in('ib.status', ['installed', 'reserved', 'available'])
|
||||
->get()
|
||||
->result();
|
||||
|
||||
if(!$row){
|
||||
echo json_encode([
|
||||
'status'=>false,
|
||||
'message'=>'Item barang tidak ditemukan.'
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
echo json_encode($row);
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'status'=>true,
|
||||
'data'=>$row
|
||||
]);
|
||||
}
|
||||
|
||||
public function get_list_barcode_id($item_id)
|
||||
{
|
||||
// $item_id = trim($this->input->post('item_id'));
|
||||
|
||||
if ($item_id == '') {
|
||||
echo json_encode([
|
||||
'status' => false,
|
||||
'message' => 'Item belum dipilih'
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
$row = $this->db
|
||||
->select('
|
||||
ib.id AS barcode_id,
|
||||
ib.barcode,
|
||||
ib.serial_number,
|
||||
i.id AS item_id,
|
||||
i.kode_detail,
|
||||
i.nama_barang,
|
||||
i.status,
|
||||
i.harga_beli,
|
||||
i.harga_jual
|
||||
')
|
||||
->from('item_barcodes ib')
|
||||
->join('items i','i.id=ib.item_id')
|
||||
->where('ib.item_id',$item_id)
|
||||
// ->where('ib.status','warehouse')
|
||||
->get()
|
||||
->result();
|
||||
|
||||
if(!$row){
|
||||
echo json_encode([
|
||||
'status'=>false,
|
||||
'message'=>'Item barang tidak ditemukan.'
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
echo json_encode($row);
|
||||
}
|
||||
|
||||
|
||||
// =========================
|
||||
// GET DATA (FIX)
|
||||
@@ -484,7 +587,7 @@ public function get_list_barcode_id($item_id)
|
||||
} else {
|
||||
$btnAdjust = '';
|
||||
}
|
||||
$action = $btnDetail . $btnEdit . $btnAdjust . $btnDelete . $btnSN;
|
||||
$action = $btnDetail . $btnEdit . $btnAdjust . $btnSN;
|
||||
|
||||
}
|
||||
|
||||
@@ -578,7 +681,8 @@ public function get_list_barcode_id($item_id)
|
||||
if(!$nama_barang || $qty <= 0 || $harga_beli <= 0 || !$warehouse_id || !$account_kas){
|
||||
echo json_encode([
|
||||
'status'=>false,
|
||||
'message'=>'Data tidak lengkap / tidak valid'
|
||||
'message'=>'Data tidak lengkap / tidak valid',
|
||||
'account_id' => $account_kas
|
||||
]);
|
||||
return;
|
||||
}
|
||||
@@ -655,7 +759,9 @@ public function get_list_barcode_id($item_id)
|
||||
// ================= Item Barcode Masuk =================
|
||||
for ($i = 1; $i <= $unit_qty; $i++) {
|
||||
|
||||
$barcode = sprintf('%s-%04d', $kode_detail, $i);
|
||||
// $barcode = sprintf('%s-%04d', $kode_detail, $i);
|
||||
|
||||
$barcode = strtoupper($kode_detail) . '-' . strtoupper(bin2hex(random_bytes(2)));
|
||||
|
||||
$this->db->insert('item_barcodes',[
|
||||
'item_id' => $item_id,
|
||||
@@ -680,39 +786,6 @@ public function get_list_barcode_id($item_id)
|
||||
'created_at' => date('Y-m-d H:i:s')
|
||||
]);
|
||||
}
|
||||
// CREATE TABLE `item_barcodes` (
|
||||
// `id` int NOT NULL AUTO_INCREMENT,
|
||||
// `item_id` int NOT NULL,
|
||||
// `barcode` varchar(100) NOT NULL,
|
||||
// `serial_number` varchar(100) DEFAULT NULL,
|
||||
// `warehouse_id` int DEFAULT NULL,
|
||||
// `qty_awal` decimal(15,2) DEFAULT NULL,
|
||||
// `qty_sisa` decimal(15,2) DEFAULT NULL,
|
||||
// `status` enum('available','reserved','installed','damaged','lost','returned_supplier') DEFAULT 'available',
|
||||
// `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
// PRIMARY KEY (`id`),
|
||||
// UNIQUE KEY `uk_barcode` (`barcode`),
|
||||
// KEY `idx_item` (`item_id`),
|
||||
// KEY `idx_warehouse` (`warehouse_id`),
|
||||
// CONSTRAINT `fk_barcode_item` FOREIGN KEY (`item_id`) REFERENCES `items` (`id`) ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
// ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||
|
||||
|
||||
// CREATE TABLE `item_movements` (
|
||||
// `id` int NOT NULL AUTO_INCREMENT,
|
||||
// `item_id` int NOT NULL,
|
||||
// `barcode_id` int DEFAULT NULL,
|
||||
// `qty` decimal(15,2) NOT NULL DEFAULT '1.00',
|
||||
// `from_type` enum('supplier','warehouse','technician','customer') DEFAULT NULL,
|
||||
// `from_id` int DEFAULT NULL,
|
||||
// `to_type` enum('supplier','warehouse','technician','customer') DEFAULT NULL,
|
||||
// `to_id` int DEFAULT NULL,
|
||||
// `movement_type` enum('purchase','transfer','installation','uninstallation','supplier_return','customer_return','adjustment') NOT NULL,
|
||||
// `reference_type` varchar(50) DEFAULT NULL,
|
||||
// `reference_id` int DEFAULT NULL,
|
||||
// `notes` varchar(255) DEFAULT NULL,
|
||||
// `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
|
||||
// ================= JURNAL =================
|
||||
$no_ref = 'BLI-'.date('Ymd').'-'.$item_id;
|
||||
@@ -737,12 +810,16 @@ public function get_list_barcode_id($item_id)
|
||||
]);
|
||||
|
||||
// 🔥 Kredit Kas (DINAMIS)
|
||||
$this->db->insert('journal_details',[
|
||||
'journal_id'=>$jid,
|
||||
'account_id'=>$account_kas,
|
||||
'debit'=>0,
|
||||
'kredit'=>$total
|
||||
]);
|
||||
foreach ($account_kas as $row) {
|
||||
|
||||
$this->db->insert('journal_details', [
|
||||
'journal_id' => $jid,
|
||||
'account_id' => $row['account_id'],
|
||||
'debit' => 0,
|
||||
'kredit' => str_replace('.', '', $row['nominal'])
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
$this->db->trans_complete();
|
||||
|
||||
@@ -988,33 +1065,157 @@ public function get_list_barcode_id($item_id)
|
||||
// =========================
|
||||
public function keluarkan()
|
||||
{
|
||||
$account_biaya = (int)$this->input->post('account_biaya');
|
||||
$tanggal_keluar = $this->input->post('tanggal_keluar');
|
||||
$account_biaya = (int)$this->input->post('account_biaya');
|
||||
$tanggal_keluar = $this->input->post('tanggal_keluar');
|
||||
$keterangan_keluar = $this->input->post('keterangan_keluar');
|
||||
|
||||
// mode baru: single barcode terpilih
|
||||
$selected_barcode = (int)$this->input->post('selected_barcode');
|
||||
if ($selected_barcode > 0) {
|
||||
|
||||
if (!$account_biaya || !$tanggal_keluar) {
|
||||
echo json_encode(['status'=>false,'message'=>'Data tidak lengkap']);
|
||||
return;
|
||||
}
|
||||
|
||||
$barcode = $this->db
|
||||
->select('
|
||||
ib.id as barcode_id,
|
||||
ib.item_id,
|
||||
ib.qty_sisa,
|
||||
ib.warehouse_id,
|
||||
ib.status as barcode_status,
|
||||
i.nama_barang,
|
||||
i.harga_beli
|
||||
')
|
||||
->from('item_barcodes ib')
|
||||
->join('items i', 'i.id = ib.item_id')
|
||||
->where('ib.id', $selected_barcode)
|
||||
->get()
|
||||
->row();
|
||||
|
||||
if (!$barcode) {
|
||||
echo json_encode(['status'=>false,'message'=>'Barcode tidak ditemukan']);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((float)$barcode->qty_sisa <= 0) {
|
||||
echo json_encode(['status'=>false,'message'=>'Qty barcode sudah habis']);
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($barcode->warehouse_id)) {
|
||||
echo json_encode(['status'=>false,'message'=>'Warehouse barcode tidak valid']);
|
||||
return;
|
||||
}
|
||||
|
||||
$qty_keluar = 1;
|
||||
$nilai = $qty_keluar * (float)$barcode->harga_beli;
|
||||
|
||||
$this->db->trans_start();
|
||||
|
||||
// stock log keluar per item
|
||||
$this->db->insert('stock_logs',[
|
||||
'item_id' => $barcode->item_id,
|
||||
'warehouse_id' => $barcode->warehouse_id,
|
||||
'qty' => $qty_keluar,
|
||||
'tipe' => 'keluar',
|
||||
'keterangan' => $keterangan_keluar
|
||||
]);
|
||||
$stock_log_id = $this->db->insert_id();
|
||||
|
||||
// jurnal
|
||||
$this->db->insert('journals',[
|
||||
'tanggal' => $tanggal_keluar,
|
||||
'no_ref' => 'GOUT-'.date('YmdHis').'-'.$barcode->item_id,
|
||||
'keterangan' => 'Pengeluaran Barang '.$barcode->nama_barang.' ( '.$keterangan_keluar.' )',
|
||||
'ref_type' => 'stock_logs',
|
||||
'ref_id' => $stock_log_id,
|
||||
'created_by' => $this->session->userdata('user_id')
|
||||
]);
|
||||
$jid = $this->db->insert_id();
|
||||
|
||||
$this->db->insert('journal_details',[
|
||||
'journal_id'=>$jid,
|
||||
'account_id'=>$account_biaya,
|
||||
'debit'=>$nilai,
|
||||
'kredit'=>0
|
||||
]);
|
||||
|
||||
$this->db->insert('journal_details',[
|
||||
'journal_id'=>$jid,
|
||||
'account_id'=>21,
|
||||
'debit'=>0,
|
||||
'kredit'=>$nilai
|
||||
]);
|
||||
|
||||
// START - Item Movement & item barcodes update status
|
||||
$this->db->where('barcode_id', $barcode->barcode_id);
|
||||
$this->db->order_by('created_at', 'DESC');
|
||||
$this->db->limit(1);
|
||||
$item_move = $this->db->get('item_movements')->row();
|
||||
|
||||
if($barcode->qty_sisa < $qty_keluar) {
|
||||
echo json_encode(['status'=>false, 'message'=>'Stok tidak cukup. Sisa: '.$barcode->qty_sisa]);
|
||||
$this->db->trans_rollback();
|
||||
return;
|
||||
}
|
||||
|
||||
$this->db->insert('item_movements',[
|
||||
'item_id' => $barcode->item_id,
|
||||
'barcode_id' => $barcode->barcode_id,
|
||||
'qty' => $qty_keluar,
|
||||
'from_type' => $item_move ? $item_move->to_type : 'warehouse', //enum('supplier','warehouse','technician','customer','invoice','asset')
|
||||
'to_type' => 'technician', //enum('supplier','warehouse','technician','customer','invoice','asset')
|
||||
'movement_type' => 'installation', //enum('purchase','transfer','installation','uninstallation','supplier_return','customer_return','adjustment','sold_out','asset')
|
||||
'notes' => $keterangan_keluar,
|
||||
'created_at' => date('Y-m-d H:i:s')
|
||||
]);
|
||||
|
||||
// update qty_sisa barcode
|
||||
$new_qty_sisa = (float)$barcode->qty_sisa - $qty_keluar;
|
||||
$this->db->where('id', $barcode->barcode_id)->update('item_barcodes', [
|
||||
'qty_sisa' => $new_qty_sisa,
|
||||
'status' => $new_qty_sisa <= 0 ? 'installed' : $barcode->barcode_status
|
||||
]);
|
||||
// END - Item Movement & item barcodes update status
|
||||
|
||||
$this->db->trans_complete();
|
||||
|
||||
if (!$this->db->trans_status()) {
|
||||
echo json_encode(['status'=>false,'message'=>'Gagal proses']);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->update_item_stok($barcode->item_id);
|
||||
|
||||
log_activity(
|
||||
'items',
|
||||
'stock_out',
|
||||
'Keluar barcode: '.$barcode->barcode_id.' | '.$barcode->nama_barang.' qty: '.$qty_keluar.' ( '.$keterangan_keluar.' )',
|
||||
'success'
|
||||
);
|
||||
|
||||
echo json_encode(['status'=>true,'message'=>'Barang berhasil dikeluarkan']);
|
||||
return;
|
||||
}
|
||||
|
||||
// fallback flow lama
|
||||
$warehouse_id_keluar = $this->input->post('warehouse_id_keluar');
|
||||
$barang_id = $this->input->post('barang_id');
|
||||
$qty_keluar = (int)$this->input->post('qty_keluar');
|
||||
$keterangan_keluar = $this->input->post('keterangan_keluar');
|
||||
|
||||
// =========================
|
||||
// VALIDASI
|
||||
// =========================
|
||||
|
||||
if(!$barang_id || !$warehouse_id_keluar || $qty_keluar <= 0){
|
||||
echo json_encode(['status'=>false,'message'=>'Data tidak valid']);
|
||||
return;
|
||||
}
|
||||
|
||||
// =========================
|
||||
// CEK ITEM
|
||||
// =========================
|
||||
|
||||
$item = $this->db->get_where('items',['id'=>$barang_id])->row();
|
||||
if(!$item){
|
||||
echo json_encode(['status'=>false,'message'=>'Item tidak ditemukan']);
|
||||
return;
|
||||
}
|
||||
|
||||
// =========================
|
||||
// HITUNG STOK
|
||||
// =========================
|
||||
|
||||
$stok = $this->db->select('
|
||||
COALESCE(SUM(qty * IF(tipe="masuk",1,-1)),0) as stok
|
||||
')
|
||||
@@ -1022,20 +1223,16 @@ public function get_list_barcode_id($item_id)
|
||||
->where('warehouse_id',$warehouse_id_keluar)
|
||||
->get('stock_logs')
|
||||
->row()->stok;
|
||||
|
||||
|
||||
if($stok < $qty_keluar){
|
||||
echo json_encode(['status'=>false,'message'=>'Stok tidak cukup']);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$nilai = $qty_keluar * (float)$item->harga_beli;
|
||||
|
||||
// =========================
|
||||
// TRANSACTION
|
||||
// =========================
|
||||
|
||||
$this->db->trans_start();
|
||||
|
||||
// log keluar
|
||||
|
||||
$this->db->insert('stock_logs',[
|
||||
'item_id'=>$barang_id,
|
||||
'warehouse_id'=>$warehouse_id_keluar,
|
||||
@@ -1043,10 +1240,9 @@ public function get_list_barcode_id($item_id)
|
||||
'tipe'=>'keluar',
|
||||
'keterangan'=>$keterangan_keluar
|
||||
]);
|
||||
|
||||
|
||||
$stock_log_id = $this->db->insert_id();
|
||||
|
||||
// jurnal
|
||||
|
||||
$this->db->insert('journals',[
|
||||
'tanggal'=>$tanggal_keluar,
|
||||
'no_ref'=>'GOUT-'.date('YmdHis').'-'.$barang_id,
|
||||
@@ -1055,44 +1251,39 @@ public function get_list_barcode_id($item_id)
|
||||
'ref_id' => $stock_log_id,
|
||||
'created_by' => $this->session->userdata('user_id')
|
||||
]);
|
||||
|
||||
|
||||
$jid = $this->db->insert_id();
|
||||
|
||||
// Debit biaya / HPP
|
||||
|
||||
$this->db->insert('journal_details',[
|
||||
'journal_id'=>$jid,
|
||||
'account_id'=>$account_biaya,
|
||||
'debit'=>$nilai,
|
||||
'kredit'=>0
|
||||
]);
|
||||
|
||||
// Kredit persediaan
|
||||
|
||||
$this->db->insert('journal_details',[
|
||||
'journal_id'=>$jid,
|
||||
'account_id'=>21,
|
||||
'debit'=>0,
|
||||
'kredit'=>$nilai
|
||||
]);
|
||||
|
||||
|
||||
$this->db->trans_complete();
|
||||
|
||||
// =========================
|
||||
// CEK TRANSACTION
|
||||
// =========================
|
||||
|
||||
if (!$this->db->trans_status()) {
|
||||
echo json_encode(['status'=>false,'message'=>'Gagal proses']);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
log_activity(
|
||||
'items',
|
||||
'stock_out',
|
||||
'Keluar barang: ' . $item->nama_barang . ' qty: ' . $qty_keluar . ' ( ' . $keterangan_keluar . ' )',
|
||||
'success'
|
||||
);
|
||||
|
||||
|
||||
$this->update_item_stok($barang_id);
|
||||
|
||||
|
||||
echo json_encode(['status'=>true,'message'=>'Barang berhasil dikeluarkan']);
|
||||
}
|
||||
|
||||
@@ -1232,4 +1423,115 @@ public function get_list_barcode_id($item_id)
|
||||
|
||||
echo json_encode($data);
|
||||
}
|
||||
|
||||
public function update_barcode_item()
|
||||
{
|
||||
$items = $this->db
|
||||
->select("
|
||||
i.id,
|
||||
i.nama_barang,
|
||||
i.stok,
|
||||
i.kode_detail,
|
||||
kb.tracking_type
|
||||
")
|
||||
->from('items i')
|
||||
->join('kode_barang kb', 'kb.id=i.kode_id')
|
||||
->where('i.status', 'active')
|
||||
->get()
|
||||
->result();
|
||||
|
||||
$this->db->trans_begin();
|
||||
|
||||
foreach ($items as $item) {
|
||||
|
||||
// ===========================================
|
||||
// Hitung jumlah barcode yang seharusnya
|
||||
// ===========================================
|
||||
|
||||
if ($item->tracking_type == 'UNIT') {
|
||||
$target = (int)$item->stok;
|
||||
} else {
|
||||
$target = (int)floor($item->stok / 1000);
|
||||
}
|
||||
|
||||
if ($target <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// ===========================================
|
||||
// Barcode yang sudah ada
|
||||
// ===========================================
|
||||
|
||||
$barcode_exist = $this->db
|
||||
->where('item_id', $item->id)
|
||||
->count_all_results('item_barcodes');
|
||||
|
||||
if ($barcode_exist >= $target) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$need = $target - $barcode_exist;
|
||||
|
||||
for ($i = 1; $i <= $need; $i++) {
|
||||
|
||||
$barcode = strtoupper($item->kode_detail) . '-' . strtoupper(bin2hex(random_bytes(2)));
|
||||
|
||||
$qty = ($item->tracking_type == 'UNIT')
|
||||
? 1
|
||||
: 1000;
|
||||
|
||||
// =============================
|
||||
// Insert Barcode
|
||||
// =============================
|
||||
|
||||
$this->db->insert('item_barcodes', [
|
||||
'item_id' => $item->id,
|
||||
'barcode' => $barcode,
|
||||
'warehouse_id' => null,
|
||||
'qty_awal' => $qty,
|
||||
'qty_sisa' => $qty,
|
||||
'status' => 'available'
|
||||
]);
|
||||
|
||||
$barcode_id = $this->db->insert_id();
|
||||
|
||||
// =============================
|
||||
// Insert Movement
|
||||
// =============================
|
||||
|
||||
$this->db->insert('item_movements', [
|
||||
'item_id' => $item->id,
|
||||
'barcode_id' => $barcode_id,
|
||||
'qty' => $qty,
|
||||
'from_type' => 'supplier',
|
||||
'from_id' => null,
|
||||
'to_type' => 'warehouse',
|
||||
'to_id' => null,
|
||||
'movement_type' => 'purchase',
|
||||
'reference_type' => 'system_generate',
|
||||
'reference_id' => null,
|
||||
'notes' => 'Generate barcode otomatis'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->db->trans_status() == false) {
|
||||
|
||||
$this->db->trans_rollback();
|
||||
|
||||
echo json_encode([
|
||||
'status' => false,
|
||||
'message' => 'Gagal generate barcode.'
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->db->trans_commit();
|
||||
|
||||
echo json_encode([
|
||||
'status' => true,
|
||||
'message' => 'Barcode berhasil diperbarui.'
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ class Kodebarang extends CI_Controller {
|
||||
// =========================
|
||||
public function get_data()
|
||||
{
|
||||
$data = $this->db->get('kode_barang')->result();
|
||||
$data = $this->db->order_by('id', 'DESC')->get('kode_barang')->result();
|
||||
|
||||
$result = [];
|
||||
$no = 1;
|
||||
@@ -35,7 +35,10 @@ class Kodebarang extends CI_Controller {
|
||||
$no++,
|
||||
$row->kode_barang,
|
||||
$row->nama,
|
||||
$row->limit_stock,
|
||||
(int)$row->limit_stock,
|
||||
strtoupper($row->tracking_type ?? 'UNIT'),
|
||||
strtolower($row->need_serial_number ?? 'false') === 'true' ? 'Ya' : 'Tidak',
|
||||
$row->unit ?? 'PCS',
|
||||
'
|
||||
<button class="btn btn-sm btn-secondary btn-editkode" data-id="'.$row->id.'">Edit</button>
|
||||
<button class="btn btn-sm btn-danger btn-delete" data-id="'.$row->id.'">Delete</button>
|
||||
@@ -61,29 +64,57 @@ class Kodebarang extends CI_Controller {
|
||||
// =========================
|
||||
public function save()
|
||||
{
|
||||
$nama = $this->input->post('nama');
|
||||
$kode = $this->input->post('kode');
|
||||
$limit_stock = $this->input->post('limit_stock');
|
||||
$nama = trim($this->input->post('nama'));
|
||||
$kode = trim($this->input->post('kode'));
|
||||
$limit_stock = (int)$this->input->post('limit_stock');
|
||||
$tracking_type = strtoupper(trim($this->input->post('tracking_type')));
|
||||
$need_serial_number = strtolower(trim($this->input->post('need_serial_number')));
|
||||
$unit = trim($this->input->post('unit'));
|
||||
|
||||
if(!$nama){
|
||||
echo json_encode(['status'=>false,'message'=>'Nama wajib diisi']);
|
||||
if(!$nama || !$kode){
|
||||
echo json_encode(['status'=>false,'message'=>'Kode dan nama wajib diisi']);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!in_array($tracking_type, ['UNIT','QTY'])){
|
||||
echo json_encode(['status'=>false,'message'=>'Tracking type tidak valid']);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!in_array($need_serial_number, ['true','false'])){
|
||||
echo json_encode(['status'=>false,'message'=>'Need serial number tidak valid']);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!in_array($unit, ['PCS','Meter','Lembar'])){
|
||||
echo json_encode(['status'=>false,'message'=>'Unit tidak valid']);
|
||||
return;
|
||||
}
|
||||
|
||||
$exists = $this->db->get_where('kode_barang', ['kode_barang' => $kode])->num_rows();
|
||||
if($exists > 0){
|
||||
echo json_encode(['status'=>false,'message'=>'Kode barang sudah digunakan']);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->db->insert('kode_barang', [
|
||||
'kode_barang' => $kode,
|
||||
'nama' => $nama,
|
||||
'limit_stock' => $limit_stock
|
||||
'created_at' => date('Y-m-d H:i:s'),
|
||||
'limit_stock' => $limit_stock,
|
||||
'tracking_type' => $tracking_type,
|
||||
'need_serial_number' => $need_serial_number,
|
||||
'unit' => $unit
|
||||
]);
|
||||
|
||||
log_activity(
|
||||
'kode_barang',
|
||||
'create',
|
||||
'Menambahkan kode barang: ' . $nama,
|
||||
'Menambahkan kode barang: ' . $kode . ' - ' . $nama,
|
||||
'success'
|
||||
);
|
||||
|
||||
echo json_encode(['status'=>true,'message'=>'Gudang berhasil ditambahkan']);
|
||||
echo json_encode(['status'=>true,'message'=>'Kode barang berhasil ditambahkan']);
|
||||
}
|
||||
|
||||
// =========================
|
||||
@@ -91,30 +122,62 @@ class Kodebarang extends CI_Controller {
|
||||
// =========================
|
||||
public function update()
|
||||
{
|
||||
$id = $this->input->post('id');
|
||||
$kode = $this->input->post('kode');
|
||||
$nama = $this->input->post('nama');
|
||||
$limit_stock = $this->input->post('limit_stock');
|
||||
$id = (int)$this->input->post('id');
|
||||
$kode = trim($this->input->post('kode'));
|
||||
$nama = trim($this->input->post('nama'));
|
||||
$limit_stock = (int)$this->input->post('limit_stock');
|
||||
$tracking_type = strtoupper(trim($this->input->post('tracking_type')));
|
||||
$need_serial_number = strtolower(trim($this->input->post('need_serial_number')));
|
||||
$unit = trim($this->input->post('unit'));
|
||||
|
||||
if(!$nama){
|
||||
echo json_encode(['status'=>false,'message'=>'Nama wajib diisi']);
|
||||
if(!$id || !$nama || !$kode){
|
||||
echo json_encode(['status'=>false,'message'=>'ID, kode dan nama wajib diisi']);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!in_array($tracking_type, ['UNIT','QTY'])){
|
||||
echo json_encode(['status'=>false,'message'=>'Tracking type tidak valid']);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!in_array($need_serial_number, ['true','false'])){
|
||||
echo json_encode(['status'=>false,'message'=>'Need serial number tidak valid']);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!in_array($unit, ['PCS','Meter','Lembar'])){
|
||||
echo json_encode(['status'=>false,'message'=>'Unit tidak valid']);
|
||||
return;
|
||||
}
|
||||
|
||||
$exists = $this->db
|
||||
->where('kode_barang', $kode)
|
||||
->where('id !=', $id)
|
||||
->get('kode_barang')
|
||||
->num_rows();
|
||||
|
||||
if($exists > 0){
|
||||
echo json_encode(['status'=>false,'message'=>'Kode barang sudah digunakan']);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->db->where('id',$id)->update('kode_barang', [
|
||||
'kode_barang' => $kode,
|
||||
'nama' => $nama,
|
||||
'limit_stock' => $limit_stock
|
||||
'limit_stock' => $limit_stock,
|
||||
'tracking_type' => $tracking_type,
|
||||
'need_serial_number' => $need_serial_number,
|
||||
'unit' => $unit
|
||||
]);
|
||||
|
||||
log_activity(
|
||||
'kode_barang',
|
||||
'update',
|
||||
'Update kode barang ID: ' . $id . ' nama: ' . $nama,
|
||||
'Update kode barang ID: ' . $id . ' (' . $kode . ' - ' . $nama . ')',
|
||||
'success'
|
||||
);
|
||||
|
||||
echo json_encode(['status'=>true,'message'=>'Gudang berhasil diupdate']);
|
||||
echo json_encode(['status'=>true,'message'=>'Kode barang berhasil diupdate']);
|
||||
}
|
||||
|
||||
// =========================
|
||||
@@ -122,13 +185,23 @@ class Kodebarang extends CI_Controller {
|
||||
// =========================
|
||||
public function delete($id)
|
||||
{
|
||||
// optional: cek relasi ke items
|
||||
$cek = $this->db->get_where('items',['warehouse_id'=>$id])->num_rows();
|
||||
$row = $this->db->get_where('kode_barang', ['id'=>$id])->row();
|
||||
|
||||
if(!$row){
|
||||
echo json_encode([
|
||||
'status'=>false,
|
||||
'message'=>'Data kode barang tidak ditemukan'
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
// cek relasi ke items (mengacu ke kode_id)
|
||||
$cek = $this->db->get_where('items',['kode_id'=>$id])->num_rows();
|
||||
|
||||
if($cek > 0){
|
||||
echo json_encode([
|
||||
'status'=>false,
|
||||
'message'=>'Gudang tidak bisa dihapus karena masih dipakai item'
|
||||
'message'=>'Kode barang tidak bisa dihapus karena masih dipakai item'
|
||||
]);
|
||||
return;
|
||||
}
|
||||
@@ -138,11 +211,11 @@ class Kodebarang extends CI_Controller {
|
||||
log_activity(
|
||||
'kode_barang',
|
||||
'delete',
|
||||
'Hapus gudang ID: ' . $id,
|
||||
'Hapus kode barang ID: ' . $id . ' (' . $row->kode_barang . ' - ' . $row->nama . ')',
|
||||
'success'
|
||||
);
|
||||
|
||||
echo json_encode(['status'=>true,'message'=>'Gudang berhasil dihapus']);
|
||||
echo json_encode(['status'=>true,'message'=>'Kode barang berhasil dihapus']);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -26,87 +26,54 @@ class Neracasaldo extends CI_Controller {
|
||||
$this->load->view('partials/footer');
|
||||
}
|
||||
|
||||
// =========================
|
||||
// HITUNG LABA BERJALAN (REALTIME)
|
||||
// =========================
|
||||
private function get_laba_berjalan()
|
||||
{
|
||||
$this->db->select('
|
||||
accounts.tipe,
|
||||
COALESCE(SUM(journal_details.debit),0) as debit,
|
||||
COALESCE(SUM(journal_details.kredit),0) as kredit
|
||||
');
|
||||
$this->db->from('accounts');
|
||||
$this->db->join('journal_details','journal_details.account_id = accounts.id','LEFT');
|
||||
$this->db->where_in('accounts.tipe',['revenue','expense']);
|
||||
|
||||
$rows = $this->db->get()->result();
|
||||
|
||||
$revenue = 0;
|
||||
$expense = 0;
|
||||
|
||||
foreach ($rows as $r) {
|
||||
if ($r->tipe == 'revenue') {
|
||||
$revenue += ($r->kredit - $r->debit);
|
||||
} else {
|
||||
$expense += ($r->debit - $r->kredit);
|
||||
}
|
||||
}
|
||||
|
||||
return $revenue - $expense;
|
||||
}
|
||||
|
||||
public function get_data()
|
||||
{
|
||||
$this->db->select('
|
||||
$tanggal_awal = $this->input->get('tanggal_awal');
|
||||
$tanggal_akhir = $this->input->get('tanggal_akhir');
|
||||
|
||||
$this->db->select("
|
||||
accounts.id,
|
||||
accounts.kode_akun,
|
||||
accounts.nama_akun,
|
||||
accounts.kategori,
|
||||
accounts.tipe,
|
||||
accounts.posisi,
|
||||
COALESCE(SUM(journal_details.debit),0) as debit,
|
||||
COALESCE(SUM(journal_details.kredit),0) as kredit
|
||||
');
|
||||
COALESCE(SUM(journal_details.debit),0) AS debit,
|
||||
COALESCE(SUM(journal_details.kredit),0) AS kredit
|
||||
");
|
||||
|
||||
$this->db->from('accounts');
|
||||
$this->db->join('journal_details','journal_details.account_id = accounts.id','LEFT');
|
||||
|
||||
// OPTIONAL (best practice)
|
||||
$this->db->where('accounts.is_active',1);
|
||||
$this->db->where('accounts.kategori','neraca');
|
||||
if (!empty($tanggal_awal) && !empty($tanggal_akhir)) {
|
||||
|
||||
$this->db->group_by('accounts.id');
|
||||
$this->db->order_by('accounts.kode_akun','ASC');
|
||||
$this->db->join(
|
||||
"(SELECT jd.*
|
||||
FROM journal_details jd
|
||||
JOIN journals j ON j.id = jd.journal_id
|
||||
WHERE j.tanggal BETWEEN ".$this->db->escape($tanggal_awal)."
|
||||
AND ".$this->db->escape($tanggal_akhir)."
|
||||
) journal_details",
|
||||
"journal_details.account_id = accounts.id",
|
||||
"left",
|
||||
false
|
||||
);
|
||||
|
||||
$rows = $this->db->get()->result();
|
||||
} else {
|
||||
|
||||
// =========================
|
||||
// HITUNG LABA BERJALAN
|
||||
// =========================
|
||||
$laba = $this->get_laba_berjalan();
|
||||
$this->db->join(
|
||||
'journal_details',
|
||||
'journal_details.account_id = accounts.id',
|
||||
'left'
|
||||
);
|
||||
|
||||
foreach ($rows as $r) {
|
||||
|
||||
// ================= SALDO NORMAL
|
||||
if ($r->posisi == 'debit') {
|
||||
$saldo = $r->debit - $r->kredit;
|
||||
} else {
|
||||
$saldo = $r->kredit - $r->debit;
|
||||
}
|
||||
|
||||
// ================= OVERRIDE LABA BERJALAN
|
||||
if ($r->kode_akun == '302') {
|
||||
$saldo = $laba;
|
||||
}
|
||||
|
||||
// ================= NORMALISASI KE KOLOM
|
||||
if ($saldo >= 0 AND $r->posisi == 'debit') {
|
||||
$r->saldo_debit = $saldo;
|
||||
$r->saldo_kredit = 0;
|
||||
} else {
|
||||
$r->saldo_debit = 0;
|
||||
$r->saldo_kredit = abs($saldo);
|
||||
}
|
||||
}
|
||||
|
||||
$rows = $this->db
|
||||
->where('accounts.is_active', 1)
|
||||
->group_by('accounts.id')
|
||||
->order_by('accounts.kode_akun', 'ASC')
|
||||
->get()
|
||||
->result();
|
||||
|
||||
echo json_encode($rows);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user