Feature/whatsapp blast #24
@@ -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,[
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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');
|
||||
|
||||
Reference in New Issue
Block a user