maskurir/app/Http/Controllers/ReportController.php

260 lines
9.7 KiB
PHP

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
use App\Models\Order;
use App\Models\Location;
use App\Models\User;
class ReportController extends Controller
{
public function index(Request $request)
{
// Ambil bulan dan tahun dari request, default ke bulan & tahun saat ini
$month = $request->input('month', now()->month);
$year = $request->input('year', now()->year);
// Ambil semua kurir dari tabel users (urutkan agar konsisten)
$kurirs = User::where('role', 'kurir')->orderBy('name')->get();
$kurirNames = $kurirs->pluck('name')->toArray();
// Hitung total pesanan per kurir pada bulan tertentu
$totalOrders = Order::select('kurir_id', Order::raw('COUNT(*) as total_orders'))
->whereMonth('created_at', $month)
->whereYear('created_at', $year)
->groupBy('kurir_id')
->pluck('total_orders', 'kurir_id');
// Ambil data presensi pertama per hari per kurir
$presences = Location::select('user_id', Location::raw('DATE(created_at) as date'), Location::raw('MIN(created_at) as check_in_time'))
->whereMonth('created_at', $month)
->whereYear('created_at', $year)
->groupBy('user_id', 'date')
->get();
// Hitung total presensi per kurir
$totalPresences = $presences->groupBy('user_id')->map->count();
// Hitung total presensi on-time (check-in sebelum 07:30)
$ontimeCount = $presences->filter(function ($presence) {
return Carbon::parse($presence->check_in_time)->format('H:i') < '07:30';
})->groupBy('user_id')->map->count();
// Hitung jumlah hari kurir mencapai target (lebih dari 5 order per hari)
$onTargetCount = Order::select('kurir_id', Order::raw('COUNT(*) as total_orders'), Order::raw('DATE(created_at) as order_date'))
->whereMonth('created_at', $month)
->whereYear('created_at', $year)
->groupBy('kurir_id', 'order_date')
->havingRaw('COUNT(*) > 5') // Hitung hanya hari dengan >5 order
->get()
->groupBy('kurir_id')
->map(fn($orders) => $orders->count()); // Hitung jumlah hari
// Mapping semua data ke dalam urutan $kurirs
$totalOrdersData = [];
$totalPresencesData = [];
$ontimePresencesData = [];
$totalDaysWorkedData = [];
foreach ($kurirs as $kurir) {
$kurirId = $kurir->id;
$totalOrdersData[] = $totalOrders[$kurirId] ?? 0;
$totalPresencesData[] = $totalPresences[$kurirId] ?? 0;
$ontimePresencesData[] = $ontimeCount[$kurirId] ?? 0;
// Optional: kalau kamu ingin "Total Hari Kerja" sama dengan total presensi
$totalDaysWorkedData[] = $totalPresences[$kurirId] ?? 0;
}
// Hitung predikat
$penilaian = $kurirs->map(function ($kurir) use ($onTargetCount, $ontimeCount) {
$targetHarian = $onTargetCount[$kurir->id] ?? 0;
$ontime = $ontimeCount[$kurir->id] ?? 0;
$total = $targetHarian + $ontime;
// Cek apakah keduanya memenuhi minimal 5
if ($ontime >= 5 && $targetHarian >= 5) {
$total = $targetHarian + $ontime;
if ($total >= 20 && $total <= 30) {
$predikat = 'Baik Sekali';
} elseif ($total >= 15 && $total < 20) {
$predikat = 'Baik';
} elseif ($total >= 5) {
$predikat = 'Cukup';
} else {
$predikat = '-';
}
} else {
// Jika salah satu belum memenuhi minimal 5, tidak diberi predikat
$predikat = '-';
}
return [
'id' => $kurir->id, // ✅ tambahkan ID
'nama_kurir' => $kurir->name,
'target_harian' => $targetHarian,
'ontime' => $ontime,
'predikat' => $predikat
];
});
return view('report.index', compact('totalOrdersData', 'kurirs', 'kurirNames',
'totalPresencesData', 'ontimePresencesData', 'totalDaysWorkedData',
'onTargetCount', 'month', 'year', 'penilaian'));
}
public function generatePdf($kurir_id)
{
$kurir = Kurir::findOrFail($kurir_id);
// Data yang akan dikirim ke view
$data = [
'kurir' => $kurir,
'total_pesanan' => $kurir->total_pesanan,
'on_target' => $kurir->on_target,
'total_presensi' => $kurir->total_presensi,
'on_time' => $kurir->on_time,
];
// Load view dan generate PDF
$pdf = PDF::loadView('report.kurir', $data);
// Download PDF dengan nama sesuai kurir
return $pdf->download('Laporan_Kinerja_'.$kurir->nama.'.pdf');
}
public function cetakKinerja($id, $month, $year)
{
// Ambil data kurir berdasarkan ID
$kurir = User::findOrFail($id);
$posisi = User::where('role', 'kurir');
$formattedMonthYear = Carbon::createFromDate($year, $month, 1)->translatedFormat('F Y');
// Hitung total pesanan per kurir pada bulan tertentu
$totalOrders = Order::select('kurir_id', Order::raw('COUNT(*) as total_orders'))
->whereMonth('created_at', $month)
->whereYear('created_at', $year)
->groupBy('kurir_id')
->pluck('total_orders', 'kurir_id');
// Ambil data presensi pertama per hari per kurir
$presences = Location::select('user_id', Location::raw('DATE(created_at) as date'), Location::raw('MIN(created_at) as check_in_time'))
->whereMonth('created_at', $month)
->whereYear('created_at', $year)
->groupBy('user_id', 'date')
->get();
// Total hari kerja (jumlah presensi hari unik untuk kurir ini)
$total_hari_kerja = $presences->where('user_id', $id)->count();
// Total ontime (presensi sebelum jam 07:30)
$total_ontime = $presences
->where('user_id', $id)
->filter(fn($presence) => Carbon::parse($presence->check_in_time)->format('H:i') < '07:30')
->count();
// Hitung jumlah hari kurir mencapai target (lebih dari 5 order per hari)
$onTargetCount = Order::select('kurir_id', Order::raw('COUNT(*) as total_orders'), Order::raw('DATE(created_at) as order_date'))
->whereMonth('created_at', $month)
->whereYear('created_at', $year)
->groupBy('kurir_id', 'order_date')
->havingRaw('COUNT(*) > 5')
->get()
->where('kurir_id', $id)
->count();
// Cek apakah keduanya memenuhi minimal 5
if ($total_ontime >= 5 && $onTargetCount >= 5) {
$total = $onTargetCount + $total_ontime;
if ($total >= 20 && $total <= 30) {
$predikat = 'Baik Sekali';
} elseif ($total >= 15 && $total < 20) {
$predikat = 'Baik';
} elseif ($total >= 5) {
$predikat = 'Cukup';
}
} else {
// Jika salah satu belum memenuhi minimal 5, tidak diberi predikat
$predikat = '-';
}
$kinerja = [
'total_hari_kerja' => $total_hari_kerja,
'total_ontime' => $total_ontime,
'total_ontarget' => $onTargetCount,
'predikat' => $predikat,
];
return view('report.cetak', compact('kurir', 'kinerja', 'month', 'year', 'posisi', 'formattedMonthYear'));
}
public function cetakSemuaKinerja($month, $year)
{
$users = User::where('role', 'kurir')->get();
$data = $users->map(function ($kurir) use ($month, $year) {
$presences = Location::select('user_id', DB::raw('DATE(created_at) as date'), DB::raw('MIN(created_at) as check_in_time'))
->where('user_id', $kurir->id)
->whereMonth('created_at', $month)
->whereYear('created_at', $year)
->groupBy('user_id', 'date')
->get();
$totalHariKerja = $presences->count();
$totalOnTime = $presences->filter(function ($presence) {
return Carbon::parse($presence->check_in_time)->format('H:i') < '07:30';
})->count();
$onTarget = Order::select(DB::raw('DATE(created_at) as order_date'), DB::raw('COUNT(*) as total'))
->where('kurir_id', $kurir->id)
->whereMonth('created_at', $month)
->whereYear('created_at', $year)
->groupBy('order_date')
->havingRaw('COUNT(*) > 5')
->get()
->count();
if ($totalOnTime >= 5 && $onTarget >= 5) {
$total = $onTarget + $totalOnTime;
if ($total >= 20 && $total <= 30) {
$predikat = 'Baik Sekali';
} elseif ($total >= 15 && $total < 20) {
$predikat = 'Baik';
} elseif ($total >= 5) {
$predikat = 'Cukup';
}
} else {
// Jika salah satu belum memenuhi minimal 5, tidak diberi predikat
$predikat = '-';
}
return [
'nama' => $kurir->name,
'total_hari_kerja' => $totalHariKerja,
'total_ontime' => $totalOnTime,
'total_ontarget' => $onTarget,
'predikat' => $predikat,
];
});
return view('report.cetak-semua', [
'data' => $data,
'month' => $month,
'year' => $year
]);
}
}