diff --git a/.env.docker b/.env.docker new file mode 100644 index 0000000..79c1ea3 --- /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/.env.staging b/.env.staging index 2730423..0be6b95 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 30d130c..ab79a87 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/.gitignore b/.gitignore index 1ed293c..80ba177 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 f821d23..ca86015 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 0000000..a80c8c5 --- /dev/null +++ b/REMARK.md @@ -0,0 +1,27 @@ +## 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 + +## Akaun +- admin@test.com +- admin2@test.com + +Module Gadai Online: +- Langkah 1 +- Langkah 2 +[x] PC akan tekan submit, then customer akan masuk ke senarai online mengikut batch +[x] PC boleh semak list customer yang pilih gadai online +- Langkah 3 (Operasi) +[x] dapat dalam bentuk list +[x] Apa jadi kalau operasi reject? - patah balik ke pc, untuk pc buat semakan balik +- Langkah 4 +- Langkah 5 +- Langkah 6 +- Langkah 7 +[x] Macam mana PC nak tahu pembayaran berjaya (Tally PAID page) +[x] Kalau online, dia kena upload kat mana (Operasi: PAID + bukti) +- Langkah 8 +[x] PC semak senarai pelanggan gadai tu tally atau tak +[ ] PC tekan butang blast ke (tanda selesai ada; WhatsApp/SMS belum wire) \ No newline at end of file diff --git a/app/Http/Controllers/AliranTunaiController.php b/app/Http/Controllers/AliranTunaiController.php index 06b0820..386007c 100644 --- a/app/Http/Controllers/AliranTunaiController.php +++ b/app/Http/Controllers/AliranTunaiController.php @@ -105,7 +105,7 @@ class AliranTunaiController extends Controller $gadai_tebus = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url').'/api/gadaitebus/listharini/'.$auth_user['cawangan'],['tarikh' => $harini->toDateString()])->json(); - $addtunai = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/getAddTunai/' . $auth_user['cawangan'] . '/kodlaluan/',['kodlaluan' => $auth_user['name']])->json(); + $addtunai = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/getAddTunai/' . $auth_user['cawangan'] . '/kodlaluan',['kodlaluan' => $auth_user['name']])->json(); $tuntutbaki = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url').'/api/TuntutBaki/'.$auth_user['cawangan'])->json(); @@ -361,7 +361,8 @@ class AliranTunaiController extends Controller $pendahuluan = $alirantunai['tambah']; $serahan = $alirantunai['kurang']; - $addtunai = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/getAddTunai/' . $auth_user['cawangan'] . '/kodlaluan/',['kodlaluan' => $auth_user['name']])->json(); + $addtunai = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/getAddTunai/' . $auth_user['cawangan'] . '/kodlaluan',['kodlaluan' => $auth_user['name']])->json(); + $addtunai = is_array($addtunai) ? $addtunai : []; $gadai = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url'). '/api/gadai/laporan/'. $auth_user['cawangan'] .'/'. $current->toDateString())->json(); $tebus = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url'). '/api/tebus/laporan/'. $auth_user['cawangan'] .'/'. $current->toDateString())->json(); @@ -617,7 +618,7 @@ class AliranTunaiController extends Controller $alirantunai = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/GetCurrentTunai/' . $auth_user['cawangan'],['kodlaluan' => $auth_user['name']])->json(); - $addtunai = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/getAddTunai/' . $auth_user['cawangan'] . '/kodlaluan/',['kodlaluan' => $auth_user['name']])->json(); + $addtunai = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/getAddTunai/' . $auth_user['cawangan'] . '/kodlaluan',['kodlaluan' => $auth_user['name']])->json(); $teller = $auth_user['name']; @@ -658,7 +659,7 @@ class AliranTunaiController extends Controller $cawangan=Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url').'/api/cawangan/detail/'.$auth_user['cawangan'])->json(); $cawangan_detail=$cawangan[0]; - $addtunai = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/getAddTunai/' . $auth_user['cawangan'] . '/kodlaluan/',['kodlaluan' => $auth_user['name']])->json(); + $addtunai = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/getAddTunai/' . $auth_user['cawangan'] . '/kodlaluan',['kodlaluan' => $auth_user['name']])->json(); $teller = $auth_user['name']; diff --git a/app/Http/Controllers/Auth/ImpersonateController.php b/app/Http/Controllers/Auth/ImpersonateController.php new file mode 100644 index 0000000..dab764a --- /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 f29fcc2..b9abb66 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/GadaianController.php b/app/Http/Controllers/GadaianController.php index a6cbbbe..2dff367 100644 --- a/app/Http/Controllers/GadaianController.php +++ b/app/Http/Controllers/GadaianController.php @@ -211,13 +211,50 @@ class GadaianController extends Controller 'teller' => $auth_user['name'] ]); - $this->AliranTunaiController->alirantunaiGadai($request, $auth_user['name']); + $caraTerima = strtoupper((string) $request->input('cara_terima', 'TUNAI')); + $pinjamanAmt = round((float) $request->pinjaman, 2); + + // Online only for RM5k–50k; otherwise force cash path. + if ($caraTerima === 'ONLINE' && ($pinjamanAmt < 5000 || $pinjamanAmt > 50000)) { + $caraTerima = 'TUNAI'; + } + + if ($caraTerima === 'ONLINE') { + $online = Http::withOptions(['verify' => config('app.api_verify')]) + ->asForm() + ->post(config('api.url') . '/api/pembiayaan-online/' . $auth_user['cawangan'], [ + 'norujukan' => $request->norujukan_gadai, + 'nokp' => $request->nokp, + 'pinjaman' => $pinjamanAmt, + 'kodbank' => $request->kodbank, + 'noakaun' => $request->noakaun, + 'nama_bank' => $request->nama_bank, + 'nama_akaun' => $request->nama_akaun ?: $request->nama_pelanggan, + 'nama_pelanggan' => $request->nama_pelanggan, + 'nopelanggan' => $request->nopelanggan, + 'created_by' => $auth_user['name'], + 'update_customer_bank' => true, + ]); + + if (!$online->successful()) { + $body = $online->json(); + $msg = is_array($body) && isset($body['message']) + ? $body['message'] + : 'Gagal daftar pembiayaan online. Sila cuba lagi.'; + return redirect()->back()->with('error', $msg); + } + } else { + $this->AliranTunaiController->alirantunaiGadai($request, $auth_user['name']); + } event(new GadaiNotify('lulus', $auth_user['cawangan'])); $request->session()->forget('page_reload'); $request->session()->forget('norujukan'); $request->session()->flash('activate_tab', 'SAG_baru'); + if ($caraTerima === 'ONLINE') { + $request->session()->flash('message', 'Gadai berjaya. Pembiayaan online menunggu semakan PC.'); + } return redirect()->route('customer_info'); } diff --git a/app/Http/Controllers/KhazanahController.php b/app/Http/Controllers/KhazanahController.php index 03e7252..3504b36 100644 --- a/app/Http/Controllers/KhazanahController.php +++ b/app/Http/Controllers/KhazanahController.php @@ -349,7 +349,7 @@ class KhazanahController extends Controller $gadai_tebus = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url').'/api/gadaitebus/listharini/'.$auth_user['cawangan'].'/teller/',['tarikh' => $harini->toDateString(),'teller' => $ls['kodlaluan']])->json(); $tuntutbaki = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url').'/api/TuntutBaki/'.$auth_user['cawangan'].'/teller/',['teller' => $ls['kodlaluan']])->json(); - $addtunai = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url').'/api/getAddTunai/'.$auth_user['cawangan'].'/kodlaluan/',['kodlaluan' => $ls['kodlaluan']])->json(); + $addtunai = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url').'/api/getAddTunai/'.$auth_user['cawangan'].'/kodlaluan',['kodlaluan' => $ls['kodlaluan']])->json(); array_push($arraygadaitebus,$gadai_tebus); array_push($arraytuntutbaki,$tuntutbaki); @@ -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 7418912..9c68534 100644 --- a/app/Http/Controllers/OperasiController.php +++ b/app/Http/Controllers/OperasiController.php @@ -321,6 +321,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/Http/Controllers/PembiayaanOnlineController.php b/app/Http/Controllers/PembiayaanOnlineController.php new file mode 100644 index 0000000..f7414a2 --- /dev/null +++ b/app/Http/Controllers/PembiayaanOnlineController.php @@ -0,0 +1,744 @@ +middleware('auth'); + } + + protected function api() + { + return Http::withOptions(['verify' => config('app.api_verify')]); + } + + protected function kodcaw() + { + return Auth::user()->cawangan; + } + + /** + * PC senarai queue + batch history. + */ + public function index(Request $request) + { + $auth_user = Auth::user(); + $kodcaw = $this->kodcaw(); + $api_url = config('api.url'); + + $cawangan_info = $this->api() + ->get($api_url . '/api/cawangan/' . $kodcaw) + ->json(); + + $queue = $this->api() + ->get($api_url . '/api/pembiayaan-online/' . $kodcaw . '/queue') + ->json(); + + $batches = $this->api() + ->get($api_url . '/api/pembiayaan-online/' . $kodcaw . '/batches') + ->json(); + + $banks = $this->api()->get($api_url . '/api/bank')->json(); + if (!is_array($banks)) { + $banks = []; + } + + $modal = $this->api() + ->get($api_url . '/api/modal-online/' . $kodcaw) + ->json(); + + $lines = $queue['data'] ?? []; + $slot = $queue['slot_cadangan'] ?? null; + if (!is_array($batches)) { + $batches = []; + } + + return view('pembiayaan_online.pc.senarai', compact( + 'auth_user', + 'kodcaw', + 'api_url', + 'cawangan_info', + 'lines', + 'batches', + 'banks', + 'modal', + 'slot', + 'queue' + )); + } + + /** + * Update bank/docs for a queue line. + */ + public function updateLine(Request $request, $id) + { + $kodcaw = $this->kodcaw(); + $api_url = config('api.url'); + + $payload = [ + 'kodbank' => $request->input('kodbank'), + 'noakaun' => $request->input('noakaun'), + 'nama_bank' => $request->input('nama_bank'), + 'nama_akaun' => $request->input('nama_akaun'), + 'nota' => $request->input('nota'), + 'update_customer_bank' => true, + ]; + + $res = $this->api() + ->asForm() + ->put($api_url . '/api/pembiayaan-online/' . $kodcaw . '/lines/' . $id, $payload); + + if (!$res->successful()) { + $body = $res->json(); + $msg = is_array($body) && isset($body['message']) ? $body['message'] : 'Gagal kemaskini rekod.'; + return redirect()->back()->with('error', $msg); + } + + return redirect()->route('pembiayaan.online.pc')->with('message', 'Rekod dikemaskini.'); + } + + /** + * Submit selected lines as a batch to Operasi. + */ + public function submitBatch(Request $request) + { + $kodcaw = $this->kodcaw(); + $api_url = config('api.url'); + $auth_user = Auth::user(); + + $ids = $request->input('ids', []); + if (!is_array($ids)) { + $ids = array_filter(explode(',', (string) $ids)); + } + + $res = $this->api() + ->asForm() + ->post($api_url . '/api/pembiayaan-online/' . $kodcaw . '/batches/submit', [ + 'ids' => $ids, + 'pc_submitted_by' => $auth_user['name'], + 'slot' => $request->input('slot'), + ]); + + if (!$res->successful()) { + $body = $res->json(); + $msg = is_array($body) && isset($body['message']) ? $body['message'] : 'Gagal hantar batch.'; + 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 : '.')); + } + + /** + * Batch detail. + */ + public function showBatch($batchId) + { + $kodcaw = $this->kodcaw(); + $api_url = config('api.url'); + + $cawangan_info = $this->api() + ->get($api_url . '/api/cawangan/' . $kodcaw) + ->json(); + + $detail = $this->api() + ->get($api_url . '/api/pembiayaan-online/' . $kodcaw . '/batches/' . $batchId) + ->json(); + + if (!is_array($detail) || empty($detail['batch'])) { + return redirect()->route('pembiayaan.online.pc')->with('error', 'Batch tidak dijumpai.'); + } + + return view('pembiayaan_online.pc.batch', [ + 'batch' => $detail['batch'], + 'lines' => $detail['lines'] ?? [], + 'kodcaw' => $kodcaw, + 'api_url' => $api_url, + 'cawangan_info' => $cawangan_info, + ]); + } + + /** + * PC: senarai PAID untuk tally + blast. + */ + public function paidIndex(Request $request) + { + $auth_user = Auth::user(); + $kodcaw = $this->kodcaw(); + $api_url = config('api.url'); + $blastFilter = $request->input('blast_sent', '0'); + + $cawangan_info = $this->api() + ->get($api_url . '/api/cawangan/' . $kodcaw) + ->json(); + + $query = []; + if ($blastFilter !== 'all' && $blastFilter !== '') { + $query['blast_sent'] = $blastFilter; + } + + $paid = $this->api() + ->get($api_url . '/api/pembiayaan-online/' . $kodcaw . '/paid', $query) + ->json(); + + $lines = $paid['data'] ?? []; + if (!is_array($lines)) { + $lines = []; + } + + $bilangan = $paid['bilangan'] ?? count($lines); + $jumlah = $paid['jumlah'] ?? 0; + + return view('pembiayaan_online.pc.paid', compact( + 'auth_user', + 'kodcaw', + 'api_url', + 'cawangan_info', + 'lines', + 'bilangan', + 'jumlah', + 'blastFilter' + )); + } + + /** + * PC: view/download bukti bayaran inline. + */ + public function viewBukti($id) + { + $kodcaw = $this->kodcaw(); + $res = $this->api() + ->get(config('api.url') . '/api/pembiayaan-online/' . $kodcaw . '/lines/' . $id . '/bukti'); + + if (!$res->successful()) { + $body = $res->json(); + $msg = is_array($body) && isset($body['message']) ? $body['message'] : 'Bukti tidak dijumpai.'; + return redirect()->back()->with('error', $msg); + } + + $payload = $res->json(); + $bukti = $payload['bukti'] ?? null; + if (!$bukti || empty($bukti['data'])) { + return redirect()->back()->with('error', 'Fail bukti kosong.'); + } + + $raw = $bukti['data']; + if (strpos($raw, 'base64,') !== false) { + $raw = substr($raw, strpos($raw, 'base64,') + 7); + } + $binary = base64_decode($raw, true); + if ($binary === false) { + $binary = base64_decode($bukti['data']); + } + + $type = $bukti['type'] ?? 'application/octet-stream'; + $filename = $bukti['filename'] ?? ('bukti-' . $id); + + return response($binary, 200, [ + 'Content-Type' => $type, + 'Content-Disposition' => 'inline; filename="' . $filename . '"', + ]); + } + + /** + * PC: tanda rekod PAID sebagai selesai semak / blast. + */ + public function markBlast(Request $request) + { + $kodcaw = $this->kodcaw(); + $ids = $request->input('ids', []); + if (!is_array($ids)) { + $ids = array_filter(explode(',', (string) $ids)); + } + + if (count($ids) === 0) { + return redirect()->back()->with('error', 'Sila pilih sekurang-kurangnya satu rekod.'); + } + + $res = $this->api() + ->asForm() + ->post(config('api.url') . '/api/pembiayaan-online/' . $kodcaw . '/paid/blast', [ + 'ids' => $ids, + 'blast_by' => Auth::user()['name'], + ]); + + if (!$res->successful()) { + $body = $res->json(); + $msg = is_array($body) && isset($body['message']) ? $body['message'] : 'Gagal tanda selesai.'; + return redirect()->back()->with('error', $msg); + } + + $n = $res->json()['dikemaskini'] ?? count($ids); + return redirect() + ->route('pembiayaan.online.pc.paid') + ->with('message', $n . ' rekod ditanda selesai semak/blast.'); + } + + /** + * Operasi: senarai batch semua cawangan. + */ + public function operasiIndex(Request $request) + { + $auth_user = Auth::user(); + $api_url = config('api.url'); + $status = $request->input('status', 'SUBMITTED'); + $tarikh = $request->input('tarikh'); + + $query = ['status' => $status]; + if ($tarikh) { + $query['tarikh'] = $tarikh; + } + + $res = $this->api() + ->get($api_url . '/api/pembiayaan-online/operasi/batches', $query) + ->json(); + + $batches = $res['data'] ?? []; + if (!is_array($batches)) { + $batches = []; + } + + return view('pembiayaan_online.operasi.senarai', compact( + 'auth_user', + 'api_url', + 'batches', + 'status', + 'tarikh' + )); + } + + /** + * Operasi: detail batch + lines. + */ + public function operasiShowBatch($kodcaw, $batchId) + { + $auth_user = Auth::user(); + $api_url = config('api.url'); + + $cawangan_info = $this->api() + ->get($api_url . '/api/cawangan/' . $kodcaw) + ->json(); + + $detail = $this->api() + ->get($api_url . '/api/pembiayaan-online/operasi/' . $kodcaw . '/batches/' . $batchId) + ->json(); + + if (!is_array($detail) || empty($detail['batch'])) { + return redirect() + ->route('pembiayaan.online.operasi') + ->with('error', 'Batch tidak dijumpai.'); + } + + return view('pembiayaan_online.operasi.batch', [ + 'auth_user' => $auth_user, + 'batch' => $detail['batch'], + 'lines' => $detail['lines'] ?? [], + 'kodcaw' => $kodcaw, + 'api_url' => $api_url, + 'cawangan_info' => $cawangan_info, + ]); + } + + public function operasiApproveLine(Request $request, $kodcaw, $id) + { + $res = $this->api() + ->asForm() + ->post(config('api.url') . '/api/pembiayaan-online/operasi/' . $kodcaw . '/lines/' . $id . '/approve', [ + 'ops_by' => Auth::user()['name'], + ]); + + return $this->opsRedirect($res, $kodcaw, $request->input('batch_id'), 'Rekod diluluskan.'); + } + + public function operasiRejectLine(Request $request, $kodcaw, $id) + { + $reason = trim((string) $request->input('reject_reason', '')); + if ($reason === '') { + return redirect()->back()->with('error', 'Sebab tolak diperlukan.'); + } + + $res = $this->api() + ->asForm() + ->post(config('api.url') . '/api/pembiayaan-online/operasi/' . $kodcaw . '/lines/' . $id . '/reject', [ + 'ops_by' => Auth::user()['name'], + 'reject_reason' => $reason, + ]); + + return $this->opsRedirect($res, $kodcaw, $request->input('batch_id'), 'Rekod ditolak. Dikembalikan ke PC.'); + } + + public function operasiApproveBatch(Request $request, $kodcaw, $batchId) + { + $res = $this->api() + ->asForm() + ->post(config('api.url') . '/api/pembiayaan-online/operasi/' . $kodcaw . '/batches/' . $batchId . '/approve', [ + 'ops_by' => Auth::user()['name'], + ]); + + return $this->opsRedirect($res, $kodcaw, $batchId, 'Semua rekod menunggu dalam batch diluluskan.'); + } + + public function operasiMarkPaid(Request $request, $kodcaw, $id) + { + $payload = $this->buildPaidPayload($request); + if (isset($payload['error'])) { + return redirect()->back()->with('error', $payload['error']); + } + + $res = $this->api() + ->asForm() + ->post(config('api.url') . '/api/pembiayaan-online/operasi/' . $kodcaw . '/lines/' . $id . '/paid', $payload); + + return $this->opsRedirect($res, $kodcaw, $request->input('batch_id'), 'Rekod ditanda PAID.'); + } + + public function operasiMarkPaidBatch(Request $request, $kodcaw, $batchId) + { + $payload = $this->buildPaidPayload($request); + if (isset($payload['error'])) { + return redirect()->back()->with('error', $payload['error']); + } + + $res = $this->api() + ->asForm() + ->post(config('api.url') . '/api/pembiayaan-online/operasi/' . $kodcaw . '/batches/' . $batchId . '/paid', $payload); + + return $this->opsRedirect($res, $kodcaw, $batchId, 'Rekod APPROVED dalam batch ditanda PAID.'); + } + + /** + * @return array + */ + protected function buildPaidPayload(Request $request) + { + $noRujukan = trim((string) $request->input('no_rujukan_bayaran', '')); + if ($noRujukan === '') { + return ['error' => 'No. rujukan bayaran diperlukan.']; + } + + if (!$request->hasFile('bukti')) { + return ['error' => 'Fail bukti bayaran diperlukan.']; + } + + $file = $request->file('bukti'); + if (!$file->isValid()) { + return ['error' => 'Fail bukti tidak sah.']; + } + + $raw = base64_encode(file_get_contents($file->getRealPath())); + $mime = $file->getMimeType() ?: 'application/octet-stream'; + + return [ + 'ops_by' => Auth::user()['name'], + 'no_rujukan_bayaran' => $noRujukan, + 'tarikh_bayaran' => $request->input('tarikh_bayaran') ?: date('Y-m-d'), + 'bukti_data' => $raw, + 'bukti_filename' => $file->getClientOriginalName(), + 'bukti_type' => $mime, + ]; + } + + protected function opsRedirect($res, $kodcaw, $batchId, $successMsg) + { + $batchId = $batchId ?: null; + + if (!$res->successful()) { + $body = $res->json(); + $msg = is_array($body) && isset($body['message']) ? $body['message'] : 'Tindakan gagal.'; + return redirect()->back()->with('error', $msg); + } + + if ($batchId) { + return redirect() + ->route('pembiayaan.online.operasi.batch', ['kodcaw' => $kodcaw, 'batchId' => $batchId]) + ->with('message', $successMsg); + } + + return redirect()->route('pembiayaan.online.operasi')->with('message', $successMsg); + } + + /** + * PC: modal online float + top-up request form/history. + */ + public function topupIndex(Request $request) + { + $auth_user = Auth::user(); + $kodcaw = $this->kodcaw(); + $api_url = config('api.url'); + $status = $request->input('status', ''); + + $cawangan_info = $this->api() + ->get($api_url . '/api/cawangan/' . $kodcaw) + ->json(); + + $modal = $this->api() + ->get($api_url . '/api/modal-online/' . $kodcaw) + ->json(); + + $query = []; + if ($status !== '' && $status !== 'all') { + $query['status'] = $status; + } + + $reqRes = $this->api() + ->get($api_url . '/api/modal-online/' . $kodcaw . '/topup/requests', $query) + ->json(); + + $requests = $reqRes['data'] ?? []; + if (!is_array($requests)) { + $requests = []; + } + + $pendingRes = $this->api() + ->get($api_url . '/api/modal-online/' . $kodcaw . '/topup/requests', ['status' => 'PENDING']) + ->json(); + $pendingList = $pendingRes['data'] ?? []; + $hasPending = is_array($pendingList) && count($pendingList) > 0; + $isMissing = !empty($modal['missing']); + $pendingRequest = $modal['pending_request'] ?? null; + if (!$pendingRequest && $hasPending) { + $pendingRequest = $pendingList[0]; + } + + return view('pembiayaan_online.pc.topup', compact( + 'auth_user', + 'kodcaw', + 'api_url', + 'cawangan_info', + 'modal', + 'requests', + 'status', + 'hasPending', + 'isMissing', + 'pendingRequest' + )); + } + + /** + * PC: submit top-up request. + */ + public function topupRequest(Request $request) + { + $kodcaw = $this->kodcaw(); + $amaun = (float) $request->input('amaun', 0); + + if ($amaun <= 0) { + return redirect()->back()->with('error', 'Amaun mesti lebih daripada 0.'); + } + + $res = $this->api() + ->asForm() + ->post(config('api.url') . '/api/modal-online/' . $kodcaw . '/topup/request', [ + 'amaun' => $amaun, + 'dimohon_oleh' => Auth::user()['name'], + 'nota' => $request->input('nota'), + ]); + + if (!$res->successful()) { + $body = $res->json(); + $msg = is_array($body) && isset($body['message']) ? $body['message'] : 'Gagal hantar permohonan.'; + return redirect()->back()->with('error', $msg)->withInput(); + } + + return redirect() + ->route('pembiayaan.online.pc.topup') + ->with('message', 'Permohonan modal online dihantar. Menunggu kelulusan Operasi.'); + } + + /** + * Operasi: senarai permohonan tambah modal online. + */ + public function operasiTopupIndex(Request $request) + { + $auth_user = Auth::user(); + $api_url = config('api.url'); + $status = $request->input('status', 'PENDING'); + $tarikh = $request->input('tarikh'); + + $query = []; + if ($status === 'all') { + $query['status'] = 'all'; + } elseif ($status !== '' && $status !== null) { + $query['status'] = $status; + } else { + $query['status'] = 'PENDING'; + } + if ($tarikh) { + $query['tarikh'] = $tarikh; + } + + $res = $this->api() + ->get($api_url . '/api/modal-online/operasi/topup/requests', $query) + ->json(); + + $requests = $res['data'] ?? []; + if (!is_array($requests)) { + $requests = []; + } + + return view('pembiayaan_online.operasi.topup', compact( + 'auth_user', + 'api_url', + 'requests', + 'status', + 'tarikh' + )); + } + + public function operasiTopupApprove(Request $request, $id) + { + $amaun = $request->input('amaun'); + if ($amaun !== null && $amaun !== '' && (float) $amaun <= 0) { + return redirect()->back()->with('error', 'Amaun diluluskan mesti lebih daripada 0.'); + } + + $res = $this->api() + ->asForm() + ->post(config('api.url') . '/api/modal-online/operasi/topup/' . $id . '/approve', [ + 'diluluskan_oleh' => Auth::user()['name'], + 'nota' => $request->input('nota'), + 'amaun' => $amaun, + ]); + + if (!$res->successful()) { + $body = $res->json(); + $msg = is_array($body) && isset($body['message']) ? $body['message'] : 'Gagal lulus permohonan.'; + return redirect()->back()->with('error', $msg); + } + + $amaunLulus = $res->json()['request']['amaun'] ?? $amaun; + return redirect() + ->route('pembiayaan.online.operasi.topup') + ->with('message', 'Permohonan diluluskan RM ' . number_format((float) $amaunLulus, 2) . '. Modal online cawangan dikemas kini.'); + } + + public function operasiTopupReject(Request $request, $id) + { + $res = $this->api() + ->asForm() + ->post(config('api.url') . '/api/modal-online/operasi/topup/' . $id . '/reject', [ + 'diluluskan_oleh' => Auth::user()['name'], + 'nota' => $request->input('nota'), + ]); + + if (!$res->successful()) { + $body = $res->json(); + $msg = is_array($body) && isset($body['message']) ? $body['message'] : 'Gagal tolak permohonan.'; + return redirect()->back()->with('error', $msg); + } + + return redirect() + ->route('pembiayaan.online.operasi.topup') + ->with('message', 'Permohonan ditolak.'); + } + + /** + * PC: EOD close branch modal online. + */ + public function closeModal(Request $request) + { + $kodcaw = $this->kodcaw(); + + $res = $this->api() + ->asForm() + ->post(config('api.url') . '/api/modal-online/' . $kodcaw . '/close', [ + 'ditutup_oleh' => Auth::user()['name'], + ]); + + if (!$res->successful()) { + $body = $res->json(); + $msg = is_array($body) && isset($body['message']) ? $body['message'] : 'Gagal tutup modal online.'; + return redirect()->back()->with('error', $msg); + } + + $dikembalikan = $res->json()['dikembalikan'] ?? 0; + return redirect() + ->route('pembiayaan.online.pc.topup') + ->with('message', 'Modal online ditutup. Baki dikembalikan RM ' . number_format((float) $dikembalikan, 2) . '.'); + } + + /** + * Operasi: EOD dashboard semua cawangan. + */ + public function operasiEodIndex(Request $request) + { + $auth_user = Auth::user(); + $api_url = config('api.url'); + $tarikh = $request->input('tarikh') ?: date('Y-m-d'); + + $res = $this->api() + ->get($api_url . '/api/modal-online/operasi/eod', [ + 'zone' => 'all', + 'tarikh' => $tarikh, + ]) + ->json(); + + $rows = $res['data'] ?? []; + if (!is_array($rows)) { + $rows = []; + } + + $summary = [ + 'open' => $res['open'] ?? 0, + 'closed' => $res['closed'] ?? 0, + 'missing' => $res['missing'] ?? 0, + 'bilangan' => $res['bilangan'] ?? count($rows), + ]; + + return view('pembiayaan_online.operasi.eod', compact( + 'auth_user', + 'api_url', + 'rows', + 'tarikh', + 'summary' + )); + } + + public function operasiCloseModal(Request $request, $kodcaw) + { + $res = $this->api() + ->asForm() + ->post(config('api.url') . '/api/modal-online/' . $kodcaw . '/close', [ + 'ditutup_oleh' => Auth::user()['name'], + ]); + + if (!$res->successful()) { + $body = $res->json(); + $msg = is_array($body) && isset($body['message']) ? $body['message'] : 'Gagal tutup modal online.'; + return redirect()->back()->with('error', $msg); + } + + return redirect() + ->route('pembiayaan.online.operasi.eod') + ->with('message', 'Modal online ' . $kodcaw . ' ditutup.'); + } + + public function operasiCloseAllModal(Request $request) + { + $res = $this->api() + ->asForm() + ->post(config('api.url') . '/api/modal-online/operasi/eod/close-all', [ + 'ditutup_oleh' => Auth::user()['name'], + 'zone' => 'all', + ]); + + if (!$res->successful()) { + $body = $res->json(); + $msg = is_array($body) && isset($body['message']) ? $body['message'] : 'Gagal tutup semua modal online.'; + return redirect()->back()->with('error', $msg); + } + + $closed = $res->json()['closed'] ?? 0; + $skipped = $res->json()['skipped'] ?? 0; + return redirect() + ->route('pembiayaan.online.operasi.eod') + ->with('message', 'EOD selesai: ' . $closed . ' ditutup, ' . $skipped . ' sudah ditutup.'); + } +} diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 3049068..08a3ae1 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 33e4953..70034b8 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 0000000..974dacb --- /dev/null +++ b/app/helpers.php @@ -0,0 +1,15 @@ + env('APP_NAME', 'Laravel'), + 'version' => env('APP_VERSION', ''), + /* |-------------------------------------------------------------------------- | Application Environment diff --git a/docker-compose.staging.yml b/docker-compose.staging.yml index 073e756..92ae34c 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 223a96c..47a1830 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/docker/php/Dockerfile b/docker/php/Dockerfile index b14f579..e2a2c4f 100644 --- a/docker/php/Dockerfile +++ b/docker/php/Dockerfile @@ -4,22 +4,22 @@ WORKDIR /var/www/html RUN apt-get update \ && apt-get install -y --no-install-recommends \ - git \ - pkg-config \ - unzip \ - libonig-dev \ - libzip-dev \ - libpng-dev \ - libjpeg62-turbo-dev \ - libfreetype6-dev \ + git \ + pkg-config \ + unzip \ + libonig-dev \ + libzip-dev \ + libpng-dev \ + libjpeg62-turbo-dev \ + libfreetype6-dev \ && docker-php-ext-configure gd --with-freetype --with-jpeg \ && docker-php-ext-install -j"$(nproc)" \ - pdo_mysql \ - mbstring \ - bcmath \ - zip \ - exif \ - gd \ + pdo_mysql \ + mbstring \ + bcmath \ + zip \ + exif \ + gd \ && rm -rf /var/lib/apt/lists/* COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer @@ -40,12 +40,12 @@ COPY --chown=www-data:www-data . /var/www/html RUN composer install --no-interaction --prefer-dist --no-dev --optimize-autoloader --no-scripts \ && mkdir -p \ - storage/logs \ - storage/framework/cache/data \ - storage/framework/views \ - storage/framework/sessions \ - storage/app/public \ - bootstrap/cache \ + storage/logs \ + storage/framework/cache/data \ + storage/framework/views \ + storage/framework/sessions \ + storage/app/public \ + bootstrap/cache \ && chown -R www-data:www-data storage bootstrap/cache vendor FROM base AS development diff --git a/resources/views/admin/customer_index.blade.php b/resources/views/admin/customer_index.blade.php index aba0ebb..e6a9dcd 100644 --- a/resources/views/admin/customer_index.blade.php +++ b/resources/views/admin/customer_index.blade.php @@ -306,7 +306,7 @@ @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 9459d54..384fad4 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 402bfd0..40638d2 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 bed2238..60a9477 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 0000000..b859cab --- /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 71c4f23..062a93e 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 2eab543..a53b02a 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 0c010b0..689f8f8 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 bfc3bc0..e0ed9ba 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', 'staging']) + && + 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', 'staging']) + && + $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 ae1333e..ee34287 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 1bce3c1..a689626 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 0000000..588e0a6 --- /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 0000000..2f2e650 --- /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 0000000..139a0ae --- /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 0000000..ac2db5a --- /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 0000000..138ba46 --- /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 0000000..a26b481 --- /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 0000000..18a5fec --- /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/penebusan/v1/index-khazanah.blade.php b/resources/views/penebusan/v1/index-khazanah.blade.php index 6d441b7..a15206b 100644 --- a/resources/views/penebusan/v1/index-khazanah.blade.php +++ b/resources/views/penebusan/v1/index-khazanah.blade.php @@ -340,7 +340,7 @@ "ordering": false }); - var api = ''; + var api = "{{ api_url_for_browser() }}"; let nw = 0; $('input[type="checkbox"]').hide(); diff --git a/resources/views/penebusan/v1/index.blade.php b/resources/views/penebusan/v1/index.blade.php index 12e7ad3..a43f13d 100644 --- a/resources/views/penebusan/v1/index.blade.php +++ b/resources/views/penebusan/v1/index.blade.php @@ -371,7 +371,7 @@ "ordering": false }); - var api = ''; + var api = "{{ api_url_for_browser() }}"; let nw = 0; $('input[type="checkbox"]').hide(); diff --git a/resources/views/penebusan/v2/index-khazanah.blade.php b/resources/views/penebusan/v2/index-khazanah.blade.php index a99406b..54a367f 100644 --- a/resources/views/penebusan/v2/index-khazanah.blade.php +++ b/resources/views/penebusan/v2/index-khazanah.blade.php @@ -470,7 +470,7 @@ "ordering": false }); - var api = ''; + var api = "{{ api_url_for_browser() }}"; let nw = 0; let jenisAT = 'none'; diff --git a/resources/views/penebusan/v2/index.blade-backup.php b/resources/views/penebusan/v2/index.blade-backup.php index 3522f50..e4fb41c 100644 --- a/resources/views/penebusan/v2/index.blade-backup.php +++ b/resources/views/penebusan/v2/index.blade-backup.php @@ -652,7 +652,7 @@ "ordering": false }); - var api = ''; + var api = "{{ api_url_for_browser() }}"; let nw = 0; let jenisAT = 'none'; diff --git a/resources/views/penebusan/v2/index.blade.php b/resources/views/penebusan/v2/index.blade.php index c3d88f2..77daaa2 100644 --- a/resources/views/penebusan/v2/index.blade.php +++ b/resources/views/penebusan/v2/index.blade.php @@ -1130,7 +1130,7 @@ let pertambahpinjaman = "{{ $pertambahpinjaman }}"; - var api = ''; + var api = "{{ api_url_for_browser() }}"; let nw = 0; let jenisAT = 'none'; @@ -1813,7 +1813,7 @@ }); try { - const pampasanListResponse = await fetch(`{{ config('api.url') }}/api/palsu/laporan?${params}`, { + const pampasanListResponse = await fetch(`{{ api_url_for_browser() }}/api/palsu/laporan?${params}`, { method: 'GET', headers: { 'Content-Type': 'application/json', diff --git a/resources/views/print/resittebus_ujrah.blade.php b/resources/views/print/resittebus_ujrah.blade.php index fb8da19..309fa63 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 020f766..e16df24 100644 --- a/routes/web.php +++ b/routes/web.php @@ -81,6 +81,12 @@ Route::get('login', 'Auth\LoginController@login')->name('login'); Route::post('login', 'Auth\LoginController@authenticate'); // Route::get('logout', 'Auth\LoginController@logout')->name('logout'); +// Impersonation (lab404/laravel-impersonate) +Route::post('/impersonate/leave', ['as' => 'impersonate.leave', 'uses' => 'Auth\ImpersonateController@leave'])->middleware('auth'); +Route::post('/impersonate/{id}', ['as' => 'impersonate.start', 'uses' => 'Auth\ImpersonateController@impersonate']) + ->where('id', '[0-9]+') + ->middleware('auth'); + Route::get('/', 'HomeController@index')->name('home'); Route::get('/home', 'HomeController@index')->name('home'); @@ -166,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'); @@ -350,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');