Merge with feature/aiman/pampasan/sempornaV2

This commit is contained in:
Afiq Hamzah
2025-10-05 16:34:16 +08:00
parent 04ed49af8a
commit cab39e6604
20 changed files with 3224 additions and 792 deletions
+192
View File
@@ -0,0 +1,192 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Repository Overview
This is the **Kaunter** application, part of the Arrahn PKB (Pajak Gadai Sistem) - an Islamic pawn shop/mortgage management system. This Laravel 7.x application serves as the counter/teller interface for managing pawn transactions, customer interactions, and branch operations within a larger microservices architecture.
## Application Architecture
### Core Business Domain
The application manages Islamic financial transactions including:
- **Gadaian** - Pawn/mortgage transactions with Islamic finance compliance
- **Penebusan** - Redemption and repayment processes
- **Customer Management** - Customer records with document management
- **Marhun** - Collateral item management (primarily gold jewelry)
- **Treasury Operations** - Cash flow and financial reconciliation
### Role-Based Access Control
The system implements 8 distinct user roles with dedicated middleware:
- `teller` - Front desk operations
- `khazanah` - Treasury/financial management
- `operasi` - Operations management
- `admin` - Administrative functions
- `penilai` - Item appraisers
- `callcenter` - Customer service
- `audit` - Financial auditing
- `akaun` - Accounting functions
Each role has specific controllers, views, and middleware (`app/Http/Middleware/`).
### API-First Architecture
Controllers primarily delegate to external APIs rather than direct database operations:
- API URLs configured via `config('api.url')`
- API verification settings via `config('app.api_verify')`
- Multi-zone API support for different business units
## Development Commands
### Laravel Application Commands
```bash
# Install dependencies (use Docker containers as per parent repository)
docker compose run --rm composer install
docker compose run --rm npm install
# Generate application key
docker compose run --rm artisan key:generate
# Run migrations
docker compose run --rm artisan migrate
docker compose run --rm artisan migrate:fresh
# Clear caches
docker compose run --rm artisan cache:clear
docker compose run --rm artisan config:clear
docker compose run --rm artisan view:clear
```
### Frontend Asset Management
```bash
# Development build with watch
docker compose run --rm npm run dev
docker compose run --rm npm run watch
# Production build
docker compose run --rm npm run production
# Hot reload for development
docker compose run --rm npm run hot
```
### Testing
```bash
# Run all tests
docker compose run --rm vendor/bin/phpunit
# Run specific test suites
docker compose run --rm vendor/bin/phpunit --testsuite=Unit
docker compose run --rm vendor/bin/phpunit --testsuite=Feature
# Run with coverage
docker compose run --rm vendor/bin/phpunit --coverage-html coverage
```
### Custom Artisan Commands (Financial Operations)
```bash
# Daily financial operations
docker compose run --rm artisan akru:daily
docker compose run --rm artisan imbangduga:daily
# Monthly operations
docker compose run --rm artisan backup:stokaudit
# System maintenance
docker compose run --rm artisan reset:role-daily
docker compose run --rm artisan check:lelong-tawarruq
```
## Key Application Components
### Core Models & Relationships
- **`Gadaian`** - Central pawn transaction model with customer and marhun relationships
- **`Customer`** - Uses Spatie MediaLibrary for document management
- **`Penebusan`** - Redemption transactions linked to gadaian records
- **`Marhun`** - Collateral items with detailed specifications
- **`HargaEmas`** - Gold pricing with historical tracking
- **`ImbangDuga`** - Trial balance for financial reconciliation
### Business Services
- **`CustomerService`** - Customer operations including automated number generation
- **`ImbangdugaServices`** - Financial reconciliation and trial balance operations
### Event System
Real-time dashboard updates via Laravel Events:
- Dashboard notifications: `GadaiNotify`, `TebusNotify`, `KeuntunganNotify`
- Process events: `AutoSerahan`, `SerahanPenilai`
- User notifications: `NotifikasiPembayaran`, `NotifikasiKelulusan`
### Configuration Files
- **`config/redeemoption.php`** - Business logic toggles for redemption features
- **`config/adminlte.php`** - AdminLTE dashboard configuration
- **Environment files** - Multiple environment configurations in `env.docker.example/`
## Technology Stack
### Laravel Packages
- **AdminLTE 3** (`jeroennoten/laravel-adminlte`) - Administrative interface
- **Spatie MediaLibrary** - File and document management
- **DomPDF** (`barryvdh/laravel-dompdf`) - PDF report generation
- **Pusher** - Real-time notifications
- **Twilio SDK** - SMS communication
- **DataTables** (`yajra/laravel-datatables-oracle`) - Advanced table management
- **QR Code & Barcode** - Document generation utilities
### Frontend Stack
- **Laravel Mix** - Asset compilation (Webpack wrapper)
- **AdminLTE 3** - Bootstrap-based admin template
- **jQuery** - DOM manipulation and AJAX
- **Socket.io** - Real-time communication client
- **Bootstrap 4** - CSS framework
## Development Workflow
### Environment Setup
1. Copy appropriate environment file from `env.docker.example/` directory
2. Configure database connections for multi-zone setup
3. Set API endpoints for microservices communication
4. Configure Pusher for real-time features
5. Set up Twilio credentials for SMS functionality
### Working with Roles
When developing role-specific features:
1. Check relevant middleware in `app/Http/Middleware/`
2. Use role-specific views in `resources/views/homepage/{role}/`
3. Follow role-based routing patterns in `routes/web.php`
4. Ensure API calls respect role permissions
### API Integration Pattern
When adding new functionality:
1. Controllers should primarily make API calls rather than direct DB operations
2. Use Laravel HTTP client for external API communication
3. Handle API responses consistently across controllers
4. Implement proper error handling for API failures
### Testing Islamic Finance Logic
- Use `php artisan check:lelong-tawarruq` to verify Islamic compliance
- Test accrual calculations with `php artisan akru:daily`
- Validate trial balance with `php artisan imbangduga:daily`
## File Structure Notes
### View Organization
- **Versioned views** - `v1/` and `v2/` directories indicate system evolution
- **Role-based dashboards** - Separate homepage views for each user role
- **Business-specific templates** - Islamic finance compliance features
### Custom Commands Location
All financial operation commands are in `app/Console/Commands/` with descriptive names indicating their business purpose.
### Configuration Patterns
- Business logic configuration separated into dedicated config files
- Environment-specific settings in docker example files
- Multi-zone database configuration support
## Important Development Notes
- This application is part of a Docker microservices architecture
- Changes should maintain Islamic finance compliance requirements
- Real-time features depend on Pusher configuration
- Role-based access control is fundamental to all operations
- API integrations are critical - local database operations are minimal
- Multi-language support focuses on Malaysian Malay context
+67 -4
View File
@@ -1,20 +1,83 @@
<?php
namespace App;
use DateTime;
class Helper
{
public static function formatNumber($amount)
{
$formattedAmount = number_format($amount, 2, '.', ',');
return $formattedAmount;
return number_format($amount, 2, '.', ',');
}
public static function formatDate($date_string)
{
return (new DateTime($date_string))->format("d-m-Y");
}
public static function terbilangBm(int $number): string
{
$units = [
0 => 'kosong',
1 => 'satu',
2 => 'dua',
3 => 'tiga',
4 => 'empat',
5 => 'lima',
6 => 'enam',
7 => 'tujuh',
8 => 'lapan',
9 => 'sembilan',
10 => 'sepuluh',
11 => 'sebelas'
];
if ($number < 0) return 'negatif ' . self::terbilangBm(abs($number));
if ($number < 12) return $units[$number];
if ($number < 20) return self::terbilangBm($number - 10) . ' belas';
if ($number < 100) {
$tens = intdiv($number, 10);
$rest = $number % 10;
return self::terbilangBm($tens) . ' puluh' . ($rest ? ' ' . self::terbilangBm($rest) : '');
}
if ($number < 200) return 'seratus' . ($number > 100 ? ' ' . self::terbilangBm($number - 100) : '');
if ($number < 1000) {
$hundreds = intdiv($number, 100);
$rest = $number % 100;
return self::terbilangBm($hundreds) . ' ratus' . ($rest ? ' ' . self::terbilangBm($rest) : '');
}
if ($number < 2000) return 'seribu' . ($number > 1000 ? ' ' . self::terbilangBm($number - 1000) : '');
if ($number < 1000000) {
$thousands = intdiv($number, 1000);
$rest = $number % 1000;
return self::terbilangBm($thousands) . ' ribu' . ($rest ? ' ' . self::terbilangBm($rest) : '');
}
if ($number < 1000000000) {
$millions = intdiv($number, 1000000);
$rest = $number % 1000000;
return self::terbilangBm($millions) . ' juta' . ($rest ? ' ' . self::terbilangBm($rest) : '');
}
return 'terlalu besar';
}
public static function ringgitTerbilang($amount, bool $tambahSahaja = true): string
{
$formatted = number_format((float)$amount, 2, '.', '');
[$ringgitStr, $senStr] = explode('.', $formatted);
$ringgit = (int)$ringgitStr;
$sen = (int)$senStr;
$parts = [];
$parts[] = self::terbilangBm($ringgit) . ' ringgit';
if ($sen > 0) {
$parts[] = 'dan ' . self::terbilangBm($sen) . ' sen';
} elseif ($tambahSahaja) {
$parts[] = 'sahaja';
}
return trim(preg_replace('/\s+/', ' ', implode(' ', $parts)));
}
}
+271 -1
View File
@@ -4417,4 +4417,274 @@ class KhazanahController extends Controller
}
}
public function pampasanDetail($id)
{
$auth_user = Auth::user();
$api_url = config('api.url');
$cawangan_info = Http::withOptions(['verify' => config('app.api_verify')])
->get(config('api.url') . '/api/cawangan/' . $auth_user['cawangan'])
->json();
$gadai = Http::withOptions(['verify' => config('app.api_verify')])
->get(config('api.url') . '/api/gadai/norujukan/' . '011237' . '/' . $id)
->json();
$gadai_info = is_array($gadai) && isset($gadai[0]) ? $gadai[0] : $gadai;
$customer_info = null;
if(isset($gadai_info['nokp'])) {
$customer = Http::withOptions(['verify' => config('app.api_verify')])
->get(config('api.url') . '/api/customers/' . $gadai_info['nokp'])
->json();
$customer_info = null;
if (isset($gadai_info['nokp'])) {
$customer = Http::withOptions(['verify' => config('app.api_verify')])
->get(config('api.url') . '/api/customers/' . $gadai_info['nokp'])
->json();
$customer_info = is_array($customer) && isset($customer[0]) ? $customer[0] : $customer;
}
$barang_kes = Http::withOptions(['verify' => config('app.api_verify')])
->get(config('api.url') . '/api/palsu/laporan/', ['kodcaw' => $auth_user['cawangan']])
->json();
// You may need to adjust the array index if the API returns an array of results
$gadai_info = is_array($gadai) && isset($gadai[0]) ? $gadai[0] : $gadai;
// $pampasan_info = is_array($pampasan) && isset($pampasan[0]) ? $pampasan[0] : $pampasan;
$barang_kes_collection = collect($barang_kes);
$barang_kes_info = $barang_kes_collection->where('norujukan', '=', $id)->first();
$customer_info = null;
if (isset($gadai_info['nokp'])) {
$customer = Http::withOptions(['verify' => config('app.api_verify')])
->get(config('api.url') . '/api/customers/' . $gadai_info['nokp'])
->json();
$customer_info = is_array($customer) && isset($customer[0]) ? $customer[0] : $customer;
}
$denominasi = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/DenominasiController/' . $auth_user['cawangan'])->json();
if (sizeof($denominasi) == 0) {
$denominasi = Http::withOptions(['verify' => config('app.api_verify')])->post(config('api.url') . '/api/DenominasiCreate/' . $auth_user['cawangan'])->json();
} else {
$denominasi = $denominasi[0];
}
$pampasan = Http::withOptions(['verify' => config('app.api_verify')])
->get(config('api.url') . '/api/pampasan', ['kodcaw' => '011237', 'norujukan' => $id])
->json()['data'][0];
$baucerno = $pampasan['baucerno'];
$nilaimarhun = $barang_kes_info['nilaimarhun'] ?? 0;
$pembiayaan = $barang_kes_info['pembiayaan'] ?? 0;
$untung = $barang_kes_info['untung'] ?? 0;
$jumlah_tebus = Http::withOptions(['verify' => config('app.api_verify')])
->get(config('api.url') . '/api/tebus/norujukan/' . $auth_user['cawangan'] . '/' . $id)
->json()[0]['bakipjm'];
$jumlah_pampasan = $nilaimarhun - $pembiayaan - $untung;
$jumlahPanjar = $jumlah_tebus + $jumlah_pampasan;
return view('khazanah.pampasan_detail', compact('gadai_info', 'barang_kes_info', 'cawangan_info', 'customer_info', 'baucerno', 'denominasi', 'jumlah_pampasan', 'jumlah_tebus', 'jumlahPanjar'));
}
}
public function initiatePampasan(Request $request)
{
$norujukan = $request->input('norujukan');
$teller = auth()->user()->name;
$kodcaw = auth()->user()->cawangan;
$baucerno = $this->generateBaucer($kodcaw);
$response = Http::post(config('api.url') . '/api/pampasan/initiatePampasan', [
'norujukan' => $norujukan,
'kodcaw' => $kodcaw,
'teller' => $teller,
'baucerno' => $baucerno,
]);
if ($response->failed()) {
throw new \Exception("HTTP error! status: " . $response->status(), 1);
}
$result = $response->json();
// $jumlah_pampasan = $nilaimarhun - $pembiayaan - $untung;
// $jumlahTebus = $pembiayaan + $untung;
// $jumlahPanjar = $jumlah_pampasan + $jumlahTebus;
//return view('khazanah.pampasan_detail', compact('gadai_info', 'pampasan_info', 'cawangan_info', 'customer_info','baucerno', 'denominasi','jumlah_pampasan', 'jumlahTebus', 'jumlahPanjar') );
return response()->json($result);
}
public function generateBaucer($kodcaw)
{
$data = Http::withOptions(['verify' => config('app.api_verify')])
->get(config('api.url').'/api/SenaraiPanjar/list/' . $kodcaw)
->json();
$today = now();
$dd = $today->format('d');
$mm = $today->format('m');
$yy = $today->format('y');
$recno = $data['recno'] ?? 0;
$baucerno = 'B' . $yy . $mm . $dd . '-' . str_pad($recno, 4, '0', STR_PAD_LEFT);
return $baucerno;
}
public function terimaPampasan(Request $request)
{
$responsePampasan = Http::withOptions(['verify' => config('app.api_verify')])
->post(config('api.url') . '/api/pampasan/terimaPampasan',[
"norujukan" => $request->norujukan,
"kodcaw" => auth()->user()->cawangan,
"jumlah_pampasan" => $request->jumlahpampasan,
"teller" => auth()->user()->name,
"denominasi" => $request->denominasi,
]
)->json();
$jumlahTebus = Http::withOptions(['verify' => config('app.api_verify')])
->get(config('api.url') . '/api/tebus/norujukan/' . auth()->user()->cawangan .'/'.$request->norujukan)->json()[0]['bakipjm'];
$bayaranPanjar = $request->jumlahpampasan + $jumlahTebus;
$responsePanjar = Http::withOptions(['verify' => config('app.api_verify')])
->post(
config('api.url') . '/api/panjar/createpanjar/' . auth()->user()->cawangan,
array_merge(
[
'tarikhbil' => now()->format('Y-m-d'),
'jenismodal' => 'belanjaam',
'deskripsi' => 'BAYARAN PAMPASAN ' . '(' . $request->norujukan . ')',
'bayaran' => $bayaranPanjar,
'kodlaluan' => auth()->user()->name,
'baucer' => $responsePampasan['data']['baucerno'],
'tuntutan' => auth()->user()->name
],
$request->denominasi
)
)->json();
if ($responsePampasan['success'] == true) {
return redirect()->route('pampasan.resit', ["pampasan" => $responsePampasan['data']]);
} else
return redirect()->route('khazanah.panjar')->with('pampasaninformation', ['status' => 'error', 'message' => 'Baki perubatan tidak mencukupi.']);
}
public function resitPampasan(Request $request)
{
$pampasan = $request->pampasan;
$kodcaw = $pampasan['kodcaw'];
$norujukan = $pampasan['norujukan'] ?? null;
if ($norujukan) {
$gadai_info = Http::withOptions(['verify' => config('app.api_verify')])
->get(config('api.url') . '/api/gadai/norujukan/' . $kodcaw . '/' . $norujukan)
->json();
$gadai_info = is_array($gadai_info) && isset($gadai_info[0]) ? $gadai_info[0] : $gadai_info;
$customer_info = null;
if (isset($gadai_info['nokp'])) {
$customer = Http::withOptions(['verify' => config('app.api_verify')])
->get(config('api.url') . '/api/customers/' . $gadai_info['nokp'])
->json();
$customer_info = is_array($customer) && isset($customer[0]) ? $customer[0] : $customer;
}
$pampasan_info = Http::withOptions(['verify' => config('app.api_verify')])
->get(config('api.url') . '/api/palsu/laporan/', ['kodcaw' => $kodcaw])
->json();
$norujukan = $norujukan;
$pampasan_info = collect($pampasan_info)->firstWhere('norujukan', $norujukan);
$nilaimarhun = $pampasan_info['nilaimarhun'] ?? 0;
$pembiayaan = $pampasan_info['pembiayaan'] ?? 0;
$untung = $pampasan_info['untung'] ?? 0;
$jumlah_pampasan = $nilaimarhun - $pembiayaan - $untung;
$status = Http::withOptions(['verify' => config('app.api_verify')])
->put(config('api.url') . '/api/pampasan/updateStatusPampasan', ['kodcaw' => $kodcaw, 'norujukan' => $norujukan])
->json();
// dd($pampasan_info, $nilaimarhun, $pembiayaan, $untung, $jumlah_pampasan);
// dd($norujukan);
return view('print.resit.resitpampasan', compact(
'pampasan',
'gadai_info',
'customer_info',
'pampasan_info',
'nilaimarhun',
'pembiayaan',
'untung',
'jumlah_pampasan',
'status'
));
}
}
public function suratPampasan(Request $request, $norujukan)
{
$auth_user = Auth::user();
$cawangan_info = Http::withOptions(['verify' => config('app.api_verify')])
->get(config('api.url') . '/api/cawangan/'.$auth_user['cawangan'])->json();
$gadai = Http::withOptions(['verify' => config('app.api_verify')])
->get(config('api.url') . '/api/gadai/norujukan/' . '011237' . '/' . $norujukan)
->json();
$gadai_info = is_array($gadai) && isset($gadai[0]) ? $gadai[0] : $gadai;
$customer_info = null;
if(isset($gadai_info['nokp'])) {
$customer = Http::withOptions(['verify' => config('app.api_verify')])
->get(config('api.url') . '/api/customers/' . $gadai_info['nokp'])
->json();
$customer_info = is_array($customer) && isset($customer[0]) ? $customer[0] : $customer;
}
$pampasan = Http::withOptions(['verify' => config('app.api_verify')])
->get(config('api.url') . '/api/palsu/laporan/' , ['kodcaw'=>'011237'])
->json();
$pampasan_collection = collect($pampasan);
$pampasan_info = $pampasan_collection->where('norujukan', '=', $norujukan)->first();
if (!$pampasan_info) {
abort(404, 'Maklumat pampasan tidak dijumpai untuk no rujukan tersebut.');
}
$nilaimarhun = $pampasan_info['nilaimarhun'] ?? 0;
$pembiayaan = $pampasan_info['pembiayaan'] ?? 0;
$untung = $pampasan_info['untung'] ?? 0;
$jumlah_pampasan = $nilaimarhun - $pembiayaan - $untung;
$jumlah = $pampasan_info['jumlah_pampasan'] ?? 0;
$jumlah_pampasan_terbilang = Helper::ringgitTerbilang($jumlah_pampasan);
return view('print.surat_pampasan', compact('cawangan_info', 'gadai', 'gadai_info', 'customer_info', 'pampasan', 'pampasan_info','jumlah_pampasan_terbilang', 'jumlah_pampasan'));
}
}
+51 -2
View File
@@ -92,11 +92,17 @@ class OperasiController extends Controller
'siri' => $request->siri
])->json();
$updatelulus = Http::withOptions(['verify' => config('app.api_verify')])->put(config('api.url') . '/api/UpdateKelulusan/' . $request->kodcaw . '/' . $norujukan,[
$updateData = [
'sahkan' => 1,
'namaoperasi' => $request->namaoperasi,
'siri' => $request->siri
])->json();
];
if ($request->has('actions')) {
$updateData['actions'] = $request->actions;
}
$updatelulus = Http::withOptions(['verify' => config('app.api_verify')])->put(config('api.url') . '/api/UpdateKelulusan/' . $request->kodcaw . '/' . $norujukan, $updateData)->json();
}else{
$updatelulus = Http::withOptions(['verify' => config('app.api_verify')])->put(config('api.url') . '/api/UpdateHapusAnsuran',[
'siri' => $request->siri,
@@ -148,6 +154,49 @@ class OperasiController extends Controller
return response()->json($updatelulus,200);
}
public function createKelulusanByKhazanah(Request $request)
{
$auth_user = Auth::user();
$api_url = config('api.url');
$current = Carbon::now();
$current = new Carbon();
$norujukan = $request->norujukan;
$cawangan_info = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/cawangan/'. $auth_user['cawangan'])->json();
$getsiri = Http::withOptions(['verify' => config('app.api_verify')])->get(config('api.url') . '/api/ListLatestLulus/'. $auth_user['cawangan'] . '/' . $norujukan)->json();
if(isset($getsiri['siri']))
{
$siri = $getsiri['siri'] + 1;
}else{
$siri = 1;
}
$createlulus = Http::withOptions(['verify' => config('app.api_verify')])->post(config('api.url') . '/api/CreateKelulusan/' . $auth_user['cawangan'] . '/' . $norujukan . '/roles/khazanah', [
'komen' => $request->komen,
'dategadai' => $current->toDateString(),
'bilgadai' => 1,
'siri' => $siri,
'margin' => $request->margin,
'berat' => $request->berat,
'nilaimarhun' => $request->nilaimarhun,
'status' => $request->status,
'jumpinjam' => $request->jumpinjam,
'jenistebus' => "G",
'teller' => $request->teller,
'peloperasi' => "operasi",
'pelulus' => "operasi",
'actions' => "Mohon Pengesahan Pembayaran Pampasan"
])->json();
event(new OperasiNotice($auth_user['cawangan'],$auth_user['name']));
return response()->json($siri,201);
}
public function createkelulusan(Request $request)
{
$auth_user = Auth::user();
+26 -1
View File
@@ -46,7 +46,10 @@ class PenebusanController extends Controller
$nilaihargasemasa = $this->tukaranhargaemas($norujukan);
$pertambahpinjaman = 0.80;
return view('penebusan.' . $cawangan_info['version'] . '.index',compact('cawangan_info','api_url','gadai','marhun','nama','nilaihargasemasa','pertambahpinjaman'));
$pampasan = $this->getPampasanByNorujukan($norujukan);
return view('penebusan.' . $cawangan_info['version'] . '.index',compact('cawangan_info','api_url','gadai','marhun','nama','nilaihargasemasa','pertambahpinjaman', 'pampasan'));
}
public function tebuspenuh(Request $request)
@@ -786,4 +789,26 @@ class PenebusanController extends Controller
return view($view, compact('cawangan_info','api_url','gadai','marhun','nama','nilaihargasemasa'));
}
public function getPampasanByNorujukan($norujukan)
{
$auth_user = Auth::user();
$pampasanListResponse = Http::get(config('api.url'). '/api/palsu/laporan', [
'kodcaw' => $auth_user['cawangan'],
'status' => 'all',
]);
if($pampasanListResponse->failed()){
throw new \Exception("Something wrong with API", 1);
}
$pampasanList = array_filter($pampasanListResponse->json(), function($pampasan) use($norujukan){
return $pampasan['norujukan'] == $norujukan;
});
$pampasan = sizeof($pampasanList) == 0 ? null : array_pop($pampasanList);
return $pampasan;
}
}
+1
View File
@@ -72,5 +72,6 @@ class Kernel extends HttpKernel
'admin' => 'App\Http\Middleware\Admin',
'audit' => 'App\Http\Middleware\Audit',
'masteradmin' => 'App\Http\Middleware\Masteradmin',
'role' => 'App\Http\Middleware\RoleAccess',
];
}
+71
View File
@@ -0,0 +1,71 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Support\Facades\Auth;
use Closure;
class RoleAccess
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string ...$roles
* @return mixed
*/
public function handle($request, Closure $next, ...$roles)
{
if (!Auth::check()) {
return redirect('/login');
}
$user = Auth::user();
$userRole = $user->roles;
$userRoleHarian = $user->role_harian ?? null;
// Check each allowed role
foreach ($roles as $role) {
switch ($role) {
case 'teller':
if ($userRoleHarian == 'teller' || $userRole == 'teller') {
return $next($request);
}
break;
case 'khazanah':
if ($userRole == 'pc' || $userRole == 'ppc') {
return $next($request);
}
break;
case 'admin':
if ($userRole == 'admin') {
return $next($request);
}
break;
case 'penilai':
if ($userRole == 'penilai') {
return $next($request);
}
break;
case 'operasi':
if ($userRole == 'operasi') {
return $next($request);
}
break;
case 'audit':
if ($userRole == 'audit') {
return $next($request);
}
break;
}
}
// If no roles matched, deny access
abort(403, 'Access denied. Required roles: ' . implode(', ', $roles));
}
}
+30
View File
@@ -0,0 +1,30 @@
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
require('./bootstrap');
window.Vue = require('vue');
/**
* The following block of code may be used to automatically register your
* Vue components. It will recursively scan this directory for the Vue
* components and automatically register them with their "basename".
*
* Eg. ./components/ExampleComponent.vue -> <example-component></example-component>
*/
// const files = require.context('./', true, /\.vue$/i)
// files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default))
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
const app = new Vue({
el: '#app',
});
+3 -3
View File
@@ -35,7 +35,7 @@ window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key: '26b0ec2f297f94b7aa9b',
cluster: 'ap1',
forceTLS: true
key: process.env.MIX_PUSHER_APP_KEY,
cluster: process.env.MIX_PUSHER_APP_CLUSTER,
forceTLS: false
});
@@ -0,0 +1,282 @@
@extends('layouts.app')
@section('content')
<div class="container">
<h2 class="text-center font-weight-bold my-4">PAMPASAN</h2>
<div class="row mb-4">
<div class="col-md-6">
<label>NAMA</label>
<input type="text" class="form-control mb-2" value="{{ $customer_info['nama'] ?? '-' }}" readonly>
</div>
<div class="col-md-6">
<label>NO PELANGGAN</label>
<input type="text" class="form-control mb-2" value="{{ $gadai_info['nopelanggan'] ?? '-' }}" readonly>
</div>
<div class="col-md-6">
<label>NO RUJUKAN</label>
<input type="text" class="form-control mb-2" value="{{ $gadai_info['norujukan'] ?? '-' }}" readonly>
</div>
<div class="col-md-6">
<label>NO KAD PENGENALAN</label>
<input type="text" class="form-control mb-2" value="{{ $gadai_info['nokp'] ?? '-' }}" readonly>
</div>
</div>
<div class="card p-4 mx-auto" style="max-width:900px;">
<div class="row mb-3">
<div class="col-md-6">
<label>BAUCER NO</label>
<input type="text" class="form-control" value="{{ $baucerno ?? '-' }}" readonly>
</div>
<div class="col-md-6">
<label>NILAI MARHUN</label>
<input type="text" class="form-control"
value="RM {{ number_format($barang_kes_info['nilaimarhun'], 2) }}" readonly>
</div>
<div class="col-md-6">
<label>BAKI PEMBIAYAAN</label>
<input type="text" class="form-control"
value="RM {{ number_format($barang_kes_info['pembiayaan'], 2) }}" readonly>
</div>
<div class="col-md-6">
<label>KEUNTUNGAN</label>
<input type="text" class="form-control" value="RM {{ number_format($barang_kes_info['untung'], 2) }}"
readonly>
</div>
<div class="col-md-6">
<label>JUMLAH PAMPASAN</label>
@php
$nilaimarhun = floatval($barang_kes_info['nilaimarhun'] ?? 0);
$pembiayaan = floatval($barang_kes_info['pembiayaan'] ?? 0);
$untung = floatval($barang_kes_info['untung'] ?? 0);
$jumlah_pampasan = $nilaimarhun - $pembiayaan - $untung;
@endphp
<input type="text" class="form-control" value="RM {{ number_format($jumlah_pampasan, 2) }}" readonly>
</div>
<div class="col-md-6">
<label>JUMLAH TEBUS</label>
<input type="text" class="form-control" value="RM {{ number_format($jumlah_tebus, 2) }}" readonly>
</div>
<div class="col-md-12 row mb-3 justify-content-center">
<div class="col-md-6 text-center">
<label><strong>JUMLAH PANJAR</strong></label>
<input type="text" class="form-control text-center"
value="RM {{ number_format($jumlahPanjar, 2) }}" readonly>
</div>
</div>
</div>
<div class="row mb-3">
<div class="col-12">
<div class="alert alert-info text-center font-weight-bold" style="font-size: 1.2rem;">
Cara Pengiraan Jumlah Pampasan:<br>
<span style="font-size:1.3rem;">
<b>Jumlah Pampasan = Nilai Marhun - Baki Pembiayaan - Keuntungan</b>
</span>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 text-right">
<button type="button" class="btn btn-success mr-2" data-toggle="modal"
data-target="#denominasipampasan" data-jumlah="{{ $jumlah_pampasan }}">
DENO
</button>
<button type="button" class="btn btn-danger" onclick="window.history.back()">BATAL</button>
</div>
</div>
</div>
</div>
<script>
const formatter = new Intl.NumberFormat('en-US', {
minimumFractionDigits: 2
});
var arrayambilan = [
["bundle1", 0],
["bundle5", 0],
["bundle10", 0],
["bundle20", 0],
["bundle50", 0],
["bundle100", 0],
["sen1", 0],
["sen5", 0],
["sen10", 0],
["sen20", 0],
["sen50", 0],
["ringgit1", 0],
["ringgit5", 0],
["ringgit10", 0],
["ringgit20", 0],
["ringgit50", 0],
["ringgit100", 0]
];
function totalamount(idwang, bilangan) {
var amount = 0;
switch (idwang) {
case 'bundle1':
amount += (bilangan * 100);
break;
case 'bundle20':
amount += (bilangan * 1000);
break;
case 'bundle5':
amount += (bilangan * 500);
break;
case 'bundle50':
amount += (bilangan * 5000);
break;
case 'bundle10':
amount += (bilangan * 1000);
break;
case 'bundle100':
amount += (bilangan * 5000);
break;
case 'sen1':
amount += (bilangan * 0.01);
break;
case 'sen5':
amount += (bilangan * 0.05);
break;
case 'sen10':
amount += (bilangan * 0.10);
break;
case 'sen20':
amount += (bilangan * 0.20);
break;
case 'sen50':
amount += (bilangan * 0.50);
break;
case 'ringgit1':
amount += (bilangan * 1);
break;
case 'ringgit5':
amount += (bilangan * 5);
break;
case 'ringgit10':
amount += (bilangan * 10);
break;
case 'ringgit20':
amount += (bilangan * 20);
break;
case 'ringgit50':
amount += (bilangan * 50);
break;
case 'ringgit100':
amount += (bilangan * 100);
break;
}
return amount;
}
function kiraanpanjar(datakeyin) {
var idkey = $(datakeyin).attr('id');
var valkey = $(datakeyin).val();
var amount = 0;
let amountkiraan = 0;
var validate = parseFloat($(datakeyin).data('amaun'));
$.each(arrayambilan, function(index, arr) {
if (arr[0] == idkey) {
arrayambilan[index][1] = totalamount(idkey, valkey);
}
amount += arr[1];
});
if (Number(valkey) > Number(validate)) {
Swal.fire({
icon: 'error',
title: 'Amaran',
text: 'Jumlah denominasi melebihi kadar'
});
$(datakeyin).val('');
} else {
$('#amaunkiraan').val(amount);
}
switch (idkey) {
case 'bundle1':
amountkiraan += (valkey * 100);
$('#totalb1').val(formatter.format(amountkiraan.toFixed(2)));
break;
case 'bundle20':
amountkiraan += (valkey * 1000);
$('#totalb20').val(formatter.format(amountkiraan.toFixed(2)));
break;
case 'bundle5':
amountkiraan += (valkey * 500);
$('#totalb5').val(formatter.format(amountkiraan.toFixed(2)));
break;
case 'bundle50':
amountkiraan += (valkey * 5000);
$('#totalb50').val(formatter.format(amountkiraan.toFixed(2)));
break;
case 'bundle10':
amountkiraan += (valkey * 1000);
$('#totalb10').val(formatter.format(amountkiraan.toFixed(2)));
break;
case 'bundle100':
amountkiraan += (valkey * 5000);
$('#totalb100').val(formatter.format(amountkiraan.toFixed(2)));
break;
case 'sen1':
amountkiraan += (valkey * 0.01);
$('#totalsen1').val(formatter.format(amountkiraan.toFixed(2)));
break;
case 'sen5':
amountkiraan += (valkey * 0.05);
$('#totalsen5').val(formatter.format(amountkiraan.toFixed(2)));
break;
case 'sen10':
amountkiraan += (valkey * 0.10);
$('#totalsen10').val(formatter.format(amountkiraan.toFixed(2)));
break;
case 'sen20':
amountkiraan += (valkey * 0.20);
$('#totalsen20').val(formatter.format(amountkiraan.toFixed(2)));
break;
case 'sen50':
amountkiraan += (valkey * 0.50);
$('#totalsen50').val(formatter.format(amountkiraan.toFixed(2)));
break;
case 'ringgit1':
amountkiraan += (valkey * 1);
$('#totalring1').val(formatter.format(amountkiraan.toFixed(2)));
break;
case 'ringgit5':
amountkiraan += (valkey * 5);
$('#totalring5').val(formatter.format(amountkiraan.toFixed(2)));
break;
case 'ringgit10':
amountkiraan += (valkey * 10);
$('#totalring10').val(formatter.format(amountkiraan.toFixed(2)));
break;
case 'ringgit20':
amountkiraan += (valkey * 20);
$('#totalring20').val(formatter.format(amountkiraan.toFixed(2)));
break;
case 'ringgit50':
amountkiraan += (valkey * 50);
$('#totalring50').val(formatter.format(amountkiraan.toFixed(2)));
break;
case 'ringgit100':
amountkiraan += (valkey * 100);
$('#totalring100').val(formatter.format(amountkiraan.toFixed(2)));
break;
}
}
</script>
@include('modal.denopampasan')
@endsection
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -39,12 +39,12 @@
<link rel="stylesheet" href="{{ asset('vendor/datepicker/css/bootstrap-datepicker.min.css') }}"/>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<script src="{{ asset('js/jquery.min.js') }}"></script>
<script src="{{ asset('js/popper.min.js') }}"></script>
<script src="{{ asset('vendor/bootstrap/js/bootstrap.min.js') }}"></script>
<script src="{{ asset('js/select2.min.js') }}"></script>
<script src="{{ asset('js/apexcharts.js') }}"></script>
<script src="{{ asset('js/numeral.min.js') }}"></script>
<script src="{{ asset('js/sweetalert.min.js') }}"></script>
<script src="{{ asset('js/popper.min.js') }}"></script>
<script src="{{ asset('vendor/DataTables/datatables.min.js') }}"></script>
<script src="{{ asset('vendor/datepicker/js/bootstrap-datepicker.min.js') }}"></script>
<script src="{{ asset('js/typehead.jquery.js') }}"></script>
@@ -0,0 +1,199 @@
<div class="modal fade" id="denominasipampasan" tabindex="-1" role="dialog"
aria-labelledby="denominasipampasanModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-xl" role="document">
<div class="modal-content">
<div class="modal-header">
<ul class="nav nav-pills">
<li class="nav-item">
<a class="nav-link active" data-toggle="pill" href="#home" role="tab"
aria-controls="pills-flamingo" aria-selected="true">Keping</a>
</li>
</ul>
<label class="mt-2 ml-3">Amaun Kiraan:</label>
<input type="text" class="form-control col-3 ml-3" id="amaunkiraan" placeholder="0.00" readonly>
<label class="mt-2 ml-3">Jumlah Panjar:</label>
<input type="text" class="form-control col-3 ml-2 bg-light font-weight-bold" id="jumlahPanjar"
value="{{ number_format($jumlahPanjar, 2) }}" readonly>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form id="formPampasan" method="POST" onsubmit="return terimadeno(event)" action="{{ route('pampasan.terima') }}">
@csrf
<input type="hidden" id="norujukan" name="norujukan" value="{{ $gadai_info['norujukan'] }}">
<input type="hidden" id="baucerno" name="baucerno" value="{{ $baucerno }}">
<input type="hidden" name="jumlahpampasan" value="{{ $jumlah_pampasan }}">
<input type="hidden" name="jumlahPanjar" value="{{ $jumlahPanjar }}">
<input type="hidden" name="teller" value="{{ auth()->user()->name }}">
<div class="tab-content">
<div class="tab-pane fade show active" id="home" role="tabpanel"
aria-labelledby="flamingo-tab">
<table class="table text-center">
<tr>
<th></th>
<th name="denominasi" class="denominasi">Peti Besi</th>
<th>Ambilan</th>
<th>Jumlah (RM)</th>
<th></th>
<th name="denominasi" class="denominasi">Peti Besi</th>
<th>Ambilan</th>
<th>Jumlah (RM)</th>
</tr>
<tr>
<td>RM0.01</td>
<td name="denominasi" class="denominasi"><input type="text" class="form-control"
value="{{ $denominasi['txtsen1'] }}" readonly /></td>
<td><input type="text" name="denominasi[ambilansen1]" class="form-control kosong" id="sen1"
data-amaun="{{ $denominasi['txtsen1'] }}" onkeyup="kiraanpanjar(this)" /> </td>
<td><input type="text" name="denominasi[totalsen1]" id="totalsen1" class="form-control kosong"
value="0.00" readonly /> </td>
<td>RM1</td>
<td name="denominasi" class="denominasi"><input type="text" class="form-control"
value="{{ $denominasi['txtring1'] }}" readonly /></td>
<td><input type="text" name="denominasi[ambilanring1]" class="form-control kosong" id="ringgit1"
data-amaun="{{ $denominasi['txtring1'] }}" onkeyup="kiraanpanjar(this)" /> </td>
<td><input type="text" name="denominasi[totalring1]" id="totalring1" class="form-control kosong"
value="0.00" readonly /> </td>
</tr>
<tr>
<td>RM0.05</td>
<td name="denominasi" class="denominasi"><input type="text" class="form-control"
value="{{ $denominasi['txtsen5'] }}" readonly /></td>
<td><input type="text" name="denominasi[ambilansen5]" class="form-control kosong" id="sen5"
data-amaun="{{ $denominasi['txtsen5'] }}" onkeyup="kiraanpanjar(this)" /> </td>
<td><input type="text" name="denominasi[totalsen5]" id="totalsen5" class="form-control kosong"
value="0.00" readonly /> </td>
<td>RM5</td>
<td name="denominasi" class="denominasi"><input type="text" class="form-control"
value="{{ $denominasi['txtring5'] }}" readonly /></td>
<td><input type="text" name="denominasi[ambilanring5]" class="form-control kosong" id="ringgit5"
data-amaun="{{ $denominasi['txtring5'] }}" onkeyup="kiraanpanjar(this)" />
</td>
<td><input type="text" name="denominasi[totalring5]" id="totalring5"
class="form-control kosong" value="0.00" readonly /> </td>
</tr>
<tr>
<td>RM0.10</td>
<td name="denominasi" class="denominasi"><input type="text" class="form-control"
value="{{ $denominasi['txtsen10'] }}" readonly /></td>
<td><input type="text" name="denominasi[ambilansen10]" class="form-control kosong"
id="sen10" data-amaun="{{ $denominasi['txtsen10'] }}"
onkeyup="kiraanpanjar(this)" /> </td>
<td><input type="text" name="denominasi[totalsen10]" id="totalsen10"
class="form-control kosong" value="0.00" readonly /> </td>
<td>RM10</td>
<td name="denominasi" class="denominasi"><input type="text" class="form-control"
value="{{ $denominasi['txtring10'] }}" readonly /></td>
<td><input type="text" name="denominasi[ambilanring10]" class="form-control kosong"
id="ringgit10" data-amaun="{{ $denominasi['txtring10'] }}"
onkeyup="kiraanpanjar(this)" /> </td>
<td><input type="text" name="denominasi[totalring10]" id="totalring10"
class="form-control kosong" value="0.00" readonly /> </td>
</tr>
<tr>
<td>RM0.20</td>
<td name="denominasi" class="denominasi"><input type="text" class="form-control"
value="{{ $denominasi['txtsen20'] }}" readonly /></td>
<td><input type="text" name="denominasi[ambilansen20]" class="form-control kosong"
id="sen20" data-amaun="{{ $denominasi['txtsen20'] }}"
onkeyup="kiraanpanjar(this)" /> </td>
<td><input type="text" name="denominasi[totalsen20]" id="totalsen20"
class="form-control kosong" value="0.00" readonly /> </td>
<td> RM20</td>
<td name="denominasi" class="denominasi"><input type="text" class="form-control"
value="{{ $denominasi['txtring20'] }}" readonly /></td>
<td><input type="text" name="denominasi[ambilanring20]" class="form-control kosong"
id="ringgit20" data-amaun="{{ $denominasi['txtring20'] }}"
onkeyup="kiraanpanjar(this)" /> </td>
<td><input type="text" name="denominasi[totalring20]" id="totalring20"
class="form-control kosong" value="0.00" readonly /> </td>
</tr>
<tr>
<td>RM0.50</td>
<td name="denominasi" class="denominasi"><input type="text" class="form-control"
value="{{ $denominasi['txtsen50'] }}" readonly /></td>
<td><input type="text" name="denominasi[ambilansen50]" class="form-control kosong"
id="sen50" data-amaun="{{ $denominasi['txtsen50'] }}"
onkeyup="kiraanpanjar(this)" /> </td>
<td><input type="text" name="denominasi[totalsen50]" id="totalsen50"
class="form-control kosong" value="0.00" readonly /> </td>
<td>RM50</td>
<td name="denominasi" class="denominasi"><input type="text" class="form-control"
value="{{ $denominasi['txtring50'] }}" readonly /></td>
<td><input type="text" name="denominasi[ambilanring50]" class="form-control kosong"
id="ringgit50" data-amaun="{{ $denominasi['txtring50'] }}"
onkeyup="kiraanpanjar(this)" /> </td>
<td><input type="text" name="denominasi[totalring50]" id="totalring50"
class="form-control kosong" value="0.00" readonly /> </td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td>RM100</td>
<td name="denominasi" class="denominasi"><input type="text" class="form-control"
value="{{ $denominasi['txtring100'] }}" readonly /></td>
<td><input type="text" name="denominasi[ambilanring100]" class="form-control kosong"
id="ringgit100" data-amaun="{{ $denominasi['txtring100'] }}"
onkeyup="kiraanpanjar(this)" /> </td>
<td><input type="text" name="denominasi[totalring100]" id="totalring100"
class="form-control kosong" value="0.00" readonly /> </td>
</tr>
</table>
</div>
</div>
<input type="hidden" id="jenisjenis" />
<input type="hidden" id="kodcawangan" />
<input type="hidden" id="tellerla" />
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger btn-lg" data-dismiss="modal">Batal</button>
<button type="submit" class="btn btn-success btn-lg">Terima</button>
</div>
</form>
</div>
</div>
</div>
<script>
function terimadeno(e) {
e.preventDefault();
let amaunKiraan = parseFloat($('#amaunkiraan').val()) || 0;
let jumlahPampasan = parseFloat($('input[name="jumlahpampasan"]').val()) || 0;
let jumlahPanjar = parseFloat($('input[name="jumlahPanjar"]').val()) || 0;
// Validation
if (amaunKiraan !== jumlahPanjar) {
Swal.fire({
icon: 'error',
title: 'Jumlah Tidak Sama',
text: 'Amaun kiraan mesti sama dengan Jumlah Panjar.'
});
return false;
}
Swal.fire({
icon: 'success',
title: 'Berjaya',
text: 'Pampasan berjaya!',
showConfirmButton: true
}).then(() => {
$('#formPampasan')[0].submit();
});
return false;
}
</script>
+23 -3
View File
@@ -1,4 +1,4 @@
<!-- Modal Keraian -->
<!-- Modal Keraian -->
<div class="modal fade" id="keraianModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
@@ -570,6 +570,26 @@
</div>
</div>
</div>
<!-- Modal Surat Agreement -->
<div class="modal fade" id="suratModal" tabindex="-1" role="dialog" aria-labelledby="suratModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="suratModalLabel">Surat Agreement</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body" id="surat-content" style="font-family: 'Times New Roman', Times, serif;">
<!-- Surat content will be injected here -->
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Batal</button>
<button type="button" class="btn btn-primary" id="btnPrintSurat">Cetak & Teruskan</button>
</div>
</div>
</div>
</div>
+499 -374
View File
@@ -2,27 +2,97 @@
@section('content')
<div class="modal fade" id="kelulusanmodal">
<div class="modal-dialog modal-lg modal-dialog-centered">
<div class="modal-content">
<!-- Modal Header -->
<div class="modal-header">
<h4 class="text-center">Maklumat Lanjut</h4>
<button type="button" class="close" data-dismiss="modal">&times;</button>
</div>
<!-- Modal body -->
<div class="modal-body">
<div class="row col-12 text-center">
<div class="row col-7">
<label>Nama : </label>
<span id="namalanjut"> </span>
</div>
<div class="modal fade" id="kelulusan_pampasan_modal">
<div class="modal-dialog modal-lg modal-dialog-centered">
<div class="modal-content">
<!-- Modal Header -->
<div class="modal-header">
<h4 class="text-center">Maklumat Lanjut</h4>
<button type="button" class="close" data-dismiss="modal">&times;</button>
</div>
<!-- Modal body -->
<div class="modal-body">
<div class="row col-5">
<label>Kad Pengenalan : </label>
<span id="nokplanjut"> </span>
<div class="row col-12 text-center">
<div class="row col-7">
<label>Nombor Rujukan : </label>
<span id="norujukan_pampasan"> </span>
</div>
</div>
<div class="row col-12 text-center">
<div class="row col-7">
<label>Nama : </label>
<span id="namalanjut_pampasan"> </span>
</div>
<div class="row col-5">
<label>Kad Pengenalan : </label>
<span id="nokplanjut_pampasan"> </span>
</div>
</div>
<div class="row mt-3">
<div class="col-12">
<div class="table-responsive">
<table class="table table-hover">
<tbody>
<tr>
<th class="bg-secondary text-white" scope="row" style="width: 30%;">Nilai Marhun</th>
<td id="nilaiMarhun">text</td>
</tr>
<tr>
<th class="bg-secondary text-white" scope="row" style="width: 30%;">Baki Pembiayaan</th>
<td id="pembiayaan"></td>
</tr>
<tr>
<th class="bg-secondary text-white" scope="row" style="width: 30%;">Jumlah Pampasan</th>
<td id="jumlahPampasan"></td>
</tr>
<tr>
<th class="bg-secondary text-white" scope="row" style="width: 30%;">Keuntungan</th>
<td id="keuntungan"></td>
</tr>
<tr>
<th class="bg-secondary text-white" scope="row" style="width: 30%;">Ansuran Pembiayaan</th>
<td id="bayaranAnsuran"></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- Modal footer -->
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="kelulusanmodal">
<div class="modal-dialog modal-lg modal-dialog-centered">
<div class="modal-content">
<!-- Modal Header -->
<div class="modal-header">
<h4 class="text-center">Maklumat Lanjut</h4>
<button type="button" class="close" data-dismiss="modal">&times;</button>
</div>
<!-- Modal body -->
<div class="modal-body">
<div class="row col-12 text-center">
<div class="row col-7">
<label>Nama : </label>
<span id="namalanjut"> </span>
</div>
<div class="row col-5">
<label>Kad Pengenalan : </label>
<span id="nokplanjut"> </span>
</div>
</div>
<div class="row mt-3">
@@ -71,404 +141,459 @@
</div>
</div>
<!-- Modal footer -->
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
</div>
<!-- Modal footer -->
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div class="container col-12">
<div class="row justify-content-center">
<div class="col-md-12">
<div class="card">
<nav aria-label="breadcrumb">
<ol class="breadcrumb pb-3">
<li class="breadcrumb-item"><a href="{{ url('/') }}">Home</a></li>
<li class="breadcrumb-item active" aria-current="page">Kelulusan</li>
</ol>
</nav>
<div class="card-body text-center">
<div class="row mb-4">
<div class="col-2 justify-content-start">
</div>
<div class="col-8 mt-3 justify-content-center">
</div>
<div class="col-2">
</div>
</div>
<table class='table mt-2 table-striped table-hover' id='table-kelulusan' style="width:100%;">
<thead class="thead-dark">
<tr>
<th>No Rujukan</th>
<th>Cawangan</th>
<th>Teller</th>
<th>Komen</th>
<th>Status</th>
<th>Nilai Pembiayaan</th>
<th>Ansuran</th>
<th>Nilai Marhun</th>
<th>Berat</th>
<th>Margin</th>
<th>Tindakan</th>
</tr>
</thead>
<tbody>
@foreach($arraykelulusan as $index=>$k)
<tr>
@php
$targetModal = '#kelulusanmodal';
$targetModal = strtolower($k['status']) == 'kelulusan pengeluaran pampasan' ? '#kelulusan_pampasan_modal' : $targetModal;
@endphp
<td><a href="#" data-toggle="modal" data-target="{{$targetModal}}" data-kodcawangan="{{ $k['cawangankod'] }}" data-norujukan="{{ $k['norujukan'] }}">{{ $k['norujukan'] }} </a></td>
<td>{{ $k['cawangan'] }}</td>
<td>{{ $k['namateller'] }}</td>
<th>{{ $k['komen'] }}</th>
<td>{{ $k['status'] }}</td>
<td>{{ number_format($k['pinjaman'],2) }}</td>
@if(isset($k['ansuran']) && $k['ansuran'] != 0)
<td>{{ number_format($k['ansuran'],2) }}</td>
@else
<td></td>
@endif
<td>{{ $k['nilaimarhun'] }}</td>
<td>{{ $k['berat'] }}</td>
<td>{{ $k['margin'] }}</td>
<td><button class="btn btn-primary mr-2" onclick="updatelulus(this)" data-taglulus="{{ isset($k['mohonid']) ? true : false }}" data-kodcaw="{{ $k['cawangankod'] }}" data-norujukan="{{ $k['norujukan'] }}" data-siri="{{ isset($k['siri']) ? $k['siri'] : $k['recno'] }}" data-status="{{ $k['status'] ?? '' }}"><i class="fas fa-thumbs-up"></i></button>
<button class="btn btn-danger" onclick="updatebatal(this)" data-taglulus="{{ isset($k['mohonid']) ? true : false }}" data-kodcaw="{{ $k['cawangankod'] }}" data-norujukan="{{ $k['norujukan'] }}" data-siri="{{ isset($k['siri']) ? $k['siri'] : $k['recno'] }}"><i class="fas fa-thumbs-down"></i></button>
</td>
</tr>
@endforeach
</tbody>
</table>
<div class="row mt-4 d-flex justify-content-end">
<a href="{{ route ('operasi.rekodlepas') }}" class="btn btn-info mr-3">Rekod Lulus</a>
</div>
</div>
</div>
</div>
</div>
<div class="container col-12">
<div class="row justify-content-center">
<div class="col-md-12">
<div class="card">
<nav aria-label="breadcrumb">
<ol class="breadcrumb pb-3">
<li class="breadcrumb-item"><a href="{{ url('/') }}">Home</a></li>
<li class="breadcrumb-item active" aria-current="page">Kelulusan</li>
</ol>
</nav>
<div class="card-body text-center">
<div class="row mb-4">
<div class="col-2 justify-content-start">
</div>
<div class="col-8 mt-3 justify-content-center">
</div>
<div class="col-2">
</div>
</div>
<table class='table mt-2 table-striped table-hover' id='table-kelulusan' style="width:100%;">
<thead class="thead-dark">
<tr>
<th>No Rujukan</th>
<th>Cawangan</th>
<th>Teller</th>
<th>Komen</th>
<th>Status</th>
<th>Nilai Pembiayaan</th>
<th>Ansuran</th>
<th>Nilai Marhun</th>
<th>Berat</th>
<th>Margin</th>
<th>Tindakan</th>
</tr>
</thead>
<tbody>
@foreach($arraykelulusan as $index=>$k)
<tr>
<td><a href="#" data-toggle="modal" data-target="#kelulusanmodal" data-kodcawangan="{{ $k['cawangankod'] }}" data-norujukan="{{ $k['norujukan'] }}">{{ $k['norujukan'] }} </a></td>
<td>{{ $k['cawangan'] }}</td>
<td>{{ $k['namateller'] }}</td>
<th>{{ $k['komen'] }}</th>
<td>{{ $k['status'] }}</td>
<td>{{ number_format($k['pinjaman'],2) }}</td>
@if(isset($k['ansuran']) && $k['ansuran'] != 0)
<td>{{ number_format($k['ansuran'],2) }}</td>
@else
<td></td>
@endif
<td>{{ $k['nilaimarhun'] }}</td>
<td>{{ $k['berat'] }}</td>
<td>{{ $k['margin'] }}</td>
<td><button class="btn btn-primary mr-2" onclick="updatelulus(this)" data-taglulus="{{ isset($k['mohonid']) ? true : false }}" data-kodcaw="{{ $k['cawangankod'] }}" data-norujukan="{{ $k['norujukan'] }}" data-siri="{{ isset($k['siri']) ? $k['siri'] : $k['recno'] }}"><i class="fas fa-thumbs-up"></i></button>
<button class="btn btn-danger" onclick="updatebatal(this)" data-taglulus="{{ isset($k['mohonid']) ? true : false }}" data-kodcaw="{{ $k['cawangankod'] }}" data-norujukan="{{ $k['norujukan'] }}" data-siri="{{ isset($k['siri']) ? $k['siri'] : $k['recno'] }}" ><i class="fas fa-thumbs-down"></i></button></td>
</tr>
@endforeach
</tbody>
</table>
<div class="row mt-4 d-flex justify-content-end">
<a href="{{ route ('operasi.rekodlepas') }}" class="btn btn-info mr-3">Rekod Lulus</a>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
var tablekelulusan = $('#table-kelulusan').DataTable({
"scrollX": true
});
var tablekelulusan = $('#table-kelulusan').DataTable({
"scrollX": true
});
let api = "{{ config('api.url') }}";
let api = "{{ config('api.url') }}";
const formatter = new Intl.NumberFormat('en-US', {
minimumFractionDigits: 2
});
const formatter = new Intl.NumberFormat('en-US', {
minimumFractionDigits: 2
});
var audio = new Audio("{{ asset('sound/3.wav') }}");
var audio = new Audio("{{ asset('sound/3.wav') }}");
if(tablekelulusan.data().any()){
audio.play();
audio.addEventListener('ended', function() {
this.currentTime = 0;
this.play();
}, false);
}else{
audio.loop = false;
audio.muted = true;
}
if (tablekelulusan.data().any()) {
audio.play();
audio.addEventListener('ended', function() {
this.currentTime = 0;
this.play();
}, false);
} else {
audio.loop = false;
audio.muted = true;
}
$('#kelulusanmodal').on('show.bs.modal', function(event) {
let button = $(event.relatedTarget);
let norujukan = $(button).data('norujukan');
let kodcaw = $(button).data('kodcawangan');
$('#kelulusanmodal').on('show.bs.modal', function(event) {
let button = $(event.relatedTarget);
let norujukan = $(button).data('norujukan');
let kodcaw = $(button).data('kodcawangan');
$.ajax({
method: 'GET',
url: api + '/api/gadai/norujukan/' + norujukan,
dataType: 'json',
success: function(datagadaiwithnorujukan) {
let nokp = datagadaiwithnorujukan[0][0].nokp;
$.ajax({
method:'GET',
url: api + '/api/gadai/norujukan/' + norujukan,
method: 'GET',
url: api + '/api/customers/' + nokp,
dataType: 'json',
success:function(datagadaiwithnorujukan){
success: function(datagadaiwithnokp) {
let nokp = datagadaiwithnorujukan[0][0].nokp;
let nama = datagadaiwithnokp.nama;
$('#namalanjut').text(nama);
$('#nokplanjut').text(nokp);
$.ajax({
method:'GET',
url: api + '/api/customers/' + nokp,
dataType: 'json',
success:function(datagadaiwithnokp){
method: 'GET',
url: api + '/api/gadai/customers/' + nokp + '/outstandingsemasa/' + kodcaw,
dataType: 'json',
success: function(outstandingsemasa) {
let nama = datagadaiwithnokp.nama;
$('#pinjterkumpul').text('RM' + formatter.format(outstandingsemasa));
$('#namalanjut').text(nama);
$('#nokplanjut').text(nokp);
$.ajax({
method:'GET',
url: api + '/api/gadai/customers/' + nokp + '/outstandingsemasa/' + kodcaw,
dataType: 'json',
success:function(outstandingsemasa){
$('#pinjterkumpul').text('RM' + formatter.format(outstandingsemasa));
},error: function(xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
alert(xhr.responseText);
}
});
}
});
$.ajax({
method:'GET',
url: api + '/api/customers/' + nokp + '/gadai/belum_tebus',
dataType: 'json',
success:function(data){
let bilanganaktif = 0;
if(data == null)
{
bilanganaktif = 0;
}else{
bilanganaktif = data[0].length;
}
$('#bilaktif').text(bilanganaktif);
}
});
$.ajax({
method:'GET',
url: api + '/api/customers/' + nokp + '/gadai/lelong',
dataType: 'json',
success:function(data){
let bilanganlelong = 0;
if(data == null)
{
bilanganlelong = 0;
}else{
bilanganlelong = data.length;
}
$('#billelong').text(bilanganlelong);
}
},
error: function(xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
alert(xhr.responseText);
}
});
}
});
$.ajax({
method: 'GET',
url: api + '/api/customers/' + nokp + '/gadai/belum_tebus',
dataType: 'json',
success: function(data) {
let bilanganaktif = 0;
if (data == null) {
bilanganaktif = 0;
} else {
bilanganaktif = data[0].length;
}
$('#bilaktif').text(bilanganaktif);
}
});
$.ajax({
method: 'GET',
url: api + '/api/customers/' + nokp + '/gadai/lelong',
dataType: 'json',
success: function(data) {
let bilanganlelong = 0;
if (data == null) {
bilanganlelong = 0;
} else {
bilanganlelong = data.length;
}
$('#billelong').text(bilanganlelong);
}
});
}
});
});
async function updatelulus(e)
{
const { value: katalaluan } = await Swal.fire({
title: 'Masukkan Katalaluan Semula',
input: 'password',
inputPlaceholder: 'Katalaluan',
confirmButtonText: 'Hantar',
showCancelButton:true,
cancelButtonText:'Batal',
allowOutsideClick: true
})
async function updatelulus(e) {
let dataminta = '';
const {
value: katalaluan
} = await Swal.fire({
title: 'Masukkan Katalaluan Semula',
input: 'password',
inputPlaceholder: 'Katalaluan',
confirmButtonText: 'Hantar',
showCancelButton: true,
cancelButtonText: 'Batal',
allowOutsideClick: true
})
$.ajax({
method:'get',
url: "{{ route('operasi.getmintasemulakelulusan') }}",
async:false,
data:{ passsemula : katalaluan },
success:function(data)
{
if(data == "False")
{
dataminta = data;
}
}
});
let dataminta = '';
if(dataminta == 'False')
{
Swal.fire({
icon: 'error',
title: 'Pengesahan Katalaluan Tidak Berjaya'
})
event.preventDefault();
return false;
$.ajax({
method: 'get',
url: "{{ route('operasi.getmintasemulakelulusan') }}",
async: false,
data: {
passsemula: katalaluan
},
success: function(data) {
if (data == "False") {
dataminta = data;
}
}
});
// var { value: komenkelulusan } = await Swal.fire({
// title: 'Masukkan Komen!',
// input: 'radio',
// customClass: {
// input: 'custom-radio'
// },
// inputOptions: {
// 'Pelanggan Baru': 'Pelanggan Baru',
// 'Pelanggan Tetap': 'Pelanggan Tetap',
// 'Rekod Gadaian Baik': 'Rekod Gadaian Baik',
// 'Lain2': 'Lain-Lain'
// },
// confirmButtonText: 'Hantar',
// showCancelButton:false,
// allowOutsideClick: false
// })
// if(komenkelulusan === 'Lain2')
// {
// var { value: komenkelulusan } = await Swal.fire({
// title: 'Masukkan Komen!',
// input: 'text',
// inputPlaceholder: 'Komen',
// confirmButtonText: 'Hantar',
// showCancelButton:false,
// allowOutsideClick: false
// });
// }
const { value: komenkelulusan } = await Swal.fire({
title: 'Masukkan Komen!',
input: 'text',
inputPlaceholder: 'Komen',
confirmButtonText: 'Hantar',
showCancelButton:false,
allowOutsideClick: false
})
let norujukan = $(e).data('norujukan');
let cawangankod = $(e).data('kodcaw');
let siri = $(e).data('siri');
let namaoperasi = "{{ Auth::user()->name }}";
let teller = $(e).closest('tr').children('td:eq(2)').text();
let taglulus = $(e).data('taglulus');
teller = String(teller);
$.ajax({
method:'put',
url: "{{ route('operasi.updatekelulusan') }}",
data: {
"_token": "{{ csrf_token() }}",
"taglulus" : taglulus,
"norujukan" : norujukan,
"kodcaw" : cawangankod,
"komenkelulusan" : komenkelulusan,
"siri" : siri,
'namaoperasi' : namaoperasi,
'teller' : teller
},
success:function(data){
console.log(data);
Swal.fire({
icon: 'success',
title: 'Pengesahan Berjaya'
}).then(function(){
location.reload();
});
},error: function(xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
alert(xhr.responseText);
}
});
if (dataminta == 'False') {
Swal.fire({
icon: 'error',
title: 'Pengesahan Katalaluan Tidak Berjaya'
})
event.preventDefault();
return false;
}
async function updatebatal(e)
{
const { value: katalaluan } = await Swal.fire({
title: 'Masukkan Katalaluan Semula',
input: 'password',
inputPlaceholder: 'Katalaluan',
confirmButtonText: 'Hantar',
showCancelButton:true,
cancelButtonText:'Batal',
allowOutsideClick: true
})
// var { value: komenkelulusan } = await Swal.fire({
// title: 'Masukkan Komen!',
// input: 'radio',
// customClass: {
// input: 'custom-radio'
// },
// inputOptions: {
// 'Pelanggan Baru': 'Pelanggan Baru',
// 'Pelanggan Tetap': 'Pelanggan Tetap',
// 'Rekod Gadaian Baik': 'Rekod Gadaian Baik',
// 'Lain2': 'Lain-Lain'
// },
// confirmButtonText: 'Hantar',
// showCancelButton:false,
// allowOutsideClick: false
// })
let dataminta = '';
// if(komenkelulusan === 'Lain2')
// {
// var { value: komenkelulusan } = await Swal.fire({
// title: 'Masukkan Komen!',
// input: 'text',
// inputPlaceholder: 'Komen',
// confirmButtonText: 'Hantar',
// showCancelButton:false,
// allowOutsideClick: false
// });
// }
$.ajax({
method:'get',
url: "{{ route('operasi.getmintasemulakelulusan') }}",
async:false,
data:{ passsemula : katalaluan },
success:function(data)
{
if(data == "False")
{
dataminta = data;
}
}
});
const {
value: komenkelulusan
} = await Swal.fire({
title: 'Masukkan Komen!',
input: 'text',
inputPlaceholder: 'Komen',
confirmButtonText: 'Hantar',
showCancelButton: false,
allowOutsideClick: false
})
if(dataminta == 'False')
{
Swal.fire({
icon: 'error',
title: 'Pengesahan Katalaluan Tidak Berjaya'
})
event.preventDefault();
return false;
}
let norujukan = $(e).data('norujukan');
let cawangankod = $(e).data('kodcaw');
let siri = $(e).data('siri');
let namaoperasi = "{{ Auth::user()->name }}";
let teller = $(e).closest('tr').children('td:eq(2)').text();
let taglulus = $(e).data('taglulus');
let status = $(e).data('status');
const { value: komenkelulusan } = await Swal.fire({
title: 'Masukkan Komen',
input: 'text',
inputPlaceholder: 'Komen',
confirmButtonText: 'Hantar',
showCancelButton:false,
allowOutsideClick: false
})
teller = String(teller);
let norujukan = $(e).data('norujukan');
let siri = $(e).data('siri');
let cawangankod = $(e).data('kodcaw');
let namaoperasi = "{{ Auth::user()->name }}";
let teller = $(e).closest('tr').children('td:eq(2)').text();
let requestData = {
"_token": "{{ csrf_token() }}",
"taglulus": taglulus,
"norujukan": norujukan,
"kodcaw": cawangankod,
"komenkelulusan": komenkelulusan,
"siri": siri,
'namaoperasi': namaoperasi,
'teller': teller
};
teller = String(teller);
$.ajax({
method:'put',
url: "{{ route('operasi.updatekelulusan') }}",
data: {
"_token": "{{ csrf_token() }}",
"norujukan" : norujukan,
"siri" : siri,
"kodcaw" : cawangankod,
"komenkelulusan" : komenkelulusan,
"pembatalan" : "batal",
'namaoperasi' : namaoperasi,
'teller' : teller
},
success:function(data){
Swal.fire({
icon: 'success',
title: 'Pengesahan Berjaya'
}).then(function(){
location.reload();
});
},error: function(xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
alert(xhr.responseText);
}
});
if (status === 'Kelulusan Pengeluaran Pampasan') {
requestData.actions = 'Pengesahan Pembayaran Pampasan';
}
$.ajax({
method: 'put',
url: "{{ route('operasi.updatekelulusan') }}",
data: requestData,
success: function(data) {
console.log(data);
Swal.fire({
icon: 'success',
title: 'Pengesahan Berjaya'
}).then(function() {
location.reload();
});
},
error: function(xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
alert(xhr.responseText);
}
});
}
async function updatebatal(e) {
const {
value: katalaluan
} = await Swal.fire({
title: 'Masukkan Katalaluan Semula',
input: 'password',
inputPlaceholder: 'Katalaluan',
confirmButtonText: 'Hantar',
showCancelButton: true,
cancelButtonText: 'Batal',
allowOutsideClick: true
})
let dataminta = '';
$.ajax({
method: 'get',
url: "{{ route('operasi.getmintasemulakelulusan') }}",
async: false,
data: {
passsemula: katalaluan
},
success: function(data) {
if (data == "False") {
dataminta = data;
}
}
});
if (dataminta == 'False') {
Swal.fire({
icon: 'error',
title: 'Pengesahan Katalaluan Tidak Berjaya'
})
event.preventDefault();
return false;
}
const {
value: komenkelulusan
} = await Swal.fire({
title: 'Masukkan Komen',
input: 'text',
inputPlaceholder: 'Komen',
confirmButtonText: 'Hantar',
showCancelButton: false,
allowOutsideClick: false
})
let norujukan = $(e).data('norujukan');
let siri = $(e).data('siri');
let cawangankod = $(e).data('kodcaw');
let namaoperasi = "{{ Auth::user()->name }}";
let teller = $(e).closest('tr').children('td:eq(2)').text();
teller = String(teller);
$.ajax({
method: 'put',
url: "{{ route('operasi.updatekelulusan') }}",
data: {
"_token": "{{ csrf_token() }}",
"norujukan": norujukan,
"siri": siri,
"kodcaw": cawangankod,
"komenkelulusan": komenkelulusan,
"pembatalan": "batal",
'namaoperasi': namaoperasi,
'teller': teller
},
success: function(data) {
Swal.fire({
icon: 'success',
title: 'Pengesahan Berjaya'
}).then(function() {
location.reload();
});
},
error: function(xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
alert(xhr.responseText);
}
});
}
$('#kelulusan_pampasan_modal').on('show.bs.modal', async function(event) {
const triggerModalButton = event.relatedTarget;
const norujukan = triggerModalButton.dataset.norujukan;
const kodcaw = triggerModalButton.dataset.kodcawangan;
const pampasan = await fetch(api + `/api/pampasan?norujukan=${norujukan}&kodcaw=${kodcaw}`)
.then(response => response.json())
.then(x => x.data.pop());
const barangkes = await fetch(api + `/api/palsu/laporan?kodcaw=${kodcaw}`)
.then(response => response.json())
.then(x => x.filter(x => x.norujukan == norujukan))
.then(x => x.pop());
const tebus = await fetch(api + `/api/tebus/norujukan/${kodcaw}/${norujukan}`)
.then(response => response.json())
.then(x => x[0]);
const customer = await fetch(api + `/api/customers/${barangkes.nokp}`)
.then(response => response.json());
const formatMYR = (value) => {
return new Intl.NumberFormat('ms-MY', {
style: 'currency',
currency: 'MYR'
}).format(value);
};
document.getElementById('norujukan_pampasan').textContent = norujukan;
document.getElementById('namalanjut_pampasan').textContent = customer.nama;
document.getElementById('nokplanjut_pampasan').textContent = customer.kpbaru;
document.getElementById('nilaiMarhun').textContent = formatMYR(barangkes.nilaimarhun);
document.getElementById('pembiayaan').textContent = formatMYR(barangkes.pembiayaan);
document.getElementById('jumlahPampasan').innerHTML = '<strong>' + formatMYR(barangkes.nilaimarhun - barangkes.pembiayaan - barangkes.untung) + '</strong>';
document.getElementById('keuntungan').textContent = formatMYR(barangkes.untung);
document.getElementById('bayaranAnsuran').textContent = formatMYR(tebus.pinjaman - (tebus.bakipjm - tebus.bakiupah));
});
</script>
@endsection
@endsection
+176 -4
View File
@@ -131,6 +131,20 @@
</div>
</div>
@if($pampasan)
<div class="bg-white p-3 my-3">
<div class="border text-center p-2 mx-auto" style="border: 2px solid red !important; width: 209px;">
<span class="text-danger font-weight-bold">PAMPASAN</span>
</div>
<div class="text-center mt-2">
<a href="{{ route('pampasan.surat', $gadai['norujukan']) }}" target="_blank"
class="btn surat-perjanjian-btn" data-norujukan="{{ $gadai['norujukan'] }}" title="Lihat Surat" style="background-color: red; color: white; border: 2px solid red;">
<i class="fas fa-file-alt fa-lg"></i> Cetak Surat Perjanjian
</a>
</div>
</div>
@endif
<div class="card" id="infomarhun">
<div class="card-body">
<table id="tablemarhun" class="table table-striped table-hover table-bordered text-center">
@@ -1082,6 +1096,28 @@
</div>
</div>
<!-- Modal Surat Agreement -->
<div class="modal fade" id="suratModal" tabindex="-1" role="dialog" aria-labelledby="suratModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="suratModalLabel">Surat Agreement</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body" id="surat-content" style="font-family: 'Times New Roman', Times, serif;">
<!-- Surat content will be injected here -->
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Batal</button>
<button type="button" class="btn btn-primary" id="btnPrintSurat">Cetak & Teruskan</button>
</div>
</div>
</div>
</div>
<script>
let elem_jenisAT = $('#jenisAT').remove();
@@ -1152,6 +1188,7 @@
var percent_mora = 0;
var pinjaman_teller = 0;
var pinjaman_pelulus = 0;
var pampasan = @json($pampasan);
@@ -1365,6 +1402,10 @@
}
});
if(pampasan != null){
$('#jumlahupah').val(pampasan.untung);
}
$.ajax({
method:'GET',
url: api + '/api/upahrebettawarruq/' + kodcaw + '/' + norujukan,
@@ -1395,7 +1436,18 @@
dataType: 'json',
async:false,
success:function(harga_tebus){
$('#perludibayar').val(formatter.format(harga_tebus));
if(pampasan != null){
let pembiayaan = safeMoneyParse(pampasan.pembiayaan);
let untung = safeMoneyParse(pampasan.untung);
$('#perludibayar').val(formatter.format(pembiayaan + untung));
$('#duitPelanggan').val(formatter.format(pembiayaan + untung));
$('#duitPelanggan').prop('readonly', true);
}else {
$('#perludibayar').val(formatter.format(harga_tebus));
}
}
});
@@ -1753,8 +1805,129 @@
let teller = "{{ Auth::user()->name }}";
function bayaransemua()
async function getPampasanByNorujukan(norujukan) {
const params = new URLSearchParams({
kodcaw: kodcaw,
status: 'all'
});
try {
const pampasanListResponse = await fetch(`{{ config('api.url') }}/api/palsu/laporan?${params}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
});
if (!pampasanListResponse.ok) {
throw new Error(`HTTP error! status: ${pampasanListResponse.status}`);
}
const pampasanListData = await pampasanListResponse.json();
const pampasanList = pampasanListData.filter(pampasan => pampasan.norujukan === norujukan);
const pampasan = pampasanList.length === 0 ? null : pampasanList.pop();
return pampasan;
} catch (error) {
console.error('Failed to fetch pampasan data:', error);
throw new Error("Something wrong with API");
}
}
// Helper function for safe money parsing
const safeMoneyParse = (value) => {
const parsed = parseFloat(value);
return isNaN(parsed) ? 0 : Math.round(parsed * 100) / 100; // Round to 2 decimal places
};
async function checkWangPetiBesiEnoughForTuntutanPampasan(pampasan) {
const currentDate = new Date().toISOString().split('T')[0];
let wangpetibesi = await fetch(api + '/api/TunaiDiTangan/' + kodcaw + '?tarikh=' + currentDate).then(response => response.json());
const nilaimarhun = safeMoneyParse(pampasan.nilaimarhun);
const pembiayaan = safeMoneyParse(pampasan.pembiayaan);
const untung = safeMoneyParse(pampasan.untung);
const jumlahpampasan = safeMoneyParse(nilaimarhun - pembiayaan - untung);
const balancewangpetibesiafterdeduct = wangpetibesi - jumlahpampasan < 0 ? false : true;
if(! balancewangpetibesiafterdeduct){
Swal.fire({
title: 'Peringatan',
html: `
<p>Wang peti besi tidak mencukupi untuk proses tuntutan pampasan</p>
<br>
<div style="text-align: left; margin: 0 auto; display: inline-block;">
<strong>Wang Peti Besi:</strong> RM ${formatter.format(wangpetibesi)}<br><br>
<strong>Jumlah Diperlukan:</strong> RM ${formatter.format(jumlahpampasan)}<br><br>
<strong>Kekurangan:</strong> <span style="color: red;">RM ${formatter.format(jumlahpampasan - wangpetibesi)}</span>
</div>
`,
icon: 'warning'
});
return false;
}
return true;
}
async function bayaransemua()
{
// Instantiate pampasan using the JavaScript function
const pampasan = await getPampasanByNorujukan(norujukan);
if(pampasan != null){
if(pampasan && !pampasan.hasOwnProperty('agreement_printed_at')){
Swal.fire({
title: 'Peringatan',
text: 'Sila print surat perjanjian',
icon: 'warning'
});
return; // Exit early if agreement not printed
}
const isEnough = await checkWangPetiBesiEnoughForTuntutanPampasan(pampasan);
if(! isEnough){
return;
}
}
if(pampasan != null){
const result = await Swal.fire({
title: 'Pengesahan Proses Tuntutan Pampasan',
html: `
<div style="text-align: left; margin: 20px 0; min-width: 500px;">
<p><strong>Sila pastikan wang untuk proses tuntutan pampasan adalah mencukupi.</strong></p>
<br>
<p style="color: #d33; font-weight: bold;">⚠️ Proses tidak dapat diundur</p>
<p style="color: #d33;">⚠️ Short wang teller atau peti besi akan ditanggung oleh anda</p>
<br>
<p>Adakah anda ingin meneruskan proses ini?</p>
</div>
`,
icon: 'question',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Ya, Teruskan',
cancelButtonText: 'Batal',
allowOutsideClick: false,
allowEscapeKey: false,
width: '600px'
});
if (!result.isConfirmed) {
return; // Exit if user cancels
}
}
$("#terima_transaksi").prop('disabled', true);
// Swal.fire({
// title: 'Memuatkan...',
@@ -3204,7 +3377,7 @@
///////////
}
//Bayaran Semua function end file
}
function gadaiautotawarruq()
@@ -4466,7 +4639,6 @@ return true;
};
}(jQuery));
</script>
@endsection
@@ -440,9 +440,12 @@
<td>{{ number_format($totalnm, 2) }}</td>
<td>{{ number_format($totalpinjamanasal, 2) }}</td>
<td>{{ number_format($totalpinjaman, 2) }}</td>
<td>@php$totalkeuntunganrebet = $totalpinjaman + $totalupah - $totalbayaran;
echo number_format($totalkeuntunganrebet, 2);
@endphp ?></td>
<td>
@php
$totalkeuntunganrebet = $totalpinjaman + $totalupah - $totalbayaran;
echo number_format($totalkeuntunganrebet, 2);
@endphp
</td>
<td>{{ number_format($totalujrah, 2) }}</td>
<td>{{ number_format($totalonepercent, 2) }}</td>
<td>{{ number_format($totalupah, 2) }}</td>
@@ -0,0 +1,258 @@
<!DOCTYPE html>
<html>
<head>
<title>Resit Pampasan</title>
<style>
body {
font-family: Arial, sans-serif;
font-size: 14px;
}
.resit {
width: 700px;
margin: 0 auto;
border: 1px solid #000;
padding: 20px;
}
.header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20px;
}
.header-left {
display: flex;
align-items: center;
gap: 10px;
}
.header img {
height: 20px;
}
.header .tag {
border: 1px solid #000;
padding: 5px 12px;
font-size: 14px;
font-weight: bold;
background: #f9f9f9;
}
h2 {
text-align: right;
margin-bottom: 10px;
}
.panel {
border-top: 1px dashed #000;
margin-top: 30px;
padding-top: 20px;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}
td {
padding: 6px;
}
.label {
width: 200px;
font-weight: bold;
}
.signature {
margin-top: 40px;
display: flex;
justify-content: space-between;
}
.signature div {
text-align: center;
width: 45%;
}
.footer {
margin-top: 20px;
text-align: center;
font-size: 12px;
}
.pelanggan-info {
text-align: center;
margin-bottom: 20px;
}
.center-table {
margin: 0 auto;
text-align: left;
width: fit-content;
}
.bayaran-info {
margin-top: 20px;
}
.jumlah-row {
margin-top: 20px;
}
.jumlah-row td {
padding-top: 15px;
font-weight: bold;
text-decoration: underline;
}
</style>
</head>
<body onload="window.print()">
<div class="resit">
<div class="header">
<div class="header-left">
<img src="{{ asset('img/kopkb.png') }}" alt="Logo KOPPKB">
<img src="{{ asset('img/ARRAHN1.png') }}" alt="Logo Ar-Rahn">
</div>
<span class="tag">Resit Pampasan</span>
<span class="tag">Untuk Kegunaan Pelanggan</span>
</div>
<div class="pelanggan-info">
<table class="center-table">
<tr>
<td class="label">Nama:</td>
<td>{{ $customer_info['nama'] }}</td>
</tr>
<tr>
<td class="label">No. KP:</td>
<td>{{ $gadai_info['nokp'] }}</td>
</tr>
<tr>
<td class="label">No. SAG:</td>
<td>{{ $pampasan['norujukan'] }}</td>
</tr>
<tr>
<td class="label">Tarikh Tuntutan:</td>
<td>{{ \Carbon\Carbon::parse($pampasan['created_at'])->format('d/m/Y') }}</td>
</tr>
</table>
</div>
<div class="bayaran-info">
<table class="center-table">
<tr>
<td class="label">Nilai Marhun:</td>
<td>RM {{ number_format($pampasan_info['nilaimarhun'], 2) }}</td>
</tr>
<tr>
<td class="label">(-) Baki Pembiayaan:</td>
<td>RM {{ number_format($pampasan_info['pembiayaan'], 2) }}</td>
</tr>
<tr>
<td class="label">(-) Keuntungan:</td>
<td>RM {{ number_format($pampasan_info['untung'], 2) }}</td>
</tr>
<tr class="jumlah-row">
<td class="label"><strong>JUMLAH PAMPASAN</strong></td>
<td><strong>RM {{ number_format($pampasan['jumlah_pampasan'], 2) }}</strong></td>
</tr>
</table>
</div>
<div class="signature">
<div>
<p>__________________________</p>
<p>PELANGGAN</p>
<p>{{ $customer_info['nama'] }}</p>
</div>
<div>
<p>__________________________</p>
<p>AR-RAHN</p>
<p>{{ auth()->user()->name }}</p>
</div>
</div>
<div class="panel">
<div class="header">
<div class="header-left">
<img src="{{ asset('img/kopkb.png') }}" alt="Logo KOPPKB">
<img src="{{ asset('img/ARRAHN1.png') }}" alt="Logo Ar-Rahn">
</div>
<span class="tag">Resit Pampasan</span>
<span class="tag">Untuk Kegunaan Pejabat</span>
</div>
<div class="pelanggan-info">
<table class="center-table">
<tr>
<td class="label">Nama:</td>
<td>{{ $customer_info['nama'] }}</td>
</tr>
<tr>
<td class="label">No. KP:</td>
<td>{{ $gadai_info['nokp'] }}</td>
</tr>
<tr>
<td class="label">No. SAG:</td>
<td>{{ $pampasan['norujukan'] }}</td>
</tr>
<tr>
<td class="label">Tarikh Tuntutan:</td>
<td>{{ \Carbon\Carbon::parse($pampasan['created_at'])->format('d/m/Y') }}</td>
</tr>
</table>
</div>
<div class="bayaran-info">
<table class="center-table">
<tr>
<td class="label">Nilai Marhun:</td>
<td>RM {{ number_format($pampasan_info['nilaimarhun'], 2) }}</td>
</tr>
<tr>
<td class="label">(-) Baki Pembiayaan:</td>
<td>RM {{ number_format($pampasan_info['pembiayaan'], 2) }}</td>
</tr>
<tr>
<td class="label">(-) Keuntungan:</td>
<td>RM {{ number_format($pampasan_info['untung'], 2) }}</td>
</tr>
<tr class="jumlah-row">
<td class="label"><strong>JUMLAH PAMPASAN</strong></td>
<td><strong>RM {{ number_format($pampasan['jumlah_pampasan'], 2) }}</strong></td>
</tr>
</table>
</div>
<div class="signature">
<div>
<p>__________________________</p>
<p>PELANGGAN</p>
<p>{{ $customer_info['nama'] }}</p>
</div>
<div>
<p>__________________________</p>
<p>AR-RAHN</p>
<p>{{ auth()->user()->name }}</p>
</div>
</div>
</div>
</div>
</body>
</html>
<script>
window.onload = function() {
window.print();
};
window.onafterprint = function() {
window.location.href = "{{ url('/panjar') }}";
};
</script>
@@ -0,0 +1,278 @@
<!DOCTYPE html>
<html lang="ms">
<head>
<meta charset="utf-8">
<title>Surat Pampasan</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
@page {
size: A4;
margin: 20mm;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: "Times New Roman", Times, serif;
color: #000;
}
.page {
width: 210mm;
min-height: 257mm;
margin: 0 auto;
position: relative;
}
.header {
text-align: center;
line-height: 1.4;
margin-bottom: 8mm;
}
.header .org-name {
font-weight: bold;
text-transform: uppercase;
}
.title {
text-align: center;
font-weight: bold;
text-transform: uppercase;
margin: 2mm 0 4mm;
font-size: 16px;
text-decoration: underline;
}
.claim-no {
text-align: center;
margin: 2mm 0 6mm;
}
.claim-no .label {
text-transform: uppercase;
font-weight: bold;
}
.content {
font-size: 12pt;
line-height: 1.65;
text-align: justify;
}
.content b {
font-weight: bold;
}
.content .emph {
font-weight: bold;
text-transform: uppercase;
}
.mt-2 {
margin-top: 2mm;
}
.mt-4 {
margin-top: 4mm;
}
.mt-8 {
margin-top: 8mm;
}
.mt-12 {
margin-top: 12mm;
}
.date-row {
margin-top: 8mm;
}
.line {
display: inline-block;
border-bottom: 1px solid #000;
width: 65mm;
height: 8mm;
vertical-align: bottom;
margin-left: 2mm;
margin-right: 6mm;
}
.signatures {
display: flex;
gap: 10mm;
margin-top: 12mm;
}
.sig-col {
width: 50%;
text-align: center;
}
.sig-line {
border-bottom: 1px solid #000;
height: 18mm;
margin: 0 10mm 2mm;
}
.sig-labels {
display: flex;
justify-content: space-between;
margin: 0 10mm;
font-weight: bold;
}
.sig-meta {
text-align: left;
margin: 2mm 10mm 0;
font-weight: bold;
}
.page-break {
page-break-after: always;
}
@media print {
html,
body {
width: 210mm;
}
.page {
min-height: 277mm;
}
.no-print {
display: none !important;
}
* {
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
}
</style>
</head>
<body>
<div class="page">
<div class="header">
<div class="org-name">KOPERASI PERMODALAN KELANTAN BERHAD (D-5-0228)</div>
<div>Lot PT 448, Tingkat 1, Jalan Kuala Krai, Batu 3 Wakaf Che Yeh, 15150 Kota Bharu, Kelantan</div>
<div>Tel : 09-7414331 / 4334 &nbsp;&nbsp; Website : www.koppkb.com &nbsp;&nbsp; Email : admin@koppkb.com
</div>
</div>
<div class="title">AKUAN TERIMAAN PAMPASAN DAN PELEPASAN</div>
<div class="claim-no"><span class="label">NO. TUNTUTAN :</span> <b>{{ $gadai_info['norujukan'] }}</b></div>
<div class="content">
<p>
1. Bahawasanya saya, Penama : <b>{{ $customer_info['nama'] }}</b><br>
No. Kad Pengenalan : <b>{{ $customer_info['kpbaru'] }}</b><br>
Adalah dengan ini atas <span class="emph">BALASAN</span> sebanyak <b>RM {{ number_format($jumlah_pampasan, 2) }}</b>
<b> (Ringgit Malaysia : {{ $jumlah_pampasan_terbilang }} sahaja)</b>
yang dibayar kepada saya oleh <b>AR-RAHN CAWANGAN SEMPORNA</b> atau
<b>KOPERASI PERMODALAN KELANTAN BERHAD (KoPKB)</b> yang mana penerimaan wang bayaran tersebut
adalah saya perakui sebagai bayaran muktamad melepaskan <b>AR-RAHN CAWANGAN SEMPORNA</b>
atau <b>KOPERASI PERMODALAN KELANTAN BERHAD (KoPKB)</b> daripada segala liabiliti, tindakan, klausa
tindakan, tuntutan dan tanggungjawab yang saya boleh kuatkuasakan, punyai atau mungkin mempunyai
pada masa ini atau pada bila-bila masa terhadap <b>AR-RAHN CAWANGAN SEMPORNA</b>,<b> KOPERASI PERMODALAN
KELANTAN BERHAD (KoPKB)</b>
berkait dengan kehilangan/kecurian barangan kemas pada bulan <b>November 2024</b> yang
telah digadaikan di <b>AR-RAHN CAWANGAN SEMPORNA, LOT F9-0 GROUND FLOOR, BANDAR MUTIARA, JALAN HOSPITAL,
91300 SEMPORNA, SABAH</b> atau apa-apa perkara
yang timbul berkait/akibat
daripada kehilangan/kecurian tersebut.
</p>
<p class="mt-4">
2. <span class="emph">DAN</span> saya memberikan sebenar-benar akujanji bahawa saya tidak akan
mengambil/memulakan
sebarang tindakan perundangan terhadap <b>AR-RAHN CAWANGAN SEMPORNA</b> atau
<b>KOPERASI PERMODALAN KELANTAN BERHAD (KoPKB)</b> berkait dengan kehilangan/kecurian tersebut
dengan penerimaan wang balasan di atas.
</p>
<p class="mt-4">
Adalah saya dengan ini memperakui bahawa dokumen ini telah dibacakan/saya baca dan saya fahami
kesan dan implikasi dokumen ini sepenuh-penuhnya.
</p>
<div class="date-row">
Bertarikh:
</div>
<div class="signatures">
<div class="sig-col">
<div class="sig-line"></div>
<div class="sig-labels"><span>(PELANGGAN)</span></div>
<div class="sig-labels"><span>{{ $customer_info['nama'] }}</span></div>
<div class="sig-meta">No K/P: </div>
</div>
<div class="sig-col">
<div class="sig-line"></div>
<div class="sig-labels"><span>(SAKSI)</span></div>
<div class="sig-meta">Nama : </div>
<div class="sig-meta">No K/P: </div>
</div>
</div>
</div>
</div>
<div class="no-print" style="text-align:center; margin: 10mm 0;">
<button onclick="cetakSuratPampasan()" style="padding:8px 16px;font-size:14px;">Cetak</button>
</div>
<script>
window.addEventListener('DOMContentLoaded', function(){
cetakSuratPampasan();
})
async function cetakSuratPampasan() {
window.print();
await initiatePampasan();
}
async function initiatePampasan() {
return fetch('/pampasan/initiate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
'norujukan': @json($gadai_info['norujukan']),
"_token": "{{ csrf_token() }}",
})
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then(result => {
return result;
})
.catch(error => {
console.error('Error initiating pampasan:', error);
Swal.fire({
title: 'Ralat',
text: 'Gagal daftar pampasan',
icon: 'error'
});
throw error;
});
}
</script>
</body>
</html>
+20 -1
View File
@@ -1,5 +1,6 @@
<?php
use App\Http\Controllers\KhazanahController;
use Illuminate\Support\Facades\Route;
use App\Services\ImbangdugaServices;
use Illuminate\Support\Facades\Storage;
@@ -185,7 +186,7 @@ Route::get('/capaian',['as'=>'khazanah.capaian','uses'=>'KhazanahController@capa
Route::get('/alirantunai',['as'=>'khazanah.alirantunai','uses'=>'KhazanahController@alirantunai'])->middleware('auth','khazanah');
Route::get('/pelangganan',['as'=>'khazanah.pelangganan','uses'=>'KhazanahController@pelanggan'])->middleware('auth','khazanah');
Route::get('/bajet',['as'=>'khazanah.bajet','uses'=>'KhazanahController@bajet'])->middleware('auth','khazanah');
//Route::get('/panjar',['as'=>'khazanah.panjar','uses'=>'KhazanahController@panjar'])->middleware('auth','khazanah');
Route::get('/panjar',['as'=>'khazanah.panjar','uses'=>'KhazanahController@panjar'])->middleware('auth','khazanah');
Route::get('/getkelulusan',['as'=>'khazanah.getkelulusan','uses'=>'KhazanahController@getkelulusan'])->middleware('auth','teller');
Route::post('/createkelulusan',['as'=>'khazanah.createkelulusan','uses'=>'KhazanahController@createkelulusan'])->middleware('auth','teller');
Route::put('/updatekelulusan',['as'=>'khazanah.updatekelulusan','uses'=>'KhazanahController@updatekelulusan'])->middleware('auth','khazanah');
@@ -335,6 +336,7 @@ Route::post('/barcodescanned',['as'=>'barcode.scanned','uses'=>'KhazanahControll
//Operasi
Route::get('/operasi/kelulusan','OperasiController@kelulusan')->name('operasi.kelulusan')->middleware('auth','operasi');
Route::post('/operasi/createkelulusan',['as'=>'operasi.createkelulusan','uses'=>'OperasiController@createkelulusan'])->middleware('auth','teller');
Route::post('/operasi/createkelulusan-by-khazanah',['as'=>'operasi.createkelulusan-by-khazanah','uses'=>'OperasiController@createkelulusanByKhazanah'])->middleware('auth', 'khazanah');
Route::get('/operasi/getkelulusan',['as'=>'operasi.getkelulusan','uses'=>'OperasiController@getkelulusan'])->middleware('auth','teller');
Route::put('/operasi/updatekelulusan',['as'=>'operasi.updatekelulusan','uses'=>'OperasiController@updatekelulusan'])->middleware('auth','operasi');
Route::get('/operasi/parameter','OperasiController@parameter')->name('parameter')->middleware('auth','operasi');
@@ -492,3 +494,20 @@ Route::get('/event/tellercash',['as'=>'event.tellercash','uses'=>'EventTriggerCo
Route::get('/perubatan',['as'=>'perubatan','uses'=>'PerubatanController@index'])->middleware('auth','operasi');
Route::get('/perubatan/search',['as'=>'perubatan.search','uses'=>'PerubatanController@search'])->middleware('auth','operasi');
Route::put('/perubatan/update',['as'=>'perubatan.update','uses'=>'PerubatanController@update'])->middleware('auth','operasi');
/* Pampasan */
//Page Pampasan Detail Payment Customer
Route::get('/pampasan/detail/{norujukan}', ['as' => 'pampasan.detail','uses' => 'KhazanahController@pampasanDetail'])->middleware('auth', 'khazanah');
//Selepas teller print surat perjanjian pampasan pelanggan
Route::post('/pampasan/initiate',['as' => 'pampasan.initiate', 'uses' => 'KhazanahController@initiatePampasan'])->middleware('auth', 'teller');
//Selepas PC masukkan Deno dan Submit Jumlah Pampasan
Route::post('/pampasan/terima',['as' => 'pampasan.terima', 'uses' => 'KhazanahController@terimaPampasan'])->middleware('auth', 'khazanah');
//Cetak Resit Pampasan
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');