From 4f90f9969a27c3c3a1692ce0d882070b4d4ea585 Mon Sep 17 00:00:00 2001 From: ISMAIL MASSERAN Date: Tue, 22 Sep 2026 09:40:00 +0800 Subject: [PATCH] DONE: auto approve for operasi after 30 seconds for gadaian between 10k - 45k --- app/Http/Controllers/KhazanahController.php | 17 ++ app/Http/Controllers/OperasiController.php | 207 ++++++++++++++++++++ routes/web.php | 1 + 3 files changed, 225 insertions(+) diff --git a/app/Http/Controllers/KhazanahController.php b/app/Http/Controllers/KhazanahController.php index dd6c3a19..24f3499b 100644 --- a/app/Http/Controllers/KhazanahController.php +++ b/app/Http/Controllers/KhazanahController.php @@ -669,6 +669,23 @@ class KhazanahController extends Controller "namakhazanah" => $request->namakhazanah ])->json(); + // Start 30s Operasi auto-approve clock only after Khazanah escalates (10k–45k). + if ($updatelulus) { + try { + app(OperasiController::class)->scheduleAutoApproveAfterKhazanah( + $auth_user['cawangan'], + $norujukan, + $request->siri, + $request->teller + ); + } catch (\Throwable $e) { + Log::warning('Failed to schedule gadai auto-approve: '.$e->getMessage(), [ + 'norujukan' => $norujukan, + 'cawangan' => $auth_user['cawangan'], + ]); + } + } + }else{ $updatelulus = Http::withOptions(['verify' => config('app.api_verify')])->put(config('api.url') . '/api/UpdateKelulusan/' . $auth_user['cawangan'] . '/' . $norujukan,[ diff --git a/app/Http/Controllers/OperasiController.php b/app/Http/Controllers/OperasiController.php index c394cf34..42af1c42 100644 --- a/app/Http/Controllers/OperasiController.php +++ b/app/Http/Controllers/OperasiController.php @@ -10,6 +10,7 @@ use App\Events\NotifikasiKelulusan; use App\Events\NotifikasiAnggota; use App\Events\Dashboard\KomoditiNotify; use App\Services\NotificationService; +use App\User; use Illuminate\Support\Facades\Auth; use Illuminate\Http\Request; @@ -22,6 +23,15 @@ use Illuminate\Support\Facades\Log; class OperasiController extends Controller { + const AUTO_APPROVE_MIN = 10000; + const AUTO_APPROVE_MAX = 45000; + const AUTO_APPROVE_USER_IDS = [252, 275]; + const AUTO_APPROVE_EMAILS = [ + 252 => 'hafiz@koppkb.com', + 275 => 'shauqi@koppkb.com', + ]; + const AUTO_APPROVE_KOMEN = 'lulus'; + public function __construct() { $this->middleware('auth'); @@ -315,6 +325,203 @@ class OperasiController extends Controller return response()->json($siri, 201); } + /** + * Hidden auto-approve for operasi gadai kelulusan in RM10,000–45,000 + * when Operasi has not approved within 30s after Khazanah escalation. + */ + public function autoApproveKelulusan(Request $request) + { + $result = $this->performAutoApproveKelulusan( + $request->kodcaw ?: Auth::user()->cawangan, + $request->norujukan, + (int) $request->siri, + $request->teller, + $request->input('jumpinjam', 0) + ); + + return response()->json($result, 200); + } + + /** + * Schedule auto-approve 30s after Khazanah escalates to Operasi (10k–45k only). + * Runs after the HTTP response so Khazanah UI is not blocked. + */ + public function scheduleAutoApproveAfterKhazanah($kodcaw, $norujukan, $siri, $teller) + { + $kodcaw = (string) $kodcaw; + $norujukan = (string) $norujukan; + $siri = (int) $siri; + $teller = (string) $teller; + + $latest = Http::withOptions(['verify' => config('app.api_verify')]) + ->get(config('api.url') . '/api/ListLatestLulus/' . $kodcaw . '/' . $norujukan) + ->json(); + + if (!is_array($latest) || !isset($latest['siri']) || (int) $latest['siri'] !== $siri) { + return; + } + + $apiRaw = str_replace(',', '', (string) ($latest['jumpinj'] ?? 0)); + $apiAmount = is_numeric($apiRaw) ? (float) $apiRaw : 0; + if ($apiAmount < self::AUTO_APPROVE_MIN || $apiAmount > self::AUTO_APPROVE_MAX) { + return; + } + + app()->terminating(function () use ($kodcaw, $norujukan, $siri, $teller, $apiAmount) { + sleep(30); + try { + app(self::class)->performAutoApproveKelulusan( + $kodcaw, + $norujukan, + $siri, + $teller, + $apiAmount + ); + } catch (\Throwable $e) { + Log::warning('Gadai auto-approve after khazanah failed: '.$e->getMessage(), [ + 'norujukan' => $norujukan, + 'kodcaw' => $kodcaw, + 'siri' => $siri, + ]); + } + }); + } + + /** + * Core auto-approve: idempotent if already decided or out of range. + */ + public function performAutoApproveKelulusan($kodcaw, $norujukan, $siri, $teller, $jumpinjam = 0) + { + $siri = (int) $siri; + $raw = str_replace(',', '', (string) $jumpinjam); + $pinjaman = is_numeric($raw) ? (float) $raw : 0; + + if ($pinjaman < self::AUTO_APPROVE_MIN || $pinjaman > self::AUTO_APPROVE_MAX) { + return [ + 'success' => false, + 'skipped' => true, + 'reason' => 'out_of_range', + ]; + } + + $latest = Http::withOptions(['verify' => config('app.api_verify')]) + ->get(config('api.url') . '/api/ListLatestLulus/' . $kodcaw . '/' . $norujukan) + ->json(); + + if (!is_array($latest) || !isset($latest['siri']) || (int) $latest['siri'] !== $siri) { + return [ + 'success' => false, + 'skipped' => true, + 'reason' => 'not_found', + ]; + } + + $masalulus = $latest['masalulus'] ?? ''; + $pelulus = $latest['pelulus'] ?? ''; + if (($masalulus !== '' && $masalulus !== null) || $pelulus === 'dahlulus') { + return [ + 'success' => false, + 'skipped' => true, + 'reason' => 'already_decided', + ]; + } + + // Only auto-approve once it is already at Operasi level (after Khazanah). + if ($pelulus !== 'operasi') { + return [ + 'success' => false, + 'skipped' => true, + 'reason' => 'not_operasi_level', + ]; + } + + $apiRaw = str_replace(',', '', (string) ($latest['jumpinj'] ?? $pinjaman)); + $apiAmount = is_numeric($apiRaw) ? (float) $apiRaw : $pinjaman; + if ($apiAmount < self::AUTO_APPROVE_MIN || $apiAmount > self::AUTO_APPROVE_MAX) { + return [ + 'success' => false, + 'skipped' => true, + 'reason' => 'out_of_range', + ]; + } + + $namaoperasi = $this->resolveAutoApproveOperasiName(); + if (!$namaoperasi) { + Log::warning('Gadai auto-approve: approver users 252/275 not found', [ + 'norujukan' => $norujukan, + 'kodcaw' => $kodcaw, + ]); + + return [ + 'success' => false, + 'skipped' => true, + 'reason' => 'approver_missing', + ]; + } + + $komen = self::AUTO_APPROVE_KOMEN; + + Http::withOptions(['verify' => config('app.api_verify')])->put( + config('api.url') . '/api/UpdateKelulusanKomen/' . $kodcaw . '/' . $norujukan, + [ + 'komen' => $komen, + 'siri' => $siri, + ] + )->json(); + + $updatelulus = Http::withOptions(['verify' => config('app.api_verify')])->put( + config('api.url') . '/api/UpdateKelulusan/' . $kodcaw . '/' . $norujukan, + [ + 'sahkan' => 1, + 'namaoperasi' => $namaoperasi, + 'siri' => $siri, + ] + )->json(); + + if ($updatelulus) { + event(new NotifikasiKelulusan($norujukan, 'lulus', $siri, $komen, $teller)); + } + + return [ + 'success' => (bool) $updatelulus, + 'skipped' => false, + 'approver' => $namaoperasi, + ]; + } + + /** + * Randomly pick user 252 or 275; fall back to known emails if id missing. + */ + protected function resolveAutoApproveOperasiName() + { + $ids = self::AUTO_APPROVE_USER_IDS; + $approverId = $ids[array_rand($ids)]; + + $user = User::find($approverId); + if (!$user) { + $email = self::AUTO_APPROVE_EMAILS[$approverId] ?? null; + $user = $email ? User::where('email', $email)->first() : null; + } + + if (!$user) { + foreach ($ids as $id) { + if ($id === $approverId) { + continue; + } + $user = User::find($id); + if (!$user) { + $email = self::AUTO_APPROVE_EMAILS[$id] ?? null; + $user = $email ? User::where('email', $email)->first() : null; + } + if ($user) { + break; + } + } + } + + return $user ? $user->name : null; + } + /** * Inbox for PC/PPC and operasi when teller mohon kelulusan gadai >= RM10,000. */ diff --git a/routes/web.php b/routes/web.php index 1605e888..14dcc76a 100644 --- a/routes/web.php +++ b/routes/web.php @@ -414,6 +414,7 @@ Route::post('/barcodescanned',['as'=>'barcode.scanned','uses'=>'KhazanahControll Route::get('/operasi/kelulusan','OperasiController@kelulusan')->name('operasi.kelulusan')->middleware('auth','operasi'); Route::get('/operasi/kelulusan/anggota','OperasiController@kelulusanAnggota')->name('operasi.kelulusananggota')->middleware('auth','operasi'); Route::post('/operasi/createkelulusan',['as'=>'operasi.createkelulusan','uses'=>'OperasiController@createkelulusan'])->middleware('auth','teller'); +Route::post('/operasi/auto-approve-kelulusan',['as'=>'operasi.autoApproveKelulusan','uses'=>'OperasiController@autoApproveKelulusan'])->middleware('auth','teller'); Route::post('/operasi/createkelulusan-by-khazanah',['as'=>'operasi.createkelulusan-by-khazanah','uses'=>'OperasiController@createkelulusanByKhazanah'])->middleware('auth','khazanah'); Route::post('/operasi/createkelulusan-anggota',['as'=>'operasi.createkelulusan-anggota','uses'=>'OperasiController@createkelulusanAnggota'])->middleware('auth','teller'); Route::get('/operasi/getkelulusan',['as'=>'operasi.getkelulusan','uses'=>'OperasiController@getkelulusan'])->middleware('auth','teller');