Commit e93afcbe authored by Mahmoud Aglan's avatar Mahmoud Aglan

test

parent c0df407f
<?php
declare(strict_types=1);
namespace App\Modules\SportsActivity\Controllers;
use App\Core\Controller;
use App\Core\Request;
use App\Modules\SportsActivity\Services\AcademyPricingService;
class AcademyPricingController extends Controller
{
public function index(Request $request)
{
$this->authorize('sa.pricing.view');
$academies = AcademyPricingService::listAcademies();
$sessionCards = AcademyPricingService::getSessionCardPricing();
return $this->view('SportsActivity.Views.pricing.academies', [
'academies' => $academies,
'sessionCards' => $sessionCards,
]);
}
public function academies(Request $request)
{
$this->authorize('sa.pricing.view');
$academies = AcademyPricingService::listAcademies();
return $this->json(['academies' => $academies]);
}
public function academyDetail(Request $request, string $code)
{
$this->authorize('sa.pricing.view');
$db = \App\Core\App::getInstance()->db();
$rows = $db->select(
"SELECT * FROM sa_academy_pricing
WHERE academy_code = ? AND is_active = 1
AND effective_from <= CURDATE()
AND (effective_to IS NULL OR effective_to >= CURDATE())
ORDER BY category, sort_order",
[$code]
);
if (empty($rows)) {
return $this->json(['error' => 'لا توجد بيانات لهذه الأكاديمية'], 404);
}
$grouped = [];
foreach ($rows as $row) {
$grouped[$row['category']][] = $row;
}
return $this->json([
'academy_code' => $code,
'academy_name_ar' => $rows[0]['academy_name_ar'],
'categories' => $grouped,
]);
}
public function sessionCards(Request $request)
{
$this->authorize('sa.pricing.view');
return $this->json(['cards' => AcademyPricingService::getSessionCardPricing()]);
}
public function laneRentals(Request $request)
{
$this->authorize('sa.pricing.view');
$laneType = $request->get('lane_type');
return $this->json(['rentals' => AcademyPricingService::getLaneRentalPricing($laneType)]);
}
public function facilityRentals(Request $request)
{
$this->authorize('sa.pricing.view');
$facilityType = $request->get('facility_type', '');
$entityType = $request->get('entity_type', '');
$db = \App\Core\App::getInstance()->db();
$sql = "SELECT * FROM sa_rental_entity_pricing WHERE is_active = 1
AND effective_from <= CURDATE()
AND (effective_to IS NULL OR effective_to >= CURDATE())";
$params = [];
if ($facilityType) {
$sql .= " AND facility_type = ?";
$params[] = $facilityType;
}
if ($entityType) {
$sql .= " AND entity_type = ?";
$params[] = $entityType;
}
$sql .= " ORDER BY facility_type, entity_type, time_period";
return $this->json(['rentals' => $db->select($sql, $params)]);
}
public function calculate(Request $request)
{
$this->authorize('sa.pricing.view');
$academyCode = (string) ($request->post('academy_code') ?? '');
$levelNameAr = (string) ($request->post('level_name_ar') ?? '');
$isMember = (bool) ($request->post('is_member') ?? false);
$months = max(1, (int) ($request->post('months') ?? 1));
$hasSibling = (bool) ($request->post('has_sibling') ?? false);
if (!$academyCode || !$levelNameAr) {
return $this->json(['error' => 'يجب تحديد الأكاديمية والمستوى'], 422);
}
$result = AcademyPricingService::getSubscriptionPrice(
$academyCode,
$levelNameAr,
$isMember,
$months,
$hasSibling
);
return $this->json($result);
}
}
...@@ -215,4 +215,13 @@ return [ ...@@ -215,4 +215,13 @@ return [
['POST', '/sa/gate/scan', 'SportsActivity\Controllers\GateController@scan', ['auth', 'csrf'], 'sa.gate.scan'], ['POST', '/sa/gate/scan', 'SportsActivity\Controllers\GateController@scan', ['auth', 'csrf'], 'sa.gate.scan'],
['GET', '/sa/gate/log', 'SportsActivity\Controllers\GateController@log', ['auth'], 'sa.gate.view'], ['GET', '/sa/gate/log', 'SportsActivity\Controllers\GateController@log', ['auth'], 'sa.gate.view'],
['GET', '/sa/gate/report', 'SportsActivity\Controllers\GateController@report', ['auth'], 'sa.gate.view'], ['GET', '/sa/gate/report', 'SportsActivity\Controllers\GateController@report', ['auth'], 'sa.gate.view'],
// ─── Academy Pricing ────────────────────────────────────────────────────────
['GET', '/sa/academy-pricing', 'SportsActivity\Controllers\AcademyPricingController@index', ['auth'], 'sa.pricing.view'],
['GET', '/sa/academy-pricing/academies', 'SportsActivity\Controllers\AcademyPricingController@academies', ['auth'], 'sa.pricing.view'],
['GET', '/sa/academy-pricing/academy/{code}', 'SportsActivity\Controllers\AcademyPricingController@academyDetail', ['auth'], 'sa.pricing.view'],
['GET', '/sa/academy-pricing/session-cards', 'SportsActivity\Controllers\AcademyPricingController@sessionCards', ['auth'], 'sa.pricing.view'],
['GET', '/sa/academy-pricing/lane-rentals', 'SportsActivity\Controllers\AcademyPricingController@laneRentals', ['auth'], 'sa.pricing.view'],
['GET', '/sa/academy-pricing/facility-rentals', 'SportsActivity\Controllers\AcademyPricingController@facilityRentals', ['auth'], 'sa.pricing.view'],
['POST', '/sa/academy-pricing/calculate', 'SportsActivity\Controllers\AcademyPricingController@calculate', ['auth', 'csrf'], 'sa.pricing.view'],
]; ];
<?php
declare(strict_types=1);
namespace App\Modules\SportsActivity\Services;
use App\Core\App;
final class AcademyPricingService
{
/**
* Get academy subscription price for a player.
* Cascading logic: base price → member/nonmember → sibling discount → advance payment discount
*/
public static function getSubscriptionPrice(
string $academyCode,
string $levelNameAr,
bool $isMember,
int $months = 1,
bool $hasSibling = false
): array {
$db = App::getInstance()->db();
$rule = $db->selectOne(
"SELECT * FROM sa_academy_pricing
WHERE academy_code = ? AND level_name_ar = ? AND category = 'subscription'
AND is_active = 1 AND effective_from <= CURDATE()
AND (effective_to IS NULL OR effective_to >= CURDATE())
ORDER BY effective_from DESC LIMIT 1",
[$academyCode, $levelNameAr]
);
if (!$rule) {
return ['found' => false, 'error' => 'لا يوجد تسعير لهذا المستوى'];
}
$basePrice = $isMember ? (float) $rule['price_member'] : (float) $rule['price_nonmember'];
$totalBeforeDiscount = $basePrice * $months;
$discounts = [];
$totalDiscount = 0.0;
// 15% discount for 3-month advance payment
if ($months >= 3) {
$advanceDiscount = self::getDiscountRule('ADVANCE_3MONTHS_15PCT');
if ($advanceDiscount && (int) $advanceDiscount['is_active']) {
$discountAmount = $totalBeforeDiscount * ((float) $advanceDiscount['discount_value'] / 100);
$totalDiscount += $discountAmount;
$discounts[] = [
'code' => 'ADVANCE_3MONTHS_15PCT',
'name_ar' => $advanceDiscount['name_ar'],
'amount' => round($discountAmount, 2),
'percentage' => (float) $advanceDiscount['discount_value'],
];
}
}
// Sibling discount (chess academy)
if ($hasSibling) {
$siblingDiscount = self::getDiscountRule('CHESS_SIBLING_10PCT');
if ($siblingDiscount && (int) $siblingDiscount['is_active']) {
$siblingAcademy = $siblingDiscount['academy_code'];
if (!$siblingAcademy || $siblingAcademy === $academyCode) {
$discountAmount = ($totalBeforeDiscount - $totalDiscount) * ((float) $siblingDiscount['discount_value'] / 100);
$totalDiscount += $discountAmount;
$discounts[] = [
'code' => 'CHESS_SIBLING_10PCT',
'name_ar' => $siblingDiscount['name_ar'],
'amount' => round($discountAmount, 2),
'percentage' => (float) $siblingDiscount['discount_value'],
];
}
}
}
$finalTotal = round($totalBeforeDiscount - $totalDiscount, 2);
return [
'found' => true,
'academy_code' => $academyCode,
'academy_name_ar' => $rule['academy_name_ar'],
'level_name_ar' => $levelNameAr,
'is_member' => $isMember,
'base_price_monthly' => $basePrice,
'months' => $months,
'subtotal' => $totalBeforeDiscount,
'discounts' => $discounts,
'total_discount' => round($totalDiscount, 2),
'final_total' => $finalTotal,
'sessions_per_week' => $rule['sessions_per_week'] ? (int) $rule['sessions_per_week'] : null,
'session_duration_minutes' => $rule['session_duration_minutes'] ? (int) $rule['session_duration_minutes'] : null,
'includes_fitness' => (bool) (int) ($rule['includes_fitness'] ?? 0),
];
}
/**
* Get pricing options for a player based on birth year and discipline.
*/
public static function getOptionsForPlayer(
string $disciplineCode,
?int $birthYear,
bool $isMember
): array {
$db = App::getInstance()->db();
$sql = "SELECT * FROM sa_academy_pricing
WHERE discipline_code = ? AND category IN ('subscription','team')
AND is_active = 1 AND effective_from <= CURDATE()
AND (effective_to IS NULL OR effective_to >= CURDATE())";
$params = [$disciplineCode];
if ($birthYear) {
$sql .= " AND (birth_year = ? OR birth_year IS NULL)";
$params[] = $birthYear;
}
$sql .= " ORDER BY academy_code, sort_order";
$rows = $db->select($sql, $params);
$results = [];
foreach ($rows as $row) {
$results[] = [
'id' => (int) $row['id'],
'academy_code' => $row['academy_code'],
'academy_name_ar' => $row['academy_name_ar'],
'level_name_ar' => $row['level_name_ar'],
'age_group' => $row['age_group'],
'birth_year' => $row['birth_year'] ? (int) $row['birth_year'] : null,
'price' => $isMember ? (float) $row['price_member'] : (float) $row['price_nonmember'],
'sessions_per_week' => $row['sessions_per_week'] ? (int) $row['sessions_per_week'] : null,
'session_duration_minutes' => $row['session_duration_minutes'] ? (int) $row['session_duration_minutes'] : null,
'billing_period' => $row['billing_period'],
];
}
return $results;
}
/**
* Get session card pricing for swimming.
*/
public static function getSessionCardPricing(): array
{
$db = App::getInstance()->db();
$rows = $db->select(
"SELECT * FROM sa_academy_pricing
WHERE category = 'session_card' AND is_active = 1
AND effective_from <= CURDATE()
AND (effective_to IS NULL OR effective_to >= CURDATE())
ORDER BY total_sessions DESC",
[]
);
$results = [];
foreach ($rows as $row) {
$results[] = [
'id' => (int) $row['id'],
'total_sessions' => (int) $row['total_sessions'],
'price' => (float) $row['price_member'],
'price_per_session' => round((float) $row['price_member'] / (int) $row['total_sessions'], 2),
'level_name_ar' => $row['level_name_ar'],
];
}
return $results;
}
/**
* Get lane rental pricing.
*/
public static function getLaneRentalPricing(?string $laneType = null): array
{
$db = App::getInstance()->db();
$sql = "SELECT * FROM sa_academy_pricing
WHERE category = 'lane_rental' AND is_active = 1
AND effective_from <= CURDATE()
AND (effective_to IS NULL OR effective_to >= CURDATE())";
$params = [];
if ($laneType) {
$sql .= " AND lane_type = ?";
$params[] = $laneType;
}
$sql .= " ORDER BY lane_type, sessions_per_month DESC";
$rows = $db->select($sql, $params);
$results = [];
foreach ($rows as $row) {
$results[] = [
'id' => (int) $row['id'],
'lane_type' => $row['lane_type'],
'sessions_per_month' => (int) $row['sessions_per_month'],
'price' => (float) $row['price_member'],
'level_name_ar' => $row['level_name_ar'],
];
}
return $results;
}
/**
* Get private training pricing for a specific academy/coach level.
*/
public static function getPrivateTrainingPrice(
string $academyCode,
int $numPlayers,
?string $coachLevel = null
): array {
$db = App::getInstance()->db();
$sql = "SELECT * FROM sa_academy_pricing
WHERE academy_code = ? AND category = 'private_training'
AND is_active = 1 AND effective_from <= CURDATE()
AND (effective_to IS NULL OR effective_to >= CURDATE())
AND (num_players_max >= ? OR num_players_max IS NULL)";
$params = [$academyCode, $numPlayers];
if ($coachLevel) {
$sql .= " AND coach_level = ?";
$params[] = $coachLevel;
}
$sql .= " ORDER BY num_players_max ASC, sort_order LIMIT 1";
$row = $db->selectOne($sql, $params);
if (!$row) {
return ['found' => false, 'error' => 'لا يوجد تسعير تدريب خاص'];
}
return [
'found' => true,
'academy_code' => $row['academy_code'],
'academy_name_ar' => $row['academy_name_ar'],
'level_name_ar' => $row['level_name_ar'],
'coach_level' => $row['coach_level'],
'num_players' => $numPlayers,
'price_member' => (float) $row['price_member'],
'price_nonmember' => (float) $row['price_nonmember'],
'total_sessions' => $row['total_sessions'] ? (int) $row['total_sessions'] : null,
'billing_period' => $row['billing_period'],
];
}
/**
* Get facility rental price based on entity type, time of day, and usage.
*/
public static function getFacilityRentalPrice(
string $facilityType,
string $entityType,
string $timePeriod,
string $usageType = 'practice'
): ?array {
$db = App::getInstance()->db();
$row = $db->selectOne(
"SELECT * FROM sa_rental_entity_pricing
WHERE facility_type = ? AND entity_type = ? AND time_period = ? AND usage_type = ?
AND is_active = 1 AND effective_from <= CURDATE()
AND (effective_to IS NULL OR effective_to >= CURDATE())
ORDER BY effective_from DESC LIMIT 1",
[$facilityType, $entityType, $timePeriod, $usageType]
);
if (!$row) {
return null;
}
return [
'facility_type' => $row['facility_type'],
'facility_name_ar' => $row['facility_name_ar'],
'entity_type' => $row['entity_type'],
'usage_type' => $row['usage_type'],
'time_period' => $row['time_period'],
'duration_minutes' => (int) $row['duration_minutes'],
'price_amount' => (float) $row['price_amount'],
'max_players' => $row['max_players'] ? (int) $row['max_players'] : null,
'notes_ar' => $row['notes_ar'],
];
}
/**
* Check if a member is in a free period (club members get free facility access during specific hours).
*/
public static function isFreePeriod(string $time, bool $isMember): bool
{
if (!$isMember) {
return false;
}
$db = App::getInstance()->db();
$month = (int) date('m');
$season = ($month >= 11 || $month <= 3) ? 'winter' : 'summer';
$rules = $db->select(
"SELECT condition_value FROM sa_discount_rules
WHERE condition_type = 'free_period' AND is_active = 1",
[]
);
$timeObj = strtotime($time);
foreach ($rules as $rule) {
$cond = json_decode($rule['condition_value'], true);
if (!$cond || ($cond['season'] ?? '') !== $season) {
continue;
}
if (!(bool) ($cond['members_only'] ?? false) || !$isMember) {
continue;
}
$start = strtotime($cond['start'] ?? '00:00');
$end = strtotime($cond['end'] ?? '00:00');
if ($timeObj >= $start && $timeObj < $end) {
return true;
}
}
return false;
}
/**
* Get all active discount rules.
*/
public static function getActiveDiscounts(?string $academyCode = null): array
{
$db = App::getInstance()->db();
$sql = "SELECT * FROM sa_discount_rules WHERE is_active = 1";
$params = [];
if ($academyCode) {
$sql .= " AND (academy_code = ? OR academy_code IS NULL)";
$params[] = $academyCode;
}
return $db->select($sql, $params);
}
/**
* List all academies with their pricing summaries.
*/
public static function listAcademies(): array
{
$db = App::getInstance()->db();
return $db->select(
"SELECT academy_code, academy_name_ar, discipline_code,
COUNT(*) as pricing_count,
MIN(price_member) as min_price_member,
MAX(price_member) as max_price_member
FROM sa_academy_pricing
WHERE is_active = 1 AND category IN ('subscription','team')
AND effective_from <= CURDATE()
AND (effective_to IS NULL OR effective_to >= CURDATE())
GROUP BY academy_code, academy_name_ar, discipline_code
ORDER BY academy_name_ar",
[]
);
}
private static function getDiscountRule(string $ruleCode): ?array
{
$db = App::getInstance()->db();
return $db->selectOne(
"SELECT * FROM sa_discount_rules WHERE rule_code = ? AND is_active = 1",
[$ruleCode]
);
}
}
<?php $__template->layout('Layout.main'); ?>
<?php $__template->section('title'); ?>تسعير الأكاديميات<?php $__template->endSection(); ?>
<?php $__template->section('page_actions'); ?>
<a href="/sa/pricing" class="btn btn-outline"><i data-lucide="calculator" style="width:15px;height:15px;vertical-align:middle;margin-left:4px;"></i> تسعير المرافق</a>
<?php $__template->endSection(); ?>
<?php $__template->section('content'); ?>
<div style="display:grid;grid-template-columns:repeat(auto-fit, minmax(140px, 1fr));gap:12px;margin-bottom:20px;">
<div class="card" style="padding:14px;text-align:center;">
<div style="font-size:11px;color:#6B7280;">أكاديميات</div>
<div style="font-size:22px;font-weight:800;"><?= count($academies) ?></div>
</div>
<div class="card" style="padding:14px;text-align:center;">
<div style="font-size:11px;color:#6B7280;">كروت الحصص</div>
<div style="font-size:22px;font-weight:800;"><?= count($sessionCards) ?></div>
</div>
</div>
<!-- Academies List -->
<div class="card" style="margin-bottom:20px;">
<div style="padding:15px 20px;border-bottom:1px solid #E5E7EB;">
<h3 style="margin:0;font-size:16px;font-weight:600;"><i data-lucide="building-2" style="width:18px;height:18px;vertical-align:middle;margin-left:6px;"></i> قائمة أسعار الأكاديميات — موسم 2025/2026</h3>
</div>
<table style="width:100%;border-collapse:collapse;font-size:13px;">
<thead>
<tr style="background:#F9FAFB;">
<th style="padding:10px 15px;text-align:right;font-weight:600;color:#6B7280;">الأكاديمية</th>
<th style="padding:10px 15px;text-align:right;font-weight:600;color:#6B7280;">التخصص</th>
<th style="padding:10px 15px;text-align:right;font-weight:600;color:#6B7280;">عدد المستويات</th>
<th style="padding:10px 15px;text-align:right;font-weight:600;color:#6B7280;">أقل سعر عضو</th>
<th style="padding:10px 15px;text-align:right;font-weight:600;color:#6B7280;">أعلى سعر عضو</th>
<th style="padding:10px 15px;text-align:right;font-weight:600;color:#6B7280;">تفاصيل</th>
</tr>
</thead>
<tbody>
<?php if (empty($academies)): ?>
<tr><td colspan="6" style="padding:30px;text-align:center;color:#9CA3AF;">لا توجد بيانات — يرجى تشغيل php cli.php seed</td></tr>
<?php else: ?>
<?php foreach ($academies as $a): ?>
<tr style="border-top:1px solid #F3F4F6;">
<td style="padding:10px 15px;font-weight:600;"><?= e($a['academy_name_ar']) ?></td>
<td style="padding:10px 15px;font-size:12px;color:#6B7280;"><?= e($a['discipline_code']) ?></td>
<td style="padding:10px 15px;"><?= (int) $a['pricing_count'] ?></td>
<td style="padding:10px 15px;direction:ltr;text-align:right;"><?= number_format((float) $a['min_price_member'], 0) ?> ج.م</td>
<td style="padding:10px 15px;direction:ltr;text-align:right;"><?= number_format((float) $a['max_price_member'], 0) ?> ج.م</td>
<td style="padding:10px 15px;">
<button type="button" class="btn btn-outline" style="padding:4px 10px;font-size:11px;" onclick="loadAcademy('<?= e($a['academy_code']) ?>')">
<i data-lucide="eye" style="width:12px;height:12px;vertical-align:middle;"></i>
</button>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
<!-- Session Cards -->
<?php if (!empty($sessionCards)): ?>
<div class="card" style="margin-bottom:20px;">
<div style="padding:15px 20px;border-bottom:1px solid #E5E7EB;">
<h3 style="margin:0;font-size:15px;font-weight:600;"><i data-lucide="credit-card" style="width:16px;height:16px;vertical-align:middle;margin-left:6px;"></i> كروت حصص السباحة</h3>
</div>
<table style="width:100%;border-collapse:collapse;font-size:13px;">
<thead>
<tr style="background:#F9FAFB;">
<th style="padding:8px 15px;text-align:right;font-weight:600;color:#6B7280;">الكارت</th>
<th style="padding:8px 15px;text-align:right;font-weight:600;color:#6B7280;">عدد الحصص</th>
<th style="padding:8px 15px;text-align:right;font-weight:600;color:#6B7280;">السعر</th>
<th style="padding:8px 15px;text-align:right;font-weight:600;color:#6B7280;">سعر الحصة</th>
</tr>
</thead>
<tbody>
<?php foreach ($sessionCards as $card): ?>
<tr style="border-top:1px solid #F3F4F6;">
<td style="padding:8px 15px;"><?= e($card['level_name_ar']) ?></td>
<td style="padding:8px 15px;"><?= $card['total_sessions'] ?></td>
<td style="padding:8px 15px;direction:ltr;text-align:right;"><?= number_format($card['price'], 0) ?> ج.م</td>
<td style="padding:8px 15px;direction:ltr;text-align:right;color:#059669;"><?= number_format($card['price_per_session'], 0) ?> ج.م</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
<!-- Academy Detail Modal -->
<div id="academyDetail" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,0.5);z-index:1000;display:none;align-items:center;justify-content:center;">
<div style="background:white;border-radius:12px;padding:25px;max-width:800px;width:90%;max-height:80vh;overflow-y:auto;">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:15px;">
<h3 id="academyDetailTitle" style="margin:0;font-size:18px;font-weight:700;"></h3>
<button type="button" onclick="closeDetail()" style="background:none;border:none;cursor:pointer;font-size:20px;"></button>
</div>
<div id="academyDetailBody"></div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
if (typeof lucide !== 'undefined') lucide.createIcons();
});
function loadAcademy(code) {
fetch('/sa/academy-pricing/academy/' + code, {headers:{'X-Requested-With':'XMLHttpRequest'}})
.then(function(r){return r.json();})
.then(function(data) {
if (data.error) { alert(data.error); return; }
document.getElementById('academyDetailTitle').textContent = data.academy_name_ar;
var html = '';
for (var cat in data.categories) {
var catLabel = {'subscription':'اشتراكات','team':'فرق','private_training':'تدريب خاص','session_card':'كروت حصص','lane_rental':'ايجار حارات'}[cat] || cat;
html += '<h4 style="margin:15px 0 8px;font-size:14px;color:#4B5563;border-bottom:1px solid #E5E7EB;padding-bottom:5px;">' + catLabel + '</h4>';
html += '<table style="width:100%;border-collapse:collapse;font-size:12px;margin-bottom:10px;"><thead><tr style="background:#F9FAFB;"><th style="padding:6px 10px;text-align:right;">المستوى</th><th style="padding:6px 10px;text-align:right;">عضو</th><th style="padding:6px 10px;text-align:right;">غير عضو</th><th style="padding:6px 10px;text-align:right;">تدريبات/اسبوع</th></tr></thead><tbody>';
data.categories[cat].forEach(function(row) {
html += '<tr style="border-top:1px solid #F3F4F6;"><td style="padding:6px 10px;">' + (row.level_name_ar||'—') + '</td><td style="padding:6px 10px;direction:ltr;text-align:right;">' + Number(row.price_member).toLocaleString() + '</td><td style="padding:6px 10px;direction:ltr;text-align:right;">' + Number(row.price_nonmember).toLocaleString() + '</td><td style="padding:6px 10px;">' + (row.sessions_per_week||'—') + '</td></tr>';
});
html += '</tbody></table>';
}
document.getElementById('academyDetailBody').innerHTML = html;
document.getElementById('academyDetail').style.display = 'flex';
});
}
function closeDetail() {
document.getElementById('academyDetail').style.display = 'none';
}
</script>
<?php $__template->endSection(); ?>
...@@ -32,6 +32,7 @@ MenuRegistry::register('sports_activity', [ ...@@ -32,6 +32,7 @@ MenuRegistry::register('sports_activity', [
['label_ar' => 'الجدول', 'label_en' => 'Schedule', 'route' => '/sa/schedule', 'permission' => 'sa.schedule.view', 'order' => 14], ['label_ar' => 'الجدول', 'label_en' => 'Schedule', 'route' => '/sa/schedule', 'permission' => 'sa.schedule.view', 'order' => 14],
['label_ar' => 'الحجوزات', 'label_en' => 'Bookings', 'route' => '/sa/bookings', 'permission' => 'sa.booking.view', 'order' => 15], ['label_ar' => 'الحجوزات', 'label_en' => 'Bookings', 'route' => '/sa/bookings', 'permission' => 'sa.booking.view', 'order' => 15],
['label_ar' => 'التسعير', 'label_en' => 'Pricing', 'route' => '/sa/pricing', 'permission' => 'sa.pricing.view', 'order' => 16], ['label_ar' => 'التسعير', 'label_en' => 'Pricing', 'route' => '/sa/pricing', 'permission' => 'sa.pricing.view', 'order' => 16],
['label_ar' => 'أسعار الأكاديميات', 'label_en' => 'Academy Pricing', 'route' => '/sa/academy-pricing','permission' => 'sa.pricing.view', 'order' => 16.5],
['label_ar' => 'الاشتراكات', 'label_en' => 'Subscriptions', 'route' => '/sa/subscriptions', 'permission' => 'sa.subscription.view', 'order' => 17], ['label_ar' => 'الاشتراكات', 'label_en' => 'Subscriptions', 'route' => '/sa/subscriptions', 'permission' => 'sa.subscription.view', 'order' => 17],
['label_ar' => 'الحضور', 'label_en' => 'Attendance', 'route' => '/sa/attendance', 'permission' => 'sa.attendance.view', 'order' => 18], ['label_ar' => 'الحضور', 'label_en' => 'Attendance', 'route' => '/sa/attendance', 'permission' => 'sa.attendance.view', 'order' => 18],
['label_ar' => 'قائمة الانتظار', 'label_en' => 'Waitlist', 'route' => '/sa/waitlist', 'permission' => 'sa.waitlist.view', 'order' => 19], ['label_ar' => 'قائمة الانتظار', 'label_en' => 'Waitlist', 'route' => '/sa/waitlist', 'permission' => 'sa.waitlist.view', 'order' => 19],
......
<?php
declare(strict_types=1);
return [
'up' => "
CREATE TABLE `sa_academy_pricing` (
`id` BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`academy_code` VARCHAR(50) NOT NULL,
`academy_name_ar` VARCHAR(300) NOT NULL,
`discipline_code` VARCHAR(30) NOT NULL,
`category` VARCHAR(50) NOT NULL COMMENT 'subscription, team, session_card, private_training, lane_rental',
`level_name_ar` VARCHAR(200) NULL COMMENT 'Group name/level/age group',
`level_name_en` VARCHAR(200) NULL,
`age_group` VARCHAR(50) NULL COMMENT 'under_13, adult, under_6, under_7, etc.',
`birth_year` INT NULL COMMENT 'Specific birth year for age-based pricing',
`age_from` INT UNSIGNED NULL,
`age_to` INT UNSIGNED NULL,
`gender` VARCHAR(10) NULL COMMENT 'male, female, NULL=mixed',
`group_size_max` INT UNSIGNED NULL COMMENT 'Max swimmers in group (for swimming)',
`sessions_per_week` INT UNSIGNED NULL,
`sessions_per_month` INT UNSIGNED NULL,
`session_duration_minutes` INT UNSIGNED NULL,
`price_member` DECIMAL(10,2) NOT NULL DEFAULT 0.00,
`price_nonmember` DECIMAL(10,2) NOT NULL DEFAULT 0.00,
`price_subscription` DECIMAL(10,2) NULL COMMENT 'Base subscription price before member/nonmember',
`billing_period` VARCHAR(20) NOT NULL DEFAULT 'monthly' COMMENT 'monthly, quarterly, per_session, per_card, yearly',
`includes_fitness` TINYINT(1) NOT NULL DEFAULT 0,
`num_players_max` INT UNSIGNED NULL COMMENT 'For private training - max players per session',
`coach_level` VARCHAR(50) NULL COMMENT 'For private training - director/coach/fitness',
`lane_type` VARCHAR(30) NULL COMMENT '50m, 25m, mix',
`total_sessions` INT UNSIGNED NULL COMMENT 'For session cards - total sessions in card',
`season` VARCHAR(20) NOT NULL DEFAULT '2025_2026',
`notes_ar` TEXT NULL,
`sort_order` INT UNSIGNED NOT NULL DEFAULT 0,
`is_active` TINYINT(1) NOT NULL DEFAULT 1,
`effective_from` DATE NOT NULL DEFAULT '2025-09-01',
`effective_to` DATE NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX `idx_sap_academy` (`academy_code`),
INDEX `idx_sap_discipline` (`discipline_code`),
INDEX `idx_sap_category` (`category`),
INDEX `idx_sap_age` (`age_from`, `age_to`),
INDEX `idx_sap_active` (`is_active`, `effective_from`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `sa_rental_entity_pricing` (
`id` BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`facility_type` VARCHAR(50) NOT NULL COMMENT 'football_full, football_five, tennis, padel, squash, multi_court, bowling, table_tennis, playstation, billiards, track, combat_hall',
`facility_name_ar` VARCHAR(200) NOT NULL,
`entity_type` VARCHAR(50) NOT NULL COMMENT 'member, non_member, non_member_private_coach, schools_gov, clubs_federations, other_entities, foreign_entities',
`usage_type` VARCHAR(50) NOT NULL DEFAULT 'practice' COMMENT 'practice, match, activity',
`time_period` VARCHAR(20) NOT NULL COMMENT 'morning, evening',
`duration_minutes` INT UNSIGNED NOT NULL DEFAULT 60,
`price_amount` DECIMAL(10,2) NOT NULL,
`max_players` INT UNSIGNED NULL,
`notes_ar` VARCHAR(500) NULL,
`is_active` TINYINT(1) NOT NULL DEFAULT 1,
`effective_from` DATE NOT NULL DEFAULT '2025-09-01',
`effective_to` DATE NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX `idx_srep_facility` (`facility_type`),
INDEX `idx_srep_entity` (`entity_type`),
INDEX `idx_srep_usage` (`usage_type`),
INDEX `idx_srep_active` (`is_active`, `effective_from`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `sa_discount_rules` (
`id` BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`rule_code` VARCHAR(50) NOT NULL UNIQUE,
`name_ar` VARCHAR(200) NOT NULL,
`discount_type` VARCHAR(20) NOT NULL COMMENT 'percentage, fixed',
`discount_value` DECIMAL(10,2) NOT NULL,
`applies_to` VARCHAR(50) NOT NULL COMMENT 'academy, facility, all',
`academy_code` VARCHAR(50) NULL COMMENT 'NULL = all academies',
`condition_type` VARCHAR(50) NOT NULL COMMENT 'advance_payment, sibling, nonmember_surcharge, free_period',
`condition_value` VARCHAR(200) NULL COMMENT 'JSON or simple value for condition params',
`is_active` TINYINT(1) NOT NULL DEFAULT 1,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX `idx_sdr_applies` (`applies_to`, `academy_code`),
INDEX `idx_sdr_condition` (`condition_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
",
'down' => "
DROP TABLE IF EXISTS `sa_discount_rules`;
DROP TABLE IF EXISTS `sa_rental_entity_pricing`;
DROP TABLE IF EXISTS `sa_academy_pricing`;
"
];
<?php
declare(strict_types=1);
use App\Core\Database;
/**
* قائمة اسعار الاكاديميات الرياضية وايجارات الملاعب والصالات والقاعات وحمام السباحة
* موسم 2025/2026
*/
return function (Database $db): void {
$ts = date('Y-m-d H:i:s');
// Check table exists
$tableExists = $db->selectOne(
"SELECT 1 FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'sa_academy_pricing'"
);
if (!$tableExists) {
return;
}
// Clear existing data for fresh import
$db->raw("DELETE FROM sa_academy_pricing WHERE season = '2025_2026'");
$db->raw("DELETE FROM sa_rental_entity_pricing WHERE effective_from = '2025-09-01'");
$db->raw("DELETE FROM sa_discount_rules");
$sort = 0;
// ══════════════════════════════════════════════════════════════════════════
// 1. السباحة — اكاديمية السباحة تحت 13 (من 6 شهور الى 12 سنة)
// ══════════════════════════════════════════════════════════════════════════
$swimUnder13 = [
// [level_name_ar, group_size_max, subscription, member, nonmember_10pct_disc]
['5 سباحين', 5, 960, 480, 870],
['4 سباحين', 4, 1200, 600, 1080],
['3 سباحين', 3, 1440, 720, 1300],
['سباح 2', 2, 1680, 840, 1520],
['سباح 1', 1, 2160, 1080, 1950],
['ذوى همم', null, 3200, 1600, 2880],
];
foreach ($swimUnder13 as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'SWIM-ACADEMY',
'academy_name_ar' => 'أكاديمية السباحة',
'discipline_code' => 'SWIMMING',
'category' => 'subscription',
'level_name_ar' => $row[0],
'age_group' => 'under_13',
'age_from' => 0,
'age_to' => 12,
'group_size_max' => $row[1],
'sessions_per_week' => 2,
'sessions_per_month' => 8,
'session_duration_minutes' => 60,
'price_member' => $row[2],
'price_nonmember' => $row[4],
'price_subscription' => $row[1] ? $row[2] : null,
'billing_period' => 'monthly',
'notes_ar' => '8 وحدات خلال الشهر مرتين اسبوعيا - مدة التمرينة ساعة - من سن 4 سنوات الى 12 سنة',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// رضع 1 (6 شهور - 3 سنوات)
$db->insert('sa_academy_pricing', [
'academy_code' => 'SWIM-ACADEMY',
'academy_name_ar' => 'أكاديمية السباحة',
'discipline_code' => 'SWIMMING',
'category' => 'subscription',
'level_name_ar' => 'رضع 1',
'age_group' => 'infant',
'age_from' => 0,
'age_to' => 3,
'group_size_max' => null,
'sessions_per_week' => 2,
'sessions_per_month' => 8,
'session_duration_minutes' => 75,
'price_member' => 1200,
'price_nonmember' => 2160,
'price_subscription' => 2400,
'billing_period' => 'monthly',
'notes_ar' => '8 وحدات خلال الشهر مرتين اسبوعيا - مدة التمرينة ساعة الا ربع - من سن 6 شهور وحتى 3 سنوات',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
// ══════════════════════════════════════════════════════════════════════════
// اكاديمية السباحة Adult (فوق 13 سنة)
// ══════════════════════════════════════════════════════════════════════════
$swimAdult = [
['5 سباحين', 5, 1200, 600, 1080],
['4 سباحين', 4, 1400, 700, 1260],
['3 سباحين', 3, 1600, 800, 1440],
['سباح 2', 2, 1800, 900, 1620],
['سباح 1', 1, 2000, 1000, 1800],
];
foreach ($swimAdult as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'SWIM-ACADEMY',
'academy_name_ar' => 'أكاديمية السباحة',
'discipline_code' => 'SWIMMING',
'category' => 'subscription',
'level_name_ar' => $row[0],
'age_group' => 'adult',
'age_from' => 13,
'age_to' => 99,
'group_size_max' => $row[1],
'sessions_per_week' => 2,
'sessions_per_month' => 8,
'session_duration_minutes' => 60,
'price_member' => $row[2],
'price_nonmember' => $row[4],
'price_subscription' => $row[2],
'billing_period' => 'monthly',
'notes_ar' => '8 وحدات خلال الشهر مرتين اسبوعيا - مدة التمرينة ساعة - فوق 13 سنة',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// ══════════════════════════════════════════════════════════════════════════
// فرق السباحة (من التجهيزى الى العموم)
// ══════════════════════════════════════════════════════════════════════════
$swimTeams = [
['اسبوعيا 3', 3, 1500, 750, 1350],
['اسبوعيا 4', 4, 1600, 800, 1440],
['اسبوعيا 5', 5, 1700, 850, 1530],
['اسبوعيا 6', 6, 1800, 900, 1620],
];
foreach ($swimTeams as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'SWIM-TEAMS',
'academy_name_ar' => 'فرق السباحة',
'discipline_code' => 'SWIMMING',
'category' => 'team',
'level_name_ar' => $row[0],
'age_group' => 'prep_to_general',
'sessions_per_week' => $row[1],
'session_duration_minutes' => 105,
'price_member' => $row[2],
'price_nonmember' => $row[4],
'price_subscription' => $row[2],
'billing_period' => 'monthly',
'notes_ar' => 'من ساعة ونص الى ساعتين - من التجهيزى الى العموم',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// فرق سباحة الاساتذة (فوق 25 سنة)
$swimMasters = [
['اسبوعيا 2', 2, 1600, 800, 1440],
['اسبوعيا 3', 3, 2100, 1050, 1890],
['اسبوعيا 4', 4, 2500, 1250, 2250],
['اسبوعيا 5', 5, 2900, 1450, 2610],
];
foreach ($swimMasters as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'SWIM-MASTERS',
'academy_name_ar' => 'فرق سباحة الاساتذة',
'discipline_code' => 'SWIMMING',
'category' => 'team',
'level_name_ar' => $row[0],
'age_group' => 'masters',
'age_from' => 25,
'age_to' => 99,
'sessions_per_week' => $row[1],
'session_duration_minutes' => 90,
'price_member' => $row[2],
'price_nonmember' => $row[4],
'price_subscription' => $row[2],
'billing_period' => 'monthly',
'notes_ar' => 'من ساعة الى ساعتين - فوق 25 سنة',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// ══════════════════════════════════════════════════════════════════════════
// ايجار الحارات (Lane Rental)
// ══════════════════════════════════════════════════════════════════════════
$laneRentals = [
// [lane_type, sessions_per_month, price]
['50m', 12, 3550],
['50m', 8, 2200],
['50m', 4, 1200],
['50m', 1, 350],
['25m', 12, 2350],
['25m', 8, 1750],
['25m', 4, 1000],
['25m', 1, 300],
['mix', 24, 5500],
];
foreach ($laneRentals as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'SWIM-LANE-RENTAL',
'academy_name_ar' => 'ايجار حارات السباحة',
'discipline_code' => 'SWIMMING',
'category' => 'lane_rental',
'level_name_ar' => 'حارة ' . $row[0],
'lane_type' => $row[0],
'total_sessions' => $row[1],
'sessions_per_month' => $row[1],
'price_member' => $row[2],
'price_nonmember' => $row[2],
'billing_period' => 'monthly',
'notes_ar' => 'ايجار حارة ' . $row[0],
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// الحصص والكروت (Session Cards)
$sessionCards = [
// [total_sessions, price]
[24, 1250],
[12, 680],
[8, 500],
[6, 450],
[4, 380],
[1, 120],
];
foreach ($sessionCards as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'SWIM-SESSION-CARD',
'academy_name_ar' => 'كروت حصص السباحة',
'discipline_code' => 'SWIMMING',
'category' => 'session_card',
'level_name_ar' => 'كارت ' . $row[0] . ' حصة',
'total_sessions' => $row[0],
'price_member' => $row[1],
'price_nonmember' => $row[1],
'billing_period' => 'per_card',
'notes_ar' => 'كارت حصص سباحة - حصة واحدة',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// ══════════════════════════════════════════════════════════════════════════
// 2. الجمباز (سبورت هوم اكاديمى) - فنى 2026/2025
// ══════════════════════════════════════════════════════════════════════════
$gymnastics = [
// [birth_year, age_group_label, sessions_per_week, duration_min, member, nonmember]
[2018, 'تحت 6 سنوات', 3, 60, 1075, 2150],
[2017, 'تحت 7 سنوات', 3, 60, 1175, 2350],
[2016, 'تحت 8 سنوات', 4, 150, 1275, 2550],
[2015, 'تحت 9 سنوات', 4, 150, 1375, 2750],
[2014, 'تحت 10 سنوات', 4, 180, 1475, 2950],
[2013, 'تحت 11 سنوات', 4, 180, 1575, 3150],
[2012, 'تحت 12 سنوات', 4, 180, 1675, 3350],
[2011, 'تحت 13 سنوات', 4, 180, 1775, 3550],
[null, 'درجة تانية', 5, 180, 2500, 5000],
[null, 'درجة اولى', 5, 180, 2500, 5000],
];
foreach ($gymnastics as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'GYM-SPORTHOME',
'academy_name_ar' => 'الجمباز (سبورت هوم اكاديمى)',
'discipline_code' => 'GYMNASTICS',
'category' => 'subscription',
'level_name_ar' => $row[1],
'birth_year' => $row[0],
'sessions_per_week' => $row[2],
'session_duration_minutes' => $row[3],
'price_member' => $row[4],
'price_nonmember' => $row[5],
'billing_period' => 'monthly',
'notes_ar' => 'فنى الانسات - موسم 2025/2026',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// جمباز - المدارس والممارسة
$gymSchools = [
[2020, 'اولاد', 'مدارس', 'male', 775, 1550],
[2021, 'بنات', 'مدارس', 'female', 775, 1550],
[null, 'بنات / اولاد', 'ممارسة', null, 1225, 2450],
];
foreach ($gymSchools as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'GYM-SPORTHOME',
'academy_name_ar' => 'الجمباز (سبورت هوم اكاديمى)',
'discipline_code' => 'GYMNASTICS',
'category' => 'subscription',
'level_name_ar' => $row[2] . ' - ' . $row[1],
'birth_year' => $row[0],
'gender' => $row[3],
'price_member' => $row[4],
'price_nonmember' => $row[5],
'billing_period' => 'monthly',
'notes_ar' => 'المدارس والممارسة 2025/2026',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// جمباز - تدريب خاص
$gymPrivate = [
[2, 400, 600],
[4, 650, 1000],
[8, 1050, 1700],
[12, 1250, 2200],
[16, 1650, 2500],
[20, 1850, 2600],
];
foreach ($gymPrivate as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'GYM-SPORTHOME',
'academy_name_ar' => 'الجمباز (سبورت هوم اكاديمى)',
'discipline_code' => 'GYMNASTICS',
'category' => 'private_training',
'level_name_ar' => $row[0] . ' وحدات',
'total_sessions' => $row[0],
'price_member' => $row[1],
'price_nonmember' => $row[2],
'billing_period' => 'per_card',
'notes_ar' => 'التدريب الخاص للفنى 2025/2026',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// ══════════════════════════════════════════════════════════════════════════
// 3. الايروبيك 2025/2026
// ══════════════════════════════════════════════════════════════════════════
$aerobics = [
[2021, 'تجهيزى', 3, 90, 825, 1650],
[2018, 'تحت 7', 3, 60, 875, 1750],
[2016, 'تحت 8 سنوات', 3, 120, 975, 1950],
[2015, 'تحت 9 سنوات', 3, 120, 1175, 2350],
[2014, 'تحت 10 سنوات', 3, 120, 1275, 2550],
[2013, 'تحت 11 سنوات', 3, 120, 1375, 2750],
[2012, 'تحت 12 سنوات', 3, 120, 1475, 2950],
[2011, 'تحت 13 سنوات', 3, 120, 1575, 3150],
[2010, 'تحت 14 سنوات', 3, 120, 1675, 3350],
[null, 'درجة تانية', 3, 120, 2000, 4000],
[null, 'درجة اولى', 3, 120, 2000, 4000],
];
foreach ($aerobics as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'AEROBICS',
'academy_name_ar' => 'الايروبيك',
'discipline_code' => 'GYMNASTICS',
'category' => 'subscription',
'level_name_ar' => $row[1],
'birth_year' => $row[0],
'sessions_per_week' => $row[2],
'session_duration_minutes' => $row[3],
'price_member' => $row[4],
'price_nonmember' => $row[5],
'billing_period' => 'monthly',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// ايروبيك - تدريب خاص
$aerobicsPrivate = [
[2, 250, 400],
[4, 500, 700],
[6, 660, 900],
[8, 800, 1000],
[12, 1080, 1320],
[16, 1280, 1600],
[20, 1800, 2000],
];
foreach ($aerobicsPrivate as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'AEROBICS',
'academy_name_ar' => 'الايروبيك',
'discipline_code' => 'GYMNASTICS',
'category' => 'private_training',
'level_name_ar' => $row[0] . ' وحدات',
'total_sessions' => $row[0],
'price_member' => $row[1],
'price_nonmember' => $row[2],
'billing_period' => 'per_card',
'notes_ar' => 'التدريب الخاص للايروبيك 2025/2026',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// ايروبيك - تدريب خاص للفرق الرياضية للاندية
$aerobicsClubs = [
[2, 20, 5000],
[2, 30, 7500],
[4, 20, 12000],
[4, 30, 15000],
];
foreach ($aerobicsClubs as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'AEROBICS',
'academy_name_ar' => 'الايروبيك',
'discipline_code' => 'GYMNASTICS',
'category' => 'private_training',
'level_name_ar' => $row[0] . ' وحدات - حد اقصى ' . $row[1] . ' لاعب',
'total_sessions' => $row[0],
'num_players_max' => $row[1],
'price_member' => $row[2],
'price_nonmember' => $row[2],
'billing_period' => 'per_card',
'notes_ar' => 'التدريب الخاص للفرق الرياضية للاندية 2025/2026',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// ══════════════════════════════════════════════════════════════════════════
// 4. الجمباز فنى الرجال 2025/2026
// ══════════════════════════════════════════════════════════════════════════
$gymMen = [
[2019, 'تحت 7 سنوات', 3, 120, 1075, 2150],
[2018, 'تحت 8 سنوات', 4, 150, 1175, 2350],
[2017, 'تحت 9 سنوات', 4, 150, 1275, 2550],
[2016, 'تحت 10 سنوات', 4, 180, 1375, 2750],
[2015, 'تحت 11 سنوات', 4, 180, 1475, 2950],
[2014, 'تحت 12 سنوات', 4, 180, 1575, 3150],
[2013, 'تحت 13 سنوات', 4, 180, 1675, 3350],
[2012, 'تحت 14 سنوات', 5, 180, 1775, 3550],
[2011, 'تحت 15 سنوات', 5, 180, 1875, 3750],
];
foreach ($gymMen as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'GYM-MEN',
'academy_name_ar' => 'الجمباز فنى الرجال',
'discipline_code' => 'GYMNASTICS',
'category' => 'subscription',
'level_name_ar' => $row[1],
'birth_year' => $row[0],
'gender' => 'male',
'sessions_per_week' => $row[2],
'session_duration_minutes' => $row[3],
'price_member' => $row[4],
'price_nonmember' => $row[5],
'billing_period' => 'monthly',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// ══════════════════════════════════════════════════════════════════════════
// 5. الرسم
// ══════════════════════════════════════════════════════════════════════════
$db->insert('sa_academy_pricing', [
'academy_code' => 'DRAWING',
'academy_name_ar' => 'الرسم',
'discipline_code' => 'DRAWING',
'category' => 'subscription',
'level_name_ar' => 'حصة واحدة اسبوعيا',
'sessions_per_week' => 1,
'session_duration_minutes' => 90,
'price_member' => 200,
'price_nonmember' => 400,
'billing_period' => 'monthly',
'notes_ar' => 'السبت والثلاثاء المدة 1 ساعة ونص حصة واحدة فالاسبوع',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
// ══════════════════════════════════════════════════════════════════════════
// 6. كرة القدم (اندر لخت)
// ══════════════════════════════════════════════════════════════════════════
$db->insert('sa_academy_pricing', [
'academy_code' => 'FOOTBALL-ANDERLECHT',
'academy_name_ar' => 'كرة القدم (اندر لخت)',
'discipline_code' => 'FOOTBALL',
'category' => 'subscription',
'level_name_ar' => '3 تدريبات اسبوعيا',
'sessions_per_week' => 3,
'session_duration_minutes' => 60,
'price_member' => 400,
'price_nonmember' => 800,
'billing_period' => 'monthly',
'notes_ar' => 'الاحد والثلاثاء والخميس من الساعة 6 مساءا',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
// كرة القدم (الموهبة)
$db->insert('sa_academy_pricing', [
'academy_code' => 'FOOTBALL-TALENT',
'academy_name_ar' => 'كرة القدم (الموهبة)',
'discipline_code' => 'FOOTBALL',
'category' => 'subscription',
'level_name_ar' => '3 تدريبات اسبوعيا',
'sessions_per_week' => 3,
'session_duration_minutes' => 60,
'price_member' => 400,
'price_nonmember' => 800,
'billing_period' => 'monthly',
'notes_ar' => 'السبت والاثنين والاربعاء من الساعة 6 مساءا',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
// كرة القدم (الرواد)
$footballRuwad = [
['شهر - 8 تدريبات', 8, 700, 1200, 'monthly'],
['نص شهر - 4 تدريبات', 4, 350, 600, 'monthly'],
['سيشن حصة واحدة', 1, 125, 200, 'per_session'],
];
foreach ($footballRuwad as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'FOOTBALL-RUWAD',
'academy_name_ar' => 'كرة القدم (الرواد)',
'discipline_code' => 'FOOTBALL',
'category' => 'subscription',
'level_name_ar' => $row[0],
'sessions_per_month' => $row[1],
'price_member' => $row[2],
'price_nonmember' => $row[3],
'billing_period' => $row[4],
'notes_ar' => 'السبت والاثنين من الساعة 9 مساءا الى 11 مساءا',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// ══════════════════════════════════════════════════════════════════════════
// 7. التنس الارضى (بريميم اكاديمى)
// ══════════════════════════════════════════════════════════════════════════
$tennis = [
['Red 1 / مدارس', 'تحت 8', 2, 60, 700, 1100, 0],
['Red 2 / تجهيزى', 'تحت 8', 3, 120, 900, 1500, 1],
['Team 8', 'تحت 8', 4, 120, 1200, 1800, 1],
['Orange 1 / مدارس', 'تحت 9', 2, 120, 800, 1200, 1],
['Orange 2 / تجهيزى', 'تحت 9', 3, 120, 1000, 1600, 1],
['Team 9', 'تحت 9', 4, 120, 1300, 2000, 1],
['Green 1 / مدارس', 'تحت 10', 2, 120, 800, 1200, 1],
['Green 2 / تجهيزى', 'تحت 10', 3, 120, 1000, 1600, 1],
['Team 10', 'تحت 10', 4, 120, 1300, 2000, 1],
['Premium 1 / مدارس', 'فوق 10', 2, 120, 800, 1200, 1],
['Premium 2 / تجهيزى', 'فوق 10', 3, 120, 1000, 1600, 1],
['Team 11:16', 'فوق 10', 4, 120, 1400, 2000, 1],
['Adults Premium', null, 2, 105, 900, 1600, 1],
];
foreach ($tennis as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'TENNIS-PREMIUM',
'academy_name_ar' => 'التنس الارضى (بريميم اكاديمى)',
'discipline_code' => 'TENNIS',
'category' => 'subscription',
'level_name_ar' => $row[0],
'age_group' => $row[1],
'sessions_per_week' => $row[2],
'session_duration_minutes' => $row[3],
'price_member' => $row[4],
'price_nonmember' => $row[5],
'includes_fitness' => $row[6],
'billing_period' => 'monthly',
'notes_ar' => 'الاحد / الثلاثاء / الاربعاء / الخميس',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// تنس - تدريب خاص
$tennisPrivate = [
['المدير الفنى', 8, 1, 2200, null, null],
['المدير الفنى', 8, 2, null, 1600, null],
['مدرب التنس', 8, 1, 1800, null, null],
['مدرب التنس', 8, 2, null, 1400, null],
['مدرب الفتنس', 8, 1, 1800, null, null],
['مدرب الفتنس', 8, 2, null, 1400, null],
['مدرب الفتنس', 8, 3, null, null, 1000],
];
foreach ($tennisPrivate as $row) {
$price = $row[3] ?? $row[4] ?? $row[5] ?? 0;
$db->insert('sa_academy_pricing', [
'academy_code' => 'TENNIS-PREMIUM',
'academy_name_ar' => 'التنس الارضى (بريميم اكاديمى)',
'discipline_code' => 'TENNIS',
'category' => 'private_training',
'level_name_ar' => $row[0] . ' - ' . $row[2] . ' لاعب',
'coach_level' => $row[0],
'sessions_per_month' => $row[1],
'num_players_max' => $row[2],
'price_member' => $price,
'price_nonmember' => $price,
'billing_period' => 'monthly',
'notes_ar' => 'التدريب الخاص للتنس',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// ══════════════════════════════════════════════════════════════════════════
// 8. الاسكواش (شادو اكاديمى)
// ══════════════════════════════════════════════════════════════════════════
$squash = [
['المستوى 1', 2, 2, 700, 1000],
['المستوى 2', 3, 2, 1100, 1400],
['المستوى 3', 3, 1, 2200, 2800],
['لياقة بدنية', 2, null, 300, 500],
];
foreach ($squash as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'SQUASH-SHADOW',
'academy_name_ar' => 'الاسكواش (شادو اكاديمى)',
'discipline_code' => 'SQUASH',
'category' => 'subscription',
'level_name_ar' => $row[0],
'sessions_per_week' => $row[1],
'num_players_max' => $row[2],
'price_member' => $row[3],
'price_nonmember' => $row[4],
'billing_period' => 'monthly',
'notes_ar' => 'السبت / الاثنين / الاربعاء / الخميس / الجمعة',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// ══════════════════════════════════════════════════════════════════════════
// 9. كرة السلة (اس زد اكاديمى)
// ══════════════════════════════════════════════════════════════════════════
$basketball = [
['شهر - 2 تدريبات اسبوعيا', 2, 'monthly', 500, 1100],
['3 اشهر - 2 تدريبات اسبوعيا', 2, 'quarterly', 1100, 2700],
['اشتراك سنوى فرق', null, 'yearly', 4800, 1080],
];
foreach ($basketball as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'BASKETBALL-SZ',
'academy_name_ar' => 'كرة السلة (اس زد اكاديمى)',
'discipline_code' => 'BASKETBALL',
'category' => 'subscription',
'level_name_ar' => $row[0],
'sessions_per_week' => $row[1],
'price_member' => $row[3],
'price_nonmember' => $row[4],
'billing_period' => $row[2],
'notes_ar' => 'الاثنين / الاربعاء',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// كرة السلة - تدريب خاص
$basketballPrivate = [
[8, 1, 4000],
[4, 1, 2000],
];
foreach ($basketballPrivate as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'BASKETBALL-SZ',
'academy_name_ar' => 'كرة السلة (اس زد اكاديمى)',
'discipline_code' => 'BASKETBALL',
'category' => 'private_training',
'level_name_ar' => $row[0] . ' تدريبات - لاعب واحد',
'sessions_per_month' => $row[0],
'num_players_max' => $row[1],
'price_member' => $row[2],
'price_nonmember' => $row[2],
'billing_period' => 'per_card',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// ══════════════════════════════════════════════════════════════════════════
// 10. البادل تنس (تروفى بادل)
// ══════════════════════════════════════════════════════════════════════════
$padel = [
[3, 8, 1000, 1500],
[2, 8, 1000, 1800],
[1, 8, 1100, 2200],
];
foreach ($padel as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'PADEL-TROPHY',
'academy_name_ar' => 'البادل تنس (تروفى بادل)',
'discipline_code' => 'PADEL',
'category' => 'private_training',
'level_name_ar' => $row[0] . ' لاعبين - 8 تدريبات',
'sessions_per_month' => $row[1],
'num_players_max' => $row[0],
'price_member' => $row[2],
'price_nonmember' => $row[3],
'billing_period' => 'monthly',
'notes_ar' => 'بالاتفاق مع الاكاديمية',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// ══════════════════════════════════════════════════════════════════════════
// 11. اكاديمية الالات الموسيقية (ايهاب محمد عبد المنعم)
// ══════════════════════════════════════════════════════════════════════════
$music = [
['بيانو', 4, 600, 1200, 4],
['اورج', 4, 600, 1200, 4],
['جيتار', 4, 600, 1200, 4],
['طبلة', 4, 600, 1200, 4],
['غناء فردى', 4, 600, 1200, 4],
['غناء جماعى', 4, 400, 800, 10],
['غناء بلغة الاشارة', 4, 600, 1200, 5],
['دورة خاصة', null, 600, 600, 1],
];
foreach ($music as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'MUSIC-EHAB',
'academy_name_ar' => 'اكاديمية الالات الموسيقية',
'discipline_code' => 'MUSIC',
'category' => 'subscription',
'level_name_ar' => $row[0],
'sessions_per_month' => $row[1],
'num_players_max' => $row[4],
'price_member' => $row[2],
'price_nonmember' => $row[3],
'billing_period' => 'monthly',
'notes_ar' => '4 ساعات - لا يقل عن ' . $row[4] . ' متدربين',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// ══════════════════════════════════════════════════════════════════════════
// 12. الكرة الطائرة (انجيلز اكاديمى)
// ══════════════════════════════════════════════════════════════════════════
$volleyball = [
['عادى / مبتدىء', 2, 90, 375, 750],
['تجهيزى / تطوير مهارات', 3, 90, 425, 850],
['فرق', 3, 120, 475, 950],
];
foreach ($volleyball as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'VOLLEYBALL-ANGELS',
'academy_name_ar' => 'الكرة الطائرة (انجيلز اكاديمى)',
'discipline_code' => 'VOLLEYBALL',
'category' => 'subscription',
'level_name_ar' => $row[0],
'sessions_per_week' => $row[1],
'session_duration_minutes' => $row[2],
'price_member' => $row[3],
'price_nonmember' => $row[4],
'billing_period' => 'monthly',
'notes_ar' => 'الاحد / الثلاثاء / الخميس',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// ══════════════════════════════════════════════════════════════════════════
// 13. كرة اليد (اكسترا هاند بول)
// ══════════════════════════════════════════════════════════════════════════
$handball = [
['عادى / اكاديمى', 3, null, 350, 700],
['تجهيزى', 3, null, 700, 800],
['الفرق', null, null, 700, 800],
['فيتنس حتى 8 لاعبين', null, 8, 900, 1000],
['فيتنس حتى 15 لاعبين', null, 15, 700, 800],
['برايفيت حتى 4 لاعبين', null, 4, 200, 200],
['برايفيت حتى 8 لاعبين', null, 8, 150, 150],
];
foreach ($handball as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'HANDBALL-EXTRA',
'academy_name_ar' => 'كرة اليد (اكسترا هاند بول)',
'discipline_code' => 'HANDBALL',
'category' => $row[2] ? ($row[2] <= 8 ? 'private_training' : 'subscription') : 'subscription',
'level_name_ar' => $row[0],
'sessions_per_week' => $row[1],
'num_players_max' => $row[2],
'price_member' => $row[3],
'price_nonmember' => $row[4],
'billing_period' => ($row[0] === 'برايفيت حتى 4 لاعبين' || $row[0] === 'برايفيت حتى 8 لاعبين') ? 'per_session' : 'monthly',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// ══════════════════════════════════════════════════════════════════════════
// 14. الالعاب القتالية (شمبيون اكاديمى)
// ══════════════════════════════════════════════════════════════════════════
// الكاراتيه
$karate = [
['مميز', 2, 300, 600],
['قطاع بطولات', 2, 400, 800],
['عادى / خارجى', null, 200, 400],
];
foreach ($karate as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'COMBAT-CHAMPION',
'academy_name_ar' => 'الالعاب القتالية (شمبيون اكاديمى)',
'discipline_code' => 'KARATE',
'category' => 'subscription',
'level_name_ar' => 'كاراتيه - ' . $row[0],
'sessions_per_week' => $row[1],
'price_member' => $row[2],
'price_nonmember' => $row[3],
'billing_period' => 'monthly',
'notes_ar' => 'السبت / الخميس من الساعة 3 ونص',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// كاراتيه - وحدات تدريبية
$karateUnits = [
[1, 1, 60, 50],
[1, 7, 90, 300],
[8, 1, 60, 1500],
[8, 1, 60, 1000],
];
foreach ($karateUnits as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'COMBAT-CHAMPION',
'academy_name_ar' => 'الالعاب القتالية (شمبيون اكاديمى)',
'discipline_code' => 'KARATE',
'category' => 'private_training',
'level_name_ar' => 'كاراتيه - ' . $row[0] . ' وحدات - ' . $row[1] . ' لاعبين',
'total_sessions' => $row[0],
'num_players_max' => $row[1],
'session_duration_minutes' => $row[2],
'price_member' => $row[3],
'price_nonmember' => $row[3],
'billing_period' => 'per_card',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// الكيك بوكس
$kickbox = [
['عادى', 2, 250, 500],
['قطاع بطولات', 2, 400, 800],
];
foreach ($kickbox as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'COMBAT-CHAMPION',
'academy_name_ar' => 'الالعاب القتالية (شمبيون اكاديمى)',
'discipline_code' => 'KICKBOXING',
'category' => 'subscription',
'level_name_ar' => 'كيك بوكس - ' . $row[0],
'sessions_per_week' => $row[1],
'price_member' => $row[2],
'price_nonmember' => $row[3],
'billing_period' => 'monthly',
'notes_ar' => 'السبت / الخميس من 5 الى 7',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// ══════════════════════════════════════════════════════════════════════════
// 15. اكاديمية الشطرنج (عدلى اكاديمى)
// ══════════════════════════════════════════════════════════════════════════
$chess = [
['الاول', 500, 1000],
['الثانى', 700, 1100],
['الثالث', 850, 1250],
['الرابع', 1000, 1400],
['الخامس', 1100, 1500],
['السادس', 1200, 1600],
['السابع', 1400, 1800],
['الثامن', 1400, 2000],
['التاسع', 1800, 2200],
['العاشر', 2000, 2400],
];
foreach ($chess as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'CHESS-ADLY',
'academy_name_ar' => 'اكاديمية الشطرنج (عدلى اكاديمى)',
'discipline_code' => 'CHESS',
'category' => 'subscription',
'level_name_ar' => 'المستوى ' . $row[0],
'sessions_per_month' => 8,
'session_duration_minutes' => 60,
'price_member' => $row[1],
'price_nonmember' => $row[2],
'billing_period' => 'monthly',
'notes_ar' => '8 محاضرات (ساعة 12) + الاختبار الشهرى - خصم 10% للاخوات اعضاء وغير اعضاء',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// شطرنج - تدريب خاص
$chessPrivate = [
['مدرب الى 1', 1, 450],
['مدرب الى 2', 2, 550],
['مدرب الى 3', 3, 650],
];
foreach ($chessPrivate as $row) {
$db->insert('sa_academy_pricing', [
'academy_code' => 'CHESS-ADLY',
'academy_name_ar' => 'اكاديمية الشطرنج (عدلى اكاديمى)',
'discipline_code' => 'CHESS',
'category' => 'private_training',
'level_name_ar' => $row[0],
'num_players_max' => $row[1],
'price_member' => $row[2],
'price_nonmember' => $row[2],
'billing_period' => 'per_session',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// ══════════════════════════════════════════════════════════════════════════
// 16. الباتيناج
// ══════════════════════════════════════════════════════════════════════════
$patinage = [
['مدرسة الباتيناج', 350, 650],
['تجهيزى الباتيناج', 600, 750],
['فريق السرعة', 1000, 1200],
['فريق (الفوتيل اسكيت)', 1000, 1200],
['حصة الباتيناج', 100, 150],
['برايفيت الباتيناج (1 لاعب)', 2000, 2000],
['برايفيت الباتيناج (2 لاعب)', 1800, 1800],
['برايفيت الباتيناج (3 لاعب)', 1600, 1600],
];
foreach ($patinage as $row) {
$isPrivate = str_contains($row[0], 'برايفيت') || $row[0] === 'حصة الباتيناج';
$db->insert('sa_academy_pricing', [
'academy_code' => 'PATINAGE',
'academy_name_ar' => 'الباتيناج',
'discipline_code' => 'SKATING',
'category' => $isPrivate ? 'private_training' : 'subscription',
'level_name_ar' => $row[0],
'session_duration_minutes' => 90,
'price_member' => $row[1],
'price_nonmember' => $row[2],
'billing_period' => ($row[0] === 'حصة الباتيناج') ? 'per_session' : 'monthly',
'notes_ar' => 'مدة الوحدة التدريبية على كافة المستويات ساعة ونصف',
'season' => '2025_2026',
'sort_order' => ++$sort,
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// ══════════════════════════════════════════════════════════════════════════
// RENTAL ENTITY PRICING — ايجار الملاعب والصالات
// ══════════════════════════════════════════════════════════════════════════
// رسوم ايجار الملاعب لاعضاء النادى
$memberRentals = [
['football_full', 'كرة القدم القانونى', 60, 300, 500],
['football_five', 'كرة القدم الخماسى', 60, 150, 200],
['tennis', 'التنس الارضى', 60, 75, 100],
['padel_no_tools', 'البادل تنس (بدون ادوات)', 60, 100, 150],
['padel_with_tools', 'البادل تنس (شامل ادوات)', 60, 150, 200],
['squash', 'الاسكواش', 60, 75, 75],
['billiards', 'البلياردو', 30, 30, 30],
['billiards_hour', 'البلياردو ساعة', 60, 60, 60],
['bowling', 'البولينج', 0, 30, 30],
['multi_court', 'الملعب المتعدد', 60, 50, 100],
['table_tennis', 'التنس الطاولة', 60, 50, 50],
['playstation_30', 'البلاشتيشن نص ساعة', 30, 30, 30],
['playstation_60', 'البلاشتيشن ساعة', 60, 60, 60],
];
foreach ($memberRentals as $row) {
$db->insert('sa_rental_entity_pricing', [
'facility_type' => $row[0],
'facility_name_ar' => $row[1],
'entity_type' => 'member',
'usage_type' => 'practice',
'time_period' => 'morning',
'duration_minutes' => $row[2],
'price_amount' => $row[3],
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
$db->insert('sa_rental_entity_pricing', [
'facility_type' => $row[0],
'facility_name_ar' => $row[1],
'entity_type' => 'member',
'usage_type' => 'practice',
'time_period' => 'evening',
'duration_minutes' => $row[2],
'price_amount' => $row[4],
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// رسوم ايجار لغير الاعضاء (ممارسة)
$nonMemberRentals = [
['tennis', 'التنس الارضى', 60, 100, 150, 2],
['padel', 'البادل تنس', 60, 200, 300, 4],
['squash', 'الاسكواش', 60, 150, 150, 2],
['billiards', 'البلياردو', 60, 100, 100, null],
['bowling', 'البولينج', 0, 60, 60, null],
['table_tennis', 'التنس الطاولة', 60, 60, 60, 2],
['playstation', 'البلاشتيشن', 60, 60, 60, null],
];
foreach ($nonMemberRentals as $row) {
$db->insert('sa_rental_entity_pricing', [
'facility_type' => $row[0],
'facility_name_ar' => $row[1],
'entity_type' => 'non_member',
'usage_type' => 'practice',
'time_period' => 'morning',
'duration_minutes' => $row[2],
'price_amount' => $row[3],
'max_players' => $row[5],
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
$db->insert('sa_rental_entity_pricing', [
'facility_type' => $row[0],
'facility_name_ar' => $row[1],
'entity_type' => 'non_member',
'usage_type' => 'practice',
'time_period' => 'evening',
'duration_minutes' => $row[2],
'price_amount' => $row[4],
'max_players' => $row[5],
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// تدريب خاص - مدرب من خارج النادى (غير اعضاء)
$privateCoachRentals = [
['football_full', 'كرة القدم القانونى', 60, 650, 1000, 16],
['football_five', 'كرة القدم الخماسى', 60, 350, 600, 16],
['tennis', 'التنس الارضى', 60, 75, 100, 2],
['padel', 'البادل تنس', 60, 300, 400, 4],
['squash', 'الاسكواش', 60, 100, 120, 2],
['track_run', 'تراك الجرى', 60, 200, 300, 10],
['track_cycle', 'تراك الدراجات والتزحلق', 60, 100, 200, 5],
['bowling', 'البولينج', 30, 60, 120, 5],
['multi_court', 'الملعب المتعدد', 60, 200, 400, 15],
['table_tennis', 'التنس الطاولة', 60, 60, 60, 2],
['combat_hall', 'صالة المنازلات', 60, 300, 300, 10],
];
foreach ($privateCoachRentals as $row) {
$db->insert('sa_rental_entity_pricing', [
'facility_type' => $row[0],
'facility_name_ar' => $row[1],
'entity_type' => 'non_member_private_coach',
'usage_type' => 'training',
'time_period' => 'morning',
'duration_minutes' => $row[2],
'price_amount' => $row[3],
'max_players' => $row[5],
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
$db->insert('sa_rental_entity_pricing', [
'facility_type' => $row[0],
'facility_name_ar' => $row[1],
'entity_type' => 'non_member_private_coach',
'usage_type' => 'training',
'time_period' => 'evening',
'duration_minutes' => $row[2],
'price_amount' => $row[4],
'max_players' => $row[5],
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// ايجار للمدارس والجامعات والهيئات الحكومية
$schoolsGov = [
// [facility, name, practice_morning, practice_evening, training_morning, training_evening]
['football_full', 'كرة القدم القانونى', 600, 800, 700, 900],
['football_five', 'كرة القدم الخماسى', 200, 300, 300, 400],
['tennis', 'التنس الارضى', 75, 100, 100, 125],
['padel', 'البادل تنس', 200, 250, 250, 300],
['squash', 'الاسكواش', 100, 100, 100, 150],
['multi_court', 'الملعب متعدد', 150, 200, 250, 300],
['bowling', 'البولينج', 60, 60, 60, 60],
['table_tennis', 'التنس الطاولة', 100, 100, 100, 100],
['playstation', 'البلاشتيشن', 100, 100, 100, 100],
];
foreach ($schoolsGov as $row) {
foreach (['practice', 'training'] as $usage) {
$mIdx = $usage === 'practice' ? 2 : 4;
$eIdx = $usage === 'practice' ? 3 : 5;
$db->insert('sa_rental_entity_pricing', [
'facility_type' => $row[0],
'facility_name_ar' => $row[1],
'entity_type' => 'schools_gov',
'usage_type' => $usage,
'time_period' => 'morning',
'duration_minutes' => 60,
'price_amount' => $row[$mIdx],
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
$db->insert('sa_rental_entity_pricing', [
'facility_type' => $row[0],
'facility_name_ar' => $row[1],
'entity_type' => 'schools_gov',
'usage_type' => $usage,
'time_period' => 'evening',
'duration_minutes' => 60,
'price_amount' => $row[$eIdx],
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
}
// الاندية والمنتخبات والاتحادات الرياضية المحلية
$clubs = [
// [facility, name, training_morning, training_evening, match_morning, match_evening]
['football_full', 'كرة القدم القانونى', 700, 900, 850, 1100],
['football_five', 'كرة القدم الخماسى', 300, 400, 400, 500],
['tennis', 'التنس الارضى', 100, 125, 125, 150],
['padel', 'البادل تنس', 200, 250, 250, 300],
['squash', 'الاسكواش', 125, 125, 150, 150],
['multi_court', 'الملعب متعدد', 300, 400, 400, 500],
['bowling', 'البولينج', 60, 60, 60, 60],
['table_tennis', 'التنس الطاولة', 100, 100, 100, 100],
['playstation', 'البلاشتيشن', 100, 100, 100, 100],
];
foreach ($clubs as $row) {
foreach (['training', 'match'] as $usage) {
$mIdx = $usage === 'training' ? 2 : 4;
$eIdx = $usage === 'training' ? 3 : 5;
$db->insert('sa_rental_entity_pricing', [
'facility_type' => $row[0],
'facility_name_ar' => $row[1],
'entity_type' => 'clubs_federations',
'usage_type' => $usage,
'time_period' => 'morning',
'duration_minutes' => 60,
'price_amount' => $row[$mIdx],
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
$db->insert('sa_rental_entity_pricing', [
'facility_type' => $row[0],
'facility_name_ar' => $row[1],
'entity_type' => 'clubs_federations',
'usage_type' => $usage,
'time_period' => 'evening',
'duration_minutes' => 60,
'price_amount' => $row[$eIdx],
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
}
// هيئات اخرى + هيئات اجنبية (simplified — combined pricing)
$otherEntities = [
// [facility, name, other_practice_m, other_practice_e, other_training_m, other_training_e, foreign_practice_m, foreign_practice_e, foreign_training_m, foreign_training_e]
['football_full', 'كرة القدم القانونى', 1000, 1200, 1100, 1300, 1200, 1400, 1300, 1500],
['football_five', 'كرة القدم الخماسى', 300, 400, 400, 500, 500, 600, 600, 700],
['tennis', 'التنس الارضى', 100, 150, 150, 200, 150, 200, 200, 250],
['padel', 'البادل تنس', 250, 300, 300, 350, 350, 400, 400, 450],
['squash', 'الاسكواش', 125, 125, 150, 150, 150, 150, 200, 200],
['multi_court', 'الملعب متعدد', 250, 350, 350, 450, 400, 500, 600, 700],
['bowling', 'البولينج', 75, 75, 75, 75, 150, 150, 150, 150],
['table_tennis', 'التنس الطاولة', 100, 100, 100, 100, 150, 150, 150, 150],
['playstation', 'البلاشتيشن', 100, 100, 100, 100, 150, 150, 150, 150],
['billiards', 'البلياردو', 150, 150, 150, 150, 200, 200, 200, 200],
];
foreach ($otherEntities as $row) {
foreach (['other_entities' => [2,3,4,5], 'foreign_entities' => [6,7,8,9]] as $entityType => $indices) {
foreach (['practice', 'training'] as $ui => $usage) {
$mIdx = $indices[$ui * 2];
$eIdx = $indices[$ui * 2 + 1];
$db->insert('sa_rental_entity_pricing', [
'facility_type' => $row[0],
'facility_name_ar' => $row[1],
'entity_type' => $entityType,
'usage_type' => $usage,
'time_period' => 'morning',
'duration_minutes' => 60,
'price_amount' => $row[$mIdx],
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
$db->insert('sa_rental_entity_pricing', [
'facility_type' => $row[0],
'facility_name_ar' => $row[1],
'entity_type' => $entityType,
'usage_type' => $usage,
'time_period' => 'evening',
'duration_minutes' => 60,
'price_amount' => $row[$eIdx],
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
}
}
// ══════════════════════════════════════════════════════════════════════════
// DISCOUNT RULES
// ══════════════════════════════════════════════════════════════════════════
$discountRules = [
[
'rule_code' => 'NONMEMBER_SURCHARGE_10PCT',
'name_ar' => 'زيادة 10% لغير الأعضاء على قيمة الاشتراك',
'discount_type' => 'percentage',
'discount_value' => 10.00,
'applies_to' => 'academy',
'academy_code' => null,
'condition_type' => 'nonmember_surcharge',
'condition_value' => '{"description":"غير عضو خصم 10% من قيمة الاشتراك الكاملة"}',
],
[
'rule_code' => 'ADVANCE_3MONTHS_15PCT',
'name_ar' => 'خصم 15% عند دفع 3 أشهر مقدما',
'discount_type' => 'percentage',
'discount_value' => 15.00,
'applies_to' => 'all',
'academy_code' => null,
'condition_type' => 'advance_payment',
'condition_value' => '{"months":3}',
],
[
'rule_code' => 'CHESS_SIBLING_10PCT',
'name_ar' => 'خصم 10% للاخوات - اكاديمية الشطرنج',
'discount_type' => 'percentage',
'discount_value' => 10.00,
'applies_to' => 'academy',
'academy_code' => 'CHESS-ADLY',
'condition_type' => 'sibling',
'condition_value' => '{"applies_to":"members_and_nonmembers"}',
],
[
'rule_code' => 'FREE_PERIOD_WINTER_MORNING',
'name_ar' => 'الفترة الحرة للأعضاء - شتاء صباحا',
'discount_type' => 'percentage',
'discount_value' => 100.00,
'applies_to' => 'facility',
'academy_code' => null,
'condition_type' => 'free_period',
'condition_value' => '{"season":"winter","period":"morning","start":"09:00","end":"12:00","members_only":true}',
],
[
'rule_code' => 'FREE_PERIOD_WINTER_EVENING',
'name_ar' => 'الفترة الحرة للأعضاء - شتاء مساءا',
'discount_type' => 'percentage',
'discount_value' => 100.00,
'applies_to' => 'facility',
'academy_code' => null,
'condition_type' => 'free_period',
'condition_value' => '{"season":"winter","period":"evening","start":"15:00","end":"17:00","members_only":true}',
],
[
'rule_code' => 'FREE_PERIOD_SUMMER_MORNING',
'name_ar' => 'الفترة الحرة للأعضاء - صيفا صباحا',
'discount_type' => 'percentage',
'discount_value' => 100.00,
'applies_to' => 'facility',
'academy_code' => null,
'condition_type' => 'free_period',
'condition_value' => '{"season":"summer","period":"morning","start":"09:00","end":"12:00","members_only":true}',
],
[
'rule_code' => 'FREE_PERIOD_SUMMER_EVENING',
'name_ar' => 'الفترة الحرة للأعضاء - صيفا مساءا',
'discount_type' => 'percentage',
'discount_value' => 100.00,
'applies_to' => 'facility',
'academy_code' => null,
'condition_type' => 'free_period',
'condition_value' => '{"season":"summer","period":"evening","start":"16:00","end":"18:00","members_only":true}',
],
[
'rule_code' => 'POOL_GOV_ENTITY_LANE_25M',
'name_ar' => 'رسوم حمام السباحة للهيئات الحكومية - حارة 25م',
'discount_type' => 'fixed',
'discount_value' => 0,
'applies_to' => 'facility',
'academy_code' => null,
'condition_type' => 'entity_pool_access',
'condition_value' => '{"entity_types":["schools_gov","clubs_federations","other_entities","foreign_entities"],"morning_per_person":[100,125,150,200],"evening_per_person":[125,150,175,250],"lane_25m_max8":[800,800,1000,1400],"lane_50m_max12":[1000,1000,1200,1700]}',
],
];
foreach ($discountRules as $rule) {
$db->insert('sa_discount_rules', array_merge($rule, [
'is_active' => 1,
'created_at' => $ts,
'updated_at' => $ts,
]));
}
// ══════════════════════════════════════════════════════════════════════════
// Pool swimming entity pricing (for the gate access integration)
// ══════════════════════════════════════════════════════════════════════════
$poolEntityPricing = [
// [entity_type, morning_per_person, evening_per_person, lane_25m_8players, lane_50m_12players]
['schools_gov', 100, 125, 500, 800],
['clubs_federations', 125, 150, 800, 1000],
['other_entities', 150, 175, 1000, 1200],
['foreign_entities', 200, 250, 1400, 1700],
];
foreach ($poolEntityPricing as $row) {
$db->insert('sa_rental_entity_pricing', [
'facility_type' => 'pool',
'facility_name_ar' => 'حمام السباحة',
'entity_type' => $row[0],
'usage_type' => 'practice',
'time_period' => 'morning',
'duration_minutes' => 60,
'price_amount' => $row[1],
'notes_ar' => 'للفرد شامل دخول الفرد حمام السباحة',
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
$db->insert('sa_rental_entity_pricing', [
'facility_type' => 'pool',
'facility_name_ar' => 'حمام السباحة',
'entity_type' => $row[0],
'usage_type' => 'practice',
'time_period' => 'evening',
'duration_minutes' => 60,
'price_amount' => $row[2],
'notes_ar' => 'للفرد شامل دخول الفرد حمام السباحة',
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
}
// Track usage fee
$db->insert('sa_rental_entity_pricing', [
'facility_type' => 'track',
'facility_name_ar' => 'تراك الجرى',
'entity_type' => 'all_entities',
'usage_type' => 'practice',
'time_period' => 'morning',
'duration_minutes' => 60,
'price_amount' => 200,
'notes_ar' => 'رسوم استخدام التراك لجميع الهيئات لمدة ساعة صباحا',
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
$db->insert('sa_rental_entity_pricing', [
'facility_type' => 'track',
'facility_name_ar' => 'تراك الجرى',
'entity_type' => 'all_entities',
'usage_type' => 'practice',
'time_period' => 'evening',
'duration_minutes' => 60,
'price_amount' => 300,
'notes_ar' => 'رسوم استخدام التراك لجميع الهيئات لمدة ساعة مساءا',
'is_active' => 1,
'effective_from' => '2025-09-01',
'created_at' => $ts,
'updated_at' => $ts,
]);
};
<?php
declare(strict_types=1);
use App\Core\Database;
/**
* إضافة التخصصات الرياضية الجديدة من قائمة الأسعار 2025/2026
* هذه التخصصات مطلوبة لربط الأسعار بالأكاديميات
*/
return function (Database $db): void {
$ts = date('Y-m-d H:i:s');
$disciplines = [
['code' => 'BASKETBALL', 'name_ar' => 'كرة السلة', 'name_en' => 'Basketball', 'category' => 'team', 'icon' => 'circle-dot', 'desc' => 'كرة السلة — أكاديمي وفرق', 'sort' => 11],
['code' => 'VOLLEYBALL', 'name_ar' => 'الكرة الطائرة', 'name_en' => 'Volleyball', 'category' => 'team', 'icon' => 'circle', 'desc' => 'الكرة الطائرة — أكاديمي وفرق', 'sort' => 12],
['code' => 'HANDBALL', 'name_ar' => 'كرة اليد', 'name_en' => 'Handball', 'category' => 'team', 'icon' => 'hand', 'desc' => 'كرة اليد — أكاديمي وفرق', 'sort' => 13],
['code' => 'CHESS', 'name_ar' => 'الشطرنج', 'name_en' => 'Chess', 'category' => 'individual', 'icon' => 'crown', 'desc' => 'الشطرنج — عدلى أكاديمى', 'sort' => 14],
['code' => 'MUSIC', 'name_ar' => 'الموسيقى', 'name_en' => 'Music', 'category' => 'individual', 'icon' => 'music', 'desc' => 'أكاديمية الآلات الموسيقية', 'sort' => 15],
['code' => 'SKATING', 'name_ar' => 'الباتيناج', 'name_en' => 'Skating', 'category' => 'individual', 'icon' => 'zap', 'desc' => 'الباتيناج والتزحلق', 'sort' => 16],
['code' => 'DRAWING', 'name_ar' => 'الرسم', 'name_en' => 'Drawing', 'category' => 'individual', 'icon' => 'pen-tool', 'desc' => 'أكاديمية الرسم والفنون', 'sort' => 17],
['code' => 'KICKBOXING', 'name_ar' => 'الكيك بوكس', 'name_en' => 'Kickboxing', 'category' => 'combat', 'icon' => 'shield-alert', 'desc' => 'الكيك بوكس — فنون قتالية', 'sort' => 18],
];
foreach ($disciplines as $d) {
$existing = $db->selectOne("SELECT id FROM sa_disciplines WHERE code = ?", [$d['code']]);
if (!$existing) {
$db->insert('sa_disciplines', [
'code' => $d['code'],
'name_ar' => $d['name_ar'],
'name_en' => $d['name_en'],
'category' => $d['category'],
'icon' => $d['icon'],
'description_ar' => $d['desc'],
'config_json' => json_encode([
'skill_levels' => [
['code' => 'beginner', 'label_ar' => 'مبتدئ'],
['code' => 'intermediate', 'label_ar' => 'متوسط'],
['code' => 'advanced', 'label_ar' => 'متقدم'],
],
], JSON_UNESCAPED_UNICODE),
'sort_order' => $d['sort'],
'is_active' => 1,
'is_archived' => 0,
'created_at' => $ts,
'updated_at' => $ts,
]);
}
}
};
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