penalty calculation

parent 1763f0f1
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
<td>{{ $claim->claim_date }}</td> <td>{{ $claim->claim_date }}</td>
<td>{{ $claim->description ?? '-' }}</td> <td>{{ $claim->description ?? '-' }}</td>
<td>{{ max(0, $claim->total_mileage - 40) }} km</td> <td>{{ max(0, $claim->total_mileage - 40) }} km</td>
<td>RM {{ number_format($claim->calculated_amount, 2) }}</td> <td>RM {{ number_format($claim->total_claim_amount, 2) }}</td>
<td>{{ $claim->status }}</td> <td>{{ $claim->status }}</td>
<td style="white-space:nowrap;"> <td style="white-space:nowrap;">
<a href="{{ route('mileage::BOD.show', $claim->id) }}" class="ui blue button tiny"> <a href="{{ route('mileage::BOD.show', $claim->id) }}" class="ui blue button tiny">
...@@ -99,7 +99,7 @@ ...@@ -99,7 +99,7 @@
<td>{{ $claim->claim_date }}</td> <td>{{ $claim->claim_date }}</td>
<td>{{ $claim->description ?? '-' }}</td> <td>{{ $claim->description ?? '-' }}</td>
<td>{{ max(0, $claim->total_mileage - 40) }} km</td> <td>{{ max(0, $claim->total_mileage - 40) }} km</td>
<td>RM {{ number_format($claim->calculated_amount, 2) }}</td> <td>RM {{ number_format($claim->total_claim_amount, 2) }}</td>
<td>{{ $claim->status }}</td> <td>{{ $claim->status }}</td>
<td> <td>
<a href="{{ route('mileage::BOD.show', $claim->id) }}" class="ui blue button tiny">Lihat</a> <a href="{{ route('mileage::BOD.show', $claim->id) }}" class="ui blue button tiny">Lihat</a>
......
...@@ -134,15 +134,27 @@ ...@@ -134,15 +134,27 @@
</td> </td>
</tr> </tr>
<tr>
<td>Penalti</td>
<td>
@if($claim->display_penalty_amount > 0)
<span style="color:#e53935;">
- RM {{ number_format($claim->display_penalty_amount, 2) }}
({{ $claim->display_penalty_reason }})
</span>
@else
{{ $claim->display_penalty_reason ?? 'Tiada penalti' }}
@endif
</td>
</tr>
<tr class="totals-row"> <tr class="totals-row">
<td>Jumlah Akhir (RM)</td> <td>Jumlah Akhir (RM)</td>
<td> <td>
@php <strong>RM {{ number_format(floatval($claim->display_total_claim_amount ?? $subtotal), 2) }}</strong>
$final = $claim->total_claim_amount ?? round($subtotal - ($displayPenalty ?? 0), 2);
@endphp
<strong>RM {{ number_format(floatval($final), 2) }}</strong>
</td> </td>
</tr> </tr>
</table> </table>
</div> </div>
......
...@@ -94,7 +94,19 @@ ...@@ -94,7 +94,19 @@
<tr> <tr>
<td style = "text-align: center;">{{ $loop->iteration }}</td> <td style = "text-align: center;">{{ $loop->iteration }}</td>
<td>{{ $claim->user->name ?? '-' }}</td> <td>{{ $claim->user->name ?? '-' }}</td>
<td>{{ $claim->claim_date }}</td> <td>
{{ $claim->claim_date }}
@php
$days = \Carbon\Carbon::parse($claim->claim_date)->diffInDays($claim->created_at ?? now());
@endphp
@if($days > 180)
<br><span class="ui red label tiny">Tertakluk BOD (&gt;6 bulan)</span>
@elseif($days > 90)
<br><span class="ui red label tiny">Lewat 3-6 bulan (-30%)</span>
@elseif($days > 30)
<span class="ui yellow label tiny">Lewat 1-3 bulan (-10%)</span>
@endif
</td>
<td>{{ $claim->description ?? '-' }}</td> <td>{{ $claim->description ?? '-' }}</td>
<td>{{ max(0, $claim->total_mileage - 40) }} km</td> <td>{{ max(0, $claim->total_mileage - 40) }} km</td>
<td>RM {{ number_format($claim->total_claim_amount, 2) }}</td> <td>RM {{ number_format($claim->total_claim_amount, 2) }}</td>
...@@ -150,7 +162,7 @@ ...@@ -150,7 +162,7 @@
<td>{{ $claim->claim_date }}</td> <td>{{ $claim->claim_date }}</td>
<td>{{ $claim->description ?? '-' }}</td> <td>{{ $claim->description ?? '-' }}</td>
<td>{{ max(0, $claim->total_mileage - 40) }} km</td> <td>{{ max(0, $claim->total_mileage - 40) }} km</td>
<td>RM {{ number_format($claim->calculated_amount, 2) }}</td> <td>RM {{ number_format($claim->total_claim_amount, 2) }}</td>
<td>{{ $claim->status }}</td> <td>{{ $claim->status }}</td>
<td> <td>
<a href="{{ route('mileage::HOD.show', $claim->id) }}" class="ui blue button tiny"> <a href="{{ route('mileage::HOD.show', $claim->id) }}" class="ui blue button tiny">
......
...@@ -133,14 +133,24 @@ ...@@ -133,14 +133,24 @@
RM {{ number_format($subtotal, 2) }} RM {{ number_format($subtotal, 2) }}
</td> </td>
</tr> </tr>
<tr>
<td>Penalti</td>
<td>
@if($claim->display_penalty_amount > 0)
<span style="color:#e53935;">
- RM {{ number_format($claim->display_penalty_amount, 2) }}
({{ $claim->display_penalty_reason }})
</span>
@else
{{ $claim->display_penalty_reason ?? 'Tiada penalti' }}
@endif
</td>
</tr>
<tr class="totals-row"> <tr class="totals-row">
<td>Jumlah Akhir (RM)</td> <td>Jumlah Akhir (RM)</td>
<td> <td>
@php <strong>RM {{ number_format(floatval($claim->display_total_claim_amount ?? $subtotal), 2) }}</strong>
$final = $claim->total_claim_amount ?? round($subtotal - ($displayPenalty ?? 0), 2);
@endphp
<strong>RM {{ number_format(floatval($final), 2) }}</strong>
</td> </td>
</tr> </tr>
</table> </table>
......
...@@ -283,6 +283,16 @@ ...@@ -283,6 +283,16 @@
</button> </button>
</form> </form>
@endif @endif
{{-- Show Bayar button only if claim is Disemak --}}
@if($claim->status === 'Disemak')
<form action="{{ route('mileage::finance.updateStatus', $claim->id) }}" method="POST" class="inline-form">
@csrf
@method('PUT')
<button type="submit" name="action" value="Dibayar" class="ui teal button tiny">
<i class="money bill alternate icon"></i> Bayar
</button>
</form>
@endif
</div> </div>
</td> </td>
</tr> </tr>
...@@ -360,25 +370,10 @@ ...@@ -360,25 +370,10 @@
$subtotal = $mileageAmount + $totalToll + $totalOthers; $subtotal = $mileageAmount + $totalToll + $totalOthers;
// === Penalty === // === Penalty ===
$claimMonthEnd = Carbon::parse($month)->endOfMonth(); $finalTotal = $subtotal - $totalPenalty;
$latestClaim = $validInMonth->sortByDesc('created_at')->first();
$submissionDate = $latestClaim ? Carbon::parse($latestClaim->created_at) : now();
$monthsDiff = $claimMonthEnd->diffInMonths($submissionDate, false);
if ($monthsDiff <= 1) {
$penaltyRate = 0; $penaltyLabel = "Tiada penalti (≤ 1 bulan)";
} elseif ($monthsDiff <= 3) {
$penaltyRate = 0.10; $penaltyLabel = "Penalti 10% (lewat ≤ 3 bulan)";
} elseif ($monthsDiff <= 6) {
$penaltyRate = 0.30; $penaltyLabel = "Penalti 30% (lewat ≤ 6 bulan)";
} else {
$penaltyRate = 'BOD'; $penaltyLabel = "Tertakluk kepada BOD (> 6 bulan)";
}
$penaltyAmount = $penaltyRate === 'BOD' ? 0 : $subtotal * $penaltyRate;
$finalTotal = $subtotal - $penaltyAmount;
@endphp @endphp
<div class="ui segment"> <div class="ui segment">
<h4><i class="calculator icon"></i> Ringkasan Pengiraan Bulanan</h4> <h4><i class="calculator icon"></i> Ringkasan Pengiraan Bulanan</h4>
<table class="ui definition table"> <table class="ui definition table">
...@@ -407,13 +402,21 @@ ...@@ -407,13 +402,21 @@
<tr> <tr>
<td>Penalti</td> <td>Penalti</td>
<td> <td>
@if($penaltyRate==='BOD') @if($isBOD)
<span style="color:#d35400;"><i class="exclamation triangle icon"></i> {{ $penaltyLabel }}</span> <span style="color:#d35400;"><i class="exclamation triangle icon"></i> Tertakluk kepada BOD</span>
@elseif($totalPenalty > 0)
Tolak: RM {{ number_format($totalPenalty, 2) }}<br>
@foreach($penaltyBreakdown as $p)
@if($p['penalty'] > 0)
• {{ \Carbon\Carbon::parse($p['claim_date'])->format('d/m/Y') }}: {{ $p['label'] }} (RM {{ number_format($p['penalty'], 2) }})<br>
@endif
@endforeach
@else @else
{{ $penaltyLabel }}<br>Tolak: RM {{ number_format($penaltyAmount,2) }} Tiada penalti
@endif @endif
</td> </td>
</tr> </tr>
<tr class="totals-row"> <tr class="totals-row">
<td><strong>Jumlah Akhir (Selepas Penalti)</strong></td> <td><strong>Jumlah Akhir (Selepas Penalti)</strong></td>
<td><strong>RM {{ number_format($finalTotal,2) }}</strong></td> <td><strong>RM {{ number_format($finalTotal,2) }}</strong></td>
......
...@@ -60,8 +60,8 @@ function () { ...@@ -60,8 +60,8 @@ function () {
Route::put('/finance/update/{id}', [FinanceController::class, 'update'])->name('.update'); Route::put('/finance/update/{id}', [FinanceController::class, 'update'])->name('.update');
Route::get('/view/claim/{id}', [FinanceController::class, 'viewEach'])->name('.viewEach'); Route::get('/view/claim/{id}', [FinanceController::class, 'viewEach'])->name('.viewEach');
Route::put('/finance/claims/{id}/update-status', [FinanceController::class, 'updateStatus'])->name('.updateStatus'); Route::put('/finance/claims/{id}/update-status', [FinanceController::class, 'updateStatus'])->name('.updateStatus');
Route::post('/{id}/review', [FinanceController::class, 'review'])->name('.review'); // Route::post('/{id}/review', [FinanceController::class, 'review'])->name('.review');
Route::post('/{id}/reject', [FinanceController::class, 'reject'])->name('.reject'); // Route::post('/{id}/reject', [FinanceController::class, 'reject'])->name('.reject');
Route::get('/export', [FinanceController::class, 'export'])->name('.export'); Route::get('/export', [FinanceController::class, 'export'])->name('.export');
}); });
......
...@@ -196,7 +196,7 @@ public function show(Request $request, $id) ...@@ -196,7 +196,7 @@ public function show(Request $request, $id)
public function viewEach($id) public function viewEach($id)
{ {
$claim = Claim::with(['project', 'jenisKenderaan'])->findOrFail($id); $claim = Claim::with(['project', 'jenisKenderaan'])->findOrFail($id);
return view('mileage.applications.viewEach', compact('claim')); return view('mileage::application.view', compact('claim'));
} }
public function updateStatus(Request $request, $id) public function updateStatus(Request $request, $id)
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
use Portal\Mileage\Model\JenisKenderaan; use Portal\Mileage\Model\JenisKenderaan;
use Portal\Mileage\Model\ProjectTeam; use Portal\Mileage\Model\ProjectTeam;
use Portal\Mileage\Model\Users; use Portal\Mileage\Model\Users;
use Portal\Mileage\Model\Claim;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Routing\Controller; use Illuminate\Routing\Controller;
use Illuminate\Http\Request; use Illuminate\Http\Request;
......
...@@ -44,7 +44,13 @@ public function show($id) ...@@ -44,7 +44,13 @@ public function show($id)
$submissionDate = $claim->created_at ?? Carbon::now(); $submissionDate = $claim->created_at ?? Carbon::now();
$daysDiff = $claimDate->diffInDays($submissionDate); $daysDiff = $claimDate->diffInDays($submissionDate);
$calculatedAmount = $claim->calculated_amount ?? 0; $claimableMileage = max(0, ($claim->total_mileage ?? 0) - 40);
if ($claim->jenis_kenderaan_id == 1) {
$rate = ($claimableMileage <= 500) ? 0.55 : 0.50;
} else {
$rate = 0.30;
}
$calculatedAmount = round($claimableMileage * $rate, 2);
if ($daysDiff <= 30) { if ($daysDiff <= 30) {
$claim->display_penalty_amount = 0; $claim->display_penalty_amount = 0;
......
...@@ -41,7 +41,7 @@ public function index(Request $request) ...@@ -41,7 +41,7 @@ public function index(Request $request)
'id' => $user->id ?? null, 'id' => $user->id ?? null,
'name' => $user->name ?? '-', 'name' => $user->name ?? '-',
'total_claims' => $userClaims->count(), 'total_claims' => $userClaims->count(),
'total_amount' => $userClaims->sum('calculated_amount'), 'total_amount' => $userClaims->sum('total_claim_amount'),
]; ];
}) })
->sortBy('name') ->sortBy('name')
...@@ -51,7 +51,7 @@ public function index(Request $request) ...@@ -51,7 +51,7 @@ public function index(Request $request)
} }
public function show($userId, Request $request) public function show($userId, Request $request)
{ {
$month = $request->get('month', Carbon::now()->format('Y-m')); $month = $request->get('month', Carbon::now()->format('Y-m'));
$parsedMonth = Carbon::parse($month); $parsedMonth = Carbon::parse($month);
...@@ -62,9 +62,56 @@ public function show($userId, Request $request) ...@@ -62,9 +62,56 @@ public function show($userId, Request $request)
->whereYear('claim_date', $parsedMonth->year) ->whereYear('claim_date', $parsedMonth->year)
->get(); ->get();
return view('mileage::finance.show', compact('user', 'claims', 'month')); // === Calculate per-claim penalty (same formula as HOD/BOD) ===
$totalPenalty = 0;
$isBOD = false;
$penaltyBreakdown = [];
foreach ($claims as $claim) {
$claimDate = Carbon::parse($claim->claim_date);
$submissionDate = $claim->created_at ?? Carbon::now();
$daysDiff = $claimDate->diffInDays($submissionDate);
$claimableMileage = max(0, ($claim->total_mileage ?? 0) - 40);
if ($claim->jenis_kenderaan_id == 1) {
$rate = ($claimableMileage <= 500) ? 0.55 : 0.50;
} else {
$rate = 0.30;
}
$claimMileageAmount = round($claimableMileage * $rate, 2);
if ($daysDiff <= 30) {
$penaltyRate = 0;
$penaltyLabel = 'Tiada penalti (≤ 1 bulan)';
} elseif ($daysDiff <= 90) {
$penaltyRate = 0.10;
$penaltyLabel = 'Lewat hantar >1 ≤3 bulan (10%)';
} elseif ($daysDiff <= 180) {
$penaltyRate = 0.30;
$penaltyLabel = 'Lewat hantar >3 ≤6 bulan (30%)';
} else {
$penaltyRate = 'BOD';
$penaltyLabel = 'Tertakluk kepada BOD';
$isBOD = true;
}
$claimPenalty = $penaltyRate === 'BOD' ? 0 : round($claimMileageAmount * $penaltyRate, 2);
$totalPenalty += $claimPenalty;
$penaltyBreakdown[] = [
'claim_date' => $claim->claim_date,
'penalty' => $claimPenalty,
'label' => $penaltyLabel,
];
} }
return view('mileage::finance.show', compact(
'user', 'claims', 'month',
'totalPenalty', 'isBOD', 'penaltyBreakdown'
));
}
public function viewEach($id) public function viewEach($id)
{ {
$claim = Claim::with(['user', 'project', 'jenisKenderaan'])->findOrFail($id); $claim = Claim::with(['user', 'project', 'jenisKenderaan'])->findOrFail($id);
...@@ -127,7 +174,7 @@ public function updateStatus(Request $request, $id) ...@@ -127,7 +174,7 @@ public function updateStatus(Request $request, $id)
$claim = Claim::findOrFail($id); $claim = Claim::findOrFail($id);
$action = $request->input('action'); $action = $request->input('action');
if (!in_array($action, ['Disemak', 'Ditolak'])) { if (!in_array($action, ['Disemak', 'Ditolak', 'Dibayar'])) {
return back()->with('error', 'Tindakan tidak sah.'); return back()->with('error', 'Tindakan tidak sah.');
} }
......
...@@ -57,7 +57,13 @@ public function show($id) ...@@ -57,7 +57,13 @@ public function show($id)
$claimDate = Carbon::parse($claim->claim_date); $claimDate = Carbon::parse($claim->claim_date);
$submissionDate = $claim->created_at ?? Carbon::now(); $submissionDate = $claim->created_at ?? Carbon::now();
$daysDiff = $claimDate->diffInDays($submissionDate); $daysDiff = $claimDate->diffInDays($submissionDate);
$calculatedAmount = $claim->calculated_amount ?? 0; $claimableMileage = max(0, ($claim->total_mileage ?? 0) - 40);
if ($claim->jenis_kenderaan_id == 1) {
$rate = ($claimableMileage <= 500) ? 0.55 : 0.50;
} else {
$rate = 0.30;
}
$calculatedAmount = round($claimableMileage * $rate, 2);
if ($daysDiff <= 30) { if ($daysDiff <= 30) {
$displayPenalty = 0; $displayPenalty = 0;
......
...@@ -16,7 +16,8 @@ class Claim extends Model ...@@ -16,7 +16,8 @@ class Claim extends Model
protected $fillable = [ protected $fillable = [
'user_id','claim_date', 'jenis_kenderaan_id', 'project_id', 'description', 'user_id','claim_date', 'jenis_kenderaan_id', 'project_id', 'description',
'distance_from', 'distance_to', 'distance_from', 'distance_to',
'total_mileage', 'toll_amount', 'others_amount', 'others_description', 'total_mileage', 'toll_amount', 'others_amount', 'others_details',
'claimable_mileage', 'rate', 'mileage_amount',
'calculated_amount','penalty_amount', 'penalty_reason', 'total_claim_amount', 'calculated_amount','penalty_amount', 'penalty_reason', 'total_claim_amount',
'status', 'status',
]; ];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment