presensi/app/Http/Controllers/Api/PresensiController.php

346 lines
12 KiB
PHP

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Presensi;
use Illuminate\Support\Facades\Validator;
use App\Models\Cuti;
use Carbon\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
class PresensiController extends Controller
{
public function store(Request $request)
{
try {
// Log semua data yang diterima untuk debugging
Log::info('Presensi store request:', $request->all());
$request->validate([
'status' => 'required',
'keterangan' => 'required',
'photo' => 'required_if:status,Hadir,Masuk',
'latitude' => 'required_if:status,Hadir,Masuk',
'longitude' => 'required_if:status,Hadir,Masuk',
'clock_type' => 'required|in:in,out'
]);
$user = Auth::user();
$now = Carbon::now();
// Cek apakah sudah presensi hari ini untuk clock type yang sama
$existingPresensi = Presensi::where('user_id', $user->id)
->whereDate('created_at', $now->toDateString())
->where('clock_type', $request->clock_type)
->first();
if ($existingPresensi) {
return response()->json([
'success' => false,
'message' => 'Anda sudah melakukan presensi ' .
($request->clock_type == 'in' ? 'masuk' : 'keluar') .
' hari ini'
], 400);
}
// Set status terlambat jika clock in setelah jam 8 pagi
$status = $request->status;
// Konversi status 'Masuk' menjadi 'Hadir'
if ($status == 'Masuk') {
$status = 'Hadir';
}
if ($request->clock_type == 'in' && $status == 'Hadir') {
$batasWaktu = Carbon::createFromTime(8, 0, 0); // 08:00:00
if ($now->greaterThan($batasWaktu)) {
$status = 'Terlambat';
}
}
$data = [
'user_id' => $user->id,
'status' => $status,
'keterangan' => $request->keterangan,
'clock_type' => $request->clock_type,
'file_pdf' => null // Pastikan file_pdf kosong untuk presensi biasa
];
// Jika status Hadir atau Masuk, simpan foto dan lokasi
if ($request->status == 'Hadir' || $request->status == 'Masuk') {
if ($request->hasFile('photo')) {
Log::info('Photo file received', ['filename' => $request->file('photo')->getClientOriginalName()]);
$photo = $request->file('photo');
$filename = 'presensi_' . time() . '_' . $user->id . '.' . $photo->getClientOriginalExtension();
$path = $photo->storeAs('public/presensi', $filename);
$data['foto'] = $filename;
} else {
Log::warning('No photo file received for status: ' . $request->status);
}
$data['latitude'] = $request->latitude;
$data['longitude'] = $request->longitude;
}
Log::info('Saving presensi data:', $data);
$presensi = Presensi::create($data);
return response()->json([
'success' => true,
'message' => 'Presensi berhasil disimpan',
'data' => $presensi
]);
} catch (\Exception $e) {
Log::error('Error in presensi store: ' . $e->getMessage());
Log::error('Stack trace: ' . $e->getTraceAsString());
return response()->json([
'success' => false,
'message' => 'Error: ' . $e->getMessage()
], 500);
}
}
public function getPresensi(Request $request)
{
try {
$user = auth()->user();
if (!$user) {
return response()->json([
'success' => false,
'message' => 'Unauthorized'
], 401);
}
$query = Presensi::where('user_id', $user->id);
// Filter by date
if ($request->has('date')) {
$query->whereDate('created_at', $request->date);
}
// Filter by status
if ($request->has('status')) {
$query->where('status', $request->status);
}
// Filter by clock_type
if ($request->has('clock_type')) {
$query->where('clock_type', $request->clock_type);
}
// Sort by latest first
$presensi = $query->orderBy('created_at', 'desc')->get();
return response()->json([
'success' => true,
'message' => 'Data presensi berhasil diambil',
'data' => $presensi
], 200);
} catch (\Exception $e) {
return response()->json([
'success' => false,
'message' => 'Error: ' . $e->getMessage()
], 500);
}
}
public function getDashboardStats()
{
try {
$user = Auth::user();
$currentMonth = Carbon::now()->month;
$currentYear = Carbon::now()->year;
// Hitung jumlah kehadiran bulan ini
// Hanya menghitung status 'Hadir' dan 'Terlambat', tidak termasuk 'Izin' dan 'Sakit'
$attendanceCount = Presensi::where('user_id', $user->id)
->whereMonth('created_at', $currentMonth)
->whereYear('created_at', $currentYear)
->whereIn('status', ['Hadir', 'Terlambat'])
->where('clock_type', 'in')
->count();
// Hitung sisa cuti
$totalLeaveTaken = Cuti::where('user_id', $user->id)
->where('status', 'Disetujui')
->whereYear('tanggal_mulai', $currentYear)
->count();
// Asumsi total cuti per tahun adalah 12 hari
$remainingLeave = 12 - $totalLeaveTaken;
$remainingLeave = max(0, $remainingLeave); // Pastikan tidak negatif
return response()->json([
'success' => true,
'data' => [
'total_presensi' => $attendanceCount,
'remaining_leave' => $remainingLeave,
'total_cuti' => $totalLeaveTaken
]
]);
} catch (\Exception $e) {
return response()->json([
'success' => false,
'message' => 'Gagal mengambil data statistik: ' . $e->getMessage()
], 500);
}
}
public function getMonthlyTotal()
{
try {
$user = Auth::user();
if (!$user) {
return response()->json([
'success' => false,
'message' => 'Unauthorized'
], 401);
}
$total = Presensi::where('user_id', $user->id)
->whereMonth('created_at', Carbon::now()->month)
->whereYear('created_at', Carbon::now()->year)
->whereIn('status', ['Hadir', 'Terlambat'])
->where('clock_type', 'in')
->count();
return response()->json([
'success' => true,
'data' => [
'total' => $total
]
]);
} catch (\Exception $e) {
return response()->json([
'success' => false,
'message' => 'Error: ' . $e->getMessage()
], 500);
}
}
public function getStats()
{
try {
$user = auth()->user();
if (!$user) {
return response()->json([
'success' => false,
'message' => 'Unauthorized'
], 401);
}
// Hitung total presensi bulan ini untuk user yang login
// Hanya menghitung kehadiran (Hadir/Terlambat), tidak termasuk Izin dan Sakit
$totalPresensi = Presensi::where('user_id', $user->id)
->whereMonth('created_at', now()->month)
->whereYear('created_at', now()->year)
->whereIn('status', ['Hadir', 'Terlambat'])
->where('clock_type', 'in') // Hanya hitung clock in
->count();
Log::info('Presensi stats for user ' . $user->id . ':', ['total' => $totalPresensi]);
return response()->json([
'success' => true,
'message' => 'Data statistik presensi berhasil diambil',
'data' => [
'total_presensi' => $totalPresensi
]
], 200);
} catch (\Exception $e) {
Log::error('Error getting presensi stats: ' . $e->getMessage());
return response()->json([
'success' => false,
'message' => 'Error: ' . $e->getMessage()
], 500);
}
}
public function storeIzin(Request $request)
{
try {
$request->validate([
'status' => 'required|in:Izin,Sakit',
'keterangan' => 'required',
'file' => 'required|mimes:pdf,jpg,jpeg,png|max:5120', // Max 5MB
]);
$user = Auth::user();
$now = Carbon::now();
// Check if user already has an Izin or Sakit entry for today
$existingLeave = Presensi::where('user_id', $user->id)
->whereDate('created_at', $now->toDateString())
->whereIn('status', ['Izin', 'Sakit'])
->first();
if ($existingLeave) {
return response()->json([
'success' => false,
'message' => 'Anda sudah mengajukan ' . $existingLeave->status . ' untuk hari ini'
], 400);
}
// Check if user already has a regular attendance for today
$existingAttendance = Presensi::where('user_id', $user->id)
->whereDate('created_at', $now->toDateString())
->whereIn('status', ['Hadir', 'Terlambat'])
->first();
if ($existingAttendance) {
return response()->json([
'success' => false,
'message' => 'Anda sudah melakukan presensi hari ini, tidak dapat mengajukan ' . $request->status
], 400);
}
$data = [
'user_id' => $user->id,
'status' => $request->status,
'keterangan' => $request->keterangan,
'clock_type' => null, // Izin tidak perlu clock type
'latitude' => null,
'longitude' => null,
'foto' => null // Pastikan foto kosong untuk pengajuan izin
];
// Upload dan simpan file
if ($request->hasFile('file')) {
$file = $request->file('file');
$extension = $file->getClientOriginalExtension();
$filename = 'izin_' . time() . '_' . $user->id . '.' . $extension;
// Simpan file ke storage
$path = $file->storeAs('public/presensi', $filename);
// Simpan semua jenis file di kolom file_pdf untuk pengajuan izin
$data['file_pdf'] = $filename;
}
$presensi = Presensi::create($data);
return response()->json([
'success' => true,
'message' => 'Pengajuan ' . $request->status . ' berhasil disimpan',
'data' => $presensi
]);
} catch (\Exception $e) {
Log::error('Error izin: ' . $e->getMessage());
return response()->json([
'success' => false,
'message' => 'Error: ' . $e->getMessage()
], 500);
}
}
}