39669-vm/center_assessment_report.php
2026-04-17 14:22:06 +00:00

235 lines
13 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/includes/app.php';
function center_report_number(float $value): string
{
return rtrim(rtrim(number_format($value, 2, '.', ''), '0'), '.');
}
$flash = consume_flash();
$applicationId = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT) ?: 0;
$requestedCycleId = filter_input(INPUT_GET, 'cycle', FILTER_VALIDATE_INT) ?: 0;
$application = $applicationId > 0 ? get_application($applicationId) : null;
$isApprovedCenter = $application && (string) ($application['status'] ?? '') === 'approved';
$cycleContext = ['cycles' => [], 'selected' => null, 'active' => null, 'read_only' => false];
$selectedCycle = null;
$selectedCycleId = 0;
$cycleLabel = 'لا توجد دورة بعد';
$buildCenterAssessmentsUrl = static function (int $targetApplicationId = 0, int $targetCycleId = 0): string {
$params = [];
if ($targetApplicationId > 0) {
$params['id'] = $targetApplicationId;
}
if ($targetCycleId > 0) {
$params['cycle'] = $targetCycleId;
}
return 'center_assessments.php' . ($params !== [] ? '?' . http_build_query($params) : '');
};
$buildCenterAssessmentCriteriaUrl = static function (int $targetApplicationId = 0, int $targetCycleId = 0, int $targetAssessmentId = 0): string {
$params = [];
if ($targetApplicationId > 0) {
$params['id'] = $targetApplicationId;
}
if ($targetCycleId > 0) {
$params['cycle'] = $targetCycleId;
}
if ($targetAssessmentId > 0) {
$params['assessment_id'] = $targetAssessmentId;
}
return 'center_assessment_criteria.php' . ($params !== [] ? '?' . http_build_query($params) : '');
};
$buildCenterAssessmentScoreUrl = static function (int $targetApplicationId = 0, int $targetCycleId = 0, int $targetAssessmentId = 0): string {
$params = [];
if ($targetApplicationId > 0) {
$params['id'] = $targetApplicationId;
}
if ($targetCycleId > 0) {
$params['cycle'] = $targetCycleId;
}
if ($targetAssessmentId > 0) {
$params['assessment_id'] = $targetAssessmentId;
}
return 'center_assessment_score_sheet.php' . ($params !== [] ? '?' . http_build_query($params) : '');
};
if ($applicationId <= 0 || $requestedCycleId <= 0) {
set_flash('error', 'اختر المركز والدورة أولاً ثم افتح تقرير التقييم من شاشة تقييم المراكز.');
header('Location: ' . $buildCenterAssessmentsUrl($applicationId, $requestedCycleId));
exit;
}
if ($isApprovedCenter) {
$cycleContext = resolve_school_cycle_context((int) $application['id'], $application, $requestedCycleId);
$selectedCycle = $cycleContext['selected'];
$selectedCycleId = $selectedCycle ? (int) ($selectedCycle['id'] ?? 0) : 0;
$cycleLabel = $selectedCycle ? (string) ($selectedCycle['cycle_name'] ?? $cycleLabel) : $cycleLabel;
}
$summary = $isApprovedCenter && $selectedCycleId > 0
? center_assessment_summary_by_cycle((int) $application['id'], $selectedCycleId)
: [
'assessments' => [],
'total_assessments' => 0,
'active_assessments' => 0,
'recorded_assessments' => 0,
'completed_assessments' => 0,
'pending_assessments' => 0,
'waived_assessments' => 0,
'missing_assessments' => 0,
'overall_percentage' => 0.0,
'score_total' => 0.0,
'max_score_total' => 0.0,
'latest_assessed_on' => '',
'performance' => student_certificate_performance_meta(0.0),
];
$pageTitle = $application && $isApprovedCenter
? 'تقرير تقييم المراكز: ' . (string) ($application['center_name'] ?? '') . ($selectedCycle ? ' — ' . $cycleLabel : '')
: 'تقرير تقييم المراكز';
$pageDescription = 'ملخص مجمع لنتائج تقييم المركز داخل الدورة المختارة، مع حالة كل تقييم ونسبة الإنجاز الكلية.';
if (!$application && $applicationId > 0) {
http_response_code(404);
}
$assessmentsUrl = $application ? $buildCenterAssessmentsUrl((int) $application['id'], $selectedCycleId) : 'center_assessments.php';
render_page_start($pageTitle, 'approved', $pageDescription, (string) ($application['favicon'] ?? ''));
render_flash($flash);
?>
<section class="py-4 py-lg-5">
<div class="container-xxl">
<div class="admin-layout row g-4 align-items-start">
<div class="col-lg-3 layout-sidebar-column">
<?php require __DIR__ . '/includes/sidebar.php'; ?>
</div>
<div class="col-lg-9 layout-content-column">
<?php if (!$application): ?>
<div class="app-card text-center py-5">
<div class="empty-title mb-2">المركز غير موجود</div>
<p class="text-muted mb-3">تحقق من الرابط أو ارجع إلى قائمة المراكز المعتمدة.</p>
<a class="btn btn-primary" href="applications.php?status=approved">المراكز المعتمدة</a>
</div>
<?php elseif (!$isApprovedCenter): ?>
<div class="app-card text-center py-5">
<div class="empty-title mb-2">التقرير يُفتح بعد الاعتماد</div>
<p class="text-muted mb-3">اعتمد المركز أولاً حتى يظهر تقرير التقييم الإشرافي.</p>
<a class="btn btn-outline-secondary" href="application_detail.php?id=<?= e((string) $application['id']) ?>">ملف الاعتماد</a>
</div>
<?php else: ?>
<div class="page-banner approved-hero mb-4">
<div class="row g-4 align-items-center">
<div class="col-lg-8">
<span class="approved-kicker mb-3">تقرير الدورة</span>
<h1 class="page-title mb-3">ملخص تقييم المركز</h1>
<p class="page-copy mb-3">هذا التقرير يجمع حالة كل تقييم إشرافي للمركز داخل دورة <strong><?= e($cycleLabel) ?></strong> ويعرض النسبة الكلية الحالية.</p>
<div class="hero-meta">
<span><?= e((string) ($summary['active_assessments'] ?? 0)) ?> تقييمات نشطة</span>
<span><?= e(center_report_number((float) ($summary['overall_percentage'] ?? 0))) ?>%</span>
<span><?= e((string) (($summary['performance']['label_ar'] ?? ''))) ?></span>
</div>
</div>
<div class="col-lg-4">
<div class="app-card h-100">
<div class="section-title mb-2">إجراءات سريعة</div>
<div class="cta-stack">
<a class="btn btn-outline-secondary" href="<?= e($assessmentsUrl) ?>">إدارة التقييمات</a>
<?php if (!empty($summary['assessments'][0]['id'])): ?>
<a class="btn btn-primary" href="<?= e($buildCenterAssessmentScoreUrl((int) $application['id'], $selectedCycleId, (int) $summary['assessments'][0]['id'])) ?>">فتح أول رصد</a>
<?php endif; ?>
</div>
</div>
</div>
</div>
</div>
<?php if ($selectedCycleId <= 0): ?>
<div class="app-card"><div class="alert alert-warning mb-0">لا توجد دورة متاحة لهذا المركز بعد. أنشئ دورة أولاً من صفحة المركز.</div></div>
<?php elseif ($summary['assessments'] === []): ?>
<div class="app-card text-center py-5">
<div class="empty-title mb-2">لا توجد تقييمات لعرض التقرير</div>
<p class="text-muted mb-3">أضف تقييمات مركز أولاً، ثم استخدم الرصد لإظهار النتيجة هنا.</p>
<a class="btn btn-primary" href="<?= e($assessmentsUrl) ?>">إضافة تقييم</a>
</div>
<?php else: ?>
<div class="row g-3 mb-4">
<div class="col-md-3"><div class="app-card h-100"><div class="section-title mb-2">النسبة الكلية</div><div class="display-6 mb-1"><?= e(center_report_number((float) ($summary['overall_percentage'] ?? 0))) ?>%</div><div class="section-subtle"><?= e((string) (($summary['performance']['label_ar'] ?? ''))) ?></div></div></div>
<div class="col-md-3"><div class="app-card h-100"><div class="section-title mb-2">المرصود</div><div class="display-6 mb-1"><?= e((string) ($summary['recorded_assessments'] ?? 0)) ?></div><div class="section-subtle">من <?= e((string) ($summary['active_assessments'] ?? 0)) ?> تقييم نشط</div></div></div>
<div class="col-md-3"><div class="app-card h-100"><div class="section-title mb-2">المكتمل</div><div class="display-6 mb-1"><?= e((string) ($summary['completed_assessments'] ?? 0)) ?></div><div class="section-subtle">المؤجل <?= e((string) ($summary['pending_assessments'] ?? 0)) ?></div></div></div>
<div class="col-md-3"><div class="app-card h-100"><div class="section-title mb-2">آخر تحديث</div><div class="display-6 mb-1" style="font-size:1.05rem;"><?= e((string) (($summary['latest_assessed_on'] ?: '—'))) ?></div><div class="section-subtle">آخر تاريخ رصد</div></div></div>
</div>
<div class="alert alert-light border mb-4">
<strong>طريقة الحساب الحالية:</strong>
مجموع الدرجات المكتملة <?= e(center_report_number((float) ($summary['score_total'] ?? 0))) ?>
من أصل <?= e(center_report_number((float) ($summary['max_score_total'] ?? 0))) ?>
للتقييمات المكتملة فقط.
</div>
<div class="app-card">
<div class="table-responsive">
<table class="table app-table align-middle mb-0">
<thead>
<tr>
<th>التقييم</th>
<th>الحالة</th>
<th>النتيجة</th>
<th>النسبة</th>
<th>البنود</th>
<th>آخر رصد</th>
<th>الإجراء</th>
</tr>
</thead>
<tbody>
<?php foreach ($summary['assessments'] as $assessment): ?>
<?php
$assessmentId = (int) ($assessment['id'] ?? 0);
$scoreText = '—';
if (($assessment['status'] ?? '') === 'completed' && isset($assessment['score']) && $assessment['score'] !== null) {
$scoreText = center_report_number((float) $assessment['score']) . ' / ' . center_report_number((float) ($assessment['saved_max_score'] ?? 0));
} elseif (($assessment['status'] ?? '') === 'missing') {
$scoreText = 'غير مرصود';
}
?>
<tr>
<td>
<div class="fw-semibold"><?= e((string) ($assessment['title'] ?? '')) ?></div>
<div class="text-muted small"><?= e((string) ($assessment['category'] ?? '')) ?> — <?= e(center_report_number((float) ($assessment['weight_percentage'] ?? 0))) ?>٪</div>
</td>
<td>
<?php if (($assessment['status'] ?? '') === 'missing'): ?>
<span class="text-muted">غير مرصود</span>
<?php else: ?>
<?= center_assessment_status_badge((string) ($assessment['status'] ?? 'pending')) ?>
<?php endif; ?>
</td>
<td><?= e($scoreText) ?></td>
<td><?= e(isset($assessment['percentage']) && $assessment['percentage'] !== null ? center_report_number((float) $assessment['percentage']) . '%' : '—') ?></td>
<td><?= e((string) ($assessment['criteria_count'] ?? 0)) ?></td>
<td>
<div><?= e((string) (($assessment['assessed_on'] ?? '') !== '' ? $assessment['assessed_on'] : '—')) ?></div>
<?php if (!empty($assessment['notes'])): ?><div class="text-muted small"><?= e((string) $assessment['notes']) ?></div><?php endif; ?>
</td>
<td>
<div class="d-flex flex-wrap gap-2">
<a class="btn btn-primary btn-sm" href="<?= e($buildCenterAssessmentScoreUrl((int) $application['id'], $selectedCycleId, $assessmentId)) ?>">رصد</a>
<a class="btn btn-outline-secondary btn-sm" href="<?= e($buildCenterAssessmentCriteriaUrl((int) $application['id'], $selectedCycleId, $assessmentId)) ?>">البنود</a>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<?php endif; ?>
<?php endif; ?>
</div>
</div>
</div>
</section>
<?php render_page_end();