Commit 5fff9330 authored by Mahmoud Aglan's avatar Mahmoud Aglan

Fix: attendance marking suspending players + partial payment receipt display

Bug 1: Attendance threshold was counting 'expected' records in the
denominator, causing any player with future sessions to have a low
attendance rate and get auto-suspended. Fixed by excluding 'expected'
status from rate calculation and requiring minimum 5 evaluated records
before triggering threshold enforcement.

Bug 2: Registration wizard and POS receipt always showed full amount
as "paid" even for partial/deposit payments. Fixed to show actual
paid_amount and due_amount from the invoice, with distinct badge for
partial payment state.
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent fb56f022
......@@ -162,6 +162,7 @@ public function calculateRate(int $participantId, ?int $groupId = null): float
$excluded = (clone $query)->whereIn('status', [
AttendanceStatus::Cancelled,
AttendanceStatus::Exempt,
AttendanceStatus::Expected,
])->count();
$denominator = $total - $excluded;
......@@ -224,6 +225,20 @@ private function checkThresholds(AttendanceRecord $record): void
return;
}
$minSample = (int) $this->settings->get('min_attendance_sample_size', 5);
$evaluatedCount = AttendanceRecord::where('subject_type', Participant::class)
->where('subject_id', $participant->id)
->whereNotIn('status', [
AttendanceStatus::Expected,
AttendanceStatus::Cancelled,
AttendanceStatus::Exempt,
])
->count();
if ($evaluatedCount < $minSample) {
return;
}
$rate = $this->calculateRate($participant->id);
$threshold = (float) $this->settings->get('minAttendancePercent', 75);
......
......@@ -46,6 +46,7 @@ class POSTerminal extends Component
public bool $showReceipt = false;
public ?string $lastReceiptNumber = null;
public ?int $lastTransactionTotal = null;
public ?int $lastTransactionPaid = null;
public ?string $lastTransactionUuid = null;
// Cash session
......@@ -369,6 +370,7 @@ public function checkout(POSService $posService): void
$this->lastReceiptNumber = $transaction->receipt_number;
$this->lastTransactionTotal = $transaction->total_amount;
$this->lastTransactionPaid = $depositPiasters ?? $transaction->total_amount;
$this->lastTransactionUuid = $transaction->uuid;
$this->showReceipt = true;
......@@ -392,6 +394,7 @@ public function closeReceipt(): void
$this->showReceipt = false;
$this->lastReceiptNumber = null;
$this->lastTransactionTotal = null;
$this->lastTransactionPaid = null;
$this->lastTransactionUuid = null;
}
......@@ -410,6 +413,7 @@ public function newTransaction(): void
$this->showReceipt = false;
$this->lastReceiptNumber = null;
$this->lastTransactionTotal = null;
$this->lastTransactionPaid = null;
$this->lastTransactionUuid = null;
}
......
......@@ -512,9 +512,19 @@ class="px-5 py-3 min-h-[48px] bg-green-600 text-white rounded-lg text-sm font-bo
<span class="font-mono font-bold text-gray-800" dir="ltr">{{ $lastReceiptNumber }}</span>
</div>
<div class="flex justify-between text-xs sm:text-sm">
<span class="text-gray-500">{{ __('المبلغ') }}</span>
<span class="font-bold text-green-700" dir="ltr">{{ number_format($lastTransactionTotal / 100, 2) }} {{ __('ج.م') }}</span>
<span class="text-gray-500">{{ __('الإجمالي') }}</span>
<span class="font-bold text-gray-800" dir="ltr">{{ number_format($lastTransactionTotal / 100, 2) }} {{ __('ج.م') }}</span>
</div>
@if($lastTransactionPaid && $lastTransactionPaid < $lastTransactionTotal)
<div class="flex justify-between text-xs sm:text-sm">
<span class="text-gray-500">{{ __('المدفوع') }}</span>
<span class="font-bold text-green-700" dir="ltr">{{ number_format($lastTransactionPaid / 100, 2) }} {{ __('ج.م') }}</span>
</div>
<div class="flex justify-between text-xs sm:text-sm">
<span class="text-gray-500">{{ __('المتبقي') }}</span>
<span class="font-bold text-orange-700" dir="ltr">{{ number_format(($lastTransactionTotal - $lastTransactionPaid) / 100, 2) }} {{ __('ج.م') }}</span>
</div>
@endif
</div>
</div>
<div class="border-t border-gray-200 p-3 sm:p-4 flex gap-3">
......
......@@ -1414,12 +1414,19 @@ class="flex-1 sm:flex-none inline-flex items-center justify-center gap-2 px-8 py
@if($payment_recorded)
<div class="flex justify-between text-green-700">
<span class="font-semibold">{{ __('المدفوع') }}</span>
<span class="font-semibold" dir="ltr">{{ number_format($inv->total_amount / 100, 2) }} {{ __('ج.م') }}</span>
<span class="font-semibold" dir="ltr">{{ number_format($inv->paid_amount / 100, 2) }} {{ __('ج.م') }}</span>
</div>
@if($inv->due_amount > 0)
<div class="flex justify-between text-orange-700">
<span class="font-semibold">{{ __('المتبقي') }}</span>
<span class="font-bold" dir="ltr">{{ number_format($inv->due_amount / 100, 2) }} {{ __('ج.م') }}</span>
</div>
@else
<div class="flex justify-between">
<span class="text-gray-500">{{ __('المتبقي') }}</span>
<span class="font-bold text-green-700" dir="ltr">0.00 {{ __('ج.م') }}</span>
</div>
@endif
@else
<div class="flex justify-between text-red-700">
<span class="font-semibold">{{ __('المتبقي') }}</span>
......@@ -1429,11 +1436,16 @@ class="flex-1 sm:flex-none inline-flex items-center justify-center gap-2 px-8 py
</div>
<div class="mt-4 text-center">
@if($payment_recorded)
@if($payment_recorded && $inv->due_amount <= 0)
<span class="inline-flex items-center gap-1 px-4 py-2 bg-green-100 text-green-800 rounded-full text-sm font-bold">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/></svg>
{{ __('تم الدفع') }}
</span>
@elseif($payment_recorded && $inv->due_amount > 0)
<span class="inline-flex items-center gap-1 px-4 py-2 bg-orange-100 text-orange-800 rounded-full text-sm font-bold">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
{{ __('دفع جزئي — متبقي') }} {{ number_format($inv->due_amount / 100, 0) }} {{ __('ج.م') }}
</span>
@else
<span class="inline-flex items-center gap-1 px-4 py-2 bg-amber-100 text-amber-800 rounded-full text-sm font-bold">
{{ __('مستحق الدفع') }}
......
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