Compare commits
19 Commits
v3.4a
...
347d99d8bd
| Author | SHA1 | Date | |
|---|---|---|---|
| 347d99d8bd | |||
| 9aee720bd0 | |||
| cdc28fb010 | |||
| 1138e193ae | |||
| a36cbcf930 | |||
| 011fbfe8b2 | |||
| 63d8c23785 | |||
| 045adcaf1a | |||
| 1d6baf3b1f | |||
| 464d3e8dbb | |||
| abccad3219 | |||
| 7ad3fd4f86 | |||
| 713d5a4923 | |||
| b76566a2d6 | |||
| 38f6db2e10 | |||
| f95bdf1214 | |||
| d614677601 | |||
| 7cd21ef610 | |||
| ca2a02e354 |
@@ -50,3 +50,5 @@ MYKAD_READER_PORT=17321
|
||||
MYKAD_READER_ENABLED_CAWANGAN=''
|
||||
|
||||
INTERNAL_NOTIFICATION_SECRET=
|
||||
|
||||
LOGVIEWER_PASSWORD=
|
||||
|
||||
@@ -7,6 +7,7 @@ APP_URL=https://ujrah.erahn.com.my
|
||||
API_URL=https://apiujrah.erahn.com.my
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOGVIEWER_PASSWORD="$2y$10$k7eiUyZdm3BruwAaT1gbmelTm.PPgZptOEQT1nlBjyiR84a4KBMlm"
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=192.168.1.216
|
||||
|
||||
+2
-5
@@ -4,17 +4,14 @@ APP_VERSION=v2.2-staging
|
||||
APP_KEY=base64:O1XZDqK4H6+3GdrODgCaLr2l+OoWvgVhYr0GJ1KizW8=
|
||||
APP_DEBUG=true
|
||||
APP_URL=https://staging.erahn.com.my
|
||||
API_URL=https://api-staging.erahn.com.my
|
||||
|
||||
HTTP_PORT=8091
|
||||
MYSQL_PUBLISH_PORT=3309
|
||||
|
||||
API_URL=https://api-staging.erahn.com.my
|
||||
API_URL_KOOP=https://api-staging.erahn.com.my
|
||||
API_URL_PKB=https://api-staging.erahn.com.my
|
||||
API_ARRAHNBID=http://lelong.test/api/
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_LEVEL=debug
|
||||
LOGVIEWER_PASSWORD=test123
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=mysql
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
APP_NAME=Laravel
|
||||
APP_ENV=local
|
||||
APP_KEY=base64:WRTHcFTq5YARKVdA8YDUzsh9Ue8vD63ivgZgXNNBiGo=
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://ujrahkopkb.erahn.com.my
|
||||
API_URL=http://apiujrah-kopkb.erahn.com.my
|
||||
#API_ARRAHNBID=http://lelong.test/api/
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=kaunter_erahn
|
||||
DB_USERNAME=spider
|
||||
DB_PASSWORD=G0dz!ll4
|
||||
|
||||
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
|
||||
@@ -1,6 +1,9 @@
|
||||
name: Deploy to Staging
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
image_tag:
|
||||
@@ -18,10 +21,22 @@ jobs:
|
||||
runs-on: host
|
||||
|
||||
steps:
|
||||
- name: Resolve image tag
|
||||
id: resolve
|
||||
run: |
|
||||
set -e
|
||||
if [ "${{ gitea.event_name }}" = "workflow_dispatch" ]; then
|
||||
IMAGE_TAG="${{ inputs.image_tag }}"
|
||||
else
|
||||
IMAGE_TAG="${{ gitea.ref_name }}"
|
||||
fi
|
||||
echo "IMAGE_TAG=${IMAGE_TAG}" >> "$GITHUB_OUTPUT"
|
||||
echo "Deploying image tag: ${IMAGE_TAG}"
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.image_tag }}
|
||||
ref: ${{ steps.resolve.outputs.IMAGE_TAG }}
|
||||
|
||||
- name: Login to Docker registry
|
||||
run: |
|
||||
@@ -33,28 +48,35 @@ jobs:
|
||||
- name: Verify image exists in registry
|
||||
run: |
|
||||
set -e
|
||||
IMAGE_TAG="${{ inputs.image_tag }}"
|
||||
IMAGE_TAG="${{ steps.resolve.outputs.IMAGE_TAG }}"
|
||||
IMAGE="${APP_IMAGE}:${IMAGE_TAG}"
|
||||
|
||||
echo "Checking if image exists: ${IMAGE}"
|
||||
if ! docker manifest inspect "${IMAGE}" > /dev/null 2>&1; then
|
||||
echo "ERROR: Image ${IMAGE} does not exist in registry!"
|
||||
echo "Run the Build Docker Image workflow first."
|
||||
exit 1
|
||||
fi
|
||||
echo "✓ ${IMAGE} found"
|
||||
# Tag pushes build in parallel — wait for the image to appear
|
||||
for i in $(seq 1 30); do
|
||||
if docker manifest inspect "${IMAGE}" > /dev/null 2>&1; then
|
||||
echo "✓ ${IMAGE} found"
|
||||
exit 0
|
||||
fi
|
||||
echo "Image not ready yet (attempt ${i}/30), waiting 20s..."
|
||||
sleep 20
|
||||
done
|
||||
|
||||
echo "ERROR: Image ${IMAGE} does not exist in registry after waiting!"
|
||||
echo "Run the Build Docker Image workflow first."
|
||||
exit 1
|
||||
|
||||
- name: Pull Docker image
|
||||
run: |
|
||||
set -e
|
||||
IMAGE_TAG="${{ inputs.image_tag }}"
|
||||
IMAGE_TAG="${{ steps.resolve.outputs.IMAGE_TAG }}"
|
||||
docker pull "${APP_IMAGE}:${IMAGE_TAG}"
|
||||
echo "✓ Image pulled successfully"
|
||||
|
||||
- name: Sync compose file and deploy
|
||||
run: |
|
||||
set -e
|
||||
IMAGE_TAG="${{ inputs.image_tag }}"
|
||||
IMAGE_TAG="${{ steps.resolve.outputs.IMAGE_TAG }}"
|
||||
|
||||
mkdir -p "${DEPLOY_DIR}/docker/nginx" "${DEPLOY_DIR}/public"
|
||||
cp docker-compose.staging.yml "${DEPLOY_DIR}/docker-compose.yml"
|
||||
@@ -62,15 +84,12 @@ jobs:
|
||||
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
|
||||
cp .env.staging "${DEPLOY_DIR}/.env.staging"
|
||||
echo "Copied .env.staging from repo (first deploy). Edit ${DEPLOY_DIR}/.env.staging on the server if needed."
|
||||
else
|
||||
echo "ERROR: ${DEPLOY_DIR}/.env.staging is missing on the server"
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -f .env.staging ]; then
|
||||
echo "ERROR: .env.staging is missing in the repository"
|
||||
exit 1
|
||||
fi
|
||||
cp .env.staging "${DEPLOY_DIR}/.env.staging"
|
||||
echo "✓ Synced .env.staging from repo"
|
||||
|
||||
cd "${DEPLOY_DIR}"
|
||||
|
||||
|
||||
@@ -125,10 +125,10 @@ class AliranTunaiController extends Controller
|
||||
|
||||
$auth_user = Auth::user();
|
||||
|
||||
$gadai = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/gadai/norujukan/'. $auth_user['cawangan'] .'/' .$request->norujukan_gadai)->json();
|
||||
$gadai = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/gadai/norujukan/'. $auth_user['cawangan'] .'/' .$request->norujukan_gadai)->throw()->json();
|
||||
$gadai_detail = $gadai[0];
|
||||
|
||||
$getTunai2=Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url').'/api/GetCurrentTunai/'.$auth_user['cawangan'],['kodlaluan' => $teller])->json();
|
||||
$getTunai2=Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url').'/api/GetCurrentTunai/'.$auth_user['cawangan'],['kodlaluan' => $teller])->throw()->json();
|
||||
|
||||
$keluar = $getTunai2['keluar'];
|
||||
$bakiakhir = $getTunai2['baki'];
|
||||
@@ -143,7 +143,7 @@ class AliranTunaiController extends Controller
|
||||
'keluar' => $keluar,
|
||||
'masuk' => $masuk,
|
||||
'bakiakhir' => $bakiakhir
|
||||
]);
|
||||
])->throw();
|
||||
|
||||
return response()->json($updateTunai,201);
|
||||
|
||||
@@ -153,13 +153,13 @@ class AliranTunaiController extends Controller
|
||||
|
||||
$auth_user = Auth::user();
|
||||
|
||||
$gadai = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/gadai/norujukan/'. $auth_user['cawangan'] .'/' .$request->norujukan)->json();
|
||||
$gadai = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/gadai/norujukan/'. $auth_user['cawangan'] .'/' .$request->norujukan)->throw()->json();
|
||||
$gadai_detail = $gadai[0];
|
||||
|
||||
$tebus = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/listpenebusanhistory/'. $auth_user['cawangan'],['norujukan' => $request->norujukan])->json();
|
||||
$tebus = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/listpenebusanhistory/'. $auth_user['cawangan'],['norujukan' => $request->norujukan])->throw()->json();
|
||||
$tebus_detail = $tebus[0];
|
||||
|
||||
$getTunai2=Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url').'/api/GetCurrentTunai/'.$auth_user['cawangan'],['kodlaluan' => $tebus_detail['teller']])->json();
|
||||
$getTunai2=Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url').'/api/GetCurrentTunai/'.$auth_user['cawangan'],['kodlaluan' => $tebus_detail['teller']])->throw()->json();
|
||||
|
||||
$keluar=$getTunai2['keluar'];
|
||||
$baki=$getTunai2['baki'];
|
||||
@@ -181,7 +181,7 @@ class AliranTunaiController extends Controller
|
||||
'keluar'=>$keluar,
|
||||
'masuk'=>$masuk,
|
||||
'bakiakhir'=>$bakiakhir
|
||||
]);
|
||||
])->throw();
|
||||
|
||||
}else{
|
||||
|
||||
@@ -199,7 +199,7 @@ class AliranTunaiController extends Controller
|
||||
'keluar'=>$keluar,
|
||||
'masuk'=>$masuk,
|
||||
'bakiakhir'=>$bakiakhir
|
||||
]);
|
||||
])->throw();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -208,13 +208,13 @@ class AliranTunaiController extends Controller
|
||||
|
||||
$auth_user = Auth::user();
|
||||
|
||||
$gadai = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/gadai/norujukan/'. $auth_user['cawangan'] .'/' .$request->norujukan)->json();
|
||||
$gadai = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/gadai/norujukan/'. $auth_user['cawangan'] .'/' .$request->norujukan)->throw()->json();
|
||||
$gadai_detail = $gadai[0];
|
||||
|
||||
$tebus = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/listpenebusanhistory/'. $auth_user['cawangan'],['norujukan' => $request->norujukan])->json();
|
||||
$tebus = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/listpenebusanhistory/'. $auth_user['cawangan'],['norujukan' => $request->norujukan])->throw()->json();
|
||||
$tebus_detail = $tebus[0];
|
||||
|
||||
$getTunai2=Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url').'/api/GetCurrentTunai/'.$auth_user['cawangan'],['kodlaluan' => $tebus_detail['teller']])->json();
|
||||
$getTunai2=Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url').'/api/GetCurrentTunai/'.$auth_user['cawangan'],['kodlaluan' => $tebus_detail['teller']])->throw()->json();
|
||||
|
||||
$keluar=$getTunai2['keluar'];
|
||||
$baki=$getTunai2['baki'];
|
||||
@@ -228,7 +228,7 @@ class AliranTunaiController extends Controller
|
||||
'keluar'=>$keluar,
|
||||
'masuk'=>$masuk,
|
||||
'bakiakhir'=>$bakiakhir
|
||||
]);
|
||||
])->throw();
|
||||
}
|
||||
|
||||
public function alirantunaiUpahBknTawarruq(Request $request){
|
||||
|
||||
@@ -5,15 +5,12 @@ namespace App\Http\Controllers\Auth;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
use App\Dashboard;
|
||||
use App\User;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class LoginController extends Controller
|
||||
{
|
||||
@@ -144,25 +141,26 @@ class LoginController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
public function logout(){
|
||||
$current = Carbon::now();
|
||||
$current = new Carbon();
|
||||
$current = $current->toDateString();
|
||||
public function logout(Request $request)
|
||||
{
|
||||
$auth_user = Auth::guard('web')->user();
|
||||
Auth::logout();
|
||||
Session::flush();
|
||||
$session = Http::withOptions(['verify' => config('app.api_verify')])->post(config('api.url') . '/api/logoutsession/' . $auth_user['cawangan'], [
|
||||
'id' => $auth_user['id'],
|
||||
'nama' => $auth_user['name'],
|
||||
'nokp' => $auth_user['no_kp'],
|
||||
'email' => $auth_user['email'],
|
||||
'taraf' => $auth_user['role_harian'],
|
||||
'tarikh' => $current,
|
||||
|
||||
|
||||
]);
|
||||
Auth::guard('web')->logout();
|
||||
$request->session()->invalidate();
|
||||
$request->session()->regenerateToken();
|
||||
|
||||
return Redirect::to('/');
|
||||
if ($auth_user) {
|
||||
Http::withOptions(['verify' => config('app.api_verify')])->post(config('api.url') . '/api/logoutsession/' . $auth_user['cawangan'], [
|
||||
'id' => $auth_user['id'],
|
||||
'nama' => $auth_user['name'],
|
||||
'nokp' => $auth_user['no_kp'],
|
||||
'email' => $auth_user['email'],
|
||||
'taraf' => $auth_user['role_harian'],
|
||||
'tarikh' => now()->toDateString(),
|
||||
]);
|
||||
}
|
||||
|
||||
return redirect('/');
|
||||
}
|
||||
|
||||
public function GetRolesHarian(Request $request, $kodcaw){
|
||||
|
||||
@@ -180,17 +180,17 @@ class GadaianController extends Controller
|
||||
Session::put('nopelanggan', $customer_info['nopelanggan']);
|
||||
Session::put('page_reload', true);
|
||||
Session::forget('borang_online_printed');
|
||||
$gadai = Http::withOptions(['verify' => config('app.api_verify')])->post(config('api.url') . '/api/gadai/' . $auth_user['cawangan'], [
|
||||
Http::withOptions(['verify' => config('app.api_verify')])->post(config('api.url') . '/api/gadai/' . $auth_user['cawangan'], [
|
||||
'norujukan' => $norujukan,
|
||||
'nopelanggan' => $customer_info['nopelanggan'],
|
||||
'nokp' => $noic,
|
||||
'sirig' => $new_sirig
|
||||
]);
|
||||
'sirig' => $new_sirig,
|
||||
])->throw();
|
||||
} else {
|
||||
$norujukan = Session::get('norujukan');
|
||||
$nokp = Session::get('nokp');
|
||||
$nopelanggan = Session::get('nopelanggan');
|
||||
$gadai_session = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/check/sag', ['kodcaw' => $auth_user['cawangan'], 'norujukan' => $norujukan, 'nokp' => $nokp])->json();
|
||||
$gadai_session = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/check/sag', ['kodcaw' => $auth_user['cawangan'], 'norujukan' => $norujukan, 'nokp' => $nokp])->throw()->json();
|
||||
if ($gadai_session == null) {
|
||||
$gadai_transaction = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/gadai/' . $auth_user['cawangan'] . '/' . $current->toDateString())->json();
|
||||
if ($gadai_transaction) {
|
||||
@@ -205,12 +205,12 @@ class GadaianController extends Controller
|
||||
Session::put('nopelanggan', $nopelanggan);
|
||||
Session::put('page_reload', true);
|
||||
Session::forget('borang_online_printed');
|
||||
$gadai_baru = Http::withOptions(['verify' => config('app.api_verify')])->post(config('api.url') . '/api/gadai/' . $auth_user['cawangan'], [
|
||||
Http::withOptions(['verify' => config('app.api_verify')])->post(config('api.url') . '/api/gadai/' . $auth_user['cawangan'], [
|
||||
'norujukan' => $norujukan_baru,
|
||||
'nopelanggan' => $nopelanggan,
|
||||
'nokp' => $nokp,
|
||||
'sirig' => $new_sirig
|
||||
]);
|
||||
'sirig' => $new_sirig,
|
||||
])->throw();
|
||||
$norujukan = $norujukan_baru;
|
||||
}
|
||||
}
|
||||
@@ -285,6 +285,15 @@ class GadaianController extends Controller
|
||||
public function store(Request $request)
|
||||
{
|
||||
$auth_user = Auth::user();
|
||||
$shoraka = app(\App\Services\ShorakaFinancingService::class);
|
||||
if ($shoraka->hasOrder($request->norujukan_gadai)) {
|
||||
$message = 'Order Shoraka telah dihantar. Jangan hantar semula.';
|
||||
if ($request->ajax() || $request->expectsJson()) {
|
||||
abort(409, $message);
|
||||
}
|
||||
return redirect()->back()->with('error', $message);
|
||||
}
|
||||
$shoraka->ensureReady();
|
||||
$caraTerima = strtoupper((string) $request->input('cara_terima', 'TUNAI'));
|
||||
$pinjamanAmt = round((float) $request->pinjaman, 2);
|
||||
|
||||
@@ -342,16 +351,21 @@ class GadaianController extends Controller
|
||||
'nokp' => $request->nokp,
|
||||
'kadar_rebate' => $this->parseMoney($request->kadar_rebate),
|
||||
'rebate' => $this->parseMoney($request->rebate),
|
||||
])->json();
|
||||
])->throw()->json();
|
||||
|
||||
|
||||
$komuditi = Http::withOptions(['verify' => config('app.api_verify')])->put(config('api.url') . '/api/komuditi/transaksi', [
|
||||
'unit_komuditi' => round($request->pinjaman, 2),
|
||||
'norujukan' => $request->norujukan_gadai,
|
||||
'kodcaw' => $auth_user['cawangan'],
|
||||
'teller' => $auth_user['name']
|
||||
return $shoraka->hold($request, $request->norujukan_gadai, 'gadai', [
|
||||
'cara_terima' => $caraTerima,
|
||||
'pinjaman' => $pinjamanAmt,
|
||||
'temporary_gadai' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function completeShorakaFinancing(Request $request)
|
||||
{
|
||||
$auth_user = Auth::user();
|
||||
$caraTerima = $request->cara_terima;
|
||||
$pinjamanAmt = round((float) $request->pinjaman, 2);
|
||||
if ($caraTerima === 'ONLINE') {
|
||||
$online = Http::withOptions(['verify' => config('app.api_verify')])
|
||||
->asForm()
|
||||
@@ -374,7 +388,7 @@ class GadaianController extends Controller
|
||||
$msg = is_array($body) && isset($body['message'])
|
||||
? $body['message']
|
||||
: 'Gagal daftar pembiayaan online. Sila cuba lagi.';
|
||||
return redirect()->back()->with('error', $msg);
|
||||
throw new \RuntimeException($msg);
|
||||
}
|
||||
|
||||
$this->notifyPcPembiayaanOnlinePending($auth_user, $request, $pinjamanAmt);
|
||||
@@ -388,9 +402,9 @@ class GadaianController extends Controller
|
||||
$request->session()->forget('norujukan');
|
||||
$request->session()->forget('borang_online_printed');
|
||||
$request->session()->flash('activate_tab', 'SAG_baru');
|
||||
if ($caraTerima === 'ONLINE') {
|
||||
$request->session()->flash('message', 'Gadai berjaya. Pembiayaan online menunggu semakan PC.');
|
||||
}
|
||||
$request->session()->flash('message', $caraTerima === 'ONLINE'
|
||||
? 'Gadai berjaya. Pembiayaan online menunggu semakan PC.'
|
||||
: 'Pembiayaan berjaya dihantar.');
|
||||
|
||||
return redirect()->route('customer_info');
|
||||
}
|
||||
@@ -535,31 +549,55 @@ class GadaianController extends Controller
|
||||
$keuntungan6bulan = $keuntungan_sebln * 6;
|
||||
$keuntungan12bulan = $keuntungan_sebln * 12;
|
||||
$hargajualan = $request->pinjaman + $keuntungan12bulan;
|
||||
$gadai = Http::withOptions(['verify' => config('app.api_verify')])->put(config('api.url') . '/api/gadai/norujukan/' . $auth_user['cawangan'] . '/' . $request->norujukan_gadai, [
|
||||
'kodcaw' => $auth_user['cawangan'],
|
||||
'nilaimarhun' => round($total_nilai_marhun, 2),
|
||||
'berat' => round($request->total_berat, 2),
|
||||
'pinjaman' => round($request->pinjaman, 2),
|
||||
'kadarupah' => round($kadarupah, 2),
|
||||
'marhun' => $request->marhun_detail,
|
||||
'percentpinj' => $margin_pinjaman,
|
||||
'teller' => $auth_user['name'],
|
||||
'upah6' => $keuntungan6bulan,
|
||||
'upah12' => $keuntungan12bulan,
|
||||
'hargajualan' => $hargajualan,
|
||||
'kuantiti_marhun' => $request->kuantiti_marhun,
|
||||
'transaction' => 'Ubah Gadai',
|
||||
'kadarujrah' => round($kadarupah, 2),
|
||||
'ujrah' => $ujrah,
|
||||
'onepercent' => $onepercent,
|
||||
'margin_semasa' => $margin_pinjaman,
|
||||
'kadar_rebate' => $this->parseMoney($request->kadar_rebate),
|
||||
'rebate' => $this->parseMoney($request->rebate),
|
||||
])->json();
|
||||
$update_komuditi = Http::withOptions(['verify' => config('app.api_verify')])->put(config('api.url') . '/api/komuditi/update', [
|
||||
'unit_komuditi' => round($request->pinjaman, 2),
|
||||
'norujukan' => $request->norujukan_gadai
|
||||
])->json();
|
||||
try {
|
||||
$gadai = Http::withOptions(['verify' => config('app.api_verify')])->put(config('api.url') . '/api/gadai/norujukan/' . $auth_user['cawangan'] . '/' . $request->norujukan_gadai, [
|
||||
'kodcaw' => $auth_user['cawangan'],
|
||||
'nilaimarhun' => round($total_nilai_marhun, 2),
|
||||
'berat' => round($request->total_berat, 2),
|
||||
'pinjaman' => round($request->pinjaman, 2),
|
||||
'kadarupah' => round($kadarupah, 2),
|
||||
'marhun' => $request->marhun_detail,
|
||||
'percentpinj' => $margin_pinjaman,
|
||||
'teller' => $auth_user['name'],
|
||||
'upah6' => $keuntungan6bulan,
|
||||
'upah12' => $keuntungan12bulan,
|
||||
'hargajualan' => $hargajualan,
|
||||
'kuantiti_marhun' => $request->kuantiti_marhun,
|
||||
'transaction' => 'Ubah Gadai',
|
||||
'kadarujrah' => round($kadarupah, 2),
|
||||
'ujrah' => $ujrah,
|
||||
'onepercent' => $onepercent,
|
||||
'margin_semasa' => $margin_pinjaman,
|
||||
'kadar_rebate' => $this->parseMoney($request->kadar_rebate),
|
||||
'rebate' => $this->parseMoney($request->rebate),
|
||||
]);
|
||||
} catch (\Illuminate\Http\Client\ConnectionException $exception) {
|
||||
return back()->withInput()->with('gadai_edit_error',
|
||||
'Sambungan terganggu. Semak rekod gadai sebelum mencuba semula.');
|
||||
}
|
||||
if (!$gadai->successful()) {
|
||||
$message = 'Ubah Gadai tidak berjaya. Sila semak dengan operasi.';
|
||||
if ($gadai->status() === 409 || $gadai->status() === 422) {
|
||||
$apiMessage = $gadai->json()['message'] ?? null;
|
||||
if (is_string($apiMessage) && $apiMessage !== '') {
|
||||
$message = $apiMessage;
|
||||
}
|
||||
}
|
||||
return back()->withInput()->with('gadai_edit_error', $message);
|
||||
}
|
||||
try {
|
||||
$update_komuditi = Http::withOptions(['verify' => config('app.api_verify')])->put(config('api.url') . '/api/komuditi/update', [
|
||||
'unit_komuditi' => round($request->pinjaman, 2),
|
||||
'norujukan' => $request->norujukan_gadai
|
||||
]);
|
||||
} catch (\Illuminate\Http\Client\ConnectionException $exception) {
|
||||
return back()->with('gadai_edit_error',
|
||||
'Rekod gadai telah dikemas kini tetapi kemas kini komoditi tidak dapat disahkan. Sila semak dengan operasi.');
|
||||
}
|
||||
if (!$update_komuditi->successful()) {
|
||||
return back()->with('gadai_edit_error',
|
||||
'Rekod gadai telah dikemas kini tetapi kemas kini komoditi gagal. Sila semak dengan operasi.');
|
||||
}
|
||||
|
||||
event(new GadaiNotify('lulus', $auth_user['cawangan']));
|
||||
|
||||
@@ -573,7 +611,7 @@ class GadaianController extends Controller
|
||||
$norujukan = $request->norujukan;
|
||||
$auth_user = Auth::user();
|
||||
|
||||
Http::withOptions(['verify' => config('app.api_verify')])->delete(config('api.url') . '/api/gadai/batal/' . $auth_user['cawangan'] . '/' . $norujukan);
|
||||
Http::withOptions(['verify' => config('app.api_verify')])->delete(config('api.url') . '/api/gadai/batal/' . $auth_user['cawangan'] . '/' . $norujukan)->throw();
|
||||
$request->session()->forget('page_reload');
|
||||
$request->session()->forget('norujukan');
|
||||
$request->session()->forget('borang_online_printed');
|
||||
@@ -594,6 +632,7 @@ class GadaianController extends Controller
|
||||
|
||||
public function cetakSAG(Request $request)
|
||||
{
|
||||
app(\App\Services\ShorakaFinancingService::class)->printData($request->norujukan_modal);
|
||||
$auth_user = Auth::user();
|
||||
|
||||
$gadai = Http::withOptions(['verify' => config('app.api_verify')])->put(config('api.url') . '/api/gadai/norujukan/cetak/' . $auth_user['cawangan'] . '/' . $request->norujukan_modal);
|
||||
@@ -614,6 +653,7 @@ class GadaianController extends Controller
|
||||
}
|
||||
|
||||
foreach ($arraynorujukan as $index => $norujukan) {
|
||||
app(\App\Services\ShorakaFinancingService::class)->printData($norujukan);
|
||||
$gadai = Http::withOptions(['verify' => config('app.api_verify')])->put(config('api.url') . '/api/gadai/norujukan/serah/' . $auth_user['cawangan'] . '/' . $norujukan);
|
||||
|
||||
if ($gadai->failed()) {
|
||||
@@ -671,6 +711,12 @@ class GadaianController extends Controller
|
||||
// $pembayaran_segera = "https://spare.arrahn.com.my/pembayaransegera";
|
||||
$pembayaran_segera = "https://pay.arrahn.com.my";
|
||||
|
||||
$shorakaPrint = app(\App\Services\ShorakaFinancingService::class)->printData($gadai_detail['norujukan']);
|
||||
if ($shorakaPrint) {
|
||||
$komoditi = $shorakaPrint['komoditi'];
|
||||
$product = $shorakaPrint['product'];
|
||||
$kuantiti = $shorakaPrint['kuantiti'];
|
||||
} else {
|
||||
$komoditi = Http::withOptions(['verify' => config('app.api_verify')])
|
||||
->get($api_url . '/api/komuditi/check')
|
||||
->json();
|
||||
@@ -678,9 +724,14 @@ class GadaianController extends Controller
|
||||
->get($api_url . '/api/komuditi/description', ['kodproduk' => $komoditi['kodproduct']])
|
||||
->json();
|
||||
$kuantiti = $gadai_detail['pinjaman'] / $komoditi['nilai'];
|
||||
}
|
||||
|
||||
if ($gadai_detail['tagbaru'] == 1) {
|
||||
return view('print.sag_ujrah_3', compact('komoditi', 'product', 'kuantiti', 'gadai_detail', 'customer_detail', 'marhun_detail', 'cawangan_detail', 'api_url', 'pembayaran_segera', 'auth_username', 'mutu', 'kadar_ujrah', 'kakitangan'));
|
||||
$cawangan_info = Http::withOptions(['verify' => config('app.api_verify')])
|
||||
->get($api_url . '/api/cawangan/' . $kodcaw)->json();
|
||||
$pembiayaanOnlineEnabled = !empty(($cawangan_info['features'] ?? [])['pembiayaan_online']);
|
||||
|
||||
return view('print.sag_ujrah_3', compact('komoditi', 'product', 'kuantiti', 'gadai_detail', 'customer_detail', 'marhun_detail', 'cawangan_detail', 'api_url', 'pembayaran_segera', 'auth_username', 'mutu', 'kadar_ujrah', 'kakitangan'))->with('pembiayaanOnlineEnabled', $pembiayaanOnlineEnabled);
|
||||
} else {
|
||||
return view('print.sag', compact('gadai_detail', 'customer_detail', 'marhun_detail', 'cawangan_detail', 'api_url', 'pembayaran_segera', 'auth_username', 'mutu', 'kakitangan'));
|
||||
}
|
||||
|
||||
@@ -156,7 +156,6 @@ class PembiayaanOnlineController extends Controller
|
||||
'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,
|
||||
];
|
||||
@@ -174,6 +173,19 @@ class PembiayaanOnlineController extends Controller
|
||||
$payload['bukti_akaun_type'] = $file->getMimeType() ?: 'application/octet-stream';
|
||||
}
|
||||
|
||||
if ($request->hasFile('borang')) {
|
||||
$file = $request->file('borang');
|
||||
if (!$file->isValid()) {
|
||||
return redirect()->back()->with('error', 'Fail borang pengesahan tidak sah.');
|
||||
}
|
||||
if ($file->getSize() > 4 * 1024 * 1024) {
|
||||
return redirect()->back()->with('error', 'Saiz fail maksimum 4MB.');
|
||||
}
|
||||
$payload['borang_data'] = base64_encode(file_get_contents($file->getRealPath()));
|
||||
$payload['borang_filename'] = $file->getClientOriginalName();
|
||||
$payload['borang_type'] = $file->getMimeType() ?: 'application/octet-stream';
|
||||
}
|
||||
|
||||
$res = $this->api()
|
||||
->asForm()
|
||||
->put($api_url . '/api/pembiayaan-online/' . $kodcaw . '/lines/' . $id, $payload);
|
||||
@@ -394,6 +406,22 @@ class PembiayaanOnlineController extends Controller
|
||||
return $this->streamBase64File($file, 'slip-bank-' . $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* PC: view uploaded Borang Pengesahan Penerimaan Pembiayaan Secara Atas Talian.
|
||||
*/
|
||||
public function viewBorang($id)
|
||||
{
|
||||
$this->abortUnlessPembiayaanOnline();
|
||||
return $this->streamLineFile(
|
||||
$this->kodcaw(),
|
||||
$id,
|
||||
'/borang',
|
||||
'Borang pengesahan tidak dijumpai.',
|
||||
'Fail borang pengesahan kosong.',
|
||||
'borang-pengesahan-' . $id
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* PC: view SAG for a queue line (does not mark SAG as printed).
|
||||
*/
|
||||
@@ -426,6 +454,21 @@ class PembiayaanOnlineController extends Controller
|
||||
return $this->streamBase64File($file, 'slip-bank-' . $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Operasi: view uploaded Borang Pengesahan Penerimaan Pembiayaan Secara Atas Talian.
|
||||
*/
|
||||
public function operasiViewBorang($kodcaw, $id)
|
||||
{
|
||||
return $this->streamLineFile(
|
||||
$kodcaw,
|
||||
$id,
|
||||
'/borang',
|
||||
'Borang pengesahan tidak dijumpai.',
|
||||
'Fail borang pengesahan kosong.',
|
||||
'borang-pengesahan-' . $id
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Operasi: view SAG for a batch line.
|
||||
*/
|
||||
@@ -434,6 +477,26 @@ class PembiayaanOnlineController extends Controller
|
||||
return $this->renderLineSag($kodcaw, $id);
|
||||
}
|
||||
|
||||
protected function streamLineFile($kodcaw, $id, $path, $missingMessage, $emptyMessage, $fallbackName)
|
||||
{
|
||||
$res = $this->api()
|
||||
->get(config('api.url') . '/api/pembiayaan-online/' . $kodcaw . '/lines/' . $id . $path);
|
||||
|
||||
if (!$res->successful()) {
|
||||
$body = $res->json();
|
||||
$msg = is_array($body) && isset($body['message']) ? $body['message'] : $missingMessage;
|
||||
return redirect()->back()->with('error', $msg);
|
||||
}
|
||||
|
||||
$payload = $res->json();
|
||||
$file = $payload['file'] ?? null;
|
||||
if (!$file || empty($file['data'])) {
|
||||
return redirect()->back()->with('error', $emptyMessage);
|
||||
}
|
||||
|
||||
return $this->streamBase64File($file, $fallbackName);
|
||||
}
|
||||
|
||||
protected function streamBase64File(array $file, $fallbackName)
|
||||
{
|
||||
$raw = $file['data'];
|
||||
@@ -522,6 +585,12 @@ class PembiayaanOnlineController extends Controller
|
||||
|
||||
$pembayaran_segera = 'https://pay.arrahn.com.my';
|
||||
|
||||
$shorakaPrint = app(\App\Services\ShorakaFinancingService::class)->printData($gadai_detail['norujukan']);
|
||||
if ($shorakaPrint) {
|
||||
$komoditi = $shorakaPrint['komoditi'];
|
||||
$product = $shorakaPrint['product'];
|
||||
$kuantiti = $shorakaPrint['kuantiti'];
|
||||
} else {
|
||||
$komoditi = $this->api()->get($api_url . '/api/komuditi/check')->json();
|
||||
$product = $this->api()
|
||||
->get($api_url . '/api/komuditi/description', [
|
||||
@@ -531,8 +600,13 @@ class PembiayaanOnlineController extends Controller
|
||||
|
||||
$nilai = is_array($komoditi) ? (float) ($komoditi['nilai'] ?? 0) : 0;
|
||||
$kuantiti = $nilai > 0 ? ((float) ($gadai_detail['pinjaman'] ?? 0) / $nilai) : 0;
|
||||
}
|
||||
|
||||
if (($gadai_detail['tagbaru'] ?? 0) == 1) {
|
||||
$cawangan_info = $this->api()
|
||||
->get($api_url . '/api/cawangan/' . $kodcaw)->json();
|
||||
$pembiayaanOnlineEnabled = !empty(($cawangan_info['features'] ?? [])['pembiayaan_online']);
|
||||
|
||||
return view('print.sag_ujrah_3', compact(
|
||||
'komoditi',
|
||||
'product',
|
||||
@@ -547,7 +621,7 @@ class PembiayaanOnlineController extends Controller
|
||||
'mutu',
|
||||
'kadar_ujrah',
|
||||
'kakitangan'
|
||||
));
|
||||
))->with('pembiayaanOnlineEnabled', $pembiayaanOnlineEnabled);
|
||||
}
|
||||
|
||||
return view('print.sag', compact(
|
||||
|
||||
@@ -271,6 +271,7 @@ class PenebusanController extends Controller
|
||||
|
||||
public function tambahpinjaman(Request $request)
|
||||
{
|
||||
app(\App\Services\ShorakaFinancingService::class)->ensureReady();
|
||||
$api_url = config('api.url');
|
||||
$current = Carbon::now();
|
||||
$current = new Carbon();
|
||||
@@ -405,33 +406,16 @@ class PenebusanController extends Controller
|
||||
'upah12' => $keuntungan12bulan,
|
||||
'hargajualan' => $hargajualan,
|
||||
'kuantiti_marhun' => $request->kuantiti_marhun
|
||||
])->json();
|
||||
|
||||
$komuditi = Http::withOptions(['verify' => config('app.api_verify')])->put(config('api.url').'/api/komuditi/transaksi',[
|
||||
'unit_komuditi' => round($request->pinjaman, 2),
|
||||
'norujukan' => $norujukanbaru,
|
||||
'kodcaw' => $auth_user['cawangan'],
|
||||
'teller' => $auth_user['name']
|
||||
]);
|
||||
|
||||
////////////////////////////
|
||||
////Update History Gadaian///
|
||||
////////////////////////////
|
||||
|
||||
$updatehistorygadaian = Http::withOptions(['verify' => config('app.api_verify')])->put(config('api.url').'/api/gadai/updatehistory/'. $auth_user['cawangan'] .'/' . $norujukanbaru,[
|
||||
'historygadaian' => $request->norujukan,
|
||||
'jenistebus' => $request->jenistebus,
|
||||
])->json();
|
||||
|
||||
|
||||
event(new TebusNotify('lulus',Auth::user()->cawangan));
|
||||
event(new GadaiNotify('lulus',Auth::user()->cawangan));
|
||||
$this->AliranTunaiController->alirantunaiTebus($request);
|
||||
])->throw()->json();
|
||||
|
||||
return app(\App\Services\ShorakaFinancingService::class)->hold(
|
||||
$request, $norujukanbaru, 'refinance', ['update_history' => true]
|
||||
);
|
||||
}
|
||||
|
||||
public function tambahpinjaman_latest(Request $request)
|
||||
{
|
||||
app(\App\Services\ShorakaFinancingService::class)->ensureReady();
|
||||
$api_url = config('api.url');
|
||||
$current = Carbon::now();
|
||||
$current = new Carbon();
|
||||
@@ -475,17 +459,18 @@ class PenebusanController extends Controller
|
||||
])->json();
|
||||
|
||||
|
||||
if($updatetebus['result'] == 'success'){
|
||||
event(new TebusNotify('lulus',Auth::user()->cawangan));
|
||||
event(new GadaiNotify('lulus',Auth::user()->cawangan));
|
||||
$this->AliranTunaiController->alirantunaiTebus($request);
|
||||
if (($updatetebus['result'] ?? null) === 'success') {
|
||||
abort_unless(!empty($updatetebus['norujukan_baru']), 502, 'Rujukan gadaian baharu tidak diterima.');
|
||||
return app(\App\Services\ShorakaFinancingService::class)->hold(
|
||||
$request, $updatetebus['norujukan_baru'], 'refinance'
|
||||
);
|
||||
}
|
||||
return response()->json($updatetebus['result'],200);
|
||||
|
||||
return response()->json($updatetebus['result'] ?? 'error', 200);
|
||||
}
|
||||
|
||||
public function tebusautotawarruq(Request $request)
|
||||
{
|
||||
app(\App\Services\ShorakaFinancingService::class)->ensureReady();
|
||||
$auth_user = Auth::user();
|
||||
|
||||
////////////////////////
|
||||
@@ -515,17 +500,18 @@ class PenebusanController extends Controller
|
||||
"noic" => $request->noic,
|
||||
"jenisAT" => $request->jenisAT,
|
||||
])->json();
|
||||
if($updatetebus['result'] == 'success'){
|
||||
$alirantunai = new AliranTunaiController();
|
||||
event(new TebusNotify('lulus',Auth::user()->cawangan));
|
||||
event(new GadaiNotify('lulus',Auth::user()->cawangan));
|
||||
$alirantunai->alirantunaiTebusAutoTawarruq($request);
|
||||
if (($updatetebus['result'] ?? null) === 'success') {
|
||||
abort_unless(!empty($updatetebus['norujukan_baru']), 502, 'Rujukan gadaian baharu tidak diterima.');
|
||||
return app(\App\Services\ShorakaFinancingService::class)->hold(
|
||||
$request, $updatetebus['norujukan_baru'], 'autotawarruq'
|
||||
);
|
||||
}
|
||||
return response()->json($updatetebus['result'],200);
|
||||
return response()->json($updatetebus['result'] ?? 'error', 200);
|
||||
}
|
||||
|
||||
public function tebusseparuh(Request $request)
|
||||
{
|
||||
app(\App\Services\ShorakaFinancingService::class)->ensureReady();
|
||||
$api_url = config('api.url');
|
||||
$current = Carbon::now();
|
||||
$current = new Carbon();
|
||||
@@ -666,39 +652,13 @@ class PenebusanController extends Controller
|
||||
'upah12' => $keuntungan12bulan,
|
||||
'hargajualan' => $hargajualan,
|
||||
'kuantiti_marhun' => $request->kuantiti_marhun
|
||||
])->json();
|
||||
])->throw()->json();
|
||||
|
||||
$komuditi = Http::withOptions(['verify' => config('app.api_verify')])->put(config('api.url').'/api/komuditi/transaksi',[
|
||||
'unit_komuditi' => round($request->pinjaman, 2),
|
||||
'norujukan' => $norujukanbaru,
|
||||
'kodcaw' => $auth_user['cawangan'],
|
||||
'teller' => $auth_user['name']
|
||||
]);
|
||||
|
||||
////////////////////////////
|
||||
////Update History Gadaian///
|
||||
////////////////////////////
|
||||
|
||||
$updatehistorygadaian = Http::withOptions(['verify' => config('app.api_verify')])->put(config('api.url').'/api/gadai/updatehistory/'. $auth_user['cawangan'] .'/' . $norujukanbaru,[
|
||||
'historygadaian' => $request->norujukan,
|
||||
'jenistebus' => $request->jenistebus,
|
||||
])->json();
|
||||
|
||||
|
||||
$alirantunai = new AliranTunaiController();
|
||||
event(new TebusNotify('lulus',Auth::user()->cawangan));
|
||||
event(new GadaiNotify('lulus',Auth::user()->cawangan));
|
||||
|
||||
$alirantunai->alirantunaiTebus($request);
|
||||
|
||||
|
||||
return response()->json($updatemarhun,200);
|
||||
|
||||
return app(\App\Services\ShorakaFinancingService::class)->hold(
|
||||
$request, $norujukanbaru, 'refinance', ['update_history' => true]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
//Wakil Function
|
||||
|
||||
public function getfirstWakil()
|
||||
{
|
||||
$auth_user = Auth::user();
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Services\ShorakaFinancingService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Throwable;
|
||||
|
||||
class ShorakaController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$records = app(ShorakaFinancingService::class)->listForBranch(Auth::user()->cawangan);
|
||||
$cawangan_info = ['details_caw' => Auth::user()->cawangan, 'kodcaw' => Auth::user()->cawangan];
|
||||
return view('shoraka.index', compact('records', 'cawangan_info'));
|
||||
}
|
||||
|
||||
public function operasiIndex(Request $request)
|
||||
{
|
||||
abort_unless(in_array(Auth::user()->roles, ['operasi', 'pc', 'ppc'], true), 403);
|
||||
$isOperasi = Auth::user()->roles === 'operasi';
|
||||
$filters = $request->validate([
|
||||
'kodcaw' => 'nullable|string|max:30',
|
||||
'norujukan' => 'nullable|string|max:100',
|
||||
'status' => 'nullable|in:PENDING,Active,Completed,Cancelled,UNKNOWN,FAILED',
|
||||
'date_from' => 'nullable|date_format:Y-m-d',
|
||||
'date_to' => 'nullable|date_format:Y-m-d' . ($request->filled('date_from') ? '|after_or_equal:date_from' : ''),
|
||||
]);
|
||||
[$records, $branches] = app(ShorakaFinancingService::class)->search(
|
||||
$filters,
|
||||
$isOperasi ? null : Auth::user()->cawangan
|
||||
);
|
||||
$cawangan_info = ['details_caw' => Auth::user()->cawangan, 'kodcaw' => Auth::user()->cawangan];
|
||||
return view('shoraka.operasi', compact('records', 'branches', 'filters', 'isOperasi', 'cawangan_info'));
|
||||
}
|
||||
|
||||
public function pcIndex(Request $request)
|
||||
{
|
||||
abort_unless(in_array(Auth::user()->roles, ['pc', 'ppc'], true), 403);
|
||||
return $this->operasiIndex($request);
|
||||
}
|
||||
|
||||
public function show(string $norujukan, ShorakaFinancingService $service)
|
||||
{
|
||||
$data = null;
|
||||
$error = null;
|
||||
try {
|
||||
$data = $service->snapshot($norujukan);
|
||||
} catch (Throwable $exception) {
|
||||
$error = 'Maklumat Shoraka tidak dapat diambil. Bayaran dan SAG masih ditahan.';
|
||||
}
|
||||
$cawangan_info = ['details_caw' => Auth::user()->cawangan, 'kodcaw' => Auth::user()->cawangan];
|
||||
return view('shoraka.show', compact('norujukan', 'data', 'error', 'cawangan_info'));
|
||||
}
|
||||
|
||||
public function certificate(string $norujukan, ShorakaFinancingService $service)
|
||||
{
|
||||
$response = $service->api()->get($service->url($norujukan, '/certificate'))->throw();
|
||||
abort_unless(substr($response->body(), 0, 5) === '%PDF-', 502);
|
||||
return response($response->body(), 200, [
|
||||
'Content-Type' => 'application/pdf',
|
||||
'Content-Disposition' => 'attachment; filename="sijil-shoraka.pdf"',
|
||||
'Cache-Control' => 'private, no-store',
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
|
||||
class LogViewerPassword
|
||||
{
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
$passwordHash = config('logviewer.password');
|
||||
|
||||
if (!is_string($passwordHash) || $passwordHash === '') {
|
||||
return response('Akses log belum dikonfigurasi.', 503)
|
||||
->header('Cache-Control', 'no-store');
|
||||
}
|
||||
|
||||
$provided = $request->getPassword();
|
||||
if ($request->getUser() !== 'logviewer' || !is_string($provided) ||
|
||||
!password_verify($provided, $passwordHash)) {
|
||||
return response('Kata laluan diperlukan untuk mengakses log.', 401, [
|
||||
'WWW-Authenticate' => 'Basic realm="Log Viewer", charset="UTF-8"',
|
||||
'Cache-Control' => 'no-store',
|
||||
]);
|
||||
}
|
||||
|
||||
$response = $next($request);
|
||||
$response->headers->set('Cache-Control', 'no-store');
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
@@ -44,6 +44,12 @@ class RoleAccess
|
||||
return $next($request);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'masteradmin':
|
||||
if ($userRole == 'masteradmin') {
|
||||
return $next($request);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'penilai':
|
||||
if ($userRole == 'penilai') {
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Http\Controllers\GadaianController;
|
||||
use App\Http\Controllers\AliranTunaiController;
|
||||
use App\Events\Dashboard\GadaiNotify;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Throwable;
|
||||
|
||||
class ShorakaFinancingService
|
||||
{
|
||||
public function ensureReady(): void
|
||||
{
|
||||
$response = $this->api()->get(rtrim(config('api.url'), '/') . '/api/shoraka/readiness')->throw()->json();
|
||||
abort_unless(!empty($response['ready']), 503, 'Shoraka belum dikonfigurasi. Pembiayaan baharu ditahan.');
|
||||
}
|
||||
|
||||
public function api()
|
||||
{
|
||||
return Http::withOptions(['verify' => config('app.api_verify')])
|
||||
->acceptJson()->timeout(75);
|
||||
}
|
||||
|
||||
public function url(string $reference, string $suffix = ''): string
|
||||
{
|
||||
return rtrim(config('api.url'), '/') . '/api/shoraka/gadai/'
|
||||
. rawurlencode(Auth::user()->cawangan) . '/' . rawurlencode($reference) . $suffix;
|
||||
}
|
||||
|
||||
public function hasOrder(string $reference): bool
|
||||
{
|
||||
$snapshot = $this->snapshot($reference);
|
||||
return !empty($snapshot['order']);
|
||||
}
|
||||
|
||||
public function snapshot(string $reference): array
|
||||
{
|
||||
$response = $this->api()->get($this->url($reference));
|
||||
if ($response->status() === 404) {
|
||||
return [];
|
||||
}
|
||||
if ($response->serverError()) {
|
||||
abort(503, 'Shoraka belum dikonfigurasi. Pembiayaan baharu ditahan.');
|
||||
}
|
||||
$response->throw();
|
||||
return $response->json()['data'] ?? [];
|
||||
}
|
||||
|
||||
public function listForBranch(string $branch)
|
||||
{
|
||||
$response = $this->api()->get(rtrim(config('api.url'), '/') . '/api/shoraka/transactions', [
|
||||
'kodcaw' => $branch,
|
||||
'per_page' => 100,
|
||||
])->throw()->json();
|
||||
return collect($response['data'] ?? []);
|
||||
}
|
||||
|
||||
public function search(array $filters, ?string $onlyBranch): array
|
||||
{
|
||||
$query = [
|
||||
'per_page' => 25,
|
||||
'page' => max(1, (int) request()->input('page', 1)),
|
||||
'with_branches' => 1,
|
||||
];
|
||||
if ($onlyBranch) {
|
||||
$query['kodcaw'] = $onlyBranch;
|
||||
$query['branch_scope'] = $onlyBranch;
|
||||
} elseif (!empty($filters['kodcaw'])) {
|
||||
$query['kodcaw'] = $filters['kodcaw'];
|
||||
}
|
||||
foreach (['norujukan', 'status', 'date_from', 'date_to'] as $field) {
|
||||
if (!empty($filters[$field])) {
|
||||
$query[$field] = $filters[$field];
|
||||
}
|
||||
}
|
||||
$response = $this->api()->get(rtrim(config('api.url'), '/') . '/api/shoraka/transactions', $query)->throw()->json();
|
||||
$items = collect($response['data'] ?? []);
|
||||
$records = new LengthAwarePaginator(
|
||||
$items,
|
||||
(int) ($response['total'] ?? 0),
|
||||
(int) ($response['per_page'] ?? 25),
|
||||
(int) ($response['current_page'] ?? 1),
|
||||
['path' => request()->url(), 'query' => request()->query()]
|
||||
);
|
||||
return [$records, collect($response['branches'] ?? [])];
|
||||
}
|
||||
|
||||
public function hold(Request $request, string $reference, string $action, array $extra = [])
|
||||
{
|
||||
if ($this->hasOrder($reference)) {
|
||||
return $this->failed($request, 'Order Shoraka telah dihantar. Jangan hantar semula.');
|
||||
}
|
||||
|
||||
$context = array_merge($request->except(['_token', 'password']), $extra, ['action' => $action]);
|
||||
try {
|
||||
$response = $this->api()->post($this->url($reference, '/submit'), [
|
||||
'teller' => Auth::user()->name,
|
||||
]);
|
||||
} catch (Throwable $exception) {
|
||||
if ($this->hasOrder($reference)) {
|
||||
return $this->failed($request, 'Order Shoraka telah dihantar. Jangan hantar semula.');
|
||||
}
|
||||
return $this->failed($request, 'Order Shoraka tidak berjaya dihantar. Gadaian tidak dihantar.');
|
||||
}
|
||||
|
||||
if (!$response->successful()) {
|
||||
$message = $response->json()['message'] ?? ($this->hasOrder($reference)
|
||||
? 'Order Shoraka telah dihantar. Jangan hantar semula.'
|
||||
: 'Order Shoraka tidak berjaya dihantar. Gadaian tidak dihantar.');
|
||||
return $this->failed($request, $message);
|
||||
}
|
||||
|
||||
$snapshot = $this->waitUntilCompleted($reference);
|
||||
$status = $snapshot['order']['status'] ?? null;
|
||||
if ($status !== 'Completed') {
|
||||
return $this->failed($request, 'Pengesahan Shoraka belum Completed. Jangan hantar semula.');
|
||||
}
|
||||
if (empty($snapshot['can_complete'])
|
||||
|| (array_key_exists('pinjaman', $context)
|
||||
&& number_format((float) $context['pinjaman'], 2, '.', '')
|
||||
!== number_format((float) ($snapshot['order_amount'] ?? 0), 2, '.', ''))) {
|
||||
return $this->failed($request, 'Amaun pembiayaan berubah. Bayaran tidak diproses.');
|
||||
}
|
||||
|
||||
return $this->complete($request, $reference, $context);
|
||||
}
|
||||
|
||||
private function waitUntilCompleted(string $reference): array
|
||||
{
|
||||
set_time_limit(150);
|
||||
$deadline = microtime(true) + 120;
|
||||
$snapshot = [];
|
||||
do {
|
||||
try {
|
||||
$this->api()->post($this->url($reference, '/refresh'))->throw();
|
||||
$snapshot = $this->snapshot($reference);
|
||||
} catch (Throwable $exception) {
|
||||
$snapshot = [];
|
||||
}
|
||||
$status = $snapshot['order']['status'] ?? null;
|
||||
if ($status === 'Completed' || in_array($status, ['Cancelled', 'FAILED', 'UNKNOWN'], true)) {
|
||||
return $snapshot;
|
||||
}
|
||||
if (microtime(true) >= $deadline) {
|
||||
return $snapshot;
|
||||
}
|
||||
sleep(2);
|
||||
} while (true);
|
||||
}
|
||||
|
||||
private function complete(Request $request, string $reference, array $context)
|
||||
{
|
||||
$branch = Auth::user()->cawangan;
|
||||
$saved = new Request($context);
|
||||
$saved->setLaravelSession($request->session());
|
||||
if (($context['action'] ?? null) === 'gadai') {
|
||||
return app(GadaianController::class)->completeShorakaFinancing($saved);
|
||||
}
|
||||
if (!empty($context['update_history'])) {
|
||||
$this->api()->put(rtrim(config('api.url'), '/') . '/api/gadai/updatehistory/'
|
||||
. rawurlencode($branch) . '/' . rawurlencode($reference), [
|
||||
'historygadaian' => $saved->norujukan,
|
||||
'jenistebus' => $saved->jenistebus,
|
||||
])->throw();
|
||||
}
|
||||
$cash = app(AliranTunaiController::class);
|
||||
if (($context['action'] ?? null) === 'autotawarruq') {
|
||||
$cash->alirantunaiTebusAutoTawarruq($saved);
|
||||
} else {
|
||||
$cash->alirantunaiTebus($saved);
|
||||
}
|
||||
event(new \App\Events\Dashboard\TebusNotify('lulus', $branch));
|
||||
event(new GadaiNotify('lulus', $branch));
|
||||
return redirect()->route('customer_info');
|
||||
}
|
||||
|
||||
public function printData(string $reference): ?array
|
||||
{
|
||||
$response = $this->api()->get($this->url($reference))->throw()->json()['data'];
|
||||
$order = $response['order'] ?? null;
|
||||
if (!$order) {
|
||||
return null;
|
||||
}
|
||||
abort_unless(!empty($response['can_complete']), 409, 'SAG ditahan: Shoraka belum Completed.');
|
||||
$details = $response['details'] ?? [];
|
||||
$certificateDetails = $details['certificateDetails1'] ?? '';
|
||||
if (is_array($certificateDetails)) {
|
||||
$certificateDetails = $certificateDetails[0] ?? '';
|
||||
}
|
||||
$certificate = is_string($certificateDetails) ? trim(explode('|', $certificateDetails)[0]) : '';
|
||||
abort_unless($certificate !== '' && isset($details['unit'], $details['volume'], $details['commodityType']),
|
||||
409, 'Maklumat sijil belum lengkap. Semak status Shoraka dahulu.');
|
||||
return [
|
||||
'komoditi' => ['no_sijil' => $certificate],
|
||||
'product' => [
|
||||
'kodproduk' => $details['commodityType'],
|
||||
'description' => $details['commodityType'] === '000-COPPER' ? 'Copper' : 'Plastic resin',
|
||||
'unit' => $details['unit'],
|
||||
],
|
||||
'kuantiti' => $details['volume'],
|
||||
];
|
||||
}
|
||||
|
||||
private function failed(Request $request, string $message)
|
||||
{
|
||||
if ($request->ajax() || $request->expectsJson()) {
|
||||
abort(502, $message);
|
||||
}
|
||||
return redirect()->back()->with('error', $message);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -2,13 +2,13 @@
|
||||
|
||||
if (!function_exists('api_url_for_browser')) {
|
||||
/**
|
||||
* Base URL for JavaScript in the browser, derived from API_URL (config api.url).
|
||||
* Base URL for JavaScript, using API_BROWSER_URL when configured.
|
||||
* Docker dev often uses host.docker.internal for PHP→host; browsers may not resolve it.
|
||||
* Same host-mapped port is reachable at 127.0.0.1. Production URLs are unchanged.
|
||||
*/
|
||||
function api_url_for_browser(): string
|
||||
{
|
||||
$url = rtrim((string) config('api.url'), '/');
|
||||
$url = rtrim((string) (config('api.browser_url') ?: config('api.url')), '/');
|
||||
|
||||
return str_ireplace('host.docker.internal', '127.0.0.1', $url);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
return [
|
||||
'url' => env('API_URL'),
|
||||
'browser_url' => env('API_BROWSER_URL'),
|
||||
'url_koop' => env('API_URL_KOOP','https://apiujrah.erahn.com.my'),
|
||||
'url_pkb' => env('API_URL_PKB','http://localhost:8000'),
|
||||
];
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'password' => env('LOGVIEWER_PASSWORD'),
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Pattern and storage path settings
|
||||
|
||||
+3
-10
@@ -5,6 +5,8 @@ services:
|
||||
dockerfile: docker/php/Dockerfile
|
||||
target: development
|
||||
working_dir: /var/www/html
|
||||
ports:
|
||||
- "8081:8000"
|
||||
volumes:
|
||||
- ./:/var/www/html:cached
|
||||
environment:
|
||||
@@ -15,16 +17,7 @@ services:
|
||||
- "host.docker.internal:host-gateway"
|
||||
depends_on:
|
||||
- mysql
|
||||
|
||||
web:
|
||||
image: nginx:1.25-alpine
|
||||
ports:
|
||||
- "8081:80"
|
||||
volumes:
|
||||
- ./:/var/www/html:cached
|
||||
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
depends_on:
|
||||
- app
|
||||
command: ["php", "artisan", "serve", "--host=0.0.0.0", "--port=8000"]
|
||||
|
||||
mysql:
|
||||
image: mysql:8.0
|
||||
|
||||
+11
-2
@@ -2,7 +2,14 @@ FROM php:7.4-fpm AS base
|
||||
|
||||
WORKDIR /var/www/html
|
||||
|
||||
RUN apt-get update \
|
||||
# PHP 7.4 uses Debian Bullseye; use its archived package repositories.
|
||||
# Archived security metadata expires, but package signatures remain verified.
|
||||
RUN printf '%s\n' \
|
||||
'deb https://archive.debian.org/debian bullseye main' \
|
||||
'deb [check-valid-until=no] https://archive.debian.org/debian-security bullseye-security main' \
|
||||
> /etc/apt/sources.list \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& apt-get -o Acquire::Retries=3 update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
git \
|
||||
pkg-config \
|
||||
@@ -28,7 +35,9 @@ COPY docker/php/php.ini /usr/local/etc/php/conf.d/app.ini
|
||||
COPY docker/php/zz-clear-env.conf /usr/local/etc/php-fpm.d/zz-clear-env.conf
|
||||
COPY docker/php/entrypoint.sh /usr/local/bin/app-entrypoint.sh
|
||||
|
||||
RUN chmod +x /usr/local/bin/app-entrypoint.sh \
|
||||
# Normalize Windows checkout line endings before executing the script.
|
||||
RUN sed -i 's/\r$//' /usr/local/bin/app-entrypoint.sh \
|
||||
&& chmod +x /usr/local/bin/app-entrypoint.sh \
|
||||
&& usermod -u 1000 www-data && groupmod -g 1000 www-data
|
||||
|
||||
ENTRYPOINT ["app-entrypoint.sh"]
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
APP_NAME=Laravel
|
||||
APP_ENV=local
|
||||
APP_KEY=base64:FFRogE6mJj8FaDSSHl/KpXpzqi2M+P4plxVSRgVM8JI=
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://kaunterv2.localhost
|
||||
API_URL=http://apiv2.localhost
|
||||
API_ARRAHNBID=http://lelong.localhost/api/
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=database_zone2
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=kaunterpkb
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=secret
|
||||
|
||||
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
|
||||
@@ -1,50 +0,0 @@
|
||||
APP_NAME=Laravel
|
||||
APP_ENV=local
|
||||
APP_KEY=base64:FFRogE6mJj8FaDSSHl/KpXpzqi2M+P4plxVSRgVM8JI=
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://kaunterv2.localhost
|
||||
API_URL=http://apiv2.kgmk.localhost
|
||||
API_ARRAHNBID=http://lelong.localhost/api/
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=database_zone_franchise
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=kaunter_koopguru
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=secret
|
||||
|
||||
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
|
||||
@@ -1,50 +0,0 @@
|
||||
APP_NAME=Laravel
|
||||
APP_ENV=local
|
||||
APP_KEY=base64:FFRogE6mJj8FaDSSHl/KpXpzqi2M+P4plxVSRgVM8JI=
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://kaunterv2.localhost
|
||||
API_URL=http://apiv2.krk.localhost
|
||||
API_ARRAHNBID=http://lelong.localhost/api/
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=database_zone_franchise
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=kaunter_krk
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=secret
|
||||
|
||||
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
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 166 KiB |
@@ -115,6 +115,9 @@
|
||||
</form>
|
||||
</div>
|
||||
<div class="card-footer text-center pt-0 px-lg-2 px-1">
|
||||
<p class="mb-3 text-sm">
|
||||
<a href="{{ route('dasar.privasi') }}" class="text-info font-weight-bold">Dasar Privasi</a>
|
||||
</p>
|
||||
<p class="mb-4 text-sm mx-auto">
|
||||
Masalah untuk log masuk?
|
||||
<a class="text-info text-gradient font-weight-bold">Hubungi
|
||||
|
||||
@@ -2814,25 +2814,25 @@
|
||||
|
||||
$.ajax({
|
||||
method:'get',
|
||||
url: api + '/api/komuditi/check',
|
||||
url: api + '/api/shoraka/readiness',
|
||||
success:function(komoditi){
|
||||
var check_komuditi = Object.keys(komoditi).length;
|
||||
if(check_komuditi == 0){
|
||||
if (!komoditi.ready){
|
||||
$("#terima_transaksi").prop('disabled', false);
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Unit Komuditi Berbaki Minumum',
|
||||
text: 'Sila Hubungi Operasi Untuk Membuat Pembelian Komuditi'
|
||||
title: 'Shoraka Belum Tersedia',
|
||||
text: 'Sila hubungi operasi untuk semakan sambungan Shoraka.'
|
||||
});
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}else{
|
||||
if(Number(komoditi['unit_komuditi']) < pinjaman_baru){
|
||||
if (!komoditi.ready){
|
||||
$("#terima_transaksi").prop('disabled', false);
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Baki Unit Komuditi Tidak Mencukupi',
|
||||
text: 'Sila Hubungi Operasi Untuk Membuat Pembelian Komuditi'
|
||||
title: 'Shoraka Belum Tersedia',
|
||||
text: 'Sila hubungi operasi untuk semakan sambungan Shoraka.'
|
||||
});
|
||||
event.preventDefault();
|
||||
return false;
|
||||
|
||||
@@ -461,25 +461,25 @@
|
||||
}else{
|
||||
$.ajax({
|
||||
method:'get',
|
||||
url: api_url + '/api/komuditi/check',
|
||||
url: api_url + '/api/shoraka/readiness',
|
||||
success:function(data){
|
||||
var check_komuditi = Object.keys(data).length;
|
||||
if(check_komuditi == 0){
|
||||
if (!data.ready){
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Unit Komoditi Berbaki Minima',
|
||||
text: 'Sila Hubungi Operasi Untuk Membuat Pembelian Komoditi'
|
||||
title: 'Shoraka Belum Tersedia',
|
||||
text: 'Sila hubungi operasi untuk semakan sambungan Shoraka.'
|
||||
});
|
||||
$("#daftar_gadai").prop('disabled', false);
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}else{
|
||||
if(Number(data['unit_komuditi']) <= min_komoditi){
|
||||
if (!data.ready){
|
||||
$("#daftar_gadai").prop('disabled', false);
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Unit Komoditi Berbaki Minima',
|
||||
text: 'Sila Hubungi Operasi Untuk Membuat Pembelian Komoditi'
|
||||
title: 'Shoraka Belum Tersedia',
|
||||
text: 'Sila hubungi operasi untuk semakan sambungan Shoraka.'
|
||||
});
|
||||
event.preventDefault();
|
||||
return false;
|
||||
|
||||
@@ -758,25 +758,25 @@
|
||||
} else {
|
||||
$.ajax({
|
||||
method: 'get',
|
||||
url: api_url + '/api/komuditi/check',
|
||||
url: api_url + '/api/shoraka/readiness',
|
||||
success: function(data) {
|
||||
var check_komuditi = Object.keys(data).length;
|
||||
if (check_komuditi == 0) {
|
||||
if (!data.ready) {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Unit Komoditi Berbaki Minima',
|
||||
text: 'Sila Hubungi Operasi Untuk Membuat Pembelian Komoditi'
|
||||
title: 'Shoraka Belum Tersedia',
|
||||
text: 'Sila hubungi operasi untuk semakan sambungan Shoraka.'
|
||||
});
|
||||
$("#daftar_gadai").prop('disabled', false);
|
||||
event.preventDefault();
|
||||
return false;
|
||||
} else {
|
||||
if (Number(data['unit_komuditi']) <= min_komoditi) {
|
||||
if (!data.ready) {
|
||||
$("#daftar_gadai").prop('disabled', false);
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Unit Komoditi Berbaki Minima',
|
||||
text: 'Sila Hubungi Operasi Untuk Membuat Pembelian Komoditi'
|
||||
title: 'Shoraka Belum Tersedia',
|
||||
text: 'Sila hubungi operasi untuk semakan sambungan Shoraka.'
|
||||
});
|
||||
event.preventDefault();
|
||||
return false;
|
||||
@@ -801,9 +801,12 @@
|
||||
}
|
||||
});
|
||||
|
||||
var pembiayaanOnlineEnabled = @json(!empty(($cawangan_info['features'] ?? [])['pembiayaan_online']));
|
||||
|
||||
var tablegadai = initErahnDatatable('#myTable', {
|
||||
order: [[1, 'desc']],
|
||||
columnDefs: [
|
||||
{ targets: 2, visible: pembiayaanOnlineEnabled, className: pembiayaanOnlineEnabled ? '' : 'no-export' },
|
||||
{ targets: 0, orderable: false, width: '40px' },
|
||||
{ targets: -1, orderable: false, searchable: false, width: '70px' }
|
||||
]
|
||||
@@ -811,6 +814,7 @@
|
||||
|
||||
var xtawarruq = initErahnDatatable('#xtawarruq', {
|
||||
columnDefs: [
|
||||
{ targets: 2, visible: pembiayaanOnlineEnabled, className: pembiayaanOnlineEnabled ? '' : 'no-export' },
|
||||
{ targets: 0, orderable: false, width: '40px' }
|
||||
]
|
||||
});
|
||||
@@ -2067,7 +2071,8 @@
|
||||
harini.setHours(0, 0, 0, 0);
|
||||
|
||||
if ($("input[name='options']:checked").val() == 'belum_tebus') {
|
||||
let test1 = $('input[name="belum"]:checked').closest('tr').children('td:eq(3)').text();
|
||||
let selectedRow = $('input[name="belum"]:checked').closest('tr');
|
||||
let test1 = selectedRow.length ? selectedRow.closest('table').DataTable().row(selectedRow).data()[3] : '';
|
||||
let tarikhgadai2 = new Date(test1);
|
||||
tarikhgadai2.setHours(0, 0, 0, 0);
|
||||
if (+harini !== +tarikhgadai2) {
|
||||
@@ -2080,7 +2085,7 @@
|
||||
}
|
||||
} else if ($("input[name='options']:checked").val() == 'sudah_tebus') {
|
||||
|
||||
let test = $('input[name="sudahtebus"]:checked').closest('tr').children('td:eq(3)').text();
|
||||
let test = $('input[name="sudahtebus"]:checked').closest('tr').children('td:eq(2)').text();
|
||||
let tarikhgadai1 = new Date(test);
|
||||
tarikhgadai1.setHours(0, 0, 0, 0);
|
||||
|
||||
@@ -2484,7 +2489,8 @@
|
||||
}
|
||||
|
||||
if ($("input[name='options']:checked").val() == 'belum_tebus') {
|
||||
let test1 = $('input[name="belum"]:checked').closest('tr').children('td:eq(3)').text();
|
||||
let selectedRow = $('input[name="belum"]:checked').closest('tr');
|
||||
let test1 = selectedRow.length ? selectedRow.closest('table').DataTable().row(selectedRow).data()[3] : '';
|
||||
let tarikhgadai2 = new Date(test1);
|
||||
tarikhgadai2.setHours(0, 0, 0, 0);
|
||||
|
||||
@@ -2669,7 +2675,7 @@
|
||||
// return false;
|
||||
|
||||
} else if ($("input[name='options']:checked").val() == 'sudah_tebus') {
|
||||
let test = $('input[name="sudahtebus"]:checked').closest('tr').children('td:eq(3)').text();
|
||||
let test = $('input[name="sudahtebus"]:checked').closest('tr').children('td:eq(2)').text();
|
||||
let tarikhgadai1 = new Date(test);
|
||||
tarikhgadai1.setHours(0, 0, 0, 0);
|
||||
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ms">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Dasar Privasi | Kaunter arOS</title>
|
||||
<link rel="icon" href="{{ asset('img/icon_pkb.png') }}">
|
||||
<link href="{{ asset('css/login-v2.css') }}" rel="stylesheet">
|
||||
<style>
|
||||
body { background: #f4f7fb; color: #344767; }
|
||||
.privacy-container { max-width: 900px; margin: 0 auto; padding: 32px 20px; }
|
||||
.privacy-brand { display: flex; align-items: center; gap: 16px; margin-bottom: 24px; }
|
||||
.privacy-brand img { width: 60px; height: auto; }
|
||||
.privacy-card { background: #fff; border-radius: 16px; padding: 40px; box-shadow: 0 8px 32px rgba(24, 49, 83, .08); }
|
||||
.privacy-card h1 { font-size: 2rem; }
|
||||
.privacy-card h2 { font-size: 1.2rem; margin-top: 28px; }
|
||||
.privacy-card p, .privacy-card li { line-height: 1.8; }
|
||||
.privacy-card ul { padding-left: 24px; }
|
||||
.privacy-back { display: inline-block; margin-top: 24px; color: #075985; text-decoration: underline; }
|
||||
a:focus-visible { outline: 3px solid #075985; outline-offset: 4px; }
|
||||
@media (max-width: 576px) {
|
||||
.privacy-container { padding: 20px 16px; }
|
||||
.privacy-card { padding: 24px 20px; }
|
||||
.privacy-card h1 { font-size: 1.7rem; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main class="privacy-container">
|
||||
<div class="privacy-brand">
|
||||
<img src="{{ asset('img/icon_pkb.png') }}" alt="Logo ar-Rahnu">
|
||||
<span class="font-weight-bold">Kaunter arOS · ar-rahn Online System</span>
|
||||
</div>
|
||||
<article class="privacy-card" aria-labelledby="privacy-title">
|
||||
<h1 id="privacy-title">Dasar Privasi</h1>
|
||||
<p class="text-sm text-muted">Versi dasar: 1.0 · Tarikh kemas kini: <time datetime="2026-09-27">27 September 2026</time></p>
|
||||
<h2>1. Pengenalan</h2>
|
||||
<p>Selamat datang ke sistem Kaunter arOS Koperasi Permodalan Kelantan Berhad (KoPKB). Kami amat menghargai kepercayaan yang anda berikan untuk mengendalikan maklumat peribadi anda. Dasar Privasi ini digubal untuk membantu anda memahami bagaimana kami mengumpul, menggunakan, mendedahkan dan melindungi data peribadi anda bagi urusan Ar-Rahn, dengan mengambil kira keperluan Akta Perlindungan Data Peribadi 2010 (PDPA) dan amalan keselamatan maklumat yang berkaitan.</p>
|
||||
<p>Dasar ini terpakai kepada kakitangan, pentadbir dan mana-mana pihak yang diberi kuasa untuk mengakses atau menggunakan sistem Kaunter arOS KoPKB, serta pengendalian data pelanggan dalam perkhidmatan yang diuruskan melalui sistem ini.</p>
|
||||
|
||||
<h2>2. Data yang Dikumpul</h2>
|
||||
<p>Kami mengumpul dan memproses maklumat yang berkaitan dengan urusan sistem, termasuk:</p>
|
||||
<ul>
|
||||
<li><strong>Maklumat Pengenalan Peribadi:</strong> Nama penuh, nombor pengenalan, alamat, alamat e-mel dan nombor telefon pelanggan atau pengguna.</li>
|
||||
<li><strong>Maklumat Akaun:</strong> Maklumat akaun pengguna, cawangan dan peranan akses dalam sistem.</li>
|
||||
<li><strong>Data Teknikal:</strong> Maklumat seperti alamat IP, jenis pelayar dan log aktiviti sistem yang direkodkan bagi tujuan operasi dan keselamatan.</li>
|
||||
<li><strong>Data Transaksi:</strong> Rekod pembiayaan, gadaian, maklumat marhun, pembayaran, penebusan, lelongan dan dokumen sokongan berkaitan.</li>
|
||||
</ul>
|
||||
|
||||
<h2>3. Tujuan Penggunaan Data</h2>
|
||||
<p>Data anda digunakan untuk tujuan berikut:</p>
|
||||
<ul>
|
||||
<li><strong>Operasi Sistem:</strong> Menguruskan akaun pengguna dan memproses urusan pelanggan serta transaksi Ar-Rahn.</li>
|
||||
<li><strong>Pengesahan:</strong> Mengesahkan identiti dan mengawal akses pengguna mengikut peranan serta cawangan yang dibenarkan.</li>
|
||||
<li><strong>Komunikasi:</strong> Menyampaikan notis berkaitan urusan, makluman pentadbiran dan sokongan pelanggan.</li>
|
||||
<li><strong>Pelaporan dan Penambahbaikan:</strong> Menyediakan laporan operasi, menyokong audit serta menambah baik prestasi dan kualiti sistem.</li>
|
||||
</ul>
|
||||
|
||||
<h2>4. Perkongsian & Pendedahan Data</h2>
|
||||
<p>Kami tidak menjual data peribadi anda. Akses, perkongsian atau pendedahan data dihadkan kepada keperluan urusan yang berkaitan, termasuk:</p>
|
||||
<ul>
|
||||
<li><strong>Kakitangan yang Diberi Kuasa:</strong> Kakitangan dan pentadbir KoPKB yang memerlukan maklumat untuk menjalankan tugas.</li>
|
||||
<li><strong>Pembekal Perkhidmatan:</strong> Penyedia teknologi atau perkhidmatan yang menyokong pengehosan, penyelenggaraan sistem dan pemprosesan pembayaran, jika berkaitan.</li>
|
||||
<li><strong>Pematuhan Undang-undang:</strong> Pihak berkuasa atau pihak lain apabila pendedahan diperlukan oleh undang-undang atau perintah mahkamah.</li>
|
||||
</ul>
|
||||
|
||||
<h2>5. Keselamatan Data</h2>
|
||||
<p>Langkah keselamatan teknikal dan pentadbiran digunakan untuk membantu melindungi data yang dikendalikan melalui sistem, termasuk kawalan akses mengikut peranan pengguna dan pengesahan akaun.</p>
|
||||
<p>Pengguna hendaklah mengakses sistem melalui sambungan HTTPS yang selamat, menjaga kerahsiaan kata laluan, tidak berkongsi akaun dan log keluar selepas selesai menggunakan sistem. Sebarang aktiviti yang mencurigakan hendaklah dilaporkan kepada pentadbir sistem.</p>
|
||||
|
||||
<h2>6. Hak Pengguna</h2>
|
||||
<p>Anda boleh menghubungi kami untuk mengemukakan permohonan berkaitan data peribadi anda, termasuk:</p>
|
||||
<ul>
|
||||
<li><strong>Akses & Pembetulan:</strong> Memohon semakan dan pembetulan maklumat peribadi yang tidak tepat atau tidak terkini.</li>
|
||||
<li><strong>Pemadaman:</strong> Memohon pemadaman akaun atau data dalam keadaan yang sesuai, tertakluk kepada keperluan penyimpanan rekod transaksi, audit dan undang-undang.</li>
|
||||
<li><strong>Sekatan:</strong> Memohon supaya pemprosesan data tertentu dihadkan, tertakluk kepada keperluan perkhidmatan dan kewajipan yang terpakai.</li>
|
||||
</ul>
|
||||
<p>Permohonan akan dinilai mengikut keperluan yang terpakai. Pengesahan identiti mungkin diperlukan sebelum permohonan diproses.</p>
|
||||
|
||||
<h2>7. Tempoh Penyimpanan</h2>
|
||||
<p>Data disimpan selama diperlukan untuk pengendalian urusan Ar-Rahn, penyelenggaraan rekod pembiayaan dan transaksi, audit serta pematuhan undang-undang. Selepas keperluan penyimpanan berakhir, data akan diuruskan untuk pemadaman atau penyahkenalpastian mengikut prosedur organisasi yang terpakai.</p>
|
||||
|
||||
<h2>8. Kuki & Teknologi Penjejakan</h2>
|
||||
<p>Sistem Kaunter arOS menggunakan kuki (cookies) dan sesi untuk menyokong log masuk, mengekalkan sesi pengguna dan melindungi permintaan dalam sistem. Anda boleh menguruskan pilihan kuki melalui tetapan pelayar. Menyekat kuki boleh menyebabkan fungsi tertentu, termasuk log masuk, tidak berfungsi dengan baik.</p>
|
||||
|
||||
<h2>9. Perubahan Dasar</h2>
|
||||
<p>Dasar ini boleh dikemas kini dari semasa ke semasa apabila terdapat perubahan pada perkhidmatan, pengendalian sistem atau keperluan organisasi. Versi terkini akan dipaparkan pada halaman ini. Sebarang perubahan besar akan dimaklumkan melalui e-mel atau notis dalam sistem sebelum tarikh kuat kuasa baharu.</p>
|
||||
|
||||
<h2>10. Hubungi Kami</h2>
|
||||
<p>Jika anda mempunyai pertanyaan, komen atau permohonan berkaitan dasar ini dan pengendalian data peribadi dalam sistem Kaunter arOS, sila hubungi:</p>
|
||||
<p><strong>AFRINA ALIMI</strong><br>
|
||||
Koperasi Permodalan Kelantan Berhad (KoPKB)<br>
|
||||
E-mel: <a href="mailto:afrina@koppkb.com">afrina@koppkb.com</a>
|
||||
</p>
|
||||
|
||||
<a class="privacy-back" href="{{ route('login') }}">Kembali ke Log Masuk</a>
|
||||
</article>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -5,6 +5,9 @@
|
||||
@section('content')
|
||||
@include('modal.editmarhun')
|
||||
<div class="container">
|
||||
@if(session('gadai_edit_error'))
|
||||
<div class="alert alert-danger" role="alert">{{ session('gadai_edit_error') }}</div>
|
||||
@endif
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-12 col-lg-12">
|
||||
<h3 class="text-center text-uppercase">Pembiayaan</h3>
|
||||
@@ -946,6 +949,7 @@
|
||||
text: `Komen : ${data.komen}`
|
||||
}).then(function(){
|
||||
$(func).attr("onSubmit","return true;");
|
||||
window.shorakaTrack(api_url + '/api/shoraka/gadai/' + encodeURIComponent($('#kodcaw').val()) + '/' + encodeURIComponent($('#norujukan').val()));
|
||||
$(func).submit();
|
||||
return true;
|
||||
});
|
||||
@@ -1058,6 +1062,7 @@
|
||||
}).then(function(){
|
||||
|
||||
$(func).attr("onSubmit","return true;");
|
||||
window.shorakaTrack(api_url + '/api/shoraka/gadai/' + encodeURIComponent($('#kodcaw').val()) + '/' + encodeURIComponent($('#norujukan').val()));
|
||||
$(func).submit();
|
||||
return true;
|
||||
|
||||
@@ -1092,11 +1097,7 @@
|
||||
return false;
|
||||
}
|
||||
else if(pinjaman < 10000 && pinjaman <= Number(pembiayaan_max_teller)){
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Berjaya!',
|
||||
text: 'Pembiayaan Berjaya Disimpan'
|
||||
});
|
||||
window.shorakaTrack(api_url + '/api/shoraka/gadai/' + encodeURIComponent($('#kodcaw').val()) + '/' + encodeURIComponent($('#norujukan').val()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -819,25 +819,25 @@
|
||||
}else{
|
||||
$.ajax({
|
||||
method:'get',
|
||||
url: api_url + '/api/komuditi/check',
|
||||
url: api_url + '/api/shoraka/readiness',
|
||||
success:function(data){
|
||||
var check_komuditi = Object.keys(data).length;
|
||||
if(check_komuditi == 0){
|
||||
if (!data.ready){
|
||||
$("#terima_gadai").prop('disabled', false);
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Unit Komuditi Berbaki Minumum',
|
||||
text: 'Sila Hubungi Operasi Untuk Membuat Pembelian Komuditi'
|
||||
title: 'Shoraka Belum Tersedia',
|
||||
text: 'Sila hubungi operasi untuk semakan sambungan Shoraka.'
|
||||
});
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}else{
|
||||
if(Number(data['unit_komuditi']) < pinjaman){
|
||||
if (!data.ready){
|
||||
$("#terima_gadai").prop('disabled', false);
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Baki Unit Komuditi Tidak Mencukupi',
|
||||
text: 'Sila Hubungi Operasi Untuk Membuat Pembelian Komuditi'
|
||||
title: 'Shoraka Belum Tersedia',
|
||||
text: 'Sila hubungi operasi untuk semakan sambungan Shoraka.'
|
||||
});
|
||||
event.preventDefault();
|
||||
return false;
|
||||
@@ -1162,9 +1162,9 @@
|
||||
return false;
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Berjaya!',
|
||||
text: 'Pembiayaan Berjaya Disimpan'
|
||||
icon: 'info',
|
||||
title: 'Sedang diproses',
|
||||
text: 'Sedang menghantar pembiayaan untuk pengesahan Shoraka.'
|
||||
});
|
||||
|
||||
$(func).attr("onSubmit","return true;");
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
@section('content')
|
||||
@include('modal.editmarhun')
|
||||
<div class="container">
|
||||
@if(session('gadai_edit_error'))
|
||||
<div class="alert alert-danger" role="alert">{{ session('gadai_edit_error') }}</div>
|
||||
@endif
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-12 col-lg-12">
|
||||
<h3 class="text-center text-uppercase">Pembiayaan</h3>
|
||||
@@ -1612,6 +1615,7 @@
|
||||
text: `Komen : ${data.komen}`
|
||||
}).then(function(){
|
||||
$(func).attr("onSubmit","return true;");
|
||||
window.shorakaTrack(api_url + '/api/shoraka/gadai/' + encodeURIComponent($('#kodcaw').val()) + '/' + encodeURIComponent($('#norujukan').val()));
|
||||
$(func).submit();
|
||||
return true;
|
||||
});
|
||||
@@ -1724,6 +1728,7 @@
|
||||
}).then(function(){
|
||||
|
||||
$(func).attr("onSubmit","return true;");
|
||||
window.shorakaTrack(api_url + '/api/shoraka/gadai/' + encodeURIComponent($('#kodcaw').val()) + '/' + encodeURIComponent($('#norujukan').val()));
|
||||
$(func).submit();
|
||||
return true;
|
||||
|
||||
@@ -1758,11 +1763,7 @@
|
||||
return false;
|
||||
}
|
||||
else if(pinjaman < 10000 && pinjaman <= Number(pembiayaan_max_teller)){
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Berjaya!',
|
||||
text: 'Pembiayaan Berjaya Disimpan'
|
||||
});
|
||||
window.shorakaTrack(api_url + '/api/shoraka/gadai/' + encodeURIComponent($('#kodcaw').val()) + '/' + encodeURIComponent($('#norujukan').val()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -435,7 +435,6 @@
|
||||
text: @json(session('error'))
|
||||
});
|
||||
@endif
|
||||
|
||||
$.ajax({
|
||||
method:'GET',
|
||||
url: api_url + '/api/jemas',
|
||||
@@ -1655,25 +1654,25 @@
|
||||
}else{
|
||||
$.ajax({
|
||||
method:'get',
|
||||
url: api_url + '/api/komuditi/check',
|
||||
url: api_url + '/api/shoraka/readiness',
|
||||
success:function(data){
|
||||
var check_komuditi = Object.keys(data).length;
|
||||
if(check_komuditi == 0){
|
||||
if (!data.ready){
|
||||
$("#terima_gadai").prop('disabled', false);
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Unit Komuditi Berbaki Minumum',
|
||||
text: 'Sila Hubungi Operasi Untuk Membuat Pembelian Komuditi'
|
||||
title: 'Shoraka Belum Tersedia',
|
||||
text: 'Sila hubungi operasi untuk semakan sambungan Shoraka.'
|
||||
});
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}else{
|
||||
if(Number(data['unit_komuditi']) < pinjaman){
|
||||
if (!data.ready){
|
||||
$("#terima_gadai").prop('disabled', false);
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Baki Unit Komuditi Tidak Mencukupi',
|
||||
text: 'Sila Hubungi Operasi Untuk Membuat Pembelian Komuditi'
|
||||
title: 'Shoraka Belum Tersedia',
|
||||
text: 'Sila hubungi operasi untuk semakan sambungan Shoraka.'
|
||||
});
|
||||
event.preventDefault();
|
||||
return false;
|
||||
@@ -1787,6 +1786,7 @@
|
||||
}).then(function(){
|
||||
|
||||
$(func).attr("onSubmit","return true;");
|
||||
window.shorakaTrack(api_url + '/api/shoraka/gadai/' + encodeURIComponent($('#kodcaw').val()) + '/' + encodeURIComponent($('#norujukan_gadai').val()));
|
||||
$(func).submit();
|
||||
return true;
|
||||
});
|
||||
@@ -1936,6 +1936,7 @@
|
||||
|
||||
|
||||
$(func).attr("onSubmit","return true;");
|
||||
window.shorakaTrack(api_url + '/api/shoraka/gadai/' + encodeURIComponent($('#kodcaw').val()) + '/' + encodeURIComponent($('#norujukan_gadai').val()));
|
||||
$(func).submit();
|
||||
return true;
|
||||
|
||||
@@ -1999,12 +2000,7 @@
|
||||
return false;
|
||||
} else {
|
||||
//insert code asal
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Berjaya!',
|
||||
text: 'Pembiayaan Berjaya Disimpan'
|
||||
});
|
||||
|
||||
window.shorakaTrack(api_url + '/api/shoraka/gadai/' + encodeURIComponent($('#kodcaw').val()) + '/' + encodeURIComponent($('#norujukan_gadai').val()));
|
||||
$(func).attr("onSubmit","return true;");
|
||||
$(func).submit();
|
||||
return true;
|
||||
|
||||
@@ -268,6 +268,11 @@
|
||||
<a href="{{ route('khazanah.harga_emas') }}"
|
||||
class="btn btn-info btn-lg btn-block mb-3">Harga Emas</a>
|
||||
</div>
|
||||
@if(in_array(Auth::user()->roles, ['pc', 'ppc'], true))
|
||||
<div class="col-4 px-2">
|
||||
<a href="{{ route('pc.shoraka.index') }}" class="btn btn-info btn-lg btn-block mb-3">Komoditi Shoraka</a>
|
||||
</div>
|
||||
@endif
|
||||
@if(!empty(($cawangan_info['features'] ?? [])['pembiayaan_online']))
|
||||
<div class="col-4 px-2">
|
||||
<a href="{{ route('pembiayaan.online.pc') }}"
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
<div class="card-body text-center">
|
||||
<a href="{{ route('operasi.kelulusananggota') }}" class="btn btn-info btn-lg d-inline-block m-1">Kelulusan Anggota</a>
|
||||
<a href="{{ route('operasi.kelulusan') }}" class="btn btn-info btn-lg d-inline-block m-1">Kelulusan</a>
|
||||
<a href="{{ route('operasi.shoraka.index') }}" class="btn btn-info btn-lg d-inline-block m-1">Komoditi Shoraka</a>
|
||||
<a href="{{ route('pembiayaan.online.operasi') }}" class="btn btn-info btn-lg d-inline-block m-1">Pembiayaan Online</a>
|
||||
<a href="{{ route('pembiayaan.online.operasi.topup') }}" class="btn btn-info btn-lg d-inline-block m-1">Modal Online</a>
|
||||
<a href="{{ route('pembiayaan.online.operasi.eod') }}" class="btn btn-info btn-lg d-inline-block m-1">EOD Modal Online</a>
|
||||
|
||||
@@ -1,16 +1,67 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<style>
|
||||
.teller-home-card {
|
||||
border: 0;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 8px 24px rgba(31, 45, 61, .12);
|
||||
}
|
||||
.teller-home-card .card-header {
|
||||
padding: 20px;
|
||||
border: 0;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.teller-home-menu {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 16px;
|
||||
padding: 28px;
|
||||
}
|
||||
.teller-home-menu .btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 88px;
|
||||
padding: 18px 16px;
|
||||
border-radius: 8px;
|
||||
white-space: normal;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
letter-spacing: .3px;
|
||||
transition: background-color .15s ease, box-shadow .15s ease;
|
||||
}
|
||||
.teller-home-menu .btn:hover,
|
||||
.teller-home-menu .btn:focus-visible {
|
||||
box-shadow: 0 4px 12px rgba(23, 162, 184, .25);
|
||||
}
|
||||
@media (max-width: 575.98px) {
|
||||
.teller-home-menu {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
gap: 12px;
|
||||
padding: 20px;
|
||||
}
|
||||
.teller-home-menu .btn {
|
||||
min-height: 68px;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<div class="container">
|
||||
<div class="row justify-content-center" style="margin-top:60px;">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header bg-secondary text-center"><span style="font-weight:500;">{{ __('Paparan Utama') }}</span></div>
|
||||
<div class="card teller-home-card">
|
||||
<div class="card-header bg-secondary text-center">{{ __('Paparan Utama') }}</div>
|
||||
|
||||
<div class="card-body text-center">
|
||||
<div class="card-body teller-home-menu text-center">
|
||||
<a class="btn btn-info btn-lg" href="#" onclick="pelangganclick()">PELANGGAN</a>
|
||||
<a class="btn btn-info btn-lg" href="{{ url('/harga_emas') }}">HARGA EMAS</a>
|
||||
<a class="btn btn-info btn-lg" href="{{ url('/aliran_tunai') }}">ALIRAN TUNAI</a>
|
||||
@if(in_array(Auth::user()->roles, ['teller', 'penilai', 'pc', 'ppc', 'admin', 'masteradmin', 'operasi']) || Auth::user()->role_harian === 'teller')
|
||||
<a class="btn btn-info btn-lg" href="{{ route('shoraka.index') }}">KOMODITI SHORAKA</a>
|
||||
@endif
|
||||
{{-- <a class="btn btn-info btn-lg" href="#">TETAPAN</a> --}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -405,6 +405,7 @@
|
||||
@endif
|
||||
|
||||
<main class="py-4">
|
||||
@include('shoraka.navigation')
|
||||
@yield('content')
|
||||
</main>
|
||||
</div>
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
id="batch_lines"
|
||||
class="table-sm text-center"
|
||||
:filename="'Batch_' . ($batch['batch_no'] ?? $batch['id'])"
|
||||
:columns="['Bil', 'Status', 'SAG', 'Pelanggan', 'No KP', 'Bank', 'No Akaun', 'Nama Akaun', 'Pinjaman (RM)', 'Rujukan Bayaran', 'Dokumen', 'Tindakan']"
|
||||
:columns="['Bil', 'Status', 'SAG', 'Pelanggan', 'No KP', 'Bank', 'No Akaun', 'Pinjaman (RM)', 'Rujukan Bayaran', 'Dokumen', 'Tindakan']"
|
||||
:skipExport="['Dokumen', 'Tindakan']"
|
||||
>
|
||||
@foreach($lines as $line)
|
||||
@@ -94,7 +94,6 @@
|
||||
<td>{{ $line['nokp'] ?? '-' }}</td>
|
||||
<td>{{ $line['nama_bank'] ?? $line['kodbank'] ?? '-' }}</td>
|
||||
<td>{{ $line['noakaun'] ?? '-' }}</td>
|
||||
<td class="text-left">{{ $line['nama_akaun'] ?? '-' }}</td>
|
||||
<td class="text-right">{{ number_format((float)($line['pinjaman'] ?? 0), 2) }}</td>
|
||||
<td>{{ $line['no_rujukan_bayaran'] ?? '-' }}</td>
|
||||
<td class="text-nowrap">
|
||||
@@ -113,6 +112,13 @@
|
||||
@else
|
||||
<span class="text-muted small">Tiada slip</span>
|
||||
@endif
|
||||
@if(!empty($line['borang_file_id']))
|
||||
<a class="btn btn-sm btn-outline-primary"
|
||||
href="{{ route('pembiayaan.online.operasi.borang', ['kodcaw' => $kodcaw, 'id' => $line['id']]) }}"
|
||||
target="_blank">
|
||||
Borang Pengesahan
|
||||
</a>
|
||||
@endif
|
||||
</td>
|
||||
<td class="text-nowrap">
|
||||
@if(in_array($st, ['IN_BATCH', 'OPS_REVIEW'], true))
|
||||
|
||||
@@ -70,6 +70,13 @@
|
||||
@else
|
||||
<span class="text-muted small">Tiada slip</span>
|
||||
@endif
|
||||
@if(!empty($line['borang_file_id']))
|
||||
<a class="btn btn-sm btn-outline-primary"
|
||||
href="{{ route('pembiayaan.online.pc.borang', ['id' => $line['id']]) }}"
|
||||
target="_blank">
|
||||
Borang Pengesahan
|
||||
</a>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
@@ -274,11 +274,11 @@
|
||||
data-nokp="{{ $line['nokp'] ?? '' }}"
|
||||
data-namabank="{{ $line['nama_bank'] ?? $line['kodbank'] ?? '' }}"
|
||||
data-noakaun="{{ $line['noakaun'] ?? '' }}"
|
||||
data-namaakaun="{{ $line['nama_akaun'] ?? '' }}"
|
||||
data-pinjaman="{{ number_format((float)($line['pinjaman'] ?? 0), 2) }}"
|
||||
data-nota="{{ $line['nota'] ?? '' }}"
|
||||
data-sebab="{{ $line['reject_reason'] ?? '' }}"
|
||||
data-bukti-akaun="{{ $line['bukti_akaun_file_id'] ?? '' }}">
|
||||
data-bukti-akaun="{{ $line['bukti_akaun_file_id'] ?? '' }}"
|
||||
data-borang-file="{{ $line['borang_file_id'] ?? '' }}">
|
||||
Semak
|
||||
</button>
|
||||
@endif
|
||||
@@ -286,11 +286,11 @@
|
||||
data-id="{{ $line['id'] }}"
|
||||
data-kodbank="{{ $line['kodbank'] ?? '' }}"
|
||||
data-noakaun="{{ $line['noakaun'] ?? '' }}"
|
||||
data-namaakaun="{{ $line['nama_akaun'] ?? '' }}"
|
||||
data-namabank="{{ $line['nama_bank'] ?? '' }}"
|
||||
data-nota="{{ $line['nota'] ?? '' }}"
|
||||
data-norujukan="{{ $line['norujukan'] ?? '' }}"
|
||||
data-bukti-akaun="{{ $line['bukti_akaun_file_id'] ?? '' }}">
|
||||
data-bukti-akaun="{{ $line['bukti_akaun_file_id'] ?? '' }}"
|
||||
data-borang-file="{{ $line['borang_file_id'] ?? '' }}">
|
||||
Edit
|
||||
</button>
|
||||
</td>
|
||||
@@ -390,10 +390,6 @@
|
||||
<label>No. Akaun</label>
|
||||
<input type="text" name="noakaun" id="editNoakaun" class="form-control" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Nama Akaun</label>
|
||||
<input type="text" name="nama_akaun" id="editNamaakaun" class="form-control">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Slip Bank / Bukti Akaun</label>
|
||||
<input type="file" name="bukti_akaun" id="editBuktiAkaun" class="form-control-file"
|
||||
@@ -405,6 +401,17 @@
|
||||
</div>
|
||||
<small class="text-muted">PDF / imej slip akaun bank pelanggan (maks 4MB)</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Borang Pengesahan Penerimaan Pembiayaan Secara Atas Talian (Online)</label>
|
||||
<input type="file" name="borang" id="editBorang" class="form-control-file"
|
||||
accept=".pdf,.jpg,.jpeg,.png,.gif">
|
||||
<div id="editBorangExisting" class="mt-2" style="display:none;">
|
||||
<a href="#" id="editBorangLink" class="btn btn-sm btn-outline-primary" target="_blank">
|
||||
Lihat borang sedia ada
|
||||
</a>
|
||||
</div>
|
||||
<small class="text-muted">PDF / imej borang yang ditandatangani pelanggan (maks 4MB). Kosongkan jika tidak mahu ganti fail sedia ada.</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Nota</label>
|
||||
<textarea name="nota" id="editNota" class="form-control" rows="2"></textarea>
|
||||
@@ -462,10 +469,6 @@
|
||||
<th>No Akaun</th>
|
||||
<td id="verifyNoakaun"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Nama Akaun</th>
|
||||
<td id="verifyNamaakaun"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Pinjaman</th>
|
||||
<td>RM <span id="verifyPinjaman"></span></td>
|
||||
@@ -485,9 +488,12 @@
|
||||
Saya sahkan maklumat pelanggan, bank dan amaun adalah betul.
|
||||
</label>
|
||||
</div>
|
||||
<a href="#" id="verifyBuktiAkaunLink" class="btn btn-sm btn-outline-primary" target="_blank" style="display:none;">
|
||||
<a href="#" id="verifyBuktiAkaunLink" class="btn btn-sm btn-outline-primary mb-2" target="_blank" style="display:none;">
|
||||
Lihat Bukti Akaun Bank
|
||||
</a>
|
||||
<a href="#" id="verifyBorangLink" class="btn btn-sm btn-outline-primary" target="_blank" style="display:none;">
|
||||
Lihat Borang Pengesahan
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<label class="d-block">Pratonton SAG</label>
|
||||
@@ -576,7 +582,6 @@
|
||||
$('#verifyNokp').text($(this).data('nokp') || '-');
|
||||
$('#verifyBank').text($(this).data('namabank') || '-');
|
||||
$('#verifyNoakaun').text($(this).data('noakaun') || '-');
|
||||
$('#verifyNamaakaun').text($(this).data('namaakaun') || '-');
|
||||
$('#verifyPinjaman').text($(this).data('pinjaman') || '0.00');
|
||||
$('#verifyNota').text($(this).data('nota') || '-');
|
||||
if (sebab) {
|
||||
@@ -592,6 +597,11 @@
|
||||
} else {
|
||||
$('#verifyBuktiAkaunLink').hide();
|
||||
}
|
||||
if ($(this).data('borangFile')) {
|
||||
$('#verifyBorangLink').attr('href', "{{ url('/pembiayaan-online/pc/lines') }}/" + id + "/borang").show();
|
||||
} else {
|
||||
$('#verifyBorangLink').hide();
|
||||
}
|
||||
$('#verifyModal').modal('show');
|
||||
});
|
||||
|
||||
@@ -605,10 +615,10 @@
|
||||
$('#editNorujukan').text($(this).data('norujukan'));
|
||||
$('#editKodbank').val($(this).data('kodbank'));
|
||||
$('#editNoakaun').val($(this).data('noakaun'));
|
||||
$('#editNamaakaun').val($(this).data('namaakaun'));
|
||||
$('#editNamabank').val($(this).data('namabank'));
|
||||
$('#editNota').val($(this).data('nota'));
|
||||
$('#editBuktiAkaun').val('');
|
||||
$('#editBorang').val('');
|
||||
$('#editSagFrame').attr('src', "{{ url('/pembiayaan-online/pc/lines') }}/" + id + "/sag");
|
||||
if ($(this).data('buktiAkaun')) {
|
||||
$('#editBuktiAkaunLink').attr('href', "{{ url('/pembiayaan-online/pc/lines') }}/" + id + "/bukti-akaun");
|
||||
@@ -616,6 +626,12 @@
|
||||
} else {
|
||||
$('#editBuktiAkaunExisting').hide();
|
||||
}
|
||||
if ($(this).data('borangFile')) {
|
||||
$('#editBorangLink').attr('href', "{{ url('/pembiayaan-online/pc/lines') }}/" + id + "/borang");
|
||||
$('#editBorangExisting').show();
|
||||
} else {
|
||||
$('#editBorangExisting').hide();
|
||||
}
|
||||
$('#editModal').modal('show');
|
||||
});
|
||||
|
||||
|
||||
@@ -2022,25 +2022,25 @@
|
||||
|
||||
$.ajax({
|
||||
method:'get',
|
||||
url: api + '/api/komuditi/check',
|
||||
url: api + '/api/shoraka/readiness',
|
||||
success:function(komoditi){
|
||||
var check_komuditi = Object.keys(komoditi).length;
|
||||
if(check_komuditi == 0){
|
||||
if (!komoditi.ready){
|
||||
$("#terima_transaksi").prop('disabled', false);
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Unit Komuditi Berbaki Minumum',
|
||||
text: 'Sila Hubungi Operasi Untuk Membuat Pembelian Komuditi'
|
||||
title: 'Shoraka Belum Tersedia',
|
||||
text: 'Sila hubungi operasi untuk semakan sambungan Shoraka.'
|
||||
});
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}else{
|
||||
if(Number(komoditi['unit_komuditi']) < pinjaman_baru){
|
||||
if (!komoditi.ready){
|
||||
$("#terima_transaksi").prop('disabled', false);
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Baki Unit Komuditi Tidak Mencukupi',
|
||||
text: 'Sila Hubungi Operasi Untuk Membuat Pembelian Komuditi'
|
||||
title: 'Shoraka Belum Tersedia',
|
||||
text: 'Sila hubungi operasi untuk semakan sambungan Shoraka.'
|
||||
});
|
||||
event.preventDefault();
|
||||
return false;
|
||||
|
||||
@@ -2258,25 +2258,25 @@
|
||||
|
||||
$.ajax({
|
||||
method:'get',
|
||||
url: api + '/api/komuditi/check',
|
||||
url: api + '/api/shoraka/readiness',
|
||||
success:function(komoditi){
|
||||
var check_komuditi = Object.keys(komoditi).length;
|
||||
if(check_komuditi == 0){
|
||||
if (!komoditi.ready){
|
||||
$("#terima_transaksi").prop('disabled', false);
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Unit Komuditi Berbaki Minumum',
|
||||
text: 'Sila Hubungi Operasi Untuk Membuat Pembelian Komuditi'
|
||||
title: 'Shoraka Belum Tersedia',
|
||||
text: 'Sila hubungi operasi untuk semakan sambungan Shoraka.'
|
||||
});
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}else{
|
||||
if(Number(komoditi['unit_komuditi']) < pinjaman_baru){
|
||||
if (!komoditi.ready){
|
||||
$("#terima_transaksi").prop('disabled', false);
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Baki Unit Komuditi Tidak Mencukupi',
|
||||
text: 'Sila Hubungi Operasi Untuk Membuat Pembelian Komuditi'
|
||||
title: 'Shoraka Belum Tersedia',
|
||||
text: 'Sila hubungi operasi untuk semakan sambungan Shoraka.'
|
||||
});
|
||||
event.preventDefault();
|
||||
return false;
|
||||
|
||||
@@ -2264,27 +2264,27 @@
|
||||
let komuditiblock = false;
|
||||
$.ajax({
|
||||
method:'get',
|
||||
url: api + '/api/komuditi/check',
|
||||
url: api + '/api/shoraka/readiness',
|
||||
async:false,
|
||||
success:function(komoditi){
|
||||
var check_komuditi = Object.keys(komoditi).length;
|
||||
if(check_komuditi == 0){
|
||||
if (!komoditi.ready){
|
||||
$("#terima_transaksi").prop('disabled', false);
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Unit Komuditi Berbaki Minumum',
|
||||
text: 'Sila Hubungi Operasi Untuk Membuat Pembelian Komuditi'
|
||||
title: 'Shoraka Belum Tersedia',
|
||||
text: 'Sila hubungi operasi untuk semakan sambungan Shoraka.'
|
||||
});
|
||||
komuditiblock = true;
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}else{
|
||||
if(Number(komoditi['unit_komuditi']) < pinjaman_baru){
|
||||
if (!komoditi.ready){
|
||||
$("#terima_transaksi").prop('disabled', false);
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Baki Unit Komuditi Tidak Mencukupi',
|
||||
text: 'Sila Hubungi Operasi Untuk Membuat Pembelian Komuditi'
|
||||
title: 'Shoraka Belum Tersedia',
|
||||
text: 'Sila hubungi operasi untuk semakan sambungan Shoraka.'
|
||||
});
|
||||
komuditiblock = true;
|
||||
event.preventDefault();
|
||||
@@ -2646,29 +2646,29 @@
|
||||
let komuditiblock = false;
|
||||
$.ajax({
|
||||
method:'get',
|
||||
url: api + '/api/komuditi/check',
|
||||
url: api + '/api/shoraka/readiness',
|
||||
async:false,
|
||||
success:function(komoditi){
|
||||
var check_komuditi = Object.keys(komoditi).length;
|
||||
if(check_komuditi == 0){
|
||||
if (!komoditi.ready){
|
||||
$("#terima_transaksi").prop('disabled', false);
|
||||
Swal.close();
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Unit Komuditi Berbaki Minumum',
|
||||
text: 'Sila Hubungi Operasi Untuk Membuat Pembelian Komuditi'
|
||||
title: 'Shoraka Belum Tersedia',
|
||||
text: 'Sila hubungi operasi untuk semakan sambungan Shoraka.'
|
||||
});
|
||||
komuditiblock = true;
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}else{
|
||||
if(Number(komoditi['unit_komuditi']) < pinjaman_baru){
|
||||
if (!komoditi.ready){
|
||||
$("#terima_transaksi").prop('disabled', false);
|
||||
Swal.close();
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Baki Unit Komuditi Tidak Mencukupi',
|
||||
text: 'Sila Hubungi Operasi Untuk Membuat Pembelian Komuditi'
|
||||
title: 'Shoraka Belum Tersedia',
|
||||
text: 'Sila hubungi operasi untuk semakan sambungan Shoraka.'
|
||||
});
|
||||
komuditiblock = true;
|
||||
event.preventDefault();
|
||||
@@ -3106,25 +3106,25 @@
|
||||
|
||||
$.ajax({
|
||||
method:'get',
|
||||
url: api + '/api/komuditi/check',
|
||||
url: api + '/api/shoraka/readiness',
|
||||
success:function(komoditi){
|
||||
var check_komuditi = Object.keys(komoditi).length;
|
||||
if(check_komuditi == 0){
|
||||
if (!komoditi.ready){
|
||||
$("#terima_transaksi").prop('disabled', false);
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Unit Komuditi Berbaki Minumum',
|
||||
text: 'Sila Hubungi Operasi Untuk Membuat Pembelian Komuditi'
|
||||
title: 'Shoraka Belum Tersedia',
|
||||
text: 'Sila hubungi operasi untuk semakan sambungan Shoraka.'
|
||||
});
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}else{
|
||||
if(Number(komoditi['unit_komuditi']) < pinjaman_baru){
|
||||
if (!komoditi.ready){
|
||||
$("#terima_transaksi").prop('disabled', false);
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Baki Unit Komuditi Tidak Mencukupi',
|
||||
text: 'Sila Hubungi Operasi Untuk Membuat Pembelian Komuditi'
|
||||
title: 'Shoraka Belum Tersedia',
|
||||
text: 'Sila hubungi operasi untuk semakan sambungan Shoraka.'
|
||||
});
|
||||
event.preventDefault();
|
||||
return false;
|
||||
|
||||
@@ -258,7 +258,7 @@
|
||||
<th style="width:13%">No. KP</th>
|
||||
<th style="width:11%">Bank</th>
|
||||
<th style="width:13%">No. Akaun</th>
|
||||
<th>Nama Akaun</th>
|
||||
<th>No. Telefon</th>
|
||||
<th style="width:12%">Pinjaman (RM)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -271,7 +271,7 @@
|
||||
<td class="num">{{ $line['nokp'] ?? '-' }}</td>
|
||||
<td>{{ $line['nama_bank'] ?? ($line['kodbank'] ?? '-') }}</td>
|
||||
<td class="num">{{ $line['noakaun'] ?? '-' }}</td>
|
||||
<td>{{ $line['nama_akaun'] ?? '-' }}</td>
|
||||
<td>{{ !empty($line['telefon']) ? $line['telefon'] : '-' }}</td>
|
||||
<td class="amt">{{ number_format((float) ($line['pinjaman'] ?? 0), 2) }}</td>
|
||||
</tr>
|
||||
@empty
|
||||
@@ -306,7 +306,7 @@
|
||||
|
||||
<div class="signs">
|
||||
<div class="sign-box">
|
||||
<div class="role">Tandatangan Operasi</div>
|
||||
<div class="role">Disemak oleh</div>
|
||||
<div class="sign-line">
|
||||
<p>Nama: {{ $opsBy }}</p>
|
||||
<p>Jawatan: Operasi</p>
|
||||
@@ -314,10 +314,10 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="sign-box">
|
||||
<div class="role">Pengurus Besar</div>
|
||||
<div class="role">Disahkan oleh</div>
|
||||
<div class="sign-line">
|
||||
<p>Nama:</p>
|
||||
<p>Cop:</p>
|
||||
<p>Jawatan:</p>
|
||||
<p>Tarikh:</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -556,9 +556,16 @@
|
||||
</table>
|
||||
|
||||
@php
|
||||
$komuditi = Http::withOptions(['verify' => config('app.api_verify')])->get($api_url . '/api/komuditi/check')->json();
|
||||
$shorakaPrint = app(\App\Services\ShorakaFinancingService::class)->printData($gadai_detail['norujukan']);
|
||||
if ($shorakaPrint) {
|
||||
$komuditi = $shorakaPrint['komoditi'];
|
||||
$product = $shorakaPrint['product'];
|
||||
$kuantiti = $shorakaPrint['kuantiti'];
|
||||
} else {
|
||||
$komuditi = Http::withOptions(['verify' => config('app.api_verify')])->get($api_url . '/api/komuditi/check')->json();
|
||||
$product = Http::withOptions(['verify' => config('app.api_verify')])->get($api_url . '/api/komuditi/description',['kodproduk'=>$komuditi['kodproduct']])->json();
|
||||
$kuantiti = $gadai_detail['pinjaman']/$komuditi['nilai'];
|
||||
}
|
||||
@endphp
|
||||
|
||||
<table style="margin-bottom:10px;" id="keuntungan">
|
||||
|
||||
@@ -654,13 +654,20 @@
|
||||
|
||||
|
||||
@php
|
||||
$komuditi = Http::withOptions(['verify' => config('app.api_verify')])
|
||||
$shorakaPrint = app(\App\Services\ShorakaFinancingService::class)->printData($gadai_detail['norujukan']);
|
||||
if ($shorakaPrint) {
|
||||
$komuditi = $shorakaPrint['komoditi'];
|
||||
$product = $shorakaPrint['product'];
|
||||
$kuantiti = $shorakaPrint['kuantiti'];
|
||||
} else {
|
||||
$komuditi = Http::withOptions(['verify' => config('app.api_verify')])
|
||||
->get($api_url . '/api/komuditi/check')
|
||||
->json();
|
||||
$product = Http::withOptions(['verify' => config('app.api_verify')])
|
||||
->get($api_url . '/api/komuditi/description', ['kodproduk' => $komuditi['kodproduct']])
|
||||
->json();
|
||||
$kuantiti = $gadai_detail['pinjaman'] / $komuditi['nilai'];
|
||||
}
|
||||
@endphp
|
||||
|
||||
<table style="margin-bottom:10px;" id="keuntungan">
|
||||
|
||||
@@ -713,13 +713,20 @@
|
||||
</tr>
|
||||
</table>
|
||||
@php
|
||||
$komuditi = Http::withOptions(['verify' => config('app.api_verify')])
|
||||
$shorakaPrint = app(\App\Services\ShorakaFinancingService::class)->printData($gadai_detail['norujukan']);
|
||||
if ($shorakaPrint) {
|
||||
$komuditi = $shorakaPrint['komoditi'];
|
||||
$product = $shorakaPrint['product'];
|
||||
$kuantiti = $shorakaPrint['kuantiti'];
|
||||
} else {
|
||||
$komuditi = Http::withOptions(['verify' => config('app.api_verify')])
|
||||
->get($api_url . '/api/komuditi/check')
|
||||
->json();
|
||||
$product = Http::withOptions(['verify' => config('app.api_verify')])
|
||||
->get($api_url . '/api/komuditi/description', ['kodproduk' => $komuditi['kodproduct']])
|
||||
->json();
|
||||
$kuantiti = $gadai_detail['pinjaman'] / $komuditi['nilai'];
|
||||
}
|
||||
@endphp
|
||||
|
||||
<table id="keuntungan" style="margin-bottom:10px;">
|
||||
|
||||
@@ -615,7 +615,7 @@
|
||||
<td>{{ $komoditi['no_sijil'] }}</td>
|
||||
<td class="text-center">4</td>
|
||||
<td>Kuantiti (Unit)</td>
|
||||
<td>{{ number_format($kuantiti, 2) }} TAN</td>
|
||||
<td>{{ $kuantiti }} TONNES</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-center">2</td>
|
||||
@@ -1849,7 +1849,7 @@
|
||||
<td>{{ $komoditi['no_sijil'] }}</td>
|
||||
<td class="text-center">4</td>
|
||||
<td>Kuantiti</td>
|
||||
<td>{{ number_format($kuantiti, 2) }}</td>
|
||||
<td>{{ $kuantiti }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-center">2</td>
|
||||
@@ -2112,6 +2112,7 @@
|
||||
</div>
|
||||
<div class="main-page" style="font-family: Arial, Helvetica, sans-serif;">
|
||||
<div class="sub-page" style="font-size: 11px;">
|
||||
@if ($pembiayaanOnlineEnabled ?? false)
|
||||
@php
|
||||
$caraTerimaBayaran = strtoupper(trim((string) ($gadai_detail['cara_terima'] ?? '')));
|
||||
@endphp
|
||||
@@ -2128,6 +2129,7 @@
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
{{-- HEADER SECTION --}}
|
||||
<table style="width: 100%; margin-top: 0;">
|
||||
<tr style="vertical-align: top;">
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<style>
|
||||
.shoraka-list-card .table th,
|
||||
.shoraka-list-card .table td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.shoraka-list-card .status-badge {
|
||||
padding: 8px 12px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
white-space: normal;
|
||||
line-height: 1.5;
|
||||
}
|
||||
</style>
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-12">
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb pb-3">
|
||||
<li class="breadcrumb-item"><a href="{{ route('home') }}">Home</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page">Komoditi Shoraka</li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<div class="card shoraka-list-card">
|
||||
<div class="card-header bg-secondary d-flex flex-wrap align-items-center justify-content-between">
|
||||
<h5 class="mb-0 py-2">Komoditi Shoraka</h5>
|
||||
<a class="btn btn-info btn-sm my-1" href="{{ route('home') }}">
|
||||
<i class="fas fa-arrow-left mr-1" aria-hidden="true"></i> Kembali ke Paparan Utama
|
||||
</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="text-muted mb-4">Semak transaksi komoditi Shoraka cawangan ini.</p>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-bordered table-hover mb-0">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th scope="col">No. rujukan</th>
|
||||
<th scope="col">Teller</th>
|
||||
<th scope="col">Status komoditi</th>
|
||||
<th scope="col" class="text-center">Tindakan</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($records as $record)
|
||||
<tr>
|
||||
<td class="text-nowrap">{{ $record['norujukan'] }}</td>
|
||||
<td>{{ $record['teller'] ?: '—' }}</td>
|
||||
<td>
|
||||
<span class="badge badge-info status-badge">{{ $record['status'] ?: '—' }}</span>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<a class="btn btn-info btn-sm" href="{{ route('shoraka.show', $record['norujukan']) }}" aria-label="Buka pembiayaan {{ $record['norujukan'] }}">Buka</a>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr><td colspan="4" class="text-center text-muted py-5">Tiada transaksi.</td></tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
@@ -0,0 +1,63 @@
|
||||
<div id="shoraka-modal" hidden style="position:fixed;inset:0;z-index:20000;background:rgba(0,0,0,.5);display:none;align-items:center;justify-content:center;padding:16px">
|
||||
<div role="dialog" aria-modal="true" aria-labelledby="shoraka-modal-title" tabindex="-1" style="background:#fff;border-radius:5px;padding:24px;max-width:460px;width:100%;text-align:center;box-shadow:0 8px 30px #0003">
|
||||
<h4 id="shoraka-modal-title">Pembelian Komoditi Shoraka</h4>
|
||||
<p id="shoraka-modal-message" role="status" aria-live="polite">Sedang memproses pembelian komoditi...</p>
|
||||
<ol style="text-align:left;padding-left:28px">
|
||||
<li data-shoraka-step="1">Menyimpan gadaian dan menghantar order</li>
|
||||
<li data-shoraka-step="2">Menunggu pengesahan Shoraka</li>
|
||||
<li data-shoraka-step="3">Menyelesaikan pembiayaan</li>
|
||||
</ol>
|
||||
<p class="text-muted small">Sila tunggu sehingga proses selesai. Jangan hantar transaksi semula.</p>
|
||||
<div id="shoraka-modal-spinner" class="spinner-border text-primary" role="status"><span class="sr-only">Sedang memproses</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
window.shorakaProgress = (function () {
|
||||
var modal = document.getElementById('shoraka-modal');
|
||||
var previousFocus;
|
||||
modal.addEventListener('keydown', function (event) {
|
||||
if (event.key === 'Tab') {
|
||||
event.preventDefault();
|
||||
modal.querySelector('[role="dialog"]').focus();
|
||||
}
|
||||
});
|
||||
return function (step, message, stopped) {
|
||||
if (stopped) {
|
||||
modal.hidden = true;
|
||||
modal.style.display = 'none';
|
||||
if (previousFocus) { previousFocus.focus(); }
|
||||
return;
|
||||
}
|
||||
if (modal.hidden) { previousFocus = document.activeElement; }
|
||||
modal.hidden = false;
|
||||
modal.style.display = 'flex';
|
||||
document.getElementById('shoraka-modal-message').textContent = message || 'Sedang memproses pembelian komoditi...';
|
||||
modal.querySelectorAll('[data-shoraka-step]').forEach(function (item) {
|
||||
var number = Number(item.getAttribute('data-shoraka-step'));
|
||||
item.className = number < step ? 'text-success' : (number === step ? 'text-primary font-weight-bold' : 'text-muted');
|
||||
if (number === step) { item.setAttribute('aria-current', 'step'); }
|
||||
else { item.removeAttribute('aria-current'); }
|
||||
});
|
||||
modal.querySelector('[role="dialog"]').focus();
|
||||
};
|
||||
}());
|
||||
window.shorakaTrack = function (statusUrl) {
|
||||
if (window.shorakaTrackTimer) { clearInterval(window.shorakaTrackTimer); }
|
||||
window.shorakaProgress(1, 'Menyimpan gadaian dan menghantar order...');
|
||||
window.shorakaTrackTimer = setInterval(function () {
|
||||
$.get(statusUrl).done(function (body) {
|
||||
var order = body && body.data && body.data.order;
|
||||
var status = order && order.status;
|
||||
if (status === 'Completed') {
|
||||
clearInterval(window.shorakaTrackTimer);
|
||||
window.shorakaProgress(3, 'Menyelesaikan pembiayaan...');
|
||||
} else if (status === 'Cancelled' || status === 'FAILED' || status === 'UNKNOWN') {
|
||||
clearInterval(window.shorakaTrackTimer);
|
||||
window.shorakaProgress(2, 'Transaksi Shoraka gagal. Sila tunggu...');
|
||||
} else if (status) {
|
||||
window.shorakaProgress(2, 'Menunggu pengesahan Shoraka...');
|
||||
}
|
||||
});
|
||||
}, 1500);
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,96 @@
|
||||
@extends($isOperasi ? 'layouts.app_operasi' : 'layouts.app')
|
||||
|
||||
@section('content')
|
||||
@php
|
||||
$listRoute = $isOperasi ? 'operasi.shoraka.index' : 'pc.shoraka.index';
|
||||
$statusLabels = ['PENDING' => 'PENDING', 'Active' => 'Active', 'Completed' => 'Completed', 'Cancelled' => 'Cancelled', 'UNKNOWN' => 'UNKNOWN', 'FAILED' => 'FAILED'];
|
||||
@endphp
|
||||
<div class="container-fluid">
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="{{ route('home') }}">Home</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page">Komoditi Shoraka — {{ $isOperasi ? 'Operasi' : strtoupper(Auth::user()->roles) }}</li>
|
||||
</ol>
|
||||
</nav>
|
||||
<div class="card">
|
||||
<div class="card-header d-flex flex-wrap justify-content-between align-items-center">
|
||||
<h5 class="mb-0 py-2">Komoditi Shoraka — {{ $isOperasi ? 'Semua Cawangan' : Auth::user()->cawangan }}</h5>
|
||||
<a href="{{ route('home') }}" class="btn btn-info btn-sm">Kembali ke Paparan Utama</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="text-muted">Paparan transaksi komoditi Shoraka {{ $isOperasi ? 'semua cawangan' : 'cawangan sendiri' }}.</p>
|
||||
@if($errors->any())
|
||||
<div class="alert alert-danger" role="alert">{{ $errors->first() }}</div>
|
||||
@endif
|
||||
<form method="get" action="{{ route($listRoute) }}" class="mb-4">
|
||||
<div class="form-row align-items-end">
|
||||
@if($isOperasi)
|
||||
<div class="form-group col-md-3">
|
||||
<label for="shoraka-branch">Cawangan</label>
|
||||
<select id="shoraka-branch" name="kodcaw" class="form-control">
|
||||
<option value="">{{ $isOperasi ? 'Semua cawangan' : Auth::user()->cawangan }}</option>
|
||||
@foreach($branches as $branch)
|
||||
<option value="{{ $branch }}" {{ ($filters['kodcaw'] ?? '') === $branch ? 'selected' : '' }}>{{ $branch }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
@endif
|
||||
<div class="form-group col-md-3">
|
||||
<label for="shoraka-reference">No. rujukan penuh</label>
|
||||
<input id="shoraka-reference" name="norujukan" class="form-control" maxlength="100" value="{{ $filters['norujukan'] ?? '' }}">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label for="shoraka-status">Status komoditi</label>
|
||||
<select id="shoraka-status" name="status" class="form-control">
|
||||
<option value="">Semua status</option>
|
||||
@foreach($statusLabels as $status => $label)
|
||||
<option value="{{ $status }}" {{ ($filters['status'] ?? '') === $status ? 'selected' : '' }}>{{ $label }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label for="shoraka-date-from">Tarikh mula didaftarkan</label>
|
||||
<input type="date" id="shoraka-date-from" name="date_from" class="form-control" value="{{ $filters['date_from'] ?? '' }}">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label for="shoraka-date-to">Tarikh akhir didaftarkan</label>
|
||||
<input type="date" id="shoraka-date-to" name="date_to" class="form-control" value="{{ $filters['date_to'] ?? '' }}">
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<button type="submit" class="btn btn-primary">Tapis</button>
|
||||
<a href="{{ route($listRoute) }}" class="btn btn-secondary">Reset</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<p>{{ $records->total() }} rekod</p>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-bordered table-hover">
|
||||
<thead class="thead-dark"><tr>
|
||||
<th scope="col">Cawangan</th>
|
||||
<th scope="col">No. rujukan</th>
|
||||
<th scope="col">Teller</th>
|
||||
<th scope="col">Status komoditi</th>
|
||||
<th scope="col">Didaftarkan</th>
|
||||
<th scope="col">Dikemas kini</th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
@forelse($records as $record)
|
||||
<tr>
|
||||
<td>{{ $record['kodcaw'] }}</td>
|
||||
<td class="text-nowrap">{{ $record['norujukan'] }}</td>
|
||||
<td>{{ $record['teller'] ?: '—' }}</td>
|
||||
<td><span class="badge badge-info p-2">{{ $record['status'] ?: '—' }}</span></td>
|
||||
<td class="text-nowrap">{{ !empty($record['created_at']) ? \Carbon\Carbon::parse($record['created_at'])->format('d/m/Y H:i') : '—' }}</td>
|
||||
<td class="text-nowrap">{{ !empty($record['updated_at']) ? \Carbon\Carbon::parse($record['updated_at'])->format('d/m/Y H:i') : '—' }}</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr><td colspan="6" class="text-center text-muted py-4">Tiada transaksi untuk tapisan ini.</td></tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{ $records->links() }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
@@ -0,0 +1,71 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-12">
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb pb-3">
|
||||
<li class="breadcrumb-item"><a href="{{ route('home') }}">Home</a></li>
|
||||
<li class="breadcrumb-item"><a href="{{ route('shoraka.index') }}">Komoditi Shoraka</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page">{{ $norujukan }}</li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header bg-secondary d-flex flex-wrap align-items-center justify-content-between">
|
||||
<h5 class="mb-0 py-2">Komoditi Shoraka</h5>
|
||||
<a class="btn btn-info btn-sm my-1" href="{{ route('shoraka.index') }}">
|
||||
<i class="fas fa-arrow-left mr-1" aria-hidden="true"></i> Kembali ke senarai
|
||||
</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if(!empty($data['simulation']))
|
||||
<div class="alert alert-warning">SIMULASI LOCAL — tiada transaksi sebenar dihantar ke Shoraka.</div>
|
||||
@endif
|
||||
@php
|
||||
$order = $data['order'] ?? null;
|
||||
$status = $order['status'] ?? 'Belum dihantar';
|
||||
$ready = !empty($data['can_complete']);
|
||||
@endphp
|
||||
@if($error)<div class="alert alert-danger">{{ $error }}</div>@endif
|
||||
<p class="text-muted mb-3">No. rujukan: <strong class="text-dark">{{ $norujukan }}</strong></p>
|
||||
<div class="table-responsive mb-4">
|
||||
<table class="table table-striped table-bordered mb-0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row" class="align-middle">Status komoditi</th>
|
||||
<td><span class="badge badge-info px-3 py-2">{{ $status }}</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Order ID</th>
|
||||
<td>{{ $order['order_id'] ?? '—' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Pembiayaan</th>
|
||||
<td class="text-nowrap font-weight-bold">RM {{ number_format($data['order_amount'] ?? 0, 2) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Harga jualan</th>
|
||||
<td class="text-nowrap font-weight-bold">RM {{ number_format($data['murabaha_amount'] ?? 0, 2) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@if(!$ready)
|
||||
<div class="alert alert-warning">Bayaran pembiayaan dan SAG ditahan sehingga transaksi komoditi Completed.</div>
|
||||
@endif
|
||||
@if(in_array($status, ['UNKNOWN', 'FAILED', 'PENDING']))
|
||||
<p>Jangan hantar order sekali lagi. Hubungi operasi untuk semakan dengan Shoraka.</p>
|
||||
@endif
|
||||
@if($ready)
|
||||
<div class="d-flex flex-wrap pt-3 mt-4 border-top">
|
||||
<a class="btn btn-secondary mb-2" href="{{ route('shoraka.certificate', $norujukan) }}">Muat Turun Sijil</a>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
+19
-2
@@ -17,6 +17,8 @@ use Illuminate\Support\Facades\Storage;
|
||||
|
||||
Route::post('/internal/notifications', ['as' => 'internal.notifications.store', 'uses' => 'InternalNotificationController@store']);
|
||||
|
||||
Route::view('/dasar-privasi', 'dasar-privasi')->name('dasar.privasi');
|
||||
|
||||
Route::get('/health', function () {
|
||||
return response()->json(['status' => 'ok']);
|
||||
});
|
||||
@@ -61,7 +63,13 @@ Route::get('test', function () {
|
||||
return "event test je";
|
||||
});
|
||||
|
||||
Route::get('logs', '\Rap2hpoutre\LaravelLogViewer\LogViewerController@index');
|
||||
Route::get('logs', '\Rap2hpoutre\LaravelLogViewer\LogViewerController@index')
|
||||
->middleware([
|
||||
'auth',
|
||||
'role:admin,masteradmin,operasi',
|
||||
'throttle:10,1',
|
||||
\App\Http\Middleware\LogViewerPassword::class,
|
||||
]);
|
||||
Route::get('change-password', ['as'=>'user.password','uses'=>'ChangePasswordController@index']);
|
||||
Route::post('change-password', ['as'=>'change.password','uses'=>'ChangePasswordController@store']);
|
||||
|
||||
@@ -204,6 +212,7 @@ Route::put('/pembiayaan-online/pc/lines/{id}',['as'=>'pembiayaan.online.pc.updat
|
||||
Route::post('/pembiayaan-online/pc/lines/{id}/verify',['as'=>'pembiayaan.online.pc.verify','uses'=>'PembiayaanOnlineController@verifyLine'])->middleware('auth','khazanah');
|
||||
Route::post('/pembiayaan-online/pc/lines/{id}/unverify',['as'=>'pembiayaan.online.pc.unverify','uses'=>'PembiayaanOnlineController@unverifyLine'])->middleware('auth','khazanah');
|
||||
Route::get('/pembiayaan-online/pc/lines/{id}/bukti-akaun',['as'=>'pembiayaan.online.pc.bukti.akaun','uses'=>'PembiayaanOnlineController@viewBuktiAkaun'])->middleware('auth','khazanah');
|
||||
Route::get('/pembiayaan-online/pc/lines/{id}/borang',['as'=>'pembiayaan.online.pc.borang','uses'=>'PembiayaanOnlineController@viewBorang'])->middleware('auth','khazanah');
|
||||
Route::get('/pembiayaan-online/pc/lines/{id}/sag',['as'=>'pembiayaan.online.pc.sag','uses'=>'PembiayaanOnlineController@viewSag'])->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');
|
||||
@@ -230,6 +239,7 @@ Route::post('/pembiayaan-online/operasi/{kodcaw}/batches/{batchId}/approve',['as
|
||||
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('/pembiayaan-online/operasi/{kodcaw}/lines/{id}/bukti-akaun',['as'=>'pembiayaan.online.operasi.bukti.akaun','uses'=>'PembiayaanOnlineController@operasiViewBuktiAkaun'])->middleware('auth','operasi');
|
||||
Route::get('/pembiayaan-online/operasi/{kodcaw}/lines/{id}/borang',['as'=>'pembiayaan.online.operasi.borang','uses'=>'PembiayaanOnlineController@operasiViewBorang'])->middleware('auth','operasi');
|
||||
Route::get('/pembiayaan-online/operasi/{kodcaw}/lines/{id}/sag',['as'=>'pembiayaan.online.operasi.sag','uses'=>'PembiayaanOnlineController@operasiViewSag'])->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');
|
||||
@@ -412,6 +422,8 @@ Route::group(['middleware' => ['khazanah']], function() {
|
||||
Route::post('/barcodescanned',['as'=>'barcode.scanned','uses'=>'KhazanahController@barcodescanned'])->middleware('auth','khazanah');
|
||||
|
||||
//Operasi
|
||||
Route::get('/pc/shoraka', 'ShorakaController@pcIndex')->name('pc.shoraka.index')->middleware('auth', 'khazanah');
|
||||
Route::get('/operasi/shoraka', 'ShorakaController@operasiIndex')->name('operasi.shoraka.index')->middleware('auth', 'operasi');
|
||||
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');
|
||||
@@ -597,4 +609,9 @@ Route::post('/pampasan/terima',['as' => 'pampasan.terima', 'uses' => 'KhazanahCo
|
||||
Route::get(('/pampasan/resit'), ['as' => 'pampasan.resit', 'uses' => 'KhazanahController@resitPampasan'])->middleware('auth', 'khazanah');
|
||||
|
||||
//Surat Pampasan
|
||||
Route::get('/pampasan/surat/{norujukan}', ['as' => 'pampasan.surat', 'uses' => 'KhazanahController@suratPampasan'])->middleware('auth', 'role:teller,khazanah');
|
||||
Route::get('/pampasan/surat/{norujukan}', ['as' => 'pampasan.surat', 'uses' => 'KhazanahController@suratPampasan'])->middleware('auth', 'role:teller,khazanah');
|
||||
Route::group(['prefix' => 'shoraka', 'middleware' => ['auth', 'role:teller,penilai,khazanah,admin,masteradmin,operasi']], function () {
|
||||
Route::get('/', 'ShorakaController@index')->name('shoraka.index');
|
||||
Route::get('/{norujukan}', 'ShorakaController@show')->name('shoraka.show');
|
||||
Route::get('/{norujukan}/certificate', 'ShorakaController@certificate')->name('shoraka.certificate');
|
||||
});
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Http\Middleware\LogViewerPassword;
|
||||
use Illuminate\Http\Request;
|
||||
use Tests\TestCase;
|
||||
|
||||
class LogViewerPasswordTest extends TestCase
|
||||
{
|
||||
public function test_missing_configuration_denies_access()
|
||||
{
|
||||
config(['logviewer.password' => null]);
|
||||
$response = $this->checkAccess();
|
||||
$this->assertSame(503, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function test_missing_or_incorrect_credentials_are_rejected()
|
||||
{
|
||||
config(['logviewer.password' => password_hash('test-only-secret', PASSWORD_DEFAULT)]);
|
||||
foreach ([[], ['PHP_AUTH_USER' => 'logs', 'PHP_AUTH_PW' => 'wrong'],
|
||||
['PHP_AUTH_USER' => 'other', 'PHP_AUTH_PW' => 'test-only-secret']] as $server) {
|
||||
$response = $this->checkAccess($server);
|
||||
$this->assertSame(401, $response->getStatusCode());
|
||||
$this->assertStringContainsString('Basic realm=', $response->headers->get('WWW-Authenticate'));
|
||||
}
|
||||
}
|
||||
|
||||
public function test_correct_credentials_allow_access_without_caching()
|
||||
{
|
||||
config(['logviewer.password' => password_hash('test-only-secret', PASSWORD_DEFAULT)]);
|
||||
$response = $this->checkAccess(['PHP_AUTH_USER' => 'logs', 'PHP_AUTH_PW' => 'test-only-secret']);
|
||||
$this->assertSame(200, $response->getStatusCode());
|
||||
$this->assertSame('allowed', $response->getContent());
|
||||
$this->assertStringContainsString('no-store', $response->headers->get('Cache-Control'));
|
||||
}
|
||||
|
||||
public function test_logs_route_has_auth_role_password_and_throttle_middleware()
|
||||
{
|
||||
$route = app('router')->getRoutes()->match(Request::create('/logs'));
|
||||
$middleware = $route->gatherMiddleware();
|
||||
$this->assertContains('auth', $middleware);
|
||||
$this->assertContains('role:admin,masteradmin', $middleware);
|
||||
$this->assertContains(LogViewerPassword::class, $middleware);
|
||||
$this->assertContains('throttle:10,1', $middleware);
|
||||
}
|
||||
|
||||
private function checkAccess(array $server = [])
|
||||
{
|
||||
$request = Request::create('/logs?dl=example', 'GET', [], [], [], $server);
|
||||
return (new LogViewerPassword)->handle($request, function () {
|
||||
return response('allowed');
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user