update tgl 8 mei
This commit is contained in:
parent
0be2b98301
commit
514596bce8
|
@ -173,17 +173,21 @@ public function index(Request $request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get monthly totals for chart
|
// Get daily totals for chart
|
||||||
$monthlyTotals = DB::table('laporan_transaksis')
|
$monthlyTotals = DB::table('laporan_transaksis')
|
||||||
->select(
|
->select(
|
||||||
DB::raw('DATE_FORMAT(Tanggal, "%Y-%m") as periode'),
|
DB::raw('DATE_FORMAT(Tanggal, "%Y-%m-%d") as periode'),
|
||||||
DB::raw('SUM(CASE WHEN LEFT(kategori, 3) IN ("241", "242") THEN uang_masuk ELSE 0 END) as total_debit'),
|
DB::raw('SUM(uang_masuk) as total_debit'),
|
||||||
DB::raw('SUM(CASE WHEN LEFT(kategori, 3) IN ("251", "252") THEN uang_keluar ELSE 0 END) as total_kredit')
|
DB::raw('SUM(uang_keluar) as total_kredit')
|
||||||
)
|
)
|
||||||
|
->whereBetween('Tanggal', [$startDate, $endDate])
|
||||||
->groupBy('periode')
|
->groupBy('periode')
|
||||||
->orderBy('periode')
|
->orderBy('periode')
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
|
// Debug untuk memastikan data terisi
|
||||||
|
Log::info('Daily Totals:', ['data' => $monthlyTotals->toArray()]);
|
||||||
|
|
||||||
// Get category totals for distribution chart
|
// Get category totals for distribution chart
|
||||||
$categoryTotals = DB::table('laporan_transaksis')
|
$categoryTotals = DB::table('laporan_transaksis')
|
||||||
->select(
|
->select(
|
||||||
|
@ -242,6 +246,63 @@ public function index(Request $request)
|
||||||
(($currentMonthLabaRugi - $lastMonthLabaRugi) / abs($lastMonthLabaRugi)) * 100 :
|
(($currentMonthLabaRugi - $lastMonthLabaRugi) / abs($lastMonthLabaRugi)) * 100 :
|
||||||
100;
|
100;
|
||||||
|
|
||||||
|
// Ambil data neraca saldo untuk pie chart
|
||||||
|
$rawTransaksis = DB::table('laporan_transaksis')
|
||||||
|
->whereBetween('Tanggal', [$startDate, $endDate])
|
||||||
|
->orderBy('kode', 'asc')
|
||||||
|
->get();
|
||||||
|
$totalsPerAkun = [];
|
||||||
|
foreach ($rawTransaksis as $transaksi) {
|
||||||
|
$processAkun = function($kode, $kategori, $debit, $kredit) use (&$totalsPerAkun) {
|
||||||
|
if (!empty($kode) && !empty($kategori)) {
|
||||||
|
if (!isset($totalsPerAkun[$kategori])) {
|
||||||
|
$totalsPerAkun[$kategori] = [
|
||||||
|
'kode' => $kode,
|
||||||
|
'kategori' => $kategori,
|
||||||
|
'debit' => 0,
|
||||||
|
'kredit' => 0
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$totalsPerAkun[$kategori]['debit'] += floatval($debit ?? 0);
|
||||||
|
$totalsPerAkun[$kategori]['kredit'] += floatval($kredit ?? 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
$processAkun($transaksi->kode, $transaksi->kategori, $transaksi->uang_masuk, $transaksi->uang_keluar);
|
||||||
|
$processAkun($transaksi->kode2, $transaksi->kategori2, $transaksi->uang_masuk2, $transaksi->uang_keluar2);
|
||||||
|
$processAkun($transaksi->kode3, $transaksi->kategori3, $transaksi->uang_masuk3, $transaksi->uang_keluar3);
|
||||||
|
$processAkun($transaksi->kode4, $transaksi->kategori4, $transaksi->uang_masuk4, $transaksi->uang_keluar4);
|
||||||
|
$processAkun($transaksi->kode5, $transaksi->kategori5, $transaksi->uang_masuk5, $transaksi->uang_keluar5);
|
||||||
|
}
|
||||||
|
$finalTransaksis = [];
|
||||||
|
foreach ($totalsPerAkun as $kategori => $data) {
|
||||||
|
$kodeAwal = substr($data['kode'], 0, 3);
|
||||||
|
$saldo = $data['debit'] - $data['kredit'];
|
||||||
|
if (in_array($kodeAwal, ['111', '112']) || in_array($kodeAwal, ['251', '252'])) {
|
||||||
|
if ($saldo != 0) {
|
||||||
|
$finalTransaksis[] = [
|
||||||
|
'kode' => $data['kode'],
|
||||||
|
'kategori' => $kategori,
|
||||||
|
'debit' => $saldo,
|
||||||
|
'kredit' => 0
|
||||||
|
];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($saldo != 0) {
|
||||||
|
$finalTransaksis[] = [
|
||||||
|
'kode' => $data['kode'],
|
||||||
|
'kategori' => $kategori,
|
||||||
|
'debit' => 0,
|
||||||
|
'kredit' => -$saldo
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$neracaTransaksis = collect($finalTransaksis);
|
||||||
|
$pieLabels = $neracaTransaksis->pluck('kategori')->toArray();
|
||||||
|
$pieData = $neracaTransaksis->map(function($item) {
|
||||||
|
return abs($item['debit']) + abs($item['kredit']);
|
||||||
|
})->toArray();
|
||||||
|
|
||||||
return view('home', compact(
|
return view('home', compact(
|
||||||
'startDate',
|
'startDate',
|
||||||
'endDate',
|
'endDate',
|
||||||
|
@ -254,7 +315,9 @@ public function index(Request $request)
|
||||||
'categoryTotals',
|
'categoryTotals',
|
||||||
'recentTransactions',
|
'recentTransactions',
|
||||||
'pendapatan',
|
'pendapatan',
|
||||||
'beban'
|
'beban',
|
||||||
|
'pieLabels',
|
||||||
|
'pieData'
|
||||||
));
|
));
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
|
|
|
@ -134,4 +134,202 @@ public function filter(Request $request)
|
||||||
{
|
{
|
||||||
return $this->index($request);
|
return $this->index($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function exportExcel(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$startDate = $request->input('start_date', Carbon::now()->startOfMonth()->format('Y-m-d'));
|
||||||
|
$endDate = $request->input('end_date', Carbon::now()->endOfMonth()->format('Y-m-d'));
|
||||||
|
|
||||||
|
// Inisialisasi array untuk menyimpan data
|
||||||
|
$pendapatan = [];
|
||||||
|
$beban = [];
|
||||||
|
|
||||||
|
// Ambil semua transaksi dalam periode
|
||||||
|
$transaksis = DB::table('laporan_transaksis')
|
||||||
|
->whereBetween('Tanggal', [$startDate, $endDate])
|
||||||
|
->get();
|
||||||
|
|
||||||
|
foreach ($transaksis as $transaksi) {
|
||||||
|
// Proses kategori1
|
||||||
|
if (!empty($transaksi->kategori)) {
|
||||||
|
$this->prosesKategori(
|
||||||
|
$transaksi->kategori,
|
||||||
|
$transaksi->uang_masuk ?? 0,
|
||||||
|
$transaksi->uang_keluar ?? 0,
|
||||||
|
$pendapatan,
|
||||||
|
$beban
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proses kategori2-5
|
||||||
|
for ($i = 2; $i <= 5; $i++) {
|
||||||
|
$kategori = $transaksi->{"kategori$i"};
|
||||||
|
if (!empty($kategori)) {
|
||||||
|
$this->prosesKategori(
|
||||||
|
$kategori,
|
||||||
|
$transaksi->{"uang_masuk$i"} ?? 0,
|
||||||
|
$transaksi->{"uang_keluar$i"} ?? 0,
|
||||||
|
$pendapatan,
|
||||||
|
$beban
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hitung total
|
||||||
|
$total_pendapatan = array_sum(array_column($pendapatan, 'nominal'));
|
||||||
|
$total_beban = abs(array_sum(array_column($beban, 'nominal')));
|
||||||
|
$laba_rugi = $total_pendapatan - $total_beban;
|
||||||
|
|
||||||
|
// Siapkan data untuk Excel
|
||||||
|
$rows = [];
|
||||||
|
|
||||||
|
// Header
|
||||||
|
$rows[] = ['Laporan Laba Rugi'];
|
||||||
|
$rows[] = ['Periode: ' . date('F Y', strtotime($startDate))];
|
||||||
|
$rows[] = []; // Baris kosong
|
||||||
|
|
||||||
|
// Pendapatan
|
||||||
|
$rows[] = ['Pendapatan'];
|
||||||
|
foreach ($pendapatan as $item) {
|
||||||
|
$rows[] = [
|
||||||
|
ucwords($item['kategori']),
|
||||||
|
number_format(abs($item['nominal']), 0, ',', '.')
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$rows[] = ['Total Pendapatan', number_format(abs($total_pendapatan), 0, ',', '.')];
|
||||||
|
$rows[] = []; // Baris kosong
|
||||||
|
|
||||||
|
// Beban
|
||||||
|
$rows[] = ['Beban'];
|
||||||
|
foreach ($beban as $item) {
|
||||||
|
$rows[] = [
|
||||||
|
ucwords($item['kategori']),
|
||||||
|
number_format(abs($item['nominal']), 0, ',', '.')
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$rows[] = ['Total Beban', number_format($total_beban, 0, ',', '.')];
|
||||||
|
$rows[] = []; // Baris kosong
|
||||||
|
|
||||||
|
// Laba/Rugi
|
||||||
|
$rows[] = ['Laba/Rugi Bersih', number_format($laba_rugi, 0, ',', '.')];
|
||||||
|
|
||||||
|
$export = new class($rows) implements \Maatwebsite\Excel\Concerns\FromArray {
|
||||||
|
protected $rows;
|
||||||
|
public function __construct($rows) { $this->rows = $rows; }
|
||||||
|
public function array(): array { return $this->rows; }
|
||||||
|
};
|
||||||
|
|
||||||
|
return \Maatwebsite\Excel\Facades\Excel::download($export, 'laporan-laba-rugi-'.date('Y-m-d').'.xlsx');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return redirect()->back()->with('error', 'Gagal mengekspor Excel: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function exportPDF(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$startDate = $request->input('start_date', Carbon::now()->startOfMonth()->format('Y-m-d'));
|
||||||
|
$endDate = $request->input('end_date', Carbon::now()->endOfMonth()->format('Y-m-d'));
|
||||||
|
|
||||||
|
// Inisialisasi array untuk menyimpan data
|
||||||
|
$pendapatan = [];
|
||||||
|
$beban = [];
|
||||||
|
|
||||||
|
// Ambil semua transaksi dalam periode
|
||||||
|
$transaksis = DB::table('laporan_transaksis')
|
||||||
|
->whereBetween('Tanggal', [$startDate, $endDate])
|
||||||
|
->get();
|
||||||
|
|
||||||
|
foreach ($transaksis as $transaksi) {
|
||||||
|
// Proses kategori1
|
||||||
|
if (!empty($transaksi->kategori)) {
|
||||||
|
$this->prosesKategori(
|
||||||
|
$transaksi->kategori,
|
||||||
|
$transaksi->uang_masuk ?? 0,
|
||||||
|
$transaksi->uang_keluar ?? 0,
|
||||||
|
$pendapatan,
|
||||||
|
$beban
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proses kategori2-5
|
||||||
|
for ($i = 2; $i <= 5; $i++) {
|
||||||
|
$kategori = $transaksi->{"kategori$i"};
|
||||||
|
if (!empty($kategori)) {
|
||||||
|
$this->prosesKategori(
|
||||||
|
$kategori,
|
||||||
|
$transaksi->{"uang_masuk$i"} ?? 0,
|
||||||
|
$transaksi->{"uang_keluar$i"} ?? 0,
|
||||||
|
$pendapatan,
|
||||||
|
$beban
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hitung total
|
||||||
|
$total_pendapatan = array_sum(array_column($pendapatan, 'nominal'));
|
||||||
|
$total_beban = abs(array_sum(array_column($beban, 'nominal')));
|
||||||
|
$laba_rugi = $total_pendapatan - $total_beban;
|
||||||
|
|
||||||
|
$html = '<!DOCTYPE html><html><head><title>Laporan Laba Rugi</title><style>
|
||||||
|
body{font-family:Arial,sans-serif;font-size:12px;}
|
||||||
|
table{width:100%;border-collapse:collapse;margin-bottom:20px;}
|
||||||
|
table,th,td{border:1px solid #ddd;}
|
||||||
|
th,td{padding:8px;text-align:left;}
|
||||||
|
th{background-color:#6b46c1;color:white;}
|
||||||
|
.bg-gray-100{background-color:#f3f4f6;}
|
||||||
|
.bg-purple-100{background-color:#f3e8ff;}
|
||||||
|
.text-right{text-align:right;}
|
||||||
|
.font-bold{font-weight:bold;}
|
||||||
|
.pl-8{padding-left:2rem;}
|
||||||
|
</style></head><body>';
|
||||||
|
|
||||||
|
$html .= '<h2 style="text-align:center">Laporan Laba Rugi</h2>';
|
||||||
|
$html .= '<p style="text-align:center">Periode: ' . date('F Y', strtotime($startDate)) . '</p>';
|
||||||
|
|
||||||
|
$html .= '<table>';
|
||||||
|
|
||||||
|
// Header
|
||||||
|
$html .= '<tr><th>Keterangan</th><th style="text-align:right">Nominal</th></tr>';
|
||||||
|
|
||||||
|
// Pendapatan
|
||||||
|
$html .= '<tr class="bg-gray-100"><td colspan="2" class="font-bold">Pendapatan</td></tr>';
|
||||||
|
foreach ($pendapatan as $item) {
|
||||||
|
$html .= '<tr>';
|
||||||
|
$html .= '<td class="pl-8">' . ucwords($item['kategori']) . '</td>';
|
||||||
|
$html .= '<td class="text-right">' . number_format(abs($item['nominal']), 0, ',', '.') . '</td>';
|
||||||
|
$html .= '</tr>';
|
||||||
|
}
|
||||||
|
$html .= '<tr class="font-bold"><td>Total Pendapatan</td><td class="text-right">' . number_format(abs($total_pendapatan), 0, ',', '.') . '</td></tr>';
|
||||||
|
|
||||||
|
// Beban
|
||||||
|
$html .= '<tr class="bg-gray-100"><td colspan="2" class="font-bold">Beban</td></tr>';
|
||||||
|
foreach ($beban as $item) {
|
||||||
|
$html .= '<tr>';
|
||||||
|
$html .= '<td class="pl-8">' . ucwords($item['kategori']) . '</td>';
|
||||||
|
$html .= '<td class="text-right">' . number_format(abs($item['nominal']), 0, ',', '.') . '</td>';
|
||||||
|
$html .= '</tr>';
|
||||||
|
}
|
||||||
|
$html .= '<tr class="font-bold"><td>Total Beban</td><td class="text-right">' . number_format($total_beban, 0, ',', '.') . '</td></tr>';
|
||||||
|
|
||||||
|
// Laba/Rugi
|
||||||
|
$html .= '<tr class="bg-purple-100"><td class="font-bold">Laba/Rugi Bersih</td><td class="text-right font-bold">';
|
||||||
|
if ($laba_rugi < 0) {
|
||||||
|
$html .= '-Rp ' . number_format(abs($laba_rugi), 0, ',', '.');
|
||||||
|
} else {
|
||||||
|
$html .= 'Rp ' . number_format($laba_rugi, 0, ',', '.');
|
||||||
|
}
|
||||||
|
$html .= '</td></tr>';
|
||||||
|
|
||||||
|
$html .= '</table></body></html>';
|
||||||
|
|
||||||
|
$pdf = \Barryvdh\DomPDF\Facade\Pdf::loadHTML($html);
|
||||||
|
return $pdf->download('laporan-laba-rugi-'.date('Y-m-d').'.pdf');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return redirect()->back()->with('error', 'Gagal mengekspor PDF: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,54 +52,117 @@ public function filter(Request $request)
|
||||||
return $this->index($request);
|
return $this->index($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exportExcel()
|
public function exportExcel(Request $request)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
// Buat class export inline
|
$startDate = $request->input('start_date', Carbon::now()->startOfMonth()->format('Y-m-d'));
|
||||||
$export = new class implements FromCollection, WithHeadings, WithMapping {
|
$endDate = $request->input('end_date', Carbon::now()->endOfMonth()->format('Y-m-d'));
|
||||||
public function collection()
|
$laporan = LaporanModel::whereBetween('Tanggal', [$startDate, $endDate])
|
||||||
{
|
->orderBy('Tanggal', 'desc')
|
||||||
return LaporanModel::orderBy('Tanggal', 'desc')->get();
|
->get();
|
||||||
|
|
||||||
|
$rows = [];
|
||||||
|
$no = 1;
|
||||||
|
$totalDebit = 0;
|
||||||
|
$totalKredit = 0;
|
||||||
|
|
||||||
|
foreach ($laporan as $item) {
|
||||||
|
// Cek apakah semua nilai adalah debit
|
||||||
|
$allDebit = true;
|
||||||
|
$debitValues = [
|
||||||
|
$item->uang_masuk,
|
||||||
|
$item->uang_masuk2,
|
||||||
|
$item->uang_masuk3,
|
||||||
|
$item->uang_masuk4,
|
||||||
|
$item->uang_masuk5
|
||||||
|
];
|
||||||
|
|
||||||
|
$validDebitValues = array_filter($debitValues, function($value) {
|
||||||
|
return $value !== null && $value > 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($item->uang_keluar > 0 ||
|
||||||
|
($item->uang_keluar2 ?? 0) > 0 ||
|
||||||
|
($item->uang_keluar3 ?? 0) > 0 ||
|
||||||
|
($item->uang_keluar4 ?? 0) > 0 ||
|
||||||
|
($item->uang_keluar5 ?? 0) > 0) {
|
||||||
|
$allDebit = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function headings(): array
|
// Proses data untuk setiap baris
|
||||||
{
|
$rowDebit = 0;
|
||||||
return [
|
$rowKredit = 0;
|
||||||
'ID',
|
|
||||||
'Tanggal',
|
if ($allDebit) {
|
||||||
'Kode',
|
$lastDebitValue = end($validDebitValues);
|
||||||
'Kategori',
|
$firstDebitValue = reset($validDebitValues);
|
||||||
'Keterangan',
|
|
||||||
'Uang Masuk',
|
if (count($validDebitValues) > 1) {
|
||||||
'Uang Keluar'
|
$rowDebit = $firstDebitValue;
|
||||||
];
|
$rowKredit = $lastDebitValue;
|
||||||
|
} else {
|
||||||
|
$rowDebit = $firstDebitValue;
|
||||||
|
$rowKredit = $firstDebitValue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$rowDebit = $item->uang_masuk +
|
||||||
|
($item->uang_masuk2 ?? 0) +
|
||||||
|
($item->uang_masuk3 ?? 0) +
|
||||||
|
($item->uang_masuk4 ?? 0) +
|
||||||
|
($item->uang_masuk5 ?? 0);
|
||||||
|
|
||||||
|
$rowKredit = $item->uang_keluar +
|
||||||
|
($item->uang_keluar2 ?? 0) +
|
||||||
|
($item->uang_keluar3 ?? 0) +
|
||||||
|
($item->uang_keluar4 ?? 0) +
|
||||||
|
($item->uang_keluar5 ?? 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function map($laporan): array
|
$totalDebit += $rowDebit;
|
||||||
{
|
$totalKredit += $rowKredit;
|
||||||
// Hitung total uang masuk untuk baris ini
|
|
||||||
$totalUangMasuk = $laporan->uang_masuk +
|
|
||||||
($laporan->uang_masuk2 ?? 0) +
|
|
||||||
($laporan->uang_masuk3 ?? 0) +
|
|
||||||
($laporan->uang_masuk4 ?? 0) +
|
|
||||||
($laporan->uang_masuk5 ?? 0);
|
|
||||||
|
|
||||||
// Hitung total uang keluar untuk baris ini
|
// Gabungkan semua kode akun
|
||||||
$totalUangKeluar = $laporan->uang_keluar +
|
$kodeAkun = $item->kode;
|
||||||
($laporan->uang_keluar2 ?? 0) +
|
if (!empty($item->kode2)) $kodeAkun .= "\n" . $item->kode2;
|
||||||
($laporan->uang_keluar3 ?? 0) +
|
if (!empty($item->kode3)) $kodeAkun .= "\n" . $item->kode3;
|
||||||
($laporan->uang_keluar4 ?? 0) +
|
if (!empty($item->kode4)) $kodeAkun .= "\n" . $item->kode4;
|
||||||
($laporan->uang_keluar5 ?? 0);
|
if (!empty($item->kode5)) $kodeAkun .= "\n" . $item->kode5;
|
||||||
|
|
||||||
return [
|
// Gabungkan semua nama akun
|
||||||
$laporan->id,
|
$namaAkun = $item->kategori;
|
||||||
$laporan->Tanggal,
|
if (!empty($item->kategori2)) $namaAkun .= "\n" . $item->kategori2;
|
||||||
$laporan->kode,
|
if (!empty($item->kategori3)) $namaAkun .= "\n" . $item->kategori3;
|
||||||
$laporan->kategori,
|
if (!empty($item->kategori4)) $namaAkun .= "\n" . $item->kategori4;
|
||||||
$laporan->keterangan,
|
if (!empty($item->kategori5)) $namaAkun .= "\n" . $item->kategori5;
|
||||||
$totalUangMasuk,
|
|
||||||
$totalUangKeluar
|
$rows[] = [
|
||||||
];
|
'No' => $no++,
|
||||||
|
'Tanggal' => date('d/m/Y', strtotime($item->Tanggal)),
|
||||||
|
'Kode Akun' => $kodeAkun,
|
||||||
|
'Nama Akun' => $namaAkun,
|
||||||
|
'Keterangan' => $item->keterangan . ' ' . $item->nama_karyawan,
|
||||||
|
'Debit' => $rowDebit > 0 ? number_format($rowDebit, 0, ',', '.') : '-',
|
||||||
|
'Kredit' => $rowKredit > 0 ? number_format($rowKredit, 0, ',', '.') : '-'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tambahkan baris total
|
||||||
|
$rows[] = [
|
||||||
|
'No' => '',
|
||||||
|
'Tanggal' => '',
|
||||||
|
'Kode Akun' => '',
|
||||||
|
'Nama Akun' => '',
|
||||||
|
'Keterangan' => 'Total',
|
||||||
|
'Debit' => number_format($totalDebit, 0, ',', '.'),
|
||||||
|
'Kredit' => number_format($totalKredit, 0, ',', '.')
|
||||||
|
];
|
||||||
|
|
||||||
|
$export = new class($rows) implements FromCollection, WithHeadings {
|
||||||
|
protected $rows;
|
||||||
|
public function __construct($rows) { $this->rows = $rows; }
|
||||||
|
public function collection() { return collect($this->rows); }
|
||||||
|
public function headings(): array {
|
||||||
|
return ['No', 'Tanggal', 'Kode Akun', 'Nama Akun', 'Keterangan', 'Debit', 'Kredit'];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -109,132 +172,132 @@ public function map($laporan): array
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exportPDF()
|
public function exportPDF(Request $request)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$laporan = LaporanModel::orderBy('Tanggal', 'desc')->get();
|
$startDate = $request->input('start_date', Carbon::now()->startOfMonth()->format('Y-m-d'));
|
||||||
|
$endDate = $request->input('end_date', Carbon::now()->endOfMonth()->format('Y-m-d'));
|
||||||
// Hitung total uang masuk
|
$laporan = LaporanModel::whereBetween('Tanggal', [$startDate, $endDate])
|
||||||
$totalUangMasuk = LaporanModel::selectRaw('SUM(uang_masuk) +
|
->orderBy('Tanggal', 'desc')
|
||||||
COALESCE(SUM(uang_masuk2), 0) +
|
->get();
|
||||||
COALESCE(SUM(uang_masuk3), 0) +
|
|
||||||
COALESCE(SUM(uang_masuk4), 0) +
|
|
||||||
COALESCE(SUM(uang_masuk5), 0) as total')
|
|
||||||
->value('total') ?? 0;
|
|
||||||
|
|
||||||
// Hitung total uang keluar
|
$rows = '';
|
||||||
$totalKredit = LaporanModel::selectRaw('SUM(uang_keluar) +
|
$no = 1;
|
||||||
COALESCE(SUM(uang_keluar2), 0) +
|
$totalDebit = 0;
|
||||||
COALESCE(SUM(uang_keluar3), 0) +
|
$totalKredit = 0;
|
||||||
COALESCE(SUM(uang_keluar4), 0) +
|
|
||||||
COALESCE(SUM(uang_keluar5), 0) as total')
|
|
||||||
->value('total') ?? 0;
|
|
||||||
|
|
||||||
$saldo = $totalUangMasuk - $totalKredit;
|
foreach ($laporan as $item) {
|
||||||
|
// Cek apakah semua nilai adalah debit
|
||||||
// Generate PDF
|
$allDebit = true;
|
||||||
$html = '
|
$debitValues = [
|
||||||
<!DOCTYPE html>
|
$item->uang_masuk,
|
||||||
<html>
|
$item->uang_masuk2,
|
||||||
<head>
|
$item->uang_masuk3,
|
||||||
<title>Laporan Keuangan</title>
|
$item->uang_masuk4,
|
||||||
<style>
|
$item->uang_masuk5
|
||||||
body {
|
];
|
||||||
font-family: Arial, sans-serif;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
table {
|
|
||||||
width: 100%;
|
|
||||||
border-collapse: collapse;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
table, th, td {
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
}
|
|
||||||
th, td {
|
|
||||||
padding: 8px;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
th {
|
|
||||||
background-color: #f2f2f2;
|
|
||||||
}
|
|
||||||
.summary {
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
.summary table {
|
|
||||||
width: 300px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h2>Laporan Keuangan</h2>
|
|
||||||
<p>Tanggal: '.date('d-m-Y').'</p>
|
|
||||||
|
|
||||||
<table>
|
$validDebitValues = array_filter($debitValues, function($value) {
|
||||||
<thead>
|
return $value !== null && $value > 0;
|
||||||
<tr>
|
});
|
||||||
<th>No</th>
|
|
||||||
<th>Tanggal</th>
|
if ($item->uang_keluar > 0 ||
|
||||||
<th>Kode</th>
|
($item->uang_keluar2 ?? 0) > 0 ||
|
||||||
<th>Kategori</th>
|
($item->uang_keluar3 ?? 0) > 0 ||
|
||||||
<th>Keterangan</th>
|
($item->uang_keluar4 ?? 0) > 0 ||
|
||||||
<th>Uang Masuk</th>
|
($item->uang_keluar5 ?? 0) > 0) {
|
||||||
<th>Uang Keluar</th>
|
$allDebit = false;
|
||||||
</tr>
|
}
|
||||||
</thead>
|
|
||||||
<tbody>';
|
// Proses data untuk setiap baris
|
||||||
|
$rowDebit = 0;
|
||||||
|
$rowKredit = 0;
|
||||||
|
|
||||||
|
if ($allDebit) {
|
||||||
|
$lastDebitValue = end($validDebitValues);
|
||||||
|
$firstDebitValue = reset($validDebitValues);
|
||||||
|
|
||||||
foreach($laporan as $index => $item) {
|
if (count($validDebitValues) > 1) {
|
||||||
// Hitung total uang masuk untuk baris ini
|
$rowDebit = $firstDebitValue;
|
||||||
$rowUangMasuk = $item->uang_masuk +
|
$rowKredit = $lastDebitValue;
|
||||||
($item->uang_masuk2 ?? 0) +
|
} else {
|
||||||
($item->uang_masuk3 ?? 0) +
|
$rowDebit = $firstDebitValue;
|
||||||
($item->uang_masuk4 ?? 0) +
|
$rowKredit = $firstDebitValue;
|
||||||
($item->uang_masuk5 ?? 0);
|
|
||||||
|
|
||||||
// Hitung total uang keluar untuk baris ini
|
|
||||||
$rowUangKeluar = $item->uang_keluar +
|
|
||||||
($item->uang_keluar2 ?? 0) +
|
|
||||||
($item->uang_keluar3 ?? 0) +
|
|
||||||
($item->uang_keluar4 ?? 0) +
|
|
||||||
($item->uang_keluar5 ?? 0);
|
|
||||||
|
|
||||||
$html .= '
|
|
||||||
<tr>
|
|
||||||
<td>'.($index + 1).'</td>
|
|
||||||
<td>'.$item->Tanggal.'</td>
|
|
||||||
<td>'.$item->kode.'</td>
|
|
||||||
<td>'.$item->kategori.'</td>
|
|
||||||
<td>'.$item->keterangan.'</td>
|
|
||||||
<td>Rp '.number_format($rowUangMasuk, 0, ',', '.').'</td>
|
|
||||||
<td>Rp '.number_format($rowUangKeluar, 0, ',', '.').'</td>
|
|
||||||
</tr>';
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
$html .= '
|
$rowDebit = $item->uang_masuk +
|
||||||
</tbody>
|
($item->uang_masuk2 ?? 0) +
|
||||||
</table>
|
($item->uang_masuk3 ?? 0) +
|
||||||
|
($item->uang_masuk4 ?? 0) +
|
||||||
<div class="summary">
|
($item->uang_masuk5 ?? 0);
|
||||||
<h3>Ringkasan</h3>
|
|
||||||
<table>
|
$rowKredit = $item->uang_keluar +
|
||||||
<tr>
|
($item->uang_keluar2 ?? 0) +
|
||||||
<td><strong>Total Uang Masuk</strong></td>
|
($item->uang_keluar3 ?? 0) +
|
||||||
<td>Rp '.number_format($totalUangMasuk, 0, ',', '.').'</td>
|
($item->uang_keluar4 ?? 0) +
|
||||||
</tr>
|
($item->uang_keluar5 ?? 0);
|
||||||
<tr>
|
}
|
||||||
<td><strong>Total Uang Keluar</strong></td>
|
|
||||||
<td>Rp '.number_format($totalKredit, 0, ',', '.').'</td>
|
$totalDebit += $rowDebit;
|
||||||
</tr>
|
$totalKredit += $rowKredit;
|
||||||
<tr>
|
|
||||||
<td><strong>Saldo</strong></td>
|
// Gabungkan semua kode akun
|
||||||
<td>Rp '.number_format($saldo, 0, ',', '.').'</td>
|
$kodeAkun = $item->kode;
|
||||||
</tr>
|
if (!empty($item->kode2)) $kodeAkun .= "<br>" . $item->kode2;
|
||||||
</table>
|
if (!empty($item->kode3)) $kodeAkun .= "<br>" . $item->kode3;
|
||||||
</div>
|
if (!empty($item->kode4)) $kodeAkun .= "<br>" . $item->kode4;
|
||||||
</body>
|
if (!empty($item->kode5)) $kodeAkun .= "<br>" . $item->kode5;
|
||||||
</html>';
|
|
||||||
|
// Gabungkan semua nama akun
|
||||||
|
$namaAkun = $item->kategori;
|
||||||
|
if (!empty($item->kategori2)) $namaAkun .= "<br>" . $item->kategori2;
|
||||||
|
if (!empty($item->kategori3)) $namaAkun .= "<br>" . $item->kategori3;
|
||||||
|
if (!empty($item->kategori4)) $namaAkun .= "<br>" . $item->kategori4;
|
||||||
|
if (!empty($item->kategori5)) $namaAkun .= "<br>" . $item->kategori5;
|
||||||
|
|
||||||
|
$rows .= '<tr>';
|
||||||
|
$rows .= '<td style="text-align:center">'.$no++.'</td>';
|
||||||
|
$rows .= '<td>'.date('d/m/Y', strtotime($item->Tanggal)).'</td>';
|
||||||
|
$rows .= '<td>'.$kodeAkun.'</td>';
|
||||||
|
$rows .= '<td>'.$namaAkun.'</td>';
|
||||||
|
$rows .= '<td>'.$item->keterangan.' '.$item->nama_karyawan.'</td>';
|
||||||
|
$rows .= '<td style="text-align:right">'.($rowDebit > 0 ? number_format($rowDebit, 0, ',', '.') : '-').'</td>';
|
||||||
|
$rows .= '<td style="text-align:right">'.($rowKredit > 0 ? number_format($rowKredit, 0, ',', '.') : '-').'</td>';
|
||||||
|
$rows .= '</tr>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tambahkan baris total
|
||||||
|
$rows .= '<tr style="font-weight:bold;background-color:#f9f9f9;">';
|
||||||
|
$rows .= '<td colspan="5" style="text-align:right">Total</td>';
|
||||||
|
$rows .= '<td style="text-align:right">'.number_format($totalDebit, 0, ',', '.').'</td>';
|
||||||
|
$rows .= '<td style="text-align:right">'.number_format($totalKredit, 0, ',', '.').'</td>';
|
||||||
|
$rows .= '</tr>';
|
||||||
|
|
||||||
|
$html = '<!DOCTYPE html><html><head><title>Laporan Keuangan</title><style>
|
||||||
|
body{font-family:Arial,sans-serif;font-size:12px;}
|
||||||
|
table{width:100%;border-collapse:collapse;margin-bottom:20px;}
|
||||||
|
table,th,td{border:1px solid #ddd;}
|
||||||
|
th,td{padding:8px;text-align:left;}
|
||||||
|
th{background-color:#f2f2f2;}
|
||||||
|
tfoot td{font-weight:bold;background-color:#f9f9f9;}
|
||||||
|
.text-right{text-align:right;}
|
||||||
|
.text-center{text-align:center;}
|
||||||
|
td{vertical-align:top;}
|
||||||
|
</style></head><body>';
|
||||||
|
$html .= '<h2 style="text-align:center">Laporan Keuangan</h2>';
|
||||||
|
$html .= '<p style="text-align:center">Periode: '.date('d/m/Y', strtotime($startDate)).' - '.date('d/m/Y', strtotime($endDate)).'</p>';
|
||||||
|
$html .= '<table><thead><tr>
|
||||||
|
<th style="text-align:center">No</th>
|
||||||
|
<th>Tanggal</th>
|
||||||
|
<th>Kode Akun</th>
|
||||||
|
<th>Nama Akun</th>
|
||||||
|
<th>Keterangan</th>
|
||||||
|
<th style="text-align:right">Debit</th>
|
||||||
|
<th style="text-align:right">Kredit</th>
|
||||||
|
</tr></thead><tbody>';
|
||||||
|
$html .= $rows;
|
||||||
|
$html .= '</tbody></table></body></html>';
|
||||||
|
|
||||||
$pdf = PDF::loadHTML($html);
|
$pdf = PDF::loadHTML($html);
|
||||||
return $pdf->download('laporan-keuangan-'.date('Y-m-d').'.pdf');
|
return $pdf->download('laporan-keuangan-'.date('Y-m-d').'.pdf');
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
|
|
|
@ -62,10 +62,9 @@ public function store(Request $request)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($validator->fails()) {
|
if ($validator->fails()) {
|
||||||
return response()->json([
|
return redirect()->back()
|
||||||
'success' => false,
|
->with('error', $validator->errors()->first())
|
||||||
'message' => $validator->errors()->first()
|
->withInput();
|
||||||
], 422);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -76,22 +75,24 @@ public function store(Request $request)
|
||||||
'tipe_pengguna' => $request->tipe_pengguna
|
'tipe_pengguna' => $request->tipe_pengguna
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return response()->json([
|
return redirect()->route('User.index')
|
||||||
'success' => true,
|
->with('success', 'User berhasil ditambahkan!');
|
||||||
'message' => 'User berhasil ditambahkan'
|
|
||||||
]);
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
return response()->json([
|
return redirect()->back()
|
||||||
'success' => false,
|
->with('error', 'Gagal menambahkan user: ' . $e->getMessage())
|
||||||
'message' => 'Gagal menambahkan user: ' . $e->getMessage()
|
->withInput();
|
||||||
], 500);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function edit($id)
|
public function edit($id)
|
||||||
{
|
{
|
||||||
$user = User::findOrFail($id);
|
try {
|
||||||
return view('EditAkun', compact('user'));
|
$user = User::findOrFail($id);
|
||||||
|
return view('EditAkun', compact('user'));
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return redirect()->route('User.index')
|
||||||
|
->with('error', 'User tidak ditemukan');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update(Request $request, $id)
|
public function update(Request $request, $id)
|
||||||
|
@ -104,10 +105,9 @@ public function update(Request $request, $id)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($validator->fails()) {
|
if ($validator->fails()) {
|
||||||
return response()->json([
|
return redirect()->back()
|
||||||
'success' => false,
|
->with('error', $validator->errors()->first())
|
||||||
'message' => $validator->errors()->first()
|
->withInput();
|
||||||
], 422);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -125,15 +125,12 @@ public function update(Request $request, $id)
|
||||||
|
|
||||||
$user->update($data);
|
$user->update($data);
|
||||||
|
|
||||||
return response()->json([
|
return redirect()->route('User.index')
|
||||||
'success' => true,
|
->with('success', 'Data user berhasil diperbarui!');
|
||||||
'message' => 'User berhasil diperbarui'
|
|
||||||
]);
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
return response()->json([
|
return redirect()->back()
|
||||||
'success' => false,
|
->with('error', 'Gagal memperbarui user: ' . $e->getMessage())
|
||||||
'message' => 'Gagal memperbarui user: ' . $e->getMessage()
|
->withInput();
|
||||||
], 500);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +142,7 @@ public function destroy($id)
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
'message' => 'User berhasil dihapus'
|
'message' => 'User berhasil dihapus!'
|
||||||
]);
|
]);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
@extends('Core.Sidebar')
|
@extends('Core.Sidebar')
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
|
<!-- Chart.js -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.9.1/dist/chart.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.2.0"></script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.chart-container {
|
.chart-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -192,18 +196,128 @@
|
||||||
<!-- Charts Section -->
|
<!-- Charts Section -->
|
||||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
|
||||||
<!-- Bar Chart -->
|
<!-- Bar Chart -->
|
||||||
<div class="bg-white p-6 rounded-xl shadow-sm">
|
<div class="max-w-sm w-full bg-white rounded-lg shadow-sm dark:bg-gray-800 p-4 md:p-6">
|
||||||
<h4 class="text-lg font-semibold text-gray-700 mb-4">Tren Pendapatan & Beban</h4>
|
<div class="flex justify-between">
|
||||||
|
<div>
|
||||||
|
<h5 class="leading-none text-3xl font-bold text-gray-900 dark:text-white pb-2">
|
||||||
|
@if($labaRugiTotal < 0)
|
||||||
|
-Rp {{ number_format(abs($labaRugiTotal), 0, ',', '.') }}
|
||||||
|
@else
|
||||||
|
Rp {{ number_format($labaRugiTotal, 0, ',', '.') }}
|
||||||
|
@endif
|
||||||
|
</h5>
|
||||||
|
<p class="text-base font-normal text-gray-500 dark:text-gray-400">Laba/Rugi Total</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center px-2.5 py-0.5 text-base font-semibold {{ $growthPercentage >= 0 ? 'text-green-500' : 'text-red-500' }} dark:text-green-500 text-center">
|
||||||
|
{{ number_format($growthPercentage, 1) }}%
|
||||||
|
<svg class="w-3 h-3 ms-1" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 14">
|
||||||
|
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13V1m0 0L1 5m4-4 4 4"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="chart-container">
|
<div class="chart-container">
|
||||||
<canvas id="financial-trend-chart"></canvas>
|
<canvas id="financial-trend-chart"></canvas>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="grid grid-cols-1 items-center border-gray-200 border-t dark:border-gray-700 justify-between">
|
||||||
|
<div class="flex justify-between items-center pt-5">
|
||||||
|
<!-- Button -->
|
||||||
|
<button
|
||||||
|
id="dropdownDefaultButton"
|
||||||
|
data-dropdown-toggle="lastDaysdropdown"
|
||||||
|
data-dropdown-placement="bottom"
|
||||||
|
class="text-sm font-medium text-gray-500 dark:text-gray-400 hover:text-gray-900 text-center inline-flex items-center dark:hover:text-white"
|
||||||
|
type="button">
|
||||||
|
{{ date('d/m/Y', strtotime($startDate)) }} - {{ date('d/m/Y', strtotime($endDate)) }}
|
||||||
|
<svg class="w-2.5 m-2.5 ms-1.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
|
||||||
|
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 4 4 4-4"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<!-- Dropdown menu -->
|
||||||
|
<div id="lastDaysdropdown" class="z-10 hidden bg-white divide-y divide-gray-100 rounded-lg shadow-sm w-44 dark:bg-gray-700">
|
||||||
|
<ul class="py-2 text-sm text-gray-700 dark:text-gray-200" aria-labelledby="dropdownDefaultButton">
|
||||||
|
<li>
|
||||||
|
<a href="{{ route('home.filter', ['start_date' => Carbon\Carbon::yesterday()->format('Y-m-d'), 'end_date' => Carbon\Carbon::yesterday()->format('Y-m-d')]) }}" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Kemarin</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ route('home.filter', ['start_date' => Carbon\Carbon::today()->format('Y-m-d'), 'end_date' => Carbon\Carbon::today()->format('Y-m-d')]) }}" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Hari Ini</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ route('home.filter', ['start_date' => Carbon\Carbon::now()->subDays(7)->format('Y-m-d'), 'end_date' => Carbon\Carbon::now()->format('Y-m-d')]) }}" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">7 Hari Terakhir</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ route('home.filter', ['start_date' => Carbon\Carbon::now()->subDays(30)->format('Y-m-d'), 'end_date' => Carbon\Carbon::now()->format('Y-m-d')]) }}" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">30 Hari Terakhir</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ route('home.filter', ['start_date' => Carbon\Carbon::now()->subDays(90)->format('Y-m-d'), 'end_date' => Carbon\Carbon::now()->format('Y-m-d')]) }}" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">90 Hari Terakhir</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center space-x-2">
|
||||||
|
<button onclick="updateChartType('line')" class="text-sm font-medium text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white px-3 py-1 rounded-lg bg-gray-100 dark:bg-gray-700">Garis</button>
|
||||||
|
<button onclick="updateChartType('bar')" class="text-sm font-medium text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white px-3 py-1 rounded-lg">Bar</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Category Chart -->
|
<!-- Category Chart -->
|
||||||
<div class="bg-white p-6 rounded-xl shadow-sm">
|
<div class="max-w-sm w-full bg-white rounded-lg shadow-sm dark:bg-gray-800 p-4 md:p-6">
|
||||||
<h4 class="text-lg font-semibold text-gray-700 mb-4">Distribusi per Kategori</h4>
|
<div class="flex flex-col w-full">
|
||||||
<div class="chart-container">
|
<div class="flex items-center justify-between mb-2">
|
||||||
<canvas id="category-distribution-chart"></canvas>
|
<div class="flex items-center">
|
||||||
|
<h5 class="text-xl font-bold leading-none text-gray-900 dark:text-white">Distribusi Neraca Saldo</h5>
|
||||||
|
<svg data-popover-target="chart-info" data-popover-placement="bottom" class="w-3.5 h-3.5 text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white cursor-pointer ms-2" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5Zm0 16a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3Zm1-5.034V12a1 1 0 0 1-2 0v-1.418a1 1 0 0 1 1.038-.999 1.436 1.436 0 0 0 1.488-1.441 1.501 1.501 0 1 0-3-.116.986.986 0 0 1-1.037.961 1 1 0 0 1-.96-1.037A3.5 3.5 0 1 1 11 11.466Z"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<button id="dateRangeButton" data-dropdown-toggle="dateRangeDropdown" data-dropdown-ignore-click-outside-class="datepicker" type="button" class="inline-flex items-center text-blue-700 dark:text-blue-600 font-medium hover:underline">
|
||||||
|
{{ date('d M', strtotime($startDate)) }} - {{ date('d M', strtotime($endDate)) }}
|
||||||
|
<svg class="w-3 h-3 ms-2" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
|
||||||
|
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 4 4 4-4"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col items-center justify-center py-4">
|
||||||
|
<div class="chart-container" style="height: 260px; width: 260px;">
|
||||||
|
<canvas id="category-distribution-chart"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-wrap justify-center gap-4 mt-4">
|
||||||
|
@php
|
||||||
|
$pieColors = ['#FF5733','#33FF57','#3357FF','#FF33A1','#FFBD33','#10b981','#f472b6','#6366f1','#f59e42','#e11d48'];
|
||||||
|
@endphp
|
||||||
|
@foreach($pieLabels as $i => $label)
|
||||||
|
<div class="flex items-center space-x-2">
|
||||||
|
<span class="w-3 h-3 rounded-full" style="background: {{ $pieColors[$i % count($pieColors)] }}"></span>
|
||||||
|
<span class="text-sm">{{ $label }}</span>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between items-center border-t border-gray-200 dark:border-gray-700 mt-6 pt-4">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<button id="dropdownDefaultButton" data-dropdown-toggle="lastDaysdropdown" data-dropdown-placement="bottom" class="text-sm font-medium text-gray-500 dark:text-gray-400 hover:text-gray-900 text-center inline-flex items-center dark:hover:text-white" type="button">
|
||||||
|
Last 7 days
|
||||||
|
<svg class="w-2.5 m-2.5 ms-1.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
|
||||||
|
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 4 4 4-4"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<div id="lastDaysdropdown" class="z-10 hidden bg-white divide-y divide-gray-100 rounded-lg shadow-sm w-44 dark:bg-gray-700">
|
||||||
|
<ul class="py-2 text-sm text-gray-700 dark:text-gray-200" aria-labelledby="dropdownDefaultButton">
|
||||||
|
<li><a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Kemarin</a></li>
|
||||||
|
<li><a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Hari Ini</a></li>
|
||||||
|
<li><a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">7 Hari Terakhir</a></li>
|
||||||
|
<li><a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">30 Hari Terakhir</a></li>
|
||||||
|
<li><a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">90 Hari Terakhir</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a href="#" class="uppercase text-sm font-semibold inline-flex items-center rounded-lg text-blue-600 hover:text-blue-700 dark:hover:text-blue-500 hover:bg-gray-100 dark:hover:bg-gray-700 dark:focus:ring-gray-700 dark:border-gray-700 px-3 py-2">
|
||||||
|
LAPORAN KATEGORI
|
||||||
|
<svg class="w-2.5 h-2.5 ms-1.5 rtl:rotate-180" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 6 10">
|
||||||
|
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 9 4-4-4-4"/>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -254,11 +368,13 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@push('scripts')
|
|
||||||
<!-- Chart.js -->
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.9.1/dist/chart.min.js"></script>
|
|
||||||
<script>
|
<script>
|
||||||
|
// Debugging untuk memastikan script berjalan
|
||||||
|
console.log('Script started');
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
console.log('DOM Content Loaded');
|
||||||
|
|
||||||
// Format number to Rupiah
|
// Format number to Rupiah
|
||||||
function formatRupiah(number) {
|
function formatRupiah(number) {
|
||||||
return 'Rp ' + number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
|
return 'Rp ' + number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
|
||||||
|
@ -270,39 +386,36 @@ function formatRupiah(number) {
|
||||||
if (trendCtx) {
|
if (trendCtx) {
|
||||||
const monthlyData = @json($monthlyTotals);
|
const monthlyData = @json($monthlyTotals);
|
||||||
const labels = monthlyData.map(item => {
|
const labels = monthlyData.map(item => {
|
||||||
const [year, month] = item.periode.split('-');
|
const date = new Date(item.periode);
|
||||||
const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Ags', 'Sep', 'Okt', 'Nov', 'Des'];
|
return date.toLocaleDateString('id-ID', { day: 'numeric', month: 'short' });
|
||||||
return `${monthNames[parseInt(month)-1]} ${year}`;
|
|
||||||
});
|
});
|
||||||
const pendapatanData = monthlyData.map(item => parseFloat(item.total_debit) || 0);
|
const pendapatanData = monthlyData.map(item => parseFloat(item.total_debit) || 0);
|
||||||
const bebanData = monthlyData.map(item => parseFloat(item.total_kredit) || 0);
|
const bebanData = monthlyData.map(item => parseFloat(item.total_kredit) || 0);
|
||||||
|
|
||||||
new Chart(trendCtx, {
|
// Create gradient for area fill
|
||||||
type: 'bar',
|
const gradientFill = trendCtx.getContext('2d').createLinearGradient(0, 0, 0, 400);
|
||||||
|
gradientFill.addColorStop(0, 'rgba(34, 197, 94, 0.2)');
|
||||||
|
gradientFill.addColorStop(1, 'rgba(34, 197, 94, 0)');
|
||||||
|
|
||||||
|
window.trendChart = new Chart(trendCtx, {
|
||||||
|
type: 'line',
|
||||||
data: {
|
data: {
|
||||||
labels: labels,
|
labels: labels,
|
||||||
datasets: [{
|
datasets: [{
|
||||||
label: 'Pendapatan',
|
label: 'Pendapatan',
|
||||||
data: pendapatanData,
|
data: pendapatanData,
|
||||||
backgroundColor: 'rgba(34, 197, 94, 0.5)',
|
|
||||||
borderColor: 'rgb(34, 197, 94)',
|
borderColor: 'rgb(34, 197, 94)',
|
||||||
borderWidth: 1,
|
backgroundColor: gradientFill,
|
||||||
order: 2
|
fill: true,
|
||||||
}, {
|
tension: 0.4,
|
||||||
label: 'Beban',
|
|
||||||
data: bebanData,
|
|
||||||
backgroundColor: 'rgba(239, 68, 68, 0.5)',
|
|
||||||
borderColor: 'rgb(239, 68, 68)',
|
|
||||||
borderWidth: 1,
|
|
||||||
order: 2
|
|
||||||
}, {
|
|
||||||
label: 'Laba/Rugi',
|
|
||||||
data: pendapatanData.map((pendapatan, index) => pendapatan - bebanData[index]),
|
|
||||||
type: 'line',
|
|
||||||
borderColor: 'rgb(59, 130, 246)',
|
|
||||||
borderWidth: 2,
|
borderWidth: 2,
|
||||||
fill: false,
|
pointRadius: 0,
|
||||||
order: 1
|
pointHoverRadius: 5,
|
||||||
|
pointHoverBackgroundColor: 'rgb(34, 197, 94)',
|
||||||
|
pointHoverBorderColor: '#fff',
|
||||||
|
pointHoverBorderWidth: 2,
|
||||||
|
cubicInterpolationMode: 'monotone',
|
||||||
|
stepped: false
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
|
@ -312,89 +425,127 @@ function formatRupiah(number) {
|
||||||
intersect: false,
|
intersect: false,
|
||||||
mode: 'index'
|
mode: 'index'
|
||||||
},
|
},
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
beginAtZero: true,
|
|
||||||
ticks: {
|
|
||||||
callback: function(value) {
|
|
||||||
return formatRupiah(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
tooltip: {
|
|
||||||
callbacks: {
|
|
||||||
label: function(context) {
|
|
||||||
return context.dataset.label + ': ' + formatRupiah(context.parsed.y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Category Distribution Chart
|
|
||||||
const categoryCtx = document.getElementById('category-distribution-chart');
|
|
||||||
if (categoryCtx) {
|
|
||||||
const categoryData = @json($categoryTotals);
|
|
||||||
const categories = categoryData.map(item => item.kategori);
|
|
||||||
const pendapatanPerKategori = categoryData.map(item => parseFloat(item.total_debit) || 0);
|
|
||||||
const bebanPerKategori = categoryData.map(item => parseFloat(item.total_kredit) || 0);
|
|
||||||
|
|
||||||
new Chart(categoryCtx, {
|
|
||||||
type: 'bar',
|
|
||||||
data: {
|
|
||||||
labels: categories,
|
|
||||||
datasets: [{
|
|
||||||
label: 'Pendapatan',
|
|
||||||
data: pendapatanPerKategori,
|
|
||||||
backgroundColor: 'rgba(34, 197, 94, 0.5)',
|
|
||||||
borderColor: 'rgb(34, 197, 94)',
|
|
||||||
borderWidth: 1
|
|
||||||
}, {
|
|
||||||
label: 'Beban',
|
|
||||||
data: bebanPerKategori,
|
|
||||||
backgroundColor: 'rgba(239, 68, 68, 0.5)',
|
|
||||||
borderColor: 'rgb(239, 68, 68)',
|
|
||||||
borderWidth: 1
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
responsive: true,
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
indexAxis: 'y',
|
|
||||||
scales: {
|
|
||||||
x: {
|
|
||||||
beginAtZero: true,
|
|
||||||
ticks: {
|
|
||||||
callback: function(value) {
|
|
||||||
return formatRupiah(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
plugins: {
|
plugins: {
|
||||||
legend: {
|
legend: {
|
||||||
position: 'bottom'
|
display: false
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
callbacks: {
|
callbacks: {
|
||||||
label: function(context) {
|
label: function(context) {
|
||||||
return context.dataset.label + ': ' + formatRupiah(context.parsed.x);
|
const value = context.parsed.y;
|
||||||
|
return formatRupiah(value);
|
||||||
|
},
|
||||||
|
title: function(context) {
|
||||||
|
return `Tanggal: ${context[0].label}`;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
||||||
|
padding: 12,
|
||||||
|
titleFont: {
|
||||||
|
size: 14,
|
||||||
|
weight: 'bold'
|
||||||
|
},
|
||||||
|
bodyFont: {
|
||||||
|
size: 13
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
y: {
|
||||||
|
beginAtZero: true,
|
||||||
|
grid: {
|
||||||
|
display: false
|
||||||
|
},
|
||||||
|
ticks: {
|
||||||
|
display: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
x: {
|
||||||
|
grid: {
|
||||||
|
display: false
|
||||||
|
},
|
||||||
|
ticks: {
|
||||||
|
font: {
|
||||||
|
size: 11
|
||||||
|
},
|
||||||
|
maxRotation: 0,
|
||||||
|
autoSkip: true,
|
||||||
|
maxTicksLimit: 7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
elements: {
|
||||||
|
line: {
|
||||||
|
tension: 0.4
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Debug untuk memastikan data terisi
|
||||||
|
console.log('Chart Data:', {
|
||||||
|
labels: labels,
|
||||||
|
data: pendapatanData
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pie Chart Neraca Saldo
|
||||||
|
var ctx = document.getElementById('category-distribution-chart').getContext('2d');
|
||||||
|
var pieLabels = @json($pieLabels);
|
||||||
|
var pieData = @json($pieData);
|
||||||
|
var pieColors = [
|
||||||
|
'#FF5733','#33FF57','#3357FF','#FF33A1','#FFBD33','#10b981','#f472b6','#6366f1','#f59e42','#e11d48'
|
||||||
|
];
|
||||||
|
var total = pieData.reduce((a, b) => a + b, 0);
|
||||||
|
var myPieChart = new Chart(ctx, {
|
||||||
|
type: 'pie',
|
||||||
|
data: {
|
||||||
|
labels: pieLabels,
|
||||||
|
datasets: [{
|
||||||
|
data: pieData,
|
||||||
|
backgroundColor: pieColors,
|
||||||
|
borderColor: '#fff',
|
||||||
|
borderWidth: 2
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
plugins: {
|
||||||
|
legend: { display: false },
|
||||||
|
datalabels: {
|
||||||
|
color: '#fff',
|
||||||
|
font: { weight: 'bold', size: 16 },
|
||||||
|
formatter: function(value) {
|
||||||
|
var percent = total ? (value / total * 100) : 0;
|
||||||
|
return percent.toFixed(1) + '%';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
callbacks: {
|
||||||
|
label: function(context) {
|
||||||
|
var label = context.label || '';
|
||||||
|
var value = context.parsed || 0;
|
||||||
|
var percent = total ? (value / total * 100) : 0;
|
||||||
|
return label + ': ' + value.toLocaleString('id-ID', {style:'currency', currency:'IDR'}) + ' (' + percent.toFixed(1) + '%)';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
plugins: [ChartDataLabels]
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error creating charts:', error);
|
console.error('Error creating charts:', error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Function to update chart type
|
||||||
|
function updateChartType(type) {
|
||||||
|
if (window.trendChart) {
|
||||||
|
window.trendChart.config.type = type;
|
||||||
|
window.trendChart.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
@endpush
|
|
||||||
|
|
||||||
@endsection
|
@endsection
|
|
@ -60,7 +60,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
@foreach($pendapatan as $item)
|
@foreach($pendapatan as $item)
|
||||||
<tr class="border-b border-gray-300">
|
<tr class="border-b border-gray-300">
|
||||||
<td class="p-2 border border-gray-300 pl-8">{{ ucwords($item['kategori']) }} ({{ $item['kode_akun'] }})</td>
|
<td class="p-2 border border-gray-300 pl-8">{{ ucwords($item['kategori']) }}</td>
|
||||||
<td class="text-right p-2 border border-gray-300">
|
<td class="text-right p-2 border border-gray-300">
|
||||||
{{ number_format(abs($item['nominal']), 0, ',', '.') }}
|
{{ number_format(abs($item['nominal']), 0, ',', '.') }}
|
||||||
</td>
|
</td>
|
||||||
|
@ -77,7 +77,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
@foreach($beban as $item)
|
@foreach($beban as $item)
|
||||||
<tr class="border-b border-gray-300">
|
<tr class="border-b border-gray-300">
|
||||||
<td class="p-2 border border-gray-300 pl-8">{{ ucwords($item['kategori']) }} ({{ $item['kode_akun'] }})</td>
|
<td class="p-2 border border-gray-300 pl-8">{{ ucwords($item['kategori']) }}</td>
|
||||||
<td class="text-right p-2 border border-gray-300">
|
<td class="text-right p-2 border border-gray-300">
|
||||||
{{ number_format(abs($item['nominal']), 0, ',', '.') }}
|
{{ number_format(abs($item['nominal']), 0, ',', '.') }}
|
||||||
</td>
|
</td>
|
||||||
|
@ -104,6 +104,84 @@
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Action Buttons -->
|
||||||
|
<div class="flex justify-between items-center mt-4 mb-4">
|
||||||
|
<div class="flex space-x-2">
|
||||||
|
<a href="{{ route('labarugi.export-excel', ['start_date' => $startDate, 'end_date' => $endDate]) }}" class="btn bg-green-500 text-white hover:bg-green-600 px-4 py-2 rounded">
|
||||||
|
<i class="fas fa-file-excel mr-2"></i>Export Excel
|
||||||
|
</a>
|
||||||
|
<a href="{{ route('labarugi.export-pdf', ['start_date' => $startDate, 'end_date' => $endDate]) }}" class="btn bg-red-500 text-white hover:bg-red-600 px-4 py-2 rounded">
|
||||||
|
<i class="fas fa-file-pdf mr-2"></i>Export PDF
|
||||||
|
</a>
|
||||||
|
<button onclick="window.print()" class="btn bg-gray-500 text-white hover:bg-gray-600 px-4 py-2 rounded">
|
||||||
|
<i class="fas fa-print mr-2"></i>Print
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Style untuk print -->
|
||||||
|
<style>
|
||||||
|
@media print {
|
||||||
|
.btn, header, footer, .no-print, nav, .aside {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
padding: 20px;
|
||||||
|
font-size: 12px;
|
||||||
|
background-color: white !important;
|
||||||
|
}
|
||||||
|
.box, .p-4, .intro-y {
|
||||||
|
padding: 0 !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
background-color: white !important;
|
||||||
|
}
|
||||||
|
.bg-gray-100 {
|
||||||
|
background-color: white !important;
|
||||||
|
}
|
||||||
|
h1.text-2xl {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 20px;
|
||||||
|
margin: 10px 0 5px 0;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
p.text-sm {
|
||||||
|
text-align: center;
|
||||||
|
margin: 5px 0 20px 0;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse !important;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
table, th, td {
|
||||||
|
border: 1px solid #000 !important;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
background-color: #6b46c1 !important;
|
||||||
|
color: white !important;
|
||||||
|
-webkit-print-color-adjust: exact;
|
||||||
|
color-adjust: exact;
|
||||||
|
print-color-adjust: exact;
|
||||||
|
}
|
||||||
|
.text-right {
|
||||||
|
text-align: right !important;
|
||||||
|
}
|
||||||
|
.bg-purple-100 {
|
||||||
|
background-color: #f3e8ff !important;
|
||||||
|
-webkit-print-color-adjust: exact;
|
||||||
|
color-adjust: exact;
|
||||||
|
print-color-adjust: exact;
|
||||||
|
}
|
||||||
|
.bg-gray-100 {
|
||||||
|
background-color: #f3f4f6 !important;
|
||||||
|
-webkit-print-color-adjust: exact;
|
||||||
|
color-adjust: exact;
|
||||||
|
print-color-adjust: exact;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
|
@ -121,7 +121,7 @@
|
||||||
<th class="py-3 px-4 text-left">Keterangan</th>
|
<th class="py-3 px-4 text-left">Keterangan</th>
|
||||||
<th class="py-3 px-4 text-right">Debit</th>
|
<th class="py-3 px-4 text-right">Debit</th>
|
||||||
<th class="py-3 px-4 text-right">Kredit</th>
|
<th class="py-3 px-4 text-right">Kredit</th>
|
||||||
<th class="py-3 px-4 text-center">Aksi</th>
|
<th class="py-3 px-4 text-center aksi-col">Aksi</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody id="tableBody">
|
<tbody id="tableBody">
|
||||||
|
@ -310,7 +310,7 @@
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="py-3 px-4 text-center">
|
<td class="py-3 px-4 text-center aksi-col">
|
||||||
<div class="flex justify-center space-x-2">
|
<div class="flex justify-center space-x-2">
|
||||||
<!-- <button class="text-blue-600 hover:text-blue-800" title="Edit">
|
<!-- <button class="text-blue-600 hover:text-blue-800" title="Edit">
|
||||||
<i class="fas fa-edit"></i> -->
|
<i class="fas fa-edit"></i> -->
|
||||||
|
@ -453,6 +453,9 @@
|
||||||
.ml-8 {
|
.ml-8 {
|
||||||
margin-left: 8px !important;
|
margin-left: 8px !important;
|
||||||
}
|
}
|
||||||
|
.aksi-col, .aksi-col * {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,10 @@
|
||||||
<title>Login Page</title>
|
<title>Login Page</title>
|
||||||
<script src="https://cdn.tailwindcss.com"></script>
|
<script src="https://cdn.tailwindcss.com"></script>
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
|
||||||
|
<!-- SweetAlert2 CSS -->
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css">
|
||||||
|
<!-- SweetAlert2 JS -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
background: linear-gradient(to bottom, #00c6ff, #0072ff, #ff00ff, #ff00ff);
|
background: linear-gradient(to bottom, #00c6ff, #0072ff, #ff00ff, #ff00ff);
|
||||||
|
@ -14,21 +18,17 @@
|
||||||
<body class="flex items-center justify-center min-h-screen">
|
<body class="flex items-center justify-center min-h-screen">
|
||||||
<div class="bg-white p-8 rounded-lg shadow-lg w-80">
|
<div class="bg-white p-8 rounded-lg shadow-lg w-80">
|
||||||
<h2 class="text-2xl font-bold text-center mb-6">Login</h2>
|
<h2 class="text-2xl font-bold text-center mb-6">Login</h2>
|
||||||
@if(session('error'))
|
<form method="POST" action="{{ route('login.authenticate') }}" id="loginForm">
|
||||||
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative mb-4" role="alert">
|
|
||||||
{{ session('error') }}
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
<form method="POST" action="{{ route('login.authenticate') }}">
|
|
||||||
@csrf
|
@csrf
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<label class="block mb-2 text-sm font-medium text-gray-600" for="email">
|
<label class="block mb-2 text-sm font-medium text-gray-600" for="email">
|
||||||
<i class="fas fa-user"></i> Email
|
<i class="fas fa-user"></i> Email
|
||||||
</label>
|
</label>
|
||||||
<input class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
|
<input class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 @error('email') border-red-500 @enderror"
|
||||||
type="email"
|
type="email"
|
||||||
id="email"
|
id="email"
|
||||||
name="email"
|
name="email"
|
||||||
|
value="{{ old('email') }}"
|
||||||
placeholder="Type your email"
|
placeholder="Type your email"
|
||||||
required>
|
required>
|
||||||
</div>
|
</div>
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
<label class="block mb-2 text-sm font-medium text-gray-600" for="password">
|
<label class="block mb-2 text-sm font-medium text-gray-600" for="password">
|
||||||
<i class="fas fa-lock"></i> Password
|
<i class="fas fa-lock"></i> Password
|
||||||
</label>
|
</label>
|
||||||
<input class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
|
<input class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 @error('password') border-red-500 @enderror"
|
||||||
type="password"
|
type="password"
|
||||||
id="password"
|
id="password"
|
||||||
name="password"
|
name="password"
|
||||||
|
@ -64,5 +64,33 @@
|
||||||
</a>
|
</a>
|
||||||
</div> -->
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@if($errors->any())
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'error',
|
||||||
|
title: 'Oops...',
|
||||||
|
text: '{{ $errors->first() }}',
|
||||||
|
confirmButtonColor: '#3085d6',
|
||||||
|
confirmButtonText: 'OK'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if(session('error'))
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'error',
|
||||||
|
title: 'Oops...',
|
||||||
|
text: '{{ session("error") }}',
|
||||||
|
confirmButtonColor: '#3085d6',
|
||||||
|
confirmButtonText: 'OK'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endif
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -163,6 +163,25 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
// Notifikasi SweetAlert2
|
||||||
|
@if(session('success'))
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: 'Berhasil!',
|
||||||
|
text: '{{ session("success") }}',
|
||||||
|
confirmButtonText: 'OK'
|
||||||
|
});
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if(session('error'))
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'error',
|
||||||
|
title: 'Gagal!',
|
||||||
|
text: '{{ session("error") }}',
|
||||||
|
confirmButtonText: 'OK'
|
||||||
|
});
|
||||||
|
@endif
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
const userType = document.getElementById('userType');
|
const userType = document.getElementById('userType');
|
||||||
const searchUser = document.getElementById('searchUser');
|
const searchUser = document.getElementById('searchUser');
|
||||||
|
@ -208,41 +227,60 @@ function loadUsers(typeFilter = '', searchFilter = '') {
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.error('Error loading users:', error);
|
console.error('Error loading users:', error);
|
||||||
Swal.fire('Error!', 'Gagal memuat data user', 'error');
|
Swal.fire({
|
||||||
|
icon: 'error',
|
||||||
|
title: 'Error!',
|
||||||
|
text: 'Gagal memuat data user',
|
||||||
|
confirmButtonText: 'OK'
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteUser(id) {
|
function deleteUser(id) {
|
||||||
Swal.fire({
|
Swal.fire({
|
||||||
title: 'Hapus User',
|
title: 'Apakah Anda yakin?',
|
||||||
text: 'Apakah Anda yakin ingin menghapus user ini?',
|
text: "Data yang dihapus tidak dapat dikembalikan!",
|
||||||
icon: 'warning',
|
icon: 'warning',
|
||||||
showCancelButton: true,
|
showCancelButton: true,
|
||||||
confirmButtonText: 'Ya, Hapus',
|
confirmButtonColor: '#3085d6',
|
||||||
|
cancelButtonColor: '#d33',
|
||||||
|
confirmButtonText: 'Ya, hapus!',
|
||||||
cancelButtonText: 'Batal'
|
cancelButtonText: 'Batal'
|
||||||
}).then((result) => {
|
}).then((result) => {
|
||||||
if (result.isConfirmed) {
|
if (result.isConfirmed) {
|
||||||
fetch(`/User/${id}`, {
|
fetch(`/User/${id}`, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
headers: {
|
headers: {
|
||||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
|
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
|
||||||
|
'Content-Type': 'application/json'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
loadUsers(
|
Swal.fire({
|
||||||
document.getElementById('userType').value,
|
icon: 'success',
|
||||||
document.getElementById('searchUser').value
|
title: 'Berhasil!',
|
||||||
);
|
text: 'Data user berhasil dihapus',
|
||||||
Swal.fire('Berhasil!', 'User telah dihapus', 'success');
|
confirmButtonText: 'OK'
|
||||||
|
}).then(() => {
|
||||||
|
loadUsers(
|
||||||
|
document.getElementById('userType').value,
|
||||||
|
document.getElementById('searchUser').value
|
||||||
|
);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
throw new Error(data.message || 'Gagal menghapus user');
|
throw new Error(data.message || 'Gagal menghapus user');
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.error('Error deleting user:', error);
|
console.error('Error:', error);
|
||||||
Swal.fire('Error!', 'Gagal menghapus user', 'error');
|
Swal.fire({
|
||||||
|
icon: 'error',
|
||||||
|
title: 'Gagal!',
|
||||||
|
text: error.message || 'Terjadi kesalahan saat menghapus data',
|
||||||
|
confirmButtonText: 'OK'
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -84,4 +84,6 @@
|
||||||
// Routes untuk Laba Rugi
|
// Routes untuk Laba Rugi
|
||||||
Route::get('/labarugi', [LabarugiController::class, 'index'])->name('labarugi.index');
|
Route::get('/labarugi', [LabarugiController::class, 'index'])->name('labarugi.index');
|
||||||
Route::get('/labarugi/filter', [LabarugiController::class, 'filter'])->name('labarugi.filter');
|
Route::get('/labarugi/filter', [LabarugiController::class, 'filter'])->name('labarugi.filter');
|
||||||
|
Route::get('/labarugi/export-excel', [LabarugiController::class, 'exportExcel'])->name('labarugi.export-excel');
|
||||||
|
Route::get('/labarugi/export-pdf', [LabarugiController::class, 'exportPDF'])->name('labarugi.export-pdf');
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue