This commit is contained in:
Saufi
2026-06-16 15:04:58 +08:00
commit 77a87fbdf1
171 changed files with 21225 additions and 0 deletions

View File

@@ -0,0 +1,183 @@
@extends('layouts.app')
@section('title', 'Kemaskini Bayaran Pukal')
@section('page-title', 'Kemaskini Bayaran Pukal')
@section('page-label', 'Modul Staff')
@section('page-actions')
<a href="{{ route('staff.bulk-payments.template') }}" class="btn btn-outline-primary">
<i class="bi bi-download me-1"></i> Download Template Excel
</a>
@endsection
@section('content')
<div class="row g-4 mb-4">
<div class="col-md-4">
<div class="card stat-card p-4 h-100">
<div class="stat-icon mb-3"><i class="bi bi-person-check-fill"></i></div>
<div class="mini-label">Akaun Aktif</div>
<div class="h3 fw-bold mb-0">{{ $activeAccountCount }}</div>
<div class="text-muted small">Akaun ansuran yang sedang aktif.</div>
</div>
</div>
<div class="col-md-4">
<div class="card stat-card p-4 h-100">
<div class="stat-icon mb-3"><i class="bi bi-list-check"></i></div>
<div class="mini-label">Ansuran Dalam Excel</div>
<div class="h3 fw-bold mb-0">{{ $activeSchedules->count() }}</div>
<div class="text-muted small">{{ $unpaidScheduleCount }} belum bayar, {{ $paidScheduleCount }} sudah dibayar.</div>
</div>
</div>
<div class="col-md-4">
<div class="card stat-card p-4 h-100">
<div class="stat-icon mb-3"><i class="bi bi-cash-coin"></i></div>
<div class="mini-label">Jumlah Belum Direkod</div>
<div class="h3 fw-bold mb-0">RM {{ number_format($totalUnpaidAmount, 2) }}</div>
<div class="text-muted small">Jumlah ansuran aktif yang belum dibayar.</div>
</div>
</div>
</div>
<div class="row g-4">
<div class="col-lg-5">
<div class="card surface-card p-4 h-100">
<h2 class="h5 fw-bold mb-3">Upload Excel/CSV Bayaran</h2>
<p class="text-muted">
Gunakan template daripada sistem supaya setiap baris mempunyai <strong>Installment_Schedule_ID</strong>,
<strong>No_Akaun</strong> dan <strong>Ansuran_Ke</strong>. Staff hanya perlu isi No_Resit, Tarikh_Bayaran,
Amaun_Bayaran dan catatan jika perlu. Baris yang sudah dibayar akan membawa transaksi sedia ada untuk semakan atau kemaskini.
</p>
<div class="alert alert-info small">
Hanya akaun berstatus <strong>aktif</strong> akan diproses. Ansuran <strong>belum bayar/lewat</strong>
akan direkodkan sebagai bayaran baharu, manakala ansuran <strong>dibayar</strong> akan mengemaskini
transaksi bayaran sedia ada dalam database.
</div>
<form method="POST" action="{{ route('staff.bulk-payments.store') }}" enctype="multipart/form-data" class="d-grid gap-3">
@csrf
<div>
<label class="form-label">Fail Bayaran Pukal</label>
<input type="file" name="file" class="form-control" accept=".xlsx,.xls,.csv" required>
@error('file')
<div class="text-danger small mt-1">{{ $message }}</div>
@enderror
</div>
<button class="btn btn-primary btn-lg">
<i class="bi bi-upload me-1"></i> Muat Naik & Kemaskini Bayaran
</button>
</form>
</div>
</div>
<div class="col-lg-7">
<div class="card surface-card p-4 h-100">
<h2 class="h5 fw-bold mb-3">Ringkasan Proses Terakhir</h2>
@if ($importResult)
<div class="row g-3 mb-3">
<div class="col-6 col-md-3">
<div class="border rounded-4 p-3">
<div class="mini-label">Diproses</div>
<div class="h4 fw-bold mb-0">{{ $importResult['processed'] }}</div>
</div>
</div>
<div class="col-6 col-md-3">
<div class="border rounded-4 p-3">
<div class="mini-label">Berjaya</div>
<div class="h4 fw-bold text-success mb-0">{{ $importResult['success'] }}</div>
</div>
</div>
<div class="col-6 col-md-3">
<div class="border rounded-4 p-3">
<div class="mini-label">Gagal</div>
<div class="h4 fw-bold text-danger mb-0">{{ $importResult['failed'] }}</div>
</div>
</div>
<div class="col-6 col-md-3">
<div class="border rounded-4 p-3">
<div class="mini-label">Diabaikan</div>
<div class="h4 fw-bold text-muted mb-0">{{ $importResult['skipped'] }}</div>
</div>
</div>
</div>
@if (! empty($importResult['errors']))
<div class="alert alert-warning mb-0">
<div class="fw-semibold mb-2">Ralat yang perlu disemak</div>
<ul class="mb-0 ps-3">
@foreach ($importResult['errors'] as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@else
<div class="alert alert-success mb-0">
Semua baris bayaran yang lengkap berjaya dikemaskini.
</div>
@endif
@else
<div class="text-muted">
Belum ada proses upload bayaran pukal dalam sesi ini.
</div>
@endif
</div>
</div>
</div>
<div class="card surface-card p-4 mt-4">
<div class="d-flex flex-wrap justify-content-between align-items-center gap-3 mb-3">
<div>
<h2 class="h5 fw-bold mb-1">Senarai Ansuran Aktif Untuk Template</h2>
<div class="text-muted small">Paparan ini menunjukkan ansuran akaun aktif termasuk transaksi yang sudah dibayar.</div>
</div>
<a href="{{ route('staff.bulk-payments.template') }}" class="btn btn-outline-primary">
Download Template
</a>
</div>
<div class="table-responsive">
<table class="table align-middle">
<thead>
<tr>
<th>No Akaun</th>
<th>No Permohonan</th>
<th>Pemohon</th>
<th>Ansuran</th>
<th>Tarikh Jadual</th>
<th>Amaun</th>
<th>Status</th>
<th>No Resit</th>
<th>No Transaksi</th>
</tr>
</thead>
<tbody>
@forelse ($activeSchedules as $schedule)
@php($payment = $schedule->payments->sortByDesc(fn ($item) => $item->paid_at?->timestamp ?? $item->id)->first())
<tr>
<td>
<div class="fw-semibold">{{ $schedule->application?->no_akaun }}</div>
<div class="text-muted small">{{ $schedule->application?->no_akaun_tunggakan }}</div>
</td>
<td>{{ $schedule->application?->application_no }}</td>
<td>{{ $schedule->application?->user?->displayName() }}</td>
<td>Ansuran {{ $schedule->installment_no }}</td>
<td>{{ optional($schedule->due_date)->format('d/m/Y') ?: '-' }}</td>
<td>RM {{ number_format((float) $schedule->amount, 2) }}</td>
<td>@include('components.status-badge', ['status' => $schedule->payment_status])</td>
<td>{{ $payment?->receipt_no ?: '-' }}</td>
<td>{{ $payment?->transaction_no ?: '-' }}</td>
</tr>
@empty
<tr>
<td colspan="9" class="text-center text-muted py-4">
Tiada ansuran akaun aktif setakat ini.
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
@endsection