167 lines
6.6 KiB
PHP
167 lines
6.6 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Api;
|
|
|
|
use App\Enums\JenisPengurangan;
|
|
use App\Enums\StatusPengajuan;
|
|
use App\Helpers\ApiResponse;
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\PenggunaanPoin;
|
|
use App\Events\PengajuanBaru;
|
|
use App\Services\NotifikasiService;
|
|
use App\Services\PoinService;
|
|
use Carbon\Carbon;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\Validator;
|
|
|
|
class PoinController extends Controller
|
|
{
|
|
protected $poinService;
|
|
|
|
public function __construct(PoinService $poinService)
|
|
{
|
|
$this->poinService = $poinService;
|
|
}
|
|
|
|
public function getExpiringPoints()
|
|
{
|
|
try {
|
|
$userId = Auth::id();
|
|
|
|
$poinExpiring = $this->poinService->getExpiringPoints($userId);
|
|
$activePoints = $this->poinService->getActivePoints($userId);
|
|
|
|
$firstExpiring = $poinExpiring->first();
|
|
$formattedExpiring = null;
|
|
|
|
if ($firstExpiring) {
|
|
$formattedExpiring = [
|
|
'poin' => (int) $firstExpiring->sisa_poin,
|
|
'tanggal_kadaluarsa' => $firstExpiring->expired_at->format('Y-m-d'),
|
|
];
|
|
}
|
|
|
|
return ApiResponse::success([
|
|
'expiring_points' => $formattedExpiring,
|
|
'total_poin' => (int) $activePoints
|
|
]);
|
|
|
|
} catch (\Exception $e) {
|
|
return ApiResponse::error('Terjadi kesalahan: ' . $e->getMessage(), 500);
|
|
}
|
|
}
|
|
|
|
public function getPointHistory()
|
|
{
|
|
try {
|
|
$userId = Auth::id();
|
|
$history = $this->poinService->getPointHistory($userId);
|
|
|
|
return ApiResponse::success(['history' => $history]);
|
|
|
|
} catch (\Exception $e) {
|
|
return ApiResponse::error('Terjadi kesalahan: ' . $e->getMessage(), 500);
|
|
}
|
|
}
|
|
|
|
public function redeem(Request $request)
|
|
{
|
|
$validator = Validator::make($request->all(), [
|
|
'jumlah' => 'required|integer|min:1',
|
|
'keterangan' => 'required|string|max:500',
|
|
'id_pengurangan' => 'required|integer',
|
|
'jam_masuk_custom' => 'required_if:id_pengurangan,' . JenisPengurangan::MASUK_SIANG_POIN . '|date_format:H:i|nullable',
|
|
'jam_pulang_custom' => 'required_if:id_pengurangan,' . JenisPengurangan::PULANG_CEPAT_POIN . '|date_format:H:i|nullable',
|
|
]);
|
|
|
|
if ($validator->fails()) {
|
|
return ApiResponse::validationError($validator->errors());
|
|
}
|
|
|
|
try {
|
|
$userId = Auth::id();
|
|
$jumlah = $request->jumlah;
|
|
|
|
$totalPoin = $this->poinService->getActivePoints($userId);
|
|
|
|
if ($totalPoin < $jumlah) {
|
|
return ApiResponse::error('Saldo poin tidak mencukupi. Saldo aktif: ' . $totalPoin . ', dibutuhkan: ' . $jumlah, 400);
|
|
}
|
|
|
|
preg_match('/\[(\d{4}-\d{2}-\d{2})\]/', $request->keterangan, $matches);
|
|
$tanggalPenggunaan = isset($matches[1]) ? $matches[1] : now()->format('Y-m-d');
|
|
|
|
$jadwal = \App\Models\JadwalKerja::with('shift')
|
|
->where('id_user', $userId)
|
|
->where('tanggal', $tanggalPenggunaan)
|
|
->first();
|
|
|
|
if (!$jadwal || !$jadwal->shift) {
|
|
return ApiResponse::error('Jadwal kerja tidak ditemukan untuk tanggal ' . Carbon::parse($tanggalPenggunaan)->format('d/m/Y') . '.', 400);
|
|
}
|
|
|
|
// --- ⚡ VALIDASI PENGGUNAAN POIN GANDA ⚡ ---
|
|
$existingPoin = PenggunaanPoin::where('id_user', $userId)
|
|
->where('tanggal_penggunaan', $tanggalPenggunaan)
|
|
->whereIn('id_status', [StatusPengajuan::PENDING, StatusPengajuan::DISETUJUI])
|
|
->exists();
|
|
|
|
if ($existingPoin) {
|
|
return ApiResponse::error('Anda sudah memiliki pengajuan penggunaan poin (Pending/Disetujui) untuk tanggal ini.', 400);
|
|
}
|
|
|
|
// --- ⚡ VALIDASI STATUS PRESENSI ⚡ ---
|
|
$presensi = \App\Models\Presensi::where('id_user', $userId)
|
|
->where('tanggal', $tanggalPenggunaan)
|
|
->first();
|
|
|
|
if ($presensi && $presensi->jam_pulang) {
|
|
return ApiResponse::error('Anda sudah melakukan absen pulang pada tanggal tersebut. Penggunaan poin tidak diperbolehkan secara retroaktif.', 400);
|
|
}
|
|
|
|
if ($presensi && $presensi->jam_masuk && $request->id_pengurangan != JenisPengurangan::PULANG_CEPAT_POIN) {
|
|
return ApiResponse::error('Anda sudah tercatat melakukan absen masuk. Anda hanya diperbolehkan menggunakan poin untuk "Pulang Cepat".', 400);
|
|
}
|
|
// -------------------------------------
|
|
|
|
if ($request->id_pengurangan == JenisPengurangan::PULANG_CEPAT_POIN) {
|
|
$waktuBatasPulang = Carbon::parse($tanggalPenggunaan . ' ' . $request->jam_pulang_custom)->subHour();
|
|
if (now()->greaterThan($waktuBatasPulang)) {
|
|
return ApiResponse::error('Pengajuan Pulang Cepat harus dilakukan maksimal 1 jam sebelum jam kepulangan yang diminta (Batas: ' . $waktuBatasPulang->format('H:i') . ').', 400);
|
|
}
|
|
} else {
|
|
$waktuBatasPengajuan = Carbon::parse($tanggalPenggunaan . ' ' . $jadwal->shift->jam_mulai)->subHour();
|
|
if (now()->greaterThan($waktuBatasPengajuan)) {
|
|
return ApiResponse::error('Pengajuan poin harus dilakukan maksimal 1 jam sebelum jam kerja dimulai (Batas: ' . $waktuBatasPengajuan->format('d/m/Y H:i') . ').', 400);
|
|
}
|
|
}
|
|
|
|
PenggunaanPoin::create([
|
|
'id_user' => $userId,
|
|
'tanggal_penggunaan' => $tanggalPenggunaan,
|
|
'jumlah_poin' => $jumlah,
|
|
'id_pengurangan' => $request->id_pengurangan,
|
|
'jam_masuk_custom' => $request->jam_masuk_custom,
|
|
'jam_pulang_custom' => $request->jam_pulang_custom,
|
|
'id_status' => StatusPengajuan::PENDING,
|
|
'tanggal_diajukan' => now(),
|
|
]);
|
|
|
|
$user = Auth::user();
|
|
app(NotifikasiService::class)->kirimKeRole(
|
|
'hrd',
|
|
'pengajuan_baru',
|
|
'Pengajuan Penggunaan Poin',
|
|
$user->nama_lengkap . ' mengajukan penggunaan ' . $jumlah . ' poin.'
|
|
);
|
|
|
|
broadcast(new PengajuanBaru('poin', $user->nama_lengkap, 'Penggunaan ' . $jumlah . ' Poin'));
|
|
|
|
return ApiResponse::success(null, 'Pengajuan penukaran poin berhasil disimpan');
|
|
} catch (\Exception $e) {
|
|
return ApiResponse::error($e->getMessage(), 400);
|
|
}
|
|
}
|
|
}
|