From 73d74878d9c1dbe3db4aa3d4985626a3cbeafe74 Mon Sep 17 00:00:00 2001 From: ISMAIL MASSERAN Date: Sun, 9 Aug 2026 10:18:26 +0800 Subject: [PATCH 01/11] DONE: use flexible name for api call in frontend --- .env.docker | 54 +++++++++++++ .gitignore | 2 +- README.md | 50 +++++++++++++ REMARK.md | 5 ++ .../Auth/ImpersonateController.php | 52 +++++++++++++ app/Http/Controllers/Auth/LoginController.php | 46 ++++++++++-- app/Http/Controllers/KhazanahController.php | 3 + app/Http/Controllers/OperasiController.php | 3 + app/Providers/AuthServiceProvider.php | 4 +- app/User.php | 12 +++ app/helpers.php | 15 ++++ composer.json | 4 + composer.lock | 75 ++++++++++++++++++- docker/php/Dockerfile | 40 +++++----- .../views/admin/customer_index.blade.php | 2 +- resources/views/admin/customer_info.blade.php | 2 +- resources/views/admin/poskod.blade.php | 2 +- resources/views/aliran_tunai/index.blade.php | 9 +-- .../views/callcenter/callnotisjbg2.blade.php | 2 +- resources/views/callcenter/index.blade.php | 2 +- .../views/callcenter/indexnama.blade.php | 2 +- resources/views/callcenter/v1/info.blade.php | 2 +- resources/views/callcenter/v2/index.blade.php | 2 +- resources/views/callcenter/v2/info.blade.php | 2 +- resources/views/customers/v1/index.blade.php | 2 +- resources/views/customers/v1/info.blade.php | 2 +- resources/views/customers/v2/index.blade.php | 9 +-- resources/views/customers/v2/info.blade.php | 32 +++++--- resources/views/errors/alert.blade.php | 2 +- resources/views/gadaian/v1/edit.blade.php | 2 +- resources/views/gadaian/v1/index.blade.php | 2 +- resources/views/gadaian/v2/edit.blade.php | 6 +- resources/views/gadaian/v2/index.blade.php | 4 +- .../views/homepage/khazanah/home.blade.php | 2 +- .../views/homepage/penilai/home.blade.php | 2 +- .../views/homepage/teller/home.blade.php | 3 +- .../views/khazanah/agingbulanan.blade.php | 2 +- resources/views/khazanah/bajet.blade.php | 2 +- resources/views/khazanah/gadaian.blade.php | 2 +- resources/views/khazanah/index.blade.php | 2 +- resources/views/khazanah/info.blade.php | 2 +- resources/views/khazanah/kelulusan.blade.php | 4 +- .../views/khazanah/khazanahserahan.blade.php | 2 +- .../khazanah/laporan/agingbulanan.blade.php | 2 +- .../khazanah/laporan/alirantunai.blade.php | 2 +- .../views/khazanah/laporan/ansuran.blade.php | 2 +- .../laporan/batalsuratgadai.blade.php | 2 +- .../khazanah/laporan/datalejer_am.blade.php | 2 +- .../khazanah/laporan/denominasi.blade.php | 2 +- .../views/khazanah/laporan/gadaian.blade.php | 2 +- .../khazanah/laporan/imbangduga.blade.php | 2 +- .../laporan/imbangduga_akru.blade.php | 2 +- .../khazanah/laporan/kawalanstok.blade.php | 2 +- .../khazanah/laporan/marhunharian.blade.php | 2 +- .../laporan/marhunterkumpul.blade.php | 2 +- .../khazanah/laporan/pelangganbaru.blade.php | 2 +- .../khazanah/laporan/penebusan.blade.php | 2 +- .../khazanah/laporan/perbelanjaan.blade.php | 2 +- .../views/khazanah/laporan/petibesi.blade.php | 2 +- .../laporan/ringkasanharian.blade.php | 2 +- .../laporan/ringkasanterkumpul.blade.php | 2 +- .../khazanah/laporan/serahgadai.blade.php | 2 +- .../khazanah/laporan/serahmarhun.blade.php | 2 +- .../laporan/stokauditbersih.blade.php | 2 +- .../laporan/stokauditdetails.blade.php | 2 +- .../khazanah/laporan/tuntutbaki.blade.php | 2 +- .../views/khazanah/laporan/upah.blade.php | 2 +- .../views/khazanah/laporan/wakil.blade.php | 2 +- .../laporanujrah/ansuranujrah.blade.php | 2 +- .../laporanujrah/gadaianujrah.blade.php | 2 +- .../ringkasanharianujrah.blade.php | 2 +- resources/views/khazanah/panjar.blade.php | 4 +- .../views/khazanah/pendahuluan.blade.php | 2 +- .../views/khazanah/pendahuluanserah.blade.php | 2 +- .../khazanah/pendahuluanserahanmain.blade.php | 2 +- .../views/khazanah/permohonanwang.blade.php | 2 +- .../views/khazanah/rekodpermohonan.blade.php | 2 +- resources/views/khazanah/saginfo.blade.php | 2 +- resources/views/khazanah/serahan.blade.php | 2 +- resources/views/khazanah/tebus.blade.php | 2 +- resources/views/khazanah/v1/info.blade.php | 2 +- resources/views/khazanah/v2/info.blade.php | 2 +- resources/views/khazanah/wakil.blade.php | 2 +- resources/views/layouts/app.blade.php | 6 +- .../views/layouts/app_callcenter.blade.php | 3 + resources/views/layouts/app_operasi.blade.php | 3 + .../partials/impersonation_nav.blade.php | 11 +++ .../views/lelongan/index-khazanah.blade.php | 6 +- resources/views/lelongan/index.blade.php | 4 +- .../views/onetimepassword/home.blade.php | 2 +- .../views/operasi/daftar_kakitangan.blade.php | 46 ++++++++++++ .../views/operasi/edit_marginmutu.blade.php | 2 +- resources/views/operasi/hargaemas.blade.php | 2 +- resources/views/operasi/kelulusan.blade.php | 4 +- .../views/operasi/komuditi/index.blade.php | 2 +- .../komuditi/rekod_transaksi.blade.php | 2 +- .../penebusan/v1/index-khazanah.blade.php | 2 +- resources/views/penebusan/v1/index.blade.php | 2 +- .../penebusan/v2/index-khazanah.blade.php | 2 +- .../views/penebusan/v2/index.blade-backup.php | 2 +- resources/views/penebusan/v2/index.blade.php | 4 +- routes/web.php | 6 ++ 102 files changed, 523 insertions(+), 146 deletions(-) create mode 100644 .env.docker create mode 100644 REMARK.md create mode 100644 app/Http/Controllers/Auth/ImpersonateController.php create mode 100644 app/helpers.php create mode 100644 resources/views/layouts/partials/impersonation_nav.blade.php diff --git a/.env.docker b/.env.docker new file mode 100644 index 00000000..79c1ea3a --- /dev/null +++ b/.env.docker @@ -0,0 +1,54 @@ +APP_NAME=Laravel +APP_ENV=local +APP_KEY=base64:O1XZDqK4H6+3GdrODgCaLr2l+OoWvgVhYr0GJ1KizW8= +APP_DEBUG=true +APP_URL=http://localhost +# API_URL=http://api-annurv2.test +API_URL=http://host.docker.internal:8080 +API_URL_KOOP=http://host.docker.internal:8080 +API_URL_PKB=http://host.docker.internal:8080 +API_ARRAHNBID=http://lelong.test/api/ + +LOG_CHANNEL=stack +LOG_LEVEL=debug + +DB_CONNECTION=mysql +DB_HOST=mysql +DB_PORT=3306 +DB_DATABASE=kaunter_erahn +DB_USERNAME=kaunteruser +DB_PASSWORD=password + +BROADCAST_DRIVER=pusher +CACHE_DRIVER=file +QUEUE_CONNECTION=sync +SESSION_DRIVER=file +SESSION_LIFETIME=120 + +REDIS_HOST=127.0.0.1 +REDIS_PASSWORD=null +REDIS_PORT=6379 + +PUSHER_APP_ID=1132718 +PUSHER_APP_KEY=26b0ec2f297f94b7aa9b +PUSHER_APP_SECRET=421b61fb5a8ecce477a6 + +MAIL_MAILER=smtp +MAIL_HOST=smtp.mailtrap.io +MAIL_PORT=2525 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null +MAIL_FROM_ADDRESS=null +MAIL_FROM_NAME="${APP_NAME}" + +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET= + +MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" +MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" + +MYKAD_READER_PORT=8085 +MYKAD_READER_ENABLED_CAWANGAN='' # IF NO CAWANGAN STATED, ALL CAWANGAN IS ENABLED \ No newline at end of file diff --git a/.gitignore b/.gitignore index 1ed293c1..80ba177a 100644 --- a/.gitignore +++ b/.gitignore @@ -11,5 +11,5 @@ Homestead.yaml npm-debug.log yarn-error.log /.vscode -docker-compose.yml docker_src/ +**/.DS_Store \ No newline at end of file diff --git a/README.md b/README.md index f821d23f..ca86015c 100644 --- a/README.md +++ b/README.md @@ -1 +1,51 @@ If you does't know what is this you probably in wrong project + +```sql +--- for all ip +CREATE USER 'kaunteruser'@'%' IDENTIFIED BY 'your_password'; + +--- for specific ip +CREATE USER 'kaunteruser'@'localhost' IDENTIFIED BY 'your_password'; + +GRANT ALL PRIVILEGES ON kaunter_erahn.* TO 'kaunteruser'@'%'; +FLUSH PRIVILEGES; +``` + +# ADDITIONAL NOTE + +## customers/v2/index.blade.php is modal to register customer + +## Min Komoditi = RM5000 + +# System Flowchart + +## Proses Gadaian +1) Pelanggan datang bawa marhun +2) Teller daftar maklumat pelanggan jika pelanggan baharu +3) Serah marhun ke penilai untuk timbang +4) Teller daftar marhun di sistem berdasarkan maklumat dari penilai +5) Penilai print SAG dan serah marhun ke Khazanah (PC/PPC) - __khazanah can still scan still scan though__ +6) Khazanah scan barcode dekat SAG untuk masuk ke dalam peti besi +* table involved - gadai.semakbarcode (default is blank, after is Lulus) +7) DONE + +## Setup new branch command: +1. Duplicate previous branch table - use erahn_{{name}} +```sql +SET FOREIGN_KEY_CHECKS = 0; + +SET SESSION group_concat_max_len = 1000000; + +SELECT GROUP_CONCAT( + CONCAT('TRUNCATE TABLE `', table_name, '`') + SEPARATOR '; ' +) INTO @sql +FROM information_schema.tables +WHERE table_schema = DATABASE(); + +SELECT @sql; --- copy the output and paste it + +SET FOREIGN_KEY_CHECKS = 1; +``` +2. Add new cawangan kod on master_erahn.arrahn_master_db and and kaunter_erahn.cawangan +3. Register new cawangan detail in erahn_{{name}}.cawangan \ No newline at end of file diff --git a/REMARK.md b/REMARK.md new file mode 100644 index 00000000..313b68a7 --- /dev/null +++ b/REMARK.md @@ -0,0 +1,5 @@ +## CAWANGAN XTRA - X0301 +- WAN NUR FATIN NATASYA BINTI W M AZHARI - PENILAI +- MOHAMAD KHAIRULNIZAN BIN JUSOF - TELLER +- MOHAMAD AZUHAIDIE BIN AHMAD - PPC +- WAN NURUL AMIRA BINTI WAN HARON - PC diff --git a/app/Http/Controllers/Auth/ImpersonateController.php b/app/Http/Controllers/Auth/ImpersonateController.php new file mode 100644 index 00000000..dab764ab --- /dev/null +++ b/app/Http/Controllers/Auth/ImpersonateController.php @@ -0,0 +1,52 @@ +middleware('auth'); + } + + public function impersonate(Request $request, $id): RedirectResponse + { + Gate::authorize('impersonate'); + + $impersonator = $request->user(); + $id = (int) $id; + $target = User::findOrFail($id); + + if ($target->id === $request->user()->id) { + return back()->with('error', 'Tidak boleh impersonate diri sendiri.'); + } + + if (method_exists($target, 'canBeImpersonated') && !$target->canBeImpersonated()) { + return back()->with('error', 'Akaun ini tidak boleh di-impersonate.'); + } + + $request->user()->impersonate($target); + + return redirect()->route('home'); + } + + public function leave(Request $request): RedirectResponse + { + if ($request->user() && method_exists($request->user(), 'isImpersonated') && $request->user()->isImpersonated()) { + $impersonated = $request->user(); + $impersonator = method_exists($impersonated, 'impersonator') ? $impersonated->impersonator() : null; + + $request->user()->leaveImpersonation(); + } + + return redirect()->route('home'); + } +} + diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index f29fcc28..b9abb660 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -60,9 +60,7 @@ class LoginController extends Controller 'password' => 'required|string', ]); - $credentials = $request->only('email', 'password'); - - if (Auth::guard('web')->attempt($credentials)) { + if ($this->attemptWebLogin($request)) { $auth_user = Auth::guard('web')->user(); $api_url = config('api.url'); @@ -103,9 +101,7 @@ class LoginController extends Controller 'password' => 'required|string', ]); - $credentials = $request->only('email', 'password'); - - if (Auth::guard('dashboard')->attempt($credentials,true)) { + if ($this->attemptDashboardLogin($request)) { $auth_user = Auth::guard('dashboard')->user(); $user_login['nama'] = $auth_user['name']; @@ -187,4 +183,42 @@ class LoginController extends Controller return response()->json($kakitangan,200); } + + /** + * In local environment, log in by email only (password ignored). + */ + private function attemptWebLogin(Request $request): bool + { + if (app()->environment('local')) { + $user = User::where('email', $request->email)->first(); + if ($user) { + Auth::guard('web')->login($user); + + return true; + } + + return false; + } + + return Auth::guard('web')->attempt($request->only('email', 'password')); + } + + /** + * In local environment, log in by email only (password ignored). + */ + private function attemptDashboardLogin(Request $request): bool + { + if (app()->environment('local')) { + $user = Dashboard::where('email', $request->email)->first(); + if ($user) { + Auth::guard('dashboard')->login($user, true); + + return true; + } + + return false; + } + + return Auth::guard('dashboard')->attempt($request->only('email', 'password'), true); + } } diff --git a/app/Http/Controllers/KhazanahController.php b/app/Http/Controllers/KhazanahController.php index 03e72524..a4b074bb 100644 --- a/app/Http/Controllers/KhazanahController.php +++ b/app/Http/Controllers/KhazanahController.php @@ -505,6 +505,9 @@ class KhazanahController extends Controller public function mintakatalaluansemula(Request $request) { + if (app()->environment('local')) { + return "True"; + } if(Hash::check($request->passsemula, Auth::user()->password)) { diff --git a/app/Http/Controllers/OperasiController.php b/app/Http/Controllers/OperasiController.php index 93a12505..7b5f6491 100644 --- a/app/Http/Controllers/OperasiController.php +++ b/app/Http/Controllers/OperasiController.php @@ -370,6 +370,9 @@ class OperasiController extends Controller public function mintakatalaluansemula(Request $request) { + if (app()->environment('local')) { + return "True"; + } if (Hash::check($request->passsemula, Auth::user()->password)) { return "True"; diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 30490683..08a3ae1b 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -25,6 +25,8 @@ class AuthServiceProvider extends ServiceProvider { $this->registerPolicies(); - // + Gate::define('impersonate', function ($user) { + return $user->canImpersonate(); + }); } } diff --git a/app/User.php b/app/User.php index 33e49532..70034b80 100644 --- a/app/User.php +++ b/app/User.php @@ -6,9 +6,11 @@ use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; +use Lab404\Impersonate\Models\Impersonate; class User extends Authenticatable { + use Impersonate; use Notifiable; protected $guard = 'web'; @@ -43,4 +45,14 @@ class User extends Authenticatable { return $this->hasOne(Cawangan::class, 'kodcaw', 'cawangan'); } + + public function canImpersonate(): bool + { + return in_array($this->roles ?? '', ['admin'], true); + } + + public function canBeImpersonated(): bool + { + return ($this->roles ?? '') !== 'admin'; + } } diff --git a/app/helpers.php b/app/helpers.php new file mode 100644 index 00000000..974dacb6 --- /dev/null +++ b/app/helpers.php @@ -0,0 +1,15 @@ + @endsection \ No newline at end of file diff --git a/resources/views/aliran_tunai/index.blade.php b/resources/views/aliran_tunai/index.blade.php index 9459d54a..384fad46 100644 --- a/resources/views/aliran_tunai/index.blade.php +++ b/resources/views/aliran_tunai/index.blade.php @@ -26,7 +26,7 @@
@php $auth_user = Auth::user();@endphp - +
@@ -348,7 +348,7 @@
@endsection diff --git a/resources/views/khazanah/saginfo.blade.php b/resources/views/khazanah/saginfo.blade.php index 402bfd01..40638d27 100644 --- a/resources/views/khazanah/saginfo.blade.php +++ b/resources/views/khazanah/saginfo.blade.php @@ -104,7 +104,7 @@ @@ -199,7 +199,7 @@
diff --git a/resources/views/layouts/app_callcenter.blade.php b/resources/views/layouts/app_callcenter.blade.php index bed22382..60a94775 100644 --- a/resources/views/layouts/app_callcenter.blade.php +++ b/resources/views/layouts/app_callcenter.blade.php @@ -105,6 +105,7 @@
diff --git a/resources/views/layouts/partials/impersonation_nav.blade.php b/resources/views/layouts/partials/impersonation_nav.blade.php new file mode 100644 index 00000000..b859caba --- /dev/null +++ b/resources/views/layouts/partials/impersonation_nav.blade.php @@ -0,0 +1,11 @@ +@if(Auth::check() && method_exists(Auth::user(), 'isImpersonated') && Auth::user()->isImpersonated()) + +@endif + diff --git a/resources/views/lelongan/index-khazanah.blade.php b/resources/views/lelongan/index-khazanah.blade.php index 71c4f233..062a93ec 100644 --- a/resources/views/lelongan/index-khazanah.blade.php +++ b/resources/views/lelongan/index-khazanah.blade.php @@ -200,7 +200,7 @@ } }); - var api = ''; + var api = "{{ api_url_for_browser() }}"; let nw = 0; function wakilfunction(e) @@ -536,7 +536,7 @@ function ubahwakil(e) { let norujukan = $('#norujukan').val(); - let api = "{{ config('api.url') }}"; + let api = "{{ api_url_for_browser() }}"; let nowakil = nw; let jenis = ''; @@ -627,7 +627,7 @@ function ubahwakil(e) let norujukan = $('#norujukan').val(); - let api = "{{ config('api.url') }}"; + let api = "{{ api_url_for_browser() }}"; let nowakil = 0; let jenis = ''; let mohon = ''; diff --git a/resources/views/lelongan/index.blade.php b/resources/views/lelongan/index.blade.php index 2eab543b..a53b02a4 100644 --- a/resources/views/lelongan/index.blade.php +++ b/resources/views/lelongan/index.blade.php @@ -229,7 +229,7 @@ } }); - var api = ''; + var api = "{{ api_url_for_browser() }}"; let nw = 0; function wakilfunction(e) @@ -565,7 +565,7 @@ function ubahwakil(e) { let norujukan = $('#norujukan').val(); - let api = "{{ config('api.url') }}"; + let api = "{{ api_url_for_browser() }}"; let nowakil = nw; let jenis = ''; diff --git a/resources/views/onetimepassword/home.blade.php b/resources/views/onetimepassword/home.blade.php index 0c010b0d..689f8f8b 100644 --- a/resources/views/onetimepassword/home.blade.php +++ b/resources/views/onetimepassword/home.blade.php @@ -102,7 +102,7 @@ $(document).ready(function() function carila() { - var api_url = ""; + var api_url = "{{ api_url_for_browser() }}"; var noic = $('#noic').val(); diff --git a/resources/views/operasi/daftar_kakitangan.blade.php b/resources/views/operasi/daftar_kakitangan.blade.php index bfc3bc03..fd619368 100644 --- a/resources/views/operasi/daftar_kakitangan.blade.php +++ b/resources/views/operasi/daftar_kakitangan.blade.php @@ -138,6 +138,19 @@ edit work settings + @if( + app()->environment('local') + && + in_array($auth_user->roles, ['admin']) + && $staff->roles != 'admin' + && $staff->id != $auth_user->id + && !(Auth::check() && method_exists(Auth::user(), 'isImpersonated') && Auth::user()->isImpersonated()) + ) +
+ @csrf + +
+ @endif @elseif($auth_user->roles == 'admin') {{--
@@ -147,6 +160,18 @@ work settings restore + @if( + app()->environment('local') + && + $staff->roles != 'admin' + && $staff->id != $auth_user->id + && !(Auth::check() && method_exists(Auth::user(), 'isImpersonated') && Auth::user()->isImpersonated()) + ) + + @csrf + +
+ @endif {{-- --}} @endif @@ -223,6 +248,27 @@ }).catch(swal.noop) }); + $("#rekod_kakitangan").on('click', ".btn-impersonate", function(){ + var form = $(this).closest('form'); + var staffName = $(this).data('staff-name'); + + Swal.fire({ + title: 'Menyamar sebagai Kakitangan?', + text: "Anda akan log masuk sebagai " + staffName + ".", + type: 'warning', + showCancelButton: true, + confirmButtonClass: 'btn btn-secondary', + cancelButtonClass: 'btn btn-warning', + confirmButtonText: 'Ya, menyamar', + cancelButtonText: 'Batal!', + buttonsStyling: false + }).then(function(result) { + if (result.isConfirmed) { + form.submit(); + } + }).catch(swal.noop) + }); + function verifyregister(){ var cawangan = $('#cawangan').val(); var role = $('#role').val(); diff --git a/resources/views/operasi/edit_marginmutu.blade.php b/resources/views/operasi/edit_marginmutu.blade.php index ae1333e1..ee34287d 100644 --- a/resources/views/operasi/edit_marginmutu.blade.php +++ b/resources/views/operasi/edit_marginmutu.blade.php @@ -85,7 +85,7 @@ $(document).ready(function() { }; $.ajax({ - url: '{{ config("api.url") }}/api/maxmutuemas/update', + url: '{{ api_url_for_browser() }}/api/maxmutuemas/update', type: 'POST', data: formData, success: function(response) { diff --git a/resources/views/operasi/hargaemas.blade.php b/resources/views/operasi/hargaemas.blade.php index 1bce3c11..a6896263 100644 --- a/resources/views/operasi/hargaemas.blade.php +++ b/resources/views/operasi/hargaemas.blade.php @@ -95,7 +95,7 @@ +@endsection diff --git a/resources/views/pembiayaan_online/operasi/eod.blade.php b/resources/views/pembiayaan_online/operasi/eod.blade.php new file mode 100644 index 00000000..588e0a69 --- /dev/null +++ b/resources/views/pembiayaan_online/operasi/eod.blade.php @@ -0,0 +1,152 @@ +@extends('layouts.app_operasi') +@section('content') +
+
+
+ + + @if(session()->has('message')) +
{{ session('message') }}
+ @endif + @if(session()->has('error')) +
{{ session('error') }}
+ @endif + +
+
+
+
Tarikh
+

{{ $tarikh }}

+
+
+
+
+
Masih Dibuka
+

{{ $summary['open'] ?? 0 }}

+
+
+
+
+
Sudah Ditutup
+

{{ $summary['closed'] ?? 0 }}

+
+
+
+
+
Belum Ada Rekod
+

{{ $summary['missing'] ?? 0 }}

+
+
+
+ +
+
+
+ + + + Top-up +
+ @if(($summary['open'] ?? 0) > 0) +
+ @csrf + +
+ @endif +
+
+ +
+
+
Status Modal Online Mengikut Cawangan
+
+
+ + + + + + + + + + + + + + + + @forelse($rows as $row) + @php + $closed = (int)($row['ditutup'] ?? 0) === 1; + $missing = !empty($row['missing']); + @endphp + + + + + + + + + + + + @empty + + + + @endforelse + +
CawanganHadTambahDigunakanKurang (EOD)BakiStatusDitutup Oleh
+
{{ $row['cawangan_nama'] ?? '-' }}
+ {{ $row['kodcaw'] ?? '' }} +
{{ number_format((float)($row['had'] ?? 0), 2) }}{{ number_format((float)($row['tambah'] ?? 0), 2) }}{{ number_format((float)($row['digunakan'] ?? 0), 2) }}{{ number_format((float)($row['kurang'] ?? 0), 2) }} + @if($missing) + — + @else + {{ number_format((float)($row['baki'] ?? 0), 2) }} + @endif + + @if($closed) + DITUTUP + @elseif($missing) + TIADA + @else + DIBUKA + @endif + + @if($closed) + {{ $row['ditutup_oleh'] ?? '-' }}
+ {{ $row['ditutup_at'] ?? '' }} + @else + — + @endif +
+ @if($closed) + OK + @elseif($missing) + Tiada had + @else +
+ @csrf + +
+ @endif +
Tiada data cawangan.
+
+
+
+
+
+@endsection diff --git a/resources/views/pembiayaan_online/operasi/senarai.blade.php b/resources/views/pembiayaan_online/operasi/senarai.blade.php new file mode 100644 index 00000000..2f2e6505 --- /dev/null +++ b/resources/views/pembiayaan_online/operasi/senarai.blade.php @@ -0,0 +1,102 @@ +@extends('layouts.app_operasi') +@section('content') +
+
+
+ + + @if(session()->has('message')) +
{{ session('message') }}
+ @endif + @if(session()->has('error')) +
{{ session('error') }}
+ @endif + +
+
+
+ + + + + + Reset +
+
+
+ +
+
+
Senarai Batch Pembiayaan Online
+
+ Modal Online + EOD + {{ count($batches) }} batch +
+
+
+ + + + + + + + + + + + + + + + @forelse($batches as $batch) + @php + $st = $batch['status'] ?? ''; + $badge = 'badge-secondary'; + if ($st === 'SUBMITTED') $badge = 'badge-primary'; + elseif ($st === 'PARTIAL') $badge = 'badge-warning'; + elseif ($st === 'OPS_DONE') $badge = 'badge-success'; + elseif ($st === 'PAID') $badge = 'badge-dark'; + @endphp + + + + + + + + + + + + @empty + + + + @endforelse + +
Batch NoCawanganTarikhSlotBilJumlah (RM)StatusDihantar Oleh
{{ $batch['batch_no'] ?? '-' }} +
{{ $batch['cawangan_nama'] ?? '-' }}
+ {{ $batch['kodcaw'] ?? '' }} +
{{ $batch['tarikh'] ?? '-' }}{{ $batch['slot'] ?? '-' }}{{ $batch['bilangan'] ?? 0 }}{{ number_format((float)($batch['jumlah_keseluruhan'] ?? 0), 2) }}{{ $st ?: '-' }}{{ $batch['pc_submitted_by'] ?? '-' }} + + Semak + +
Tiada batch untuk tapisan ini.
+
+
+
+
+
+@endsection diff --git a/resources/views/pembiayaan_online/operasi/topup.blade.php b/resources/views/pembiayaan_online/operasi/topup.blade.php new file mode 100644 index 00000000..139a0ae4 --- /dev/null +++ b/resources/views/pembiayaan_online/operasi/topup.blade.php @@ -0,0 +1,198 @@ +@extends('layouts.app_operasi') +@section('content') +
+
+
+ + + @if(session()->has('message')) +
{{ session('message') }}
+ @endif + @if(session()->has('error')) +
{{ session('error') }}
+ @endif + +
+
+
+ + + + + + Reset + Batch Online +
+
+
+ +
+
+
Permohonan Had / Tambah Modal Online
+ {{ count($requests) }} rekod +
+
+ + + + + + + + + + + + + + + @forelse($requests as $req) + @php + $st = $req['status'] ?? ''; + $badge = 'badge-secondary'; + if ($st === 'PENDING') $badge = 'badge-warning'; + elseif ($st === 'APPROVED') $badge = 'badge-success'; + elseif ($st === 'REJECTED') $badge = 'badge-danger'; + @endphp + + + + + + + + + + + @empty + + + + @endforelse + +
IDCawanganTarikhAmaun (RM)Dimohon OlehStatusNotaTindakan
{{ $req['id'] ?? '-' }} +
{{ $req['cawangan_nama'] ?? '-' }}
+ {{ $req['kodcaw'] ?? '' }} +
{{ $req['tarikh'] ?? '-' }}{{ number_format((float)($req['amaun'] ?? 0), 2) }}{{ $req['dimohon_oleh'] ?? '-' }}{{ $st ?: '-' }}{{ $req['nota'] ?? '-' }} + @if($st === 'PENDING') + + + @else + {{ $req['diluluskan_oleh'] ?? '-' }} + @endif +
Tiada permohonan untuk tapisan ini.
+
+
+
+
+
+ + + + + + +@endsection diff --git a/resources/views/pembiayaan_online/pc/batch.blade.php b/resources/views/pembiayaan_online/pc/batch.blade.php new file mode 100644 index 00000000..ac2db5af --- /dev/null +++ b/resources/views/pembiayaan_online/pc/batch.blade.php @@ -0,0 +1,65 @@ +@extends('layouts.app') +@section('content') +
+
+
+ + +
+
+
+
Batch No
{{ $batch['batch_no'] ?? '-' }}
+
Tarikh
{{ $batch['tarikh'] ?? '-' }}
+
Slot
{{ $batch['slot'] ?? '-' }}
+
Status
{{ $batch['status'] ?? '-' }}
+
Jumlah
RM {{ number_format((float)($batch['jumlah_keseluruhan'] ?? 0), 2) }}
+
+
+
+ +
+
+
Senarai Dalam Batch
+ Kembali +
+
+ + + + + + + + + + + + + + + @foreach($lines as $line) + + + + + + + + + + + @endforeach + +
StatusSAGPelangganNo KPBankNo AkaunPinjaman (RM)Rujukan Bayaran
{{ $line['status'] ?? '-' }}{{ $line['norujukan'] ?? '-' }}{{ $line['nama_pelanggan'] ?? '-' }}{{ $line['nokp'] ?? '-' }}{{ $line['nama_bank'] ?? $line['kodbank'] ?? '-' }}{{ $line['noakaun'] ?? '-' }}{{ number_format((float)($line['pinjaman'] ?? 0), 2) }}{{ $line['no_rujukan_bayaran'] ?? '-' }}
+
+
+
+
+
+@endsection diff --git a/resources/views/pembiayaan_online/pc/paid.blade.php b/resources/views/pembiayaan_online/pc/paid.blade.php new file mode 100644 index 00000000..138ba469 --- /dev/null +++ b/resources/views/pembiayaan_online/pc/paid.blade.php @@ -0,0 +1,187 @@ +@extends('layouts.app') +@section('content') +
+
+
+ + + @if(session()->has('message')) +
{{ session('message') }}
+ @endif + @if(session()->has('error')) +
{{ session('error') }}
+ @endif + +
+
+
+
+
Bilangan PAID
+

{{ $bilangan }} rekod

+
+
+
+
+
+
+
Jumlah Pinjaman
+

RM {{ number_format((float) $jumlah, 2) }}

+
+
+
+
+
+
+
Tapisan
+

+ @if(($blastFilter ?? '0') === '0') Belum Blast + @elseif(($blastFilter ?? '') === '1') Sudah Blast + @else Semua + @endif +

+
+
+
+
+ +
+
+
+ + + + Kembali Queue +
+
+
+ +
+
+
Senarai Pembiayaan Online — PAID
+ +
+
+

+ Semak jumlah & bukti bayaran sepadan dengan pelanggan. Setelah semak, tanda selesai. + (WhatsApp/SMS blast boleh disambung kemudian — butang ini menanda rekod sebagai selesai semak.) +

+
+ @csrf +
+ + + + + + + + + + + + + + + + + + + @forelse($lines as $line) + @php $blasted = (int)($line['blast_sent'] ?? 0) === 1; @endphp + + + + + + + + + + + + + + + @empty + + + + @endforelse + + @if(count($lines) > 0) + + + + + + + + @endif +
+ @if(($blastFilter ?? '0') !== '1') + + @endif + BlastSAGPelangganNo KPBankNo AkaunPinjaman (RM)Rujukan BayaranTarikh BayaranPaid AtBukti
+ @if(!$blasted) + + @else + — + @endif + + @if($blasted) + SELESAI + @else + BELUM + @endif + {{ $line['norujukan'] ?? '-' }}{{ $line['nama_pelanggan'] ?? '-' }}{{ $line['nokp'] ?? '-' }}{{ $line['nama_bank'] ?? $line['kodbank'] ?? '-' }}{{ $line['noakaun'] ?? '-' }}{{ number_format((float)($line['pinjaman'] ?? 0), 2) }}{{ $line['no_rujukan_bayaran'] ?? '-' }}{{ $line['tarikh_bayaran'] ?? '-' }}{{ $line['paid_at'] ?? '-' }} + @if(!empty($line['bukti_file_id'])) + + Lihat + + @else + Tiada + @endif +
Tiada rekod PAID untuk tapisan ini.
Jumlah dipaparkan{{ number_format((float) $jumlah, 2) }}
+
+
+
+
+
+
+
+ + +@endsection diff --git a/resources/views/pembiayaan_online/pc/senarai.blade.php b/resources/views/pembiayaan_online/pc/senarai.blade.php new file mode 100644 index 00000000..a26b4819 --- /dev/null +++ b/resources/views/pembiayaan_online/pc/senarai.blade.php @@ -0,0 +1,304 @@ +@extends('layouts.app') +@section('content') +
+
+
+ + + + + @if(session()->has('message')) +
{{ session('message') }}
+ @endif + @if(session()->has('error')) +
{{ session('error') }}
+ @endif + + @php + $isMissing = !empty($modal['missing']); + $isClosed = (int)($modal['ditutup'] ?? 0) === 1; + $pendingReq = $modal['pending_request'] ?? null; + if (is_object($pendingReq)) { + $pendingReq = json_decode(json_encode($pendingReq), true); + } + @endphp + + @if($isClosed) +
Modal online hari ini sudah ditutup (EOD).
+ @elseif($isMissing) +
+ Belum ada had modal online hari ini. + @if($pendingReq) + Permohonan RM {{ number_format((float)($pendingReq['amaun'] ?? 0), 2) }} + daripada {{ $pendingReq['dimohon_oleh'] ?? '-' }} masih PENDING. + @else + Mohon had di + Had Modal Online. + @endif +
+ @elseif($pendingReq) +
+ Permohonan tambah RM {{ number_format((float)($pendingReq['amaun'] ?? 0), 2) }} + daripada {{ $pendingReq['dimohon_oleh'] ?? '-' }} menunggu kelulusan Operasi. + Semak +
+ @endif + +
+
+
+
+
Modal Online Hari Ini
+

+ @if(!empty($modal['missing'])) + Belum ada had + @else + Baki RM {{ number_format((float)($modal['baki'] ?? 0), 2) }} + @endif +

+ + @if(!empty($modal['missing'])) + Tunggu kelulusan Operasi + @else + Digunakan RM {{ number_format((float)($modal['digunakan'] ?? 0), 2) }} + / Had RM {{ number_format((float)($modal['had'] ?? 0) + (float)($modal['tambah'] ?? 0), 2) }} + @endif + +
+
+
+
+
+
+
Queue PC
+

{{ count($lines) }} rekod

+ Jumlah RM {{ number_format((float)($queue['jumlah'] ?? 0), 2) }} +
+
+
+
+
+
+
Slot Cadangan
+

{{ $slot['slot'] ?? '-' }}

+ {{ $slot['nota'] ?? '' }} +
+
+
+
+ +
+
+
Senarai Menunggu (PENDING / REJECTED)
+ +
+
+
+ @csrf + +
+ + + + + + + + + + + + + + + + + @forelse($lines as $line) + + + + + + + + + + + + + @empty + + + + @endforelse + +
StatusSAGPelangganNo KPBankNo AkaunPinjaman (RM)Sebab TolakTindakan
+ + + @if(($line['status'] ?? '') === 'REJECTED_PC') + REJECTED + @else + PENDING + @endif + {{ $line['norujukan'] ?? '-' }}{{ $line['nama_pelanggan'] ?? '-' }}{{ $line['nokp'] ?? '-' }}{{ $line['nama_bank'] ?? $line['kodbank'] ?? '-' }}{{ $line['noakaun'] ?? '-' }}{{ number_format((float)($line['pinjaman'] ?? 0), 2) }}{{ $line['reject_reason'] ?? '-' }} + +
Tiada rekod dalam queue.
+
+
+
+
+ +
+
+
Sejarah Batch
+
+
+
+ + + + + + + + + + + + + + + @forelse($batches as $batch) + + + + + + + + + + + @empty + + + + @endforelse + +
Batch NoTarikhSlotBilJumlah (RM)StatusDihantar Oleh
{{ $batch['batch_no'] ?? '-' }}{{ $batch['tarikh'] ?? '-' }}{{ $batch['slot'] ?? '-' }}{{ $batch['bilangan'] ?? 0 }}{{ number_format((float)($batch['jumlah_keseluruhan'] ?? 0), 2) }}{{ $batch['status'] ?? '-' }}{{ $batch['pc_submitted_by'] ?? '-' }} + + Lihat + +
Belum ada batch.
+
+
+
+
+
+
+ +{{-- Edit modal --}} + + + +@endsection diff --git a/resources/views/pembiayaan_online/pc/topup.blade.php b/resources/views/pembiayaan_online/pc/topup.blade.php new file mode 100644 index 00000000..18a5fec9 --- /dev/null +++ b/resources/views/pembiayaan_online/pc/topup.blade.php @@ -0,0 +1,215 @@ +@extends('layouts.app') +@section('content') +@php + $isClosed = (int)($modal['ditutup'] ?? 0) === 1; + $isMissing = !empty($isMissing) || !empty($modal['missing']); + $pendingRequest = $pendingRequest ?? ($modal['pending_request'] ?? null); +@endphp +
+
+
+ + + @if(session()->has('message')) +
{{ session('message') }}
+ @endif + @if(session()->has('error')) +
{{ session('error') }}
+ @endif + + @if($isClosed) +
+ Modal online hari ini sudah ditutup (EOD) + oleh {{ $modal['ditutup_oleh'] ?? '-' }} + pada {{ $modal['ditutup_at'] ?? '-' }}. + Esok PC perlu mohon had baru daripada Operasi. +
+ @elseif($isMissing) +
+ Belum ada had modal online hari ini. + Mohon amaun di bawah. Operasi akan luluskan permohonan. +
+ @endif + + @if($hasPending && $pendingRequest) +
+ Permohonan PENDING RM {{ number_format((float)($pendingRequest['amaun'] ?? 0), 2) }} + daripada {{ $pendingRequest['dimohon_oleh'] ?? '-' }}. + Menunggu kelulusan Operasi. +
+ @endif + +
+
+
+
+
Baki Hari Ini
+

+ @if($isMissing) + — + @else + RM {{ number_format((float)($modal['baki'] ?? 0), 2) }} + @endif +

+
+
+
+
+
+
+
Had Asas
+

+ @if($isMissing) + — + @else + RM {{ number_format((float)($modal['had'] ?? 0), 2) }} + @endif +

+
+
+
+
+
+
+
Tambah Diluluskan
+

RM {{ number_format((float)($modal['tambah'] ?? 0), 2) }}

+
+
+
+
+
+
+
Digunakan
+

RM {{ number_format((float)($modal['digunakan'] ?? 0), 2) }}

+
+
+
+
+ +
+
+
+
+
{{ $isMissing ? 'Mohon Had Modal Online' : 'Mohon Tambah Modal Online' }}
+
+
+ @if($isClosed) +
+ Tidak boleh mohon selepas EOD. +
+ @else + @if($hasPending) +
+ Masih ada permohonan PENDING. Tunggu kelulusan Operasi sebelum mohon lagi. +
+ @endif +
+ @csrf +
+ + +
+
+ + +
+ + Kembali +
+ @endif +
+
+ +
+
+
Tutup Modal Online (EOD)
+
+
+

+ Tutup hari ini: baki yang tidak digunakan akan dikembalikan, + dan tiada lagi gadai online / permohonan untuk hari ini. + Esok mohon had baru daripada Operasi. +

+ @if($isClosed) + + @elseif($isMissing) + + @else +
+ @csrf + +
+ @endif +
+
+
+ +
+
+
+
Permohonan PC
+
+ +
+
+
+ + + + + + + + + + + + + @forelse($requests as $req) + @php + $st = $req['status'] ?? ''; + $badge = 'badge-secondary'; + if ($st === 'PENDING') $badge = 'badge-warning'; + elseif ($st === 'APPROVED') $badge = 'badge-success'; + elseif ($st === 'REJECTED') $badge = 'badge-danger'; + @endphp + + + + + + + + + @empty + + + + @endforelse + +
TarikhAmaun (RM)StatusDimohon OlehDiluluskan OlehNota
{{ $req['tarikh'] ?? '-' }}{{ number_format((float)($req['amaun'] ?? 0), 2) }}{{ $st ?: '-' }}{{ $req['dimohon_oleh'] ?? '-' }}{{ $req['diluluskan_oleh'] ?? '-' }}{{ $req['nota'] ?? '-' }}
Belum ada permohonan.
+
+
+
+
+
+
+
+@endsection diff --git a/resources/views/print/resittebus_ujrah.blade.php b/resources/views/print/resittebus_ujrah.blade.php index fb8da19e..309fa63c 100644 --- a/resources/views/print/resittebus_ujrah.blade.php +++ b/resources/views/print/resittebus_ujrah.blade.php @@ -634,7 +634,7 @@ (-) Rebat Untung : RM - {{ number_format($keuntungan_rebate,2) }} + {{ number_format($totalrebate['onepercent'], 2) }} @@ -644,7 +644,7 @@ (-) Rebat Lain-Lain Caj : RM - {{ number_format($ujrah_rebate, 2) }} + {{ number_format($totalrebate['ujrah'], 2) }} Jumlah Keuntungan + Lain-Lain Caj @@ -867,7 +867,7 @@ (-) Rebat Untung : RM - {{ number_format($keuntungan_rebate, 2) }} + {{ number_format($totalrebate['onepercent'], 2) }} @@ -877,7 +877,7 @@ (-) Rebat Lain-Lain Caj : RM - {{ number_format($ujrah_rebate, 2) }} + {{ number_format($totalrebate['ujrah'], 2) }} Jumlah Keuntungan + Lain-Lain Caj diff --git a/routes/web.php b/routes/web.php index a570aeec..e16df247 100644 --- a/routes/web.php +++ b/routes/web.php @@ -172,6 +172,33 @@ Route::post('/khazanah/pendahuluanserahanHQ',['as'=>'khazanah.pendahuluanserahan Route::get('/penebusankhazanah/{norujukan}',['as'=>'penebusan.khazanah','uses' => 'PenebusanController@PenebusanKhazanah'])->middleware('auth','khazanah'); Route::get('/lelongankhazanah/{norujukan}',['as'=>'lelongan.khazanah','uses' => 'KhazanahController@lelongan'])->middleware('auth','khazanah'); Route::get('/permohonan',['as'=>'permohonan.index','uses' => 'KhazanahController@PaparanPermohonan'])->middleware('auth','khazanah'); + +// Pembiayaan Online — PC +Route::get('/pembiayaan-online/pc',['as'=>'pembiayaan.online.pc','uses'=>'PembiayaanOnlineController@index'])->middleware('auth','khazanah'); +Route::put('/pembiayaan-online/pc/lines/{id}',['as'=>'pembiayaan.online.pc.update','uses'=>'PembiayaanOnlineController@updateLine'])->middleware('auth','khazanah'); +Route::post('/pembiayaan-online/pc/batches/submit',['as'=>'pembiayaan.online.pc.submit','uses'=>'PembiayaanOnlineController@submitBatch'])->middleware('auth','khazanah'); +Route::get('/pembiayaan-online/pc/batches/{batchId}',['as'=>'pembiayaan.online.pc.batch','uses'=>'PembiayaanOnlineController@showBatch'])->middleware('auth','khazanah'); +Route::get('/pembiayaan-online/pc/paid',['as'=>'pembiayaan.online.pc.paid','uses'=>'PembiayaanOnlineController@paidIndex'])->middleware('auth','khazanah'); +Route::get('/pembiayaan-online/pc/lines/{id}/bukti',['as'=>'pembiayaan.online.pc.bukti','uses'=>'PembiayaanOnlineController@viewBukti'])->middleware('auth','khazanah'); +Route::post('/pembiayaan-online/pc/paid/blast',['as'=>'pembiayaan.online.pc.blast','uses'=>'PembiayaanOnlineController@markBlast'])->middleware('auth','khazanah'); +Route::get('/pembiayaan-online/pc/topup',['as'=>'pembiayaan.online.pc.topup','uses'=>'PembiayaanOnlineController@topupIndex'])->middleware('auth','khazanah'); +Route::post('/pembiayaan-online/pc/topup',['as'=>'pembiayaan.online.pc.topup.request','uses'=>'PembiayaanOnlineController@topupRequest'])->middleware('auth','khazanah'); +Route::post('/pembiayaan-online/pc/topup/close',['as'=>'pembiayaan.online.pc.topup.close','uses'=>'PembiayaanOnlineController@closeModal'])->middleware('auth','khazanah'); + +// Pembiayaan Online — Operasi +Route::get('/pembiayaan-online/operasi',['as'=>'pembiayaan.online.operasi','uses'=>'PembiayaanOnlineController@operasiIndex'])->middleware('auth','operasi'); +Route::get('/pembiayaan-online/operasi/topup',['as'=>'pembiayaan.online.operasi.topup','uses'=>'PembiayaanOnlineController@operasiTopupIndex'])->middleware('auth','operasi'); +Route::post('/pembiayaan-online/operasi/topup/{id}/approve',['as'=>'pembiayaan.online.operasi.topup.approve','uses'=>'PembiayaanOnlineController@operasiTopupApprove'])->middleware('auth','operasi'); +Route::post('/pembiayaan-online/operasi/topup/{id}/reject',['as'=>'pembiayaan.online.operasi.topup.reject','uses'=>'PembiayaanOnlineController@operasiTopupReject'])->middleware('auth','operasi'); +Route::get('/pembiayaan-online/operasi/eod',['as'=>'pembiayaan.online.operasi.eod','uses'=>'PembiayaanOnlineController@operasiEodIndex'])->middleware('auth','operasi'); +Route::post('/pembiayaan-online/operasi/eod/close-all',['as'=>'pembiayaan.online.operasi.eod.closeall','uses'=>'PembiayaanOnlineController@operasiCloseAllModal'])->middleware('auth','operasi'); +Route::post('/pembiayaan-online/operasi/eod/{kodcaw}/close',['as'=>'pembiayaan.online.operasi.eod.close','uses'=>'PembiayaanOnlineController@operasiCloseModal'])->middleware('auth','operasi'); +Route::get('/pembiayaan-online/operasi/{kodcaw}/batches/{batchId}',['as'=>'pembiayaan.online.operasi.batch','uses'=>'PembiayaanOnlineController@operasiShowBatch'])->middleware('auth','operasi'); +Route::post('/pembiayaan-online/operasi/{kodcaw}/lines/{id}/approve',['as'=>'pembiayaan.online.operasi.approve','uses'=>'PembiayaanOnlineController@operasiApproveLine'])->middleware('auth','operasi'); +Route::post('/pembiayaan-online/operasi/{kodcaw}/lines/{id}/reject',['as'=>'pembiayaan.online.operasi.reject','uses'=>'PembiayaanOnlineController@operasiRejectLine'])->middleware('auth','operasi'); +Route::post('/pembiayaan-online/operasi/{kodcaw}/batches/{batchId}/approve',['as'=>'pembiayaan.online.operasi.approve.batch','uses'=>'PembiayaanOnlineController@operasiApproveBatch'])->middleware('auth','operasi'); +Route::post('/pembiayaan-online/operasi/{kodcaw}/lines/{id}/paid',['as'=>'pembiayaan.online.operasi.paid','uses'=>'PembiayaanOnlineController@operasiMarkPaid'])->middleware('auth','operasi'); +Route::post('/pembiayaan-online/operasi/{kodcaw}/batches/{batchId}/paid',['as'=>'pembiayaan.online.operasi.paid.batch','uses'=>'PembiayaanOnlineController@operasiMarkPaidBatch'])->middleware('auth','operasi'); Route::get('/permohonan/rekod',['as'=>'permohonan.rekod','uses' => 'KhazanahController@RekodPermohonan'])->middleware('auth','khazanah'); Route::post('/permohonan/simpan',['as'=>'permohonan.simpan','uses' => 'KhazanahController@SimpanPermohonan'])->middleware('auth','khazanah'); Route::get('/permohonan/status/{mohonid}',['as'=>'permohonan.status','uses' => 'KhazanahController@StatusPermohonan'])->middleware('auth','khazanah'); @@ -356,6 +383,8 @@ 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/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'); Route::put('/operasi/updatekelulusan',['as'=>'operasi.updatekelulusan','uses'=>'OperasiController@updatekelulusan'])->middleware('auth','operasi'); Route::put('/operasi/updatekelulusananggota',['as'=>'operasi.updatekelulusananggota','uses'=>'OperasiController@updatekelulusananggota'])->middleware('auth','operasi'); -- 2.52.0 From 541a094ce18e559782c9ab806bab249cf54c5d1d Mon Sep 17 00:00:00 2001 From: ISMAIL MASSERAN Date: Thu, 27 Aug 2026 10:33:09 +0800 Subject: [PATCH 03/11] DONE: fix error on nginx, add version on env, enable impersonate on staging --- .env.staging | 1 + .gitea/workflows/deploy-staging.yml | 8 ++++---- config/app.php | 2 ++ docker-compose.staging.yml | 17 +---------------- docker/nginx/default.conf | 2 +- resources/views/auth/v2/login.blade.php | 4 ++-- .../views/operasi/daftar_kakitangan.blade.php | 4 ++-- 7 files changed, 13 insertions(+), 25 deletions(-) diff --git a/.env.staging b/.env.staging index 27304237..0be6b95c 100644 --- a/.env.staging +++ b/.env.staging @@ -1,5 +1,6 @@ APP_NAME=Laravel APP_ENV=staging +APP_VERSION=v2.2-staging APP_KEY=base64:O1XZDqK4H6+3GdrODgCaLr2l+OoWvgVhYr0GJ1KizW8= APP_DEBUG=true APP_URL=http://172.16.6.200:8091 diff --git a/.gitea/workflows/deploy-staging.yml b/.gitea/workflows/deploy-staging.yml index 30d130cd..ab79a87f 100644 --- a/.gitea/workflows/deploy-staging.yml +++ b/.gitea/workflows/deploy-staging.yml @@ -56,11 +56,11 @@ jobs: set -e IMAGE_TAG="${{ inputs.image_tag }}" - mkdir -p "${DEPLOY_DIR}/docker/nginx" + mkdir -p "${DEPLOY_DIR}/docker/nginx" "${DEPLOY_DIR}/public" cp docker-compose.staging.yml "${DEPLOY_DIR}/docker-compose.yml" cp docker/nginx/default.conf "${DEPLOY_DIR}/docker/nginx/default.conf" - rm -rf "${DEPLOY_DIR}/public" - cp -R public "${DEPLOY_DIR}/public" + find "${DEPLOY_DIR}/public" -mindepth 1 -delete + cp -R public/. "${DEPLOY_DIR}/public/" if [ ! -f "${DEPLOY_DIR}/.env.staging" ]; then if [ -f .env.staging ]; then @@ -78,7 +78,7 @@ jobs: export IMAGE_TAG docker compose --env-file .env.staging -f docker-compose.yml pull app - docker compose --env-file .env.staging -f docker-compose.yml up -d --no-build --remove-orphans + docker compose --env-file .env.staging -f docker-compose.yml up -d --no-build --force-recreate --remove-orphans app web echo "✓ Deployed IMAGE_TAG=${IMAGE_TAG}" diff --git a/config/app.php b/config/app.php index 0025b5bc..345406b5 100644 --- a/config/app.php +++ b/config/app.php @@ -15,6 +15,8 @@ return [ 'name' => env('APP_NAME', 'Laravel'), + 'version' => env('APP_VERSION', ''), + /* |-------------------------------------------------------------------------- | Application Environment diff --git a/docker-compose.staging.yml b/docker-compose.staging.yml index 073e756d..92ae34c7 100644 --- a/docker-compose.staging.yml +++ b/docker-compose.staging.yml @@ -1,23 +1,8 @@ -# Staging stack — isolated from local docker-compose.yml (8081 / 3307) -# and from api_arrahn staging (8090 / 3308). -# -# Local: -# docker compose --env-file .env.staging -f docker-compose.staging.yml up -d --build -# -# CI (image already in registry): -# APP_IMAGE=git.koppkb.com/kopkb/kaunter IMAGE_TAG= \ -# docker compose --env-file .env.staging -f docker-compose.staging.yml up -d --no-build -# -# Host nginx reverse-proxies the public domain to 127.0.0.1:${HTTP_PORT}. -# See docker/nginx/host-proxy.example.conf -# -# If 8091 or 3309 is already taken, set HTTP_PORT / MYSQL_PUBLISH_PORT in .env.staging. - name: kaunter_staging services: app: - image: ${APP_IMAGE:-kaunter}:${IMAGE_TAG:-staging} + image: ${APP_IMAGE:-git.koppkb.com/kopkb/kaunter}:${IMAGE_TAG:-staging} build: context: . dockerfile: docker/php/Dockerfile diff --git a/docker/nginx/default.conf b/docker/nginx/default.conf index 223a96c0..47a18309 100644 --- a/docker/nginx/default.conf +++ b/docker/nginx/default.conf @@ -9,7 +9,7 @@ server { client_max_body_size 50M; location / { - try_files $uri $uri/ @php; + try_files $uri @php; } location @php { diff --git a/resources/views/auth/v2/login.blade.php b/resources/views/auth/v2/login.blade.php index 164d9d3a..e17ff087 100644 --- a/resources/views/auth/v2/login.blade.php +++ b/resources/views/auth/v2/login.blade.php @@ -7,7 +7,7 @@ - arOS v2.2 + arOS {{ config('app.version') }} + + + +
+ merge(['class' => 'table table-striped table-hover nowrap']) }} + style="width:100%" + data-exportable="{{ $exportable ? 1 : 0 }}" + data-export-filename="{{ $filename !== '' ? $filename : $id }}" + > + + + @foreach ($columns as $column) + + @endforeach + + + + {{ $slot }} +
{{ $column }}
+
diff --git a/resources/views/components/print/footer.blade.php b/resources/views/components/print/footer.blade.php new file mode 100644 index 00000000..3c21f8bd --- /dev/null +++ b/resources/views/components/print/footer.blade.php @@ -0,0 +1,44 @@ +@props([ + 'showCopies' => true, +]) + + + +
merge(['class' => 'print-footer']) }}> + @if($showCopies) +
+ Salinan: Kad Pengenalan    Akaun Bank/ Slip/ Penyata Bank +
+ @endif + + @if(trim($slot) !== '') +
+ {{ $slot }} +
+ @endif +
diff --git a/resources/views/components/print/header.blade.php b/resources/views/components/print/header.blade.php new file mode 100644 index 00000000..cd65e30a --- /dev/null +++ b/resources/views/components/print/header.blade.php @@ -0,0 +1,101 @@ +@props([ + 'cawangan' => '', + 'kodcaw' => '', + 'alamat1' => '', + 'alamat2' => '', + 'notel' => '', + 'tarikh' => '', + 'norujukan' => '', + 'rujukanLabel' => 'No. Rujukan SAG', + 'showDummyBadge' => false, +]) + + + +
merge(['class' => 'print-header']) }}> +
+

KOPERASI PERMODALAN KELANTAN BERHAD (D-5-0228)

+

Ar-Rahn {{ $cawangan }}

+

{{ $alamat1 }}

+

{{ $alamat2 }}

+

Tel: {{ $notel }}

+
+
+ KPKB + Ar-Rahn +
+
+ @if($kodcaw || $cawangan) +
+ Cawangan
+ {{ trim(implode(' — ', array_filter([$kodcaw, $cawangan]))) }} +
+ @endif + @if($tarikh) +
Tarikh
{{ $tarikh }}
+ @endif + @if($norujukan) +
{{ $rujukanLabel }}
{{ $norujukan }}
+ @endif + {{ $slot }} + @if($showDummyBadge) +
CONTOH SAHAJA
+ @endif +
+
diff --git a/resources/views/components/print/watermark.blade.php b/resources/views/components/print/watermark.blade.php new file mode 100644 index 00000000..38e1b73c --- /dev/null +++ b/resources/views/components/print/watermark.blade.php @@ -0,0 +1,25 @@ + + + diff --git a/resources/views/customers/v1/info.blade.php b/resources/views/customers/v1/info.blade.php index 59cd4265..2dcdd490 100644 --- a/resources/views/customers/v1/info.blade.php +++ b/resources/views/customers/v1/info.blade.php @@ -21,6 +21,10 @@ + @if(session()->has('message')) +
{{ session('message') }}
+ @endif + @if(!empty($customer_info['photo_base64']))
diff --git a/resources/views/customers/v2/info.blade.php b/resources/views/customers/v2/info.blade.php index 8a3dd9b0..729ef101 100644 --- a/resources/views/customers/v2/info.blade.php +++ b/resources/views/customers/v2/info.blade.php @@ -22,6 +22,10 @@ + @if(session()->has('message')) +
{{ session('message') }}
+ @endif + @if(!empty($customer_info['photo_base64']))
@@ -359,7 +363,7 @@
@@ -787,27 +741,32 @@ } }); - $('a[data-toggle="tab"]').on('shown.bs.tab', function(e) { - // here is the new selected tab id - var selectedTabId = e.target.id; - + $('a[data-toggle="tab"]').on('shown.bs.tab', function () { + if (typeof adjustErahnDatatables === 'function') { + adjustErahnDatatables(); + } }); - var tablegadai = $('#myTable').DataTable({ - "scrollX": false, - order: [ - [1, 'desc'] + var tablegadai = initErahnDatatable('#myTable', { + order: [[1, 'desc']], + columnDefs: [ + { targets: 0, orderable: false, width: '40px' }, + { targets: -1, orderable: false, searchable: false, width: '70px' } ] }); - var xtawarruq = $('#xtawarruq').DataTable({ - "scrollX": false + var xtawarruq = initErahnDatatable('#xtawarruq', { + columnDefs: [ + { targets: 0, orderable: false, width: '40px' } + ] }); - var tabledahtebus = $('#dahtebusTable').DataTable({}); + var tabledahtebus = initErahnDatatable('#dahtebusTable'); - var tablelelong = $('#lelongTable').DataTable({ - "scrollX": false + var tablelelong = initErahnDatatable('#lelongTable', { + columnDefs: [ + { targets: -1, orderable: false, searchable: false, width: '80px' } + ] }); var historybayarandatatable = $('#tablehistorybayaran').DataTable({ @@ -822,6 +781,41 @@ minimumFractionDigits: 2 }); + function urlBorangOnline(norujukan) { + return '{{ url("/gadai/borang-pengesahan-online") }}/' + encodeURIComponent(norujukan); + } + + function cetakBorangOnlineCell(gadai_detail) { + var cara = String(gadai_detail['cara_terima'] || '').toUpperCase(); + if (cara !== 'ONLINE') { + return ''; + } + return ''; + } + + function cetakBorangOnlineSelected() { + var selected = $('input[name="belum"]:checked'); + if (!selected.length) { + Swal.fire({ + icon: 'warning', + title: 'Sila pilih SAG', + text: 'Pilih pembiayaan untuk cetak borang pengesahan.' + }); + return; + } + var cara = String(selected.data('cara-terima') || '').toUpperCase(); + if (cara !== 'ONLINE') { + Swal.fire({ + icon: 'info', + title: 'Bukan pembiayaan online', + text: 'Borang ini hanya untuk SAG yang terima pembiayaan secara online.' + }); + return; + } + window.open(urlBorangOnline(selected.val()), '_blank'); + } + function getGadaiByNorujukan(norujukan) { console.log(norujukan); let gadai_tawarruq = fetch(api_url + '/api/gadai/norujukan/' + norujukan); @@ -1223,8 +1217,8 @@ let table_norujukan = gadai_detail["norujukan"]; tablegadai.row.add([ - '', + '', '' + taglel + '
', + cetakBorangOnlineCell(gadai_detail), ]).draw(); } } else if (jenistebus == "sudah_tebus") { @@ -1560,6 +1555,9 @@ success: function(data) { $('#myTable').parents('div.dataTables_wrapper').first().show(); gadaiTable(data, "belum_tebus"); + if (typeof adjustErahnDatatables === 'function') { + adjustErahnDatatables(); + } } }); @@ -2816,6 +2814,9 @@ url: api_url + "/api/customers/" + noic + "/gadai/belum_tebus/" + kodcaw, success: function(data) { gadaiTable(data, "belum_tebus"); + if (typeof adjustErahnDatatables === 'function') { + adjustErahnDatatables(); + } } }); } diff --git a/resources/views/dummy/borang_batch_pembiayaan_online.blade.php b/resources/views/dummy/borang_batch_pembiayaan_online.blade.php new file mode 100644 index 00000000..077471ac --- /dev/null +++ b/resources/views/dummy/borang_batch_pembiayaan_online.blade.php @@ -0,0 +1,354 @@ + + + + + + Dummy — Borang Kelulusan Batch Pembiayaan Online + + + +@php + $cawangan = 'KOTA BHARU 2'; + $kodcaw = 'KB2'; + $alamat1 = 'Lot 123, Jalan Sultan Yahya Petra'; + $alamat2 = '15200 Kota Bharu, Kelantan'; + $notel = '09-123 4567'; + $tarikh = '03/09/2026'; + $batchNo = 'KB2-PO-20260903-B1-001'; + $slot = 'BATCH1'; + $status = 'SUBMITTED'; + $dihantarOleh = 'NUR AINA BINTI HASSAN'; + $dihantarPada = '03/09/2026 10:42'; + $opsBy = 'MOHD FAIZ BIN ISMAIL'; + + $lines = [ + ['norujukan' => 'KB2-260903-0001', 'nama' => 'AHMAD BIN ABDULLAH', 'nokp' => '900101-03-1234', 'bank' => 'MAYBANK', 'noakaun' => '123456789012', 'nama_akaun' => 'AHMAD BIN ABDULLAH', 'pinjaman' => 15000.00], + ['norujukan' => 'KB2-260903-0004', 'nama' => 'SITI MARIAM BINTI YUSOF', 'nokp' => '850215-03-5678', 'bank' => 'CIMB', 'noakaun' => '800123456789', 'nama_akaun' => 'SITI MARIAM BINTI YUSOF', 'pinjaman' => 8200.50], + ['norujukan' => 'KB2-260903-0007', 'nama' => 'MOHD RAZAK BIN ALI', 'nokp' => '780930-03-1122', 'bank' => 'BANK ISLAM', 'noakaun' => '140234567890', 'nama_akaun' => 'MOHD RAZAK BIN ALI', 'pinjaman' => 5000.00], + ['norujukan' => 'KB2-260903-0010', 'nama' => 'FATIMAH BINTI OMAR', 'nokp' => '920408-03-3344', 'bank' => 'RHB', 'noakaun' => '212345678901', 'nama_akaun' => 'FATIMAH BINTI OMAR', 'pinjaman' => 12500.00], + ['norujukan' => 'KB2-260903-0012', 'nama' => 'HASSAN BIN IBRAHIM', 'nokp' => '700112-03-5566', 'bank' => 'MAYBANK', 'noakaun' => '156789012345', 'nama_akaun' => 'HASSAN BIN IBRAHIM', 'pinjaman' => 3400.00], + ]; + $jumlah = array_sum(array_column($lines, 'pinjaman')); +@endphp + +
+
+ DUMMY FORM + — reka bentuk borang kelulusan batch pembiayaan online (Operasi). Data ini contoh sahaja. +
+ +
+ +
+
+ + +
+

Borang Kelulusan Pembiayaan Online
Senarai Batch Pembayaran

+

Untuk semakan Operasi dan kelulusan Pengurus Besar. Bukan untuk tandatangan pelanggan.

+
+ +
+
A. Maklumat Batch
+ + + + + + + + + + + + + + + + + + + + + + + + + +
No. Batch{{ $batchNo }}Cawangan{{ $kodcaw }} — {{ $cawangan }}
Tarikh / Slot{{ $tarikh }}  ·  {{ $slot }}Status Batch{{ $status }}
Dihantar Oleh (PC){{ $dihantarOleh }}Dihantar Pada{{ $dihantarPada }}
Bilangan Rekod{{ count($lines) }}Jumlah KeseluruhanRM {{ number_format($jumlah, 2) }}
+
+ +
+
B. Senarai Penerima Dalam Batch
+ + + + + + + + + + + + + + + @foreach($lines as $i => $line) + + + + + + + + + + + @endforeach + + + + + + + +
BilNo. SAGPelangganNo. KPBankNo. AkaunNama AkaunPinjaman (RM)
{{ $i + 1 }}{{ $line['norujukan'] }}{{ $line['nama'] }}{{ $line['nokp'] }}{{ $line['bank'] }}{{ $line['noakaun'] }}{{ $line['nama_akaun'] }}{{ number_format($line['pinjaman'], 2) }}
JUMLAH{{ number_format($jumlah, 2) }}
+
+ +
+
C. Pengesahan Operasi
+
+ Dengan ini disahkan bahawa senarai di Bahagian B telah disemak dan amaun pembiayaan + sebanyak RM {{ number_format($jumlah, 2) }} ({{ count($lines) }} rekod) + bagi batch {{ $batchNo }} cawangan {{ $cawangan }} adalah lengkap + untuk proses pembayaran ke akaun bank pelanggan. +
    +
  1. Maklumat SAG, nama, no. KP, bank dan no. akaun telah disemak terhadap rekod sistem.
  2. +
  3. Pembayaran akan dikreditkan ke akaun penerima seperti senarai, bukan tunai di kaunter.
  4. +
  5. Sebarang ralat akaun yang dikesan selepas kelulusan hendaklah dilaporkan serta-merta.
  6. +
+
+
+ +
+
+
Tandatangan Operasi
+
+

Nama: {{ $opsBy }}

+

Jawatan: Operasi

+

Tarikh: {{ $tarikh }}

+
+
+
+
Pengurus Besar
+
+

Nama:

+

Cop / Paraf:

+

Tarikh:

+
+
+
+ + + Nota: +

1. Borang ini dicetak dari skrin Operasi — Pembiayaan Online (Batch) untuk kelulusan pembayaran.

+

2. Hanya dua tandatangan diperlukan: Operasi dan Pengurus Besar.

+

3. Simpan salinan bersama bukti pindahan bank selepas status PAID.

+
+
+
+ + diff --git a/resources/views/dummy/borang_pengesahan_online.blade.php b/resources/views/dummy/borang_pengesahan_online.blade.php new file mode 100644 index 00000000..acdc772f --- /dev/null +++ b/resources/views/dummy/borang_pengesahan_online.blade.php @@ -0,0 +1,322 @@ + + + + + + Dummy — Borang Pengesahan Pembiayaan Online + + + +@php + // Dummy data — replace later with real gadai / customer / bank values + $cawangan = 'KOTA BHARU 2'; + $kodcaw = 'KB2'; + $alamat1 = 'Lot 123, Jalan Sultan Yahya Petra'; + $alamat2 = '15200 Kota Bharu, Kelantan'; + $notel = '09-123 4567'; + $norujukan = 'KB2-260903-0001'; + $tarikh = '03/09/2026'; + $teller = 'SITI AMINAH BINTI ALI'; + $nama = 'AHMAD BIN ABDULLAH'; + $nokp = '900101-03-1234'; + $nopelanggan = 'KB2001234'; + $telefon = '012-3456789'; + $pinjaman = '15,000.00'; + $bank = 'Malayan Banking Berhad (MAYBANK)'; + $noakaun = '123456789012'; + $nama_akaun = 'AHMAD BIN ABDULLAH'; +@endphp + +
+
+ DUMMY FORM + — reka bentuk borang pengesahan pembiayaan online. Data ini contoh sahaja. +
+ +
+ +
+
+ + +
+

Borang Pengesahan Penerimaan Pembiayaan
Secara Online (Akaun Bank)

+

Untuk diisi dan ditandatangani oleh pelanggan semasa transaksi gadai.

+
+ +
+
A. Maklumat Pelanggan
+ + + + + + + + + + + + + + + + + +
Nama Pelanggan{{ $nama }}
No. MyKad / Passport{{ $nokp }}No. Pelanggan{{ $nopelanggan }}
No. Telefon{{ $telefon }}Cawangan{{ $cawangan }}
+
+ +
+
B. Maklumat Pembiayaan
+ + + + + + + + + + + + + + + + + +
No. Surat Akuan Gadai{{ $norujukan }}
Amaun PembiayaanRM {{ $pinjaman }}
Cara Terima PembiayaanOnline (kredit ke akaun bank) — bukan tunai
Teller{{ $teller }}
+
+ +
+
C. Maklumat Akaun Bank Penerima
+ + + + + + + + + + + + + +
Nama Bank{{ $bank }}
No. Akaun{{ $noakaun }}
Nama Pemegang Akaun{{ $nama_akaun }}
+
+ +
+
D. Akuan Pelanggan
+
+ Saya, {{ $nama }} (No. KP: {{ $nokp }}), dengan ini mengesahkan bahawa: +
    +
  1. Maklumat akaun bank di Bahagian C adalah benar, tepat, dan milik saya sendiri.
  2. +
  3. Saya memohon supaya amaun pembiayaan gadai sebanyak RM {{ $pinjaman }} dikreditkan ke akaun tersebut dan bukan diterima secara tunai.
  4. +
  5. Saya faham kredit ke akaun tertakluk kepada semakan Pengurus Cawangan dan proses pembayaran pihak Koperasi.
  6. +
  7. Saya bertanggungjawab sepenuhnya jika maklumat akaun tidak tepat, dan tidak akan menuntut ganti rugi atas kelewatan atau ralat yang berpunca daripadanya.
  8. +
+
+
+ +
+
+
Tandatangan Pelanggan
+
+

Nama: {{ $nama }}

+

No. KP: {{ $nokp }}

+

Tarikh: {{ $tarikh }}

+
+
+
+
Tandatangan Teller
+
+

Nama: {{ $teller }}

+

Cop / Paraf:

+

Tarikh: {{ $tarikh }}

+
+
+
+
Pengurus Cawangan
+
+

Nama:

+

Cop cawangan:

+

Tarikh:

+
+
+
+ + + Nota: +

1. Borang ini dicetak semasa pelanggan memilih cara terima pembiayaan secara Online.

+

2. Pembiayaan akan dikreditkan ke akaun selepas semakan PC. Pelanggan tidak menerima wang tunai di kaunter.

+

3. Sila pastikan nama pemegang akaun sepadan dengan nama pelanggan pada MyKad.

+
+
+
+ + diff --git a/resources/views/gadaian/v2/index.blade.php b/resources/views/gadaian/v2/index.blade.php index 9238a6e2..455b8ac0 100644 --- a/resources/views/gadaian/v2/index.blade.php +++ b/resources/views/gadaian/v2/index.blade.php @@ -290,6 +290,7 @@
Batal +
@@ -1271,6 +1272,7 @@ } else { $('#cara_terima_section').hide(); $('#bank_online_section').hide(); + $('#cetak_borang_online').hide(); $('#cara_terima_tunai').prop('checked', true); } } @@ -1278,11 +1280,13 @@ function toggleBankOnlineSection() { if ($('input[name="cara_terima"]:checked').val() === 'ONLINE') { $('#bank_online_section').show(); + $('#cetak_borang_online').show(); var nama = $('#gadai_kodbank option:selected').data('nama') || ''; $('#gadai_nama_bank').val(nama); refreshModalOnlineStatus(); } else { $('#bank_online_section').hide(); + $('#cetak_borang_online').hide(); } } @@ -1294,6 +1298,40 @@ $('#gadai_nama_bank').val($('#gadai_kodbank option:selected').data('nama') || ''); }); + $(document).on('click', '#cetak_borang_online', function () { + var kodbank = $('#gadai_kodbank').val(); + var noakaun = ($('#gadai_noakaun').val() || '').trim(); + var namaAkaun = ($('#gadai_nama_akaun').val() || '').trim(); + var namaBank = $('#gadai_kodbank option:selected').data('nama') || $('#gadai_nama_bank').val() || ''; + var pinjaman = String($('#pinjaman').val() || '').replace(/,/g, ''); + + if (!kodbank || !noakaun) { + Swal.fire({ + icon: 'warning', + title: 'Maklumat bank tidak lengkap', + text: 'Sila lengkapkan bank dan no. akaun sebelum cetak borang. Anda boleh betulkan dan cetak semula tanpa tekan Terima.' + }); + return; + } + + var form = $('
', { + method: 'POST', + action: '{{ route("gadai.print.borang.online.preview") }}', + target: '_blank' + }); + form.append($('', { type: 'hidden', name: '_token', value: '{{ csrf_token() }}' })); + form.append($('', { type: 'hidden', name: 'norujukan', value: $('#norujukan_gadai').val() || $('#norujukan').val() || '' })); + form.append($('', { type: 'hidden', name: 'nokp', value: $('#nokp').val() || '' })); + form.append($('', { type: 'hidden', name: 'nopelanggan', value: $('#nopelanggan').val() || '' })); + form.append($('', { type: 'hidden', name: 'nama_pelanggan', value: $('input[name="nama_pelanggan"]').val() || '' })); + form.append($('', { type: 'hidden', name: 'pinjaman', value: pinjaman })); + form.append($('', { type: 'hidden', name: 'kodbank', value: kodbank })); + form.append($('', { type: 'hidden', name: 'nama_bank', value: namaBank })); + form.append($('', { type: 'hidden', name: 'noakaun', value: noakaun })); + form.append($('', { type: 'hidden', name: 'nama_akaun', value: namaAkaun })); + form.appendTo('body').trigger('submit').remove(); + }); + async function getModalOnline() { let kodcaw = $('#kodcaw').val(); let apiUrl = api_url + '/api/modal-online/' + kodcaw; diff --git a/resources/views/pembiayaan_online/operasi/batch.blade.php b/resources/views/pembiayaan_online/operasi/batch.blade.php index fd0e14d6..bff70354 100644 --- a/resources/views/pembiayaan_online/operasi/batch.blade.php +++ b/resources/views/pembiayaan_online/operasi/batch.blade.php @@ -45,6 +45,11 @@
Senarai Dalam Batch
+ + Cetak Borang + Kembali @if($pendingCount > 0) + + + + + Borang Kelulusan Batch — {{ $batchNo }} + + + + + +
+
Borang Kelulusan Batch Pembiayaan Online
+ +
+ +
+
+ + +
+

Borang Kelulusan Pembiayaan Online
Senarai Batch Pembayaran

+

Untuk semakan Operasi dan kelulusan Pengurus Besar. Bukan untuk tandatangan pelanggan.

+
+ +
+
A. Maklumat Batch
+ + + + + + + + + + + + + + + + + + + + + + + + + +
No. Batch{{ $batchNo }}Cawangan{{ $kodcaw }} — {{ $cawangan }}
Tarikh / Slot{{ $tarikh }}  ·  {{ $slot }}Status Batch{{ $status }}
Dihantar Oleh (PC){{ $dihantarOleh }}Dihantar Pada{{ $dihantarPada }}
Bilangan Rekod{{ count($lines) }}Jumlah KeseluruhanRM {{ number_format((float) $jumlah, 2) }}
+
+ +
+
B. Senarai Penerima Dalam Batch
+ + + + + + + + + + + + + + + @forelse($lines as $i => $line) + + + + + + + + + + + @empty + + + + @endforelse + + + + + + + +
BilNo. SAGPelangganNo. KPBankNo. AkaunNama AkaunPinjaman (RM)
{{ $i + 1 }}{{ $line['norujukan'] ?? '-' }}{{ $line['nama_pelanggan'] ?? '-' }}{{ $line['nokp'] ?? '-' }}{{ $line['nama_bank'] ?? ($line['kodbank'] ?? '-') }}{{ $line['noakaun'] ?? '-' }}{{ $line['nama_akaun'] ?? '-' }}{{ number_format((float) ($line['pinjaman'] ?? 0), 2) }}
Tiada rekod dalam batch.
JUMLAH{{ number_format((float) $jumlah, 2) }}
+
+ +
+
C. Pengesahan Operasi
+
+ Dengan ini disahkan bahawa senarai di Bahagian B telah disemak dan amaun pembiayaan + sebanyak RM {{ number_format((float) $jumlah, 2) }} ({{ count($lines) }} rekod) + bagi batch {{ $batchNo }} cawangan {{ $cawangan }} adalah lengkap + untuk proses pembayaran ke akaun bank pelanggan. +
    +
  1. Maklumat SAG, nama, no. KP, bank dan no. akaun telah disemak terhadap rekod sistem.
  2. +
  3. Pembayaran akan dikreditkan ke akaun penerima seperti senarai, bukan tunai di kaunter.
  4. +
  5. Sebarang ralat akaun yang dikesan selepas kelulusan hendaklah dilaporkan serta-merta.
  6. +
+
+
+ +
+
+
Tandatangan Operasi
+
+

Nama: {{ $opsBy }}

+

Jawatan: Operasi

+

Tarikh: {{ $tarikh }}

+
+
+
+
Pengurus Besar
+
+

Nama:

+

Cop / Paraf:

+

Tarikh:

+
+
+
+ + + Nota: +

1. Borang ini dicetak dari skrin Operasi — Pembiayaan Online (Batch) untuk kelulusan pembayaran.

+

2. Hanya dua tandatangan diperlukan: Operasi dan Pengurus Besar.

+

3. Simpan salinan bersama bukti pindahan bank selepas status PAID.

+
+
+
+ + diff --git a/resources/views/print/borang_pengesahan_online.blade.php b/resources/views/print/borang_pengesahan_online.blade.php new file mode 100644 index 00000000..b6c98b97 --- /dev/null +++ b/resources/views/print/borang_pengesahan_online.blade.php @@ -0,0 +1,302 @@ + + + + + + Borang Pengesahan Online — {{ $norujukan }} + + + + + +
+
Borang Pengesahan Pembiayaan Online
+ +
+ +
+
+ + +
+

Borang Pengesahan Penerimaan Pembiayaan
Secara Online (Akaun Bank)

+

Untuk diisi dan ditandatangani oleh pelanggan semasa transaksi gadai.

+
+ +
+
A. Maklumat Pelanggan
+ + + + + + + + + + + + + + + + + +
Nama Pelanggan{{ $nama }}
No. MyKad / Passport{{ $nokp }}No. Pelanggan{{ $nopelanggan }}
No. Telefon{{ $telefon }}Cawangan{{ $cawangan }}
+
+ +
+
B. Maklumat Pembiayaan
+ + + + + + + + + + + + + + + + + +
No. Surat Akuan Gadai{{ $norujukan }}
Amaun PembiayaanRM {{ $pinjaman }}
Cara Terima PembiayaanOnline (kredit ke akaun bank) — bukan tunai
Teller{{ $teller }}
+
+ +
+
C. Maklumat Akaun Bank Penerima
+ + + + + + + + + + + + + +
Nama Bank{{ $bank }}
No. Akaun{{ $noakaun }}
Nama Pemegang Akaun{{ $nama_akaun }}
+
+ +
+
D. Akuan Pelanggan
+
+ Saya, {{ $nama }} (No. KP: {{ $nokp }}), dengan ini mengesahkan bahawa: +
    +
  1. Maklumat akaun bank di Bahagian C adalah benar, tepat, dan milik saya sendiri.
  2. +
  3. Saya memohon supaya amaun pembiayaan gadai sebanyak RM {{ $pinjaman }} dikreditkan ke akaun tersebut dan bukan diterima secara tunai.
  4. +
  5. Saya faham kredit ke akaun tertakluk kepada semakan Pengurus Cawangan dan proses pembayaran pihak Koperasi.
  6. +
  7. Saya bertanggungjawab sepenuhnya jika maklumat akaun tidak tepat, dan tidak akan menuntut ganti rugi atas kelewatan atau ralat yang berpunca daripadanya.
  8. +
+
+
+ +
+
+
Tandatangan Pelanggan
+
+

Nama: {{ $nama }}

+

No. KP: {{ $nokp }}

+

Tarikh: {{ $tarikh }}

+
+
+
+
Tandatangan Teller
+
+

Nama: {{ $teller }}

+

Cop / Paraf:

+

Tarikh: {{ $tarikh }}

+
+
+
+
Pengurus Cawangan
+
+

Nama:

+

Cop cawangan:

+

Tarikh:

+
+
+
+ + + Nota: +

1. Borang ini dicetak semasa pelanggan memilih cara terima pembiayaan secara Online.

+

2. Pembiayaan akan dikreditkan ke akaun selepas semakan PC. Pelanggan tidak menerima wang tunai di kaunter.

+

3. Sila pastikan nama pemegang akaun sepadan dengan nama pelanggan pada MyKad.

+
+
+
+ + diff --git a/routes/web.php b/routes/web.php index e16df247..d7254bd1 100644 --- a/routes/web.php +++ b/routes/web.php @@ -19,6 +19,15 @@ Route::get('/health', function () { return response()->json(['status' => 'ok']); }); +// Dummy print form — no auth, for layout design only +Route::get('/dummy/borang-pengesahan-online', function () { + return view('dummy.borang_pengesahan_online'); +}); + +Route::get('/dummy/borang-batch-pembiayaan-online', function () { + return view('dummy.borang_batch_pembiayaan_online'); +}); + Route::get('/',['as'=>'login','uses'=>'HomeController@index']); Route::get('/testtry',function(ImbangdugaServices $imbangduga){ @@ -113,6 +122,8 @@ Route::post('/profile/edit/store',['as'=>'profile.editstore','uses'=>'UserContro Route::get('/customer/search',['as'=>'customer.search','uses'=>'CustomersController@search'])->middleware('auth','teller'); Route::post('/customer/store',['as'=>'customer.store','uses'=>'CustomersController@store'])->middleware('auth','teller'); Route::post('/gadai/store',['as'=>'gadai.store','uses'=>'GadaianController@store'])->middleware('auth','teller'); +Route::get('/gadai/borang-pengesahan-online/{norujukan}',['as'=>'gadai.print.borang.online','uses'=>'GadaianController@printBorangPengesahanOnline'])->middleware('auth','teller'); +Route::post('/gadai/borang-pengesahan-online/preview',['as'=>'gadai.print.borang.online.preview','uses'=>'GadaianController@previewBorangPengesahanOnline'])->middleware('auth','teller'); Route::get('/gadai/batal',['as'=>'gadai.batal','uses'=>'GadaianController@batal'])->middleware('auth','teller'); Route::get('/customer/otp',['as'=>'customer.otp','uses'=>'CustomersController@getOTP'])->middleware('auth','teller'); Route::get('/getwakil',['as'=>'wakil.search','uses'=>'PenebusanController@getWakil'])->middleware('auth','teller'); @@ -194,6 +205,7 @@ Route::get('/pembiayaan-online/operasi/eod',['as'=>'pembiayaan.online.operasi.eo Route::post('/pembiayaan-online/operasi/eod/close-all',['as'=>'pembiayaan.online.operasi.eod.closeall','uses'=>'PembiayaanOnlineController@operasiCloseAllModal'])->middleware('auth','operasi'); Route::post('/pembiayaan-online/operasi/eod/{kodcaw}/close',['as'=>'pembiayaan.online.operasi.eod.close','uses'=>'PembiayaanOnlineController@operasiCloseModal'])->middleware('auth','operasi'); Route::get('/pembiayaan-online/operasi/{kodcaw}/batches/{batchId}',['as'=>'pembiayaan.online.operasi.batch','uses'=>'PembiayaanOnlineController@operasiShowBatch'])->middleware('auth','operasi'); +Route::get('/pembiayaan-online/operasi/{kodcaw}/batches/{batchId}/print',['as'=>'pembiayaan.online.operasi.batch.print','uses'=>'PembiayaanOnlineController@operasiPrintBatch'])->middleware('auth','operasi'); Route::post('/pembiayaan-online/operasi/{kodcaw}/lines/{id}/approve',['as'=>'pembiayaan.online.operasi.approve','uses'=>'PembiayaanOnlineController@operasiApproveLine'])->middleware('auth','operasi'); Route::post('/pembiayaan-online/operasi/{kodcaw}/lines/{id}/reject',['as'=>'pembiayaan.online.operasi.reject','uses'=>'PembiayaanOnlineController@operasiRejectLine'])->middleware('auth','operasi'); Route::post('/pembiayaan-online/operasi/{kodcaw}/batches/{batchId}/approve',['as'=>'pembiayaan.online.operasi.approve.batch','uses'=>'PembiayaanOnlineController@operasiApproveBatch'])->middleware('auth','operasi'); -- 2.52.0 From 9fbcf8632599e2dbc156cedad550a2ff759c9c9e Mon Sep 17 00:00:00 2001 From: ISMAIL MASSERAN Date: Sun, 6 Sep 2026 10:21:04 +0800 Subject: [PATCH 07/11] DONE: optimize loading page on employee, append the online payment under same batch --- app/Http/Controllers/KakitanganController.php | 39 ++++- .../PembiayaanOnlineController.php | 11 +- .../views/operasi/daftar_kakitangan.blade.php | 152 +++++++++--------- .../pembiayaan_online/operasi/batch.blade.php | 2 +- 4 files changed, 117 insertions(+), 87 deletions(-) diff --git a/app/Http/Controllers/KakitanganController.php b/app/Http/Controllers/KakitanganController.php index f8346092..3a519525 100644 --- a/app/Http/Controllers/KakitanganController.php +++ b/app/Http/Controllers/KakitanganController.php @@ -20,10 +20,43 @@ class KakitanganController extends Controller public function daftarKakitangan(){ $api_url = config('api.url'); $auth_user = Auth::user(); - $cawangan_info = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/cawangan/'. $auth_user['cawangan'])->json(); + $http = Http::withOptions(['verify' => config('app.api_verify')]); + + $cawangan_all = $http->get($api_url . '/api/cawangan')->json(); + $cawangan_all = is_array($cawangan_all) ? $cawangan_all : []; + $cawangan_by_kod = collect($cawangan_all)->keyBy('kodcaw'); + $cawangan_info = $cawangan_by_kod->get($auth_user['cawangan'], []); + $role = Role::get(); - $kakitangan = User::all(); - return view('operasi.daftar_kakitangan',compact('cawangan_info','api_url','role','kakitangan','auth_user')); + $kakitangan_rows = User::where('roles', '!=', 'admin') + ->get() + ->values() + ->map(function ($staff) use ($cawangan_by_kod) { + $kod = (string) $staff->cawangan; + if (in_array($kod, ['operasi', 'callcenter', 'admin'], true)) { + $cawangan_nama = ucwords($kod); + } else { + $cawangan_nama = ucwords((string) data_get($cawangan_by_kod, $kod . '.details_caw', $kod)); + } + + return [ + 'id' => $staff->id, + 'name' => $staff->name, + 'roles' => strtoupper((string) $staff->roles), + 'role_harian' => $staff->role_harian ? strtoupper($staff->role_harian) : '-', + 'role_asal' => $staff->role_asal ? strtoupper($staff->role_asal) : '-', + 'cawangan' => $cawangan_nama, + ]; + }); + + return view('operasi.daftar_kakitangan', compact( + 'cawangan_info', + 'api_url', + 'role', + 'kakitangan_rows', + 'auth_user', + 'cawangan_all' + )); } public function registerStaff(Request $request){ diff --git a/app/Http/Controllers/PembiayaanOnlineController.php b/app/Http/Controllers/PembiayaanOnlineController.php index ef11bd52..93b24e24 100644 --- a/app/Http/Controllers/PembiayaanOnlineController.php +++ b/app/Http/Controllers/PembiayaanOnlineController.php @@ -132,9 +132,14 @@ class PembiayaanOnlineController extends Controller return redirect()->back()->with('error', $msg); } - $batchNo = $res->json()['batch']['batch_no'] ?? ''; - return redirect()->route('pembiayaan.online.pc') - ->with('message', 'Batch dihantar ke Operasi' . ($batchNo ? ': ' . $batchNo : '.')); + $payload = $res->json(); + $batchNo = is_array($payload) ? ($payload['batch']['batch_no'] ?? '') : ''; + $appended = is_array($payload) && !empty($payload['appended']); + $message = $appended + ? ('Rekod ditambah ke batch' . ($batchNo ? ' ' . $batchNo : '') . '.') + : ('Batch dihantar ke Operasi' . ($batchNo ? ': ' . $batchNo : '.')); + + return redirect()->route('pembiayaan.online.pc')->with('message', $message); } /** diff --git a/resources/views/operasi/daftar_kakitangan.blade.php b/resources/views/operasi/daftar_kakitangan.blade.php index e0ed9ba9..e3b1bb45 100644 --- a/resources/views/operasi/daftar_kakitangan.blade.php +++ b/resources/views/operasi/daftar_kakitangan.blade.php @@ -43,9 +43,6 @@ Cawangan
- @php - $cawangan_all = Http::withOptions(['verify' => config('app.api_verify')])->get($api_url . '/api/cawangan')->json(); - @endphp - edit - work - settings - restore - @if( - app()->environment(['local', 'staging']) - && - $staff->roles != 'admin' - && $staff->id != $auth_user->id - && !(Auth::check() && method_exists(Auth::user(), 'isImpersonated') && Auth::user()->isImpersonated()) - ) - - @csrf - - - @endif - - {{-- --}} - @endif - - - @endif - @endforeach - - +
@@ -189,8 +117,72 @@ +