input('periode'); session(['periode_pengadaan' => $periode]); return redirect('/rencana-pengadaan'); } public function index(Request $request) { $periodes = DB::table('prediction_results') ->selectRaw("CONCAT(tahun_prediksi,'-',LPAD(bulan_prediksi,2,'0')) as periode") ->distinct() ->orderBy('periode', 'desc') ->get(); $periodeList = $periodes->pluck('periode')->toArray(); $periodeStep = 1; if (count($periodeList) >= 2) { $first = Carbon::createFromFormat('Y-m', $periodeList[count($periodeList) - 1]); $second = Carbon::createFromFormat('Y-m', $periodeList[count($periodeList) - 2]); $periodeStep = abs($first->diffInMonths($second)); } $minPeriode = $periodes->last()->periode ?? null; $maxPeriode = $periodes->first()->periode ?? null; $periode = session('periode_pengadaan', $maxPeriode); $periodeDefault = $periode; [$tahun, $bulan] = explode('-', $periode); $tahun = (int) $tahun; $bulan = (int) $bulan; $tanggalAkhir = Carbon::create($tahun, $bulan, 1)->endOfMonth()->toDateString(); $stokSubquery = DB::table('stock_transaction_details as std') ->join('stock_transactions as st', 'std.no_transaksi', '=', 'st.no_transaksi') ->select( 'std.kode', DB::raw('SUM(std.qty_masuk - std.qty_keluar) as stok') ) ->whereDate('st.tanggal', '<=', $tanggalAkhir) ->groupBy('std.kode'); $data = DB::table('prediction_results as pr') ->join('items as i', 'pr.kode', '=', 'i.kode') ->leftJoinSub($stokSubquery, 'stok_data', function ($join) { $join->on('pr.kode', '=', 'stok_data.kode'); }) ->where('pr.bulan_prediksi', $bulan) ->where('pr.tahun_prediksi', $tahun) ->where('i.kategori', 0) ->select( 'pr.kode', 'i.nama_barang', 'i.satuan', 'pr.jumlah_prediksi', DB::raw('COALESCE(stok_data.stok, 0) as stok') ) ->get(); $rows = $data->map(function ($item) { $stokReal = (int) $item->stok; $stok = max(0, $stokReal); $selisih = $stok - $item->jumlah_prediksi; $usulan = $selisih < 0 ? abs($selisih) : 0; return [ 'kode' => $item->kode, 'nama_barang' => $item->nama_barang, 'satuan' => $item->satuan, 'prediksi' => $item->jumlah_prediksi, 'stok' => $stok, 'stok_real' => $stokReal, 'selisih' => $selisih, 'usulan' => $usulan, 'status' => $usulan > 0 ? 'Perlu Restock' : 'Aman', ]; }); $totalBarang = $rows->count(); $perluRestock = $rows->where('status', 'Perlu Restock')->count(); $aman = $rows->where('status', 'Aman')->count(); $totalUsulan = $rows->sum('usulan'); return view('rencana-pengadaan', compact( 'rows', 'minPeriode', 'maxPeriode', 'periodeDefault', 'periodeList', 'periodeStep', 'totalBarang', 'perluRestock', 'aman', 'totalUsulan' )); } public function cetak(Request $request) { $periode = session('periode_pengadaan'); [$tahun, $bulan] = explode('-', $periode); $tahun = (int) $tahun; $bulan = (int) $bulan; $tanggalAkhir = Carbon::create($tahun, $bulan, 1)->endOfMonth()->toDateString(); $stokSubquery = DB::table('stock_transaction_details as std') ->join('stock_transactions as st', 'std.no_transaksi', '=', 'st.no_transaksi') ->select( 'std.kode', DB::raw('SUM(std.qty_masuk - std.qty_keluar) as stok') ) ->whereDate('st.tanggal', '<=', $tanggalAkhir) ->groupBy('std.kode'); $data = DB::table('prediction_results as pr') ->join('items as i', 'pr.kode', '=', 'i.kode') ->leftJoinSub($stokSubquery, 'stok_data', function ($join) { $join->on('pr.kode', '=', 'stok_data.kode'); }) ->where('pr.bulan_prediksi', $bulan) ->where('pr.tahun_prediksi', $tahun) ->where('i.kategori', 0) ->select( 'pr.kode', 'i.nama_barang', 'i.satuan', 'pr.jumlah_prediksi', DB::raw('COALESCE(stok_data.stok, 0) as stok') ) ->get(); $rows = $data->map(function ($item) { $stok = max(0, (int) $item->stok); $selisih = $stok - $item->jumlah_prediksi; $usulan = $selisih < 0 ? abs($selisih) : 0; return [ 'kode' => $item->kode, 'nama_barang' => $item->nama_barang, 'satuan' => $item->satuan, 'prediksi' => $item->jumlah_prediksi, 'stok' => $stok, 'selisih' => $selisih, 'usulan' => $usulan, 'status' => $usulan > 0 ? 'Perlu Restock' : 'Aman', ]; }); $totalBarang = $rows->count(); $perluRestock = $rows->where('status', 'Perlu Restock')->count(); $totalUsulan = $rows->sum('usulan'); $pdf = Pdf::loadView('rencana-pengadaan-pdf', compact( 'rows', 'periode', 'totalBarang', 'perluRestock', 'totalUsulan' )) ->setPaper('a4', 'portrait'); return $pdf->download('rencana-pengadaan.pdf'); } public function detail($kode, $periode) { [$tahun, $bulan] = explode('-', $periode); $tahun = (int) $tahun; $bulan = (int) $bulan; $tanggalAkhir = Carbon::create($tahun, $bulan, 1)->endOfMonth()->toDateString(); $stok = DB::table('stock_transaction_details as std') ->join('stock_transactions as st', 'std.no_transaksi', '=', 'st.no_transaksi') ->where('std.kode', $kode) ->whereDate('st.tanggal', '<=', $tanggalAkhir) ->selectRaw('SUM(std.qty_masuk - std.qty_keluar) as stok') ->value('stok'); $stok = max(0, (int) $stok); $barang = DB::table('items') ->where('kode', $kode) ->first(); $prediksi = DB::table('prediction_results') ->where('kode', $kode) ->where('bulan_prediksi', $bulan) ->where('tahun_prediksi', $tahun) ->first(); if (!$barang || !$prediksi) { abort(404); } $selisih = $stok - $prediksi->jumlah_prediksi; $usulan = $selisih < 0 ? abs($selisih) : 0; $hasHistoricalPrediction = DB::table('item_usage_monthly as um') ->leftJoin('prediction_results as pr', function ($join) { $join->on('um.kode', '=', 'pr.kode') ->on('um.tahun', '=', 'pr.tahun_prediksi') ->on('um.bulan', '=', 'pr.bulan_prediksi'); }) ->where('um.kode', $kode) ->whereNotNull('pr.jumlah_prediksi') ->exists(); if (!$hasHistoricalPrediction) { $riwayat = DB::table('item_usage_monthly as um') ->where('um.kode', $kode) ->select( 'um.tahun', 'um.bulan', 'um.total_pemakaian', DB::raw('NULL as hasil_prediksi') ) ->orderBy('um.tahun', 'desc') ->orderBy('um.bulan', 'desc') ->limit(12) ->get() ->reverse() ->map(function ($item) { $item->selisih_prediksi = null; return $item; }) ->values(); } else { $riwayat = DB::table('item_usage_monthly as um') ->leftJoin('prediction_results as pr', function ($join) { $join->on('um.kode', '=', 'pr.kode') ->on(DB::raw('CAST(um.tahun AS UNSIGNED)'), '=', DB::raw('CAST(pr.tahun_prediksi AS UNSIGNED)')) ->on(DB::raw('CAST(um.bulan AS UNSIGNED)'), '=', DB::raw('CAST(pr.bulan_prediksi AS UNSIGNED)')); }) ->where('um.kode', $kode) ->select( 'um.tahun', 'um.bulan', 'um.total_pemakaian', DB::raw('COALESCE(pr.jumlah_prediksi, 0) as hasil_prediksi') ) ->orderBy('um.tahun', 'desc') ->orderBy('um.bulan', 'desc') ->limit(12) ->get() ->reverse() ->map(function ($item) { $item->selisih_prediksi = $item->hasil_prediksi - $item->total_pemakaian; return $item; }) ->values(); } return view('detail-rencana-pengadaan', compact( 'barang', 'prediksi', 'stok', 'selisih', 'usulan', 'periode', 'riwayat', 'hasHistoricalPrediction' )); } }