260 lines
9.7 KiB
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
|
|
]);
|
|
}
|
|
}
|