get_syllabus_details()#

Belirtilen müfredatın detaylı bilgilerini, ana konuları ve alt konuları içeren hiyerarşik yapıyla getiren güvenli fonksiyon.


Fonksiyon İmzası#

CREATE OR REPLACE FUNCTION get_syllabus_details(p_syllabus_id INTEGER)
RETURNS JSON
SECURITY DEFINER

Amaç#

Bir müfredatın tüm bilgilerini (başlık, açıklama, dosya yolu) ve o müfredata ait tüm konuları (ana konular + alt konular) hiyerarşik JSON formatında getirir. Yetki kontrolü ile sadece yetkili kullanıcılar erişebilir.


Parametreler#

ParametreTipAçıklama
p_syllabus_idINTEGERDetayı istenilen müfredatın ID’si

Dönüş Değeri#

Type: JSON

Başarılı Yanıt:

{
  "id": 1,
  "class_id": 15,
  "title": "2024-2025 Matematik Müfredatı",
  "description": "10. Sınıf Matematik Yıllık Planı",
  "original_file_path": "syllabi/math_2024.pdf",
  "created_at": "2024-09-01T08:00:00Z",
  "topics": [
    {
      "id": 101,
      "topic_name": "Trigonometri",
      "description": "Trigonometrik fonksiyonlar ve uygulamalar",
      "expected_week": 1,
      "parent_topic_id": null
    },
    {
      "id": 102,
      "topic_name": "Sinüs Teoremi",
      "description": "Sinüs teoremi ve çözüm yöntemleri",
      "expected_week": 2,
      "parent_topic_id": 101
    },
    {
      "id": 103,
      "topic_name": "Fonksiyonlar",
      "description": "Fonksiyon kavramı ve türleri",
      "expected_week": 5,
      "parent_topic_id": null
    }
  ]
}

Hata Mesajları#

HataAçıklama
User not foundOturum açılmamış
Syllabus not foundBelirtilen ID’de müfredat yok
Access denied: You can only view syllabi from your own classesÖğretmen başkasının müfredatına erişmeye çalıştı
Access denied: You can only view syllabi from classes you are enrolled inÖğrenci kayıtlı olmadığı sınıfın müfredatını görmeye çalıştı
Access denied: Invalid roleGeçersiz kullanıcı rolü

SQL Kodu#

CREATE OR REPLACE FUNCTION public.get_syllabus_details(p_syllabus_id integer)
 RETURNS json
 LANGUAGE plpgsql
 SECURITY DEFINER
AS $function$
DECLARE
  v_result json;
  v_user_id integer;
  v_user_role text;
  v_class_id integer;
BEGIN
  SELECT u.id, r.name INTO v_user_id, v_user_role
  FROM public.users u
  JOIN public.roles r ON u.role_id = r.id
  WHERE u.auth_user_id = auth.uid();

  IF v_user_id IS NULL THEN
    RAISE EXCEPTION 'User not found';
  END IF;

  SELECT s.class_id INTO v_class_id
  FROM public.syllabi s
  WHERE s.id = p_syllabus_id;

  IF v_class_id IS NULL THEN
    RAISE EXCEPTION 'Syllabus not found';
  END IF;

  IF v_user_role = 'teacher' THEN
    IF NOT EXISTS (
      SELECT 1 FROM public.classes 
      WHERE id = v_class_id AND teacher_id = v_user_id
    ) THEN
      RAISE EXCEPTION 'Access denied: You can only view syllabi from your own classes';
    END IF;
  ELSIF v_user_role = 'student' THEN
    IF NOT EXISTS (
      SELECT 1 FROM public.class_members 
      WHERE class_id = v_class_id 
      AND student_id = v_user_id 
      AND deleted_at IS NULL
    ) THEN
      RAISE EXCEPTION 'Access denied: You can only view syllabi from classes you are enrolled in';
    END IF;
  ELSE
    RAISE EXCEPTION 'Access denied: Invalid role';
  END IF;

  SELECT json_build_object(
    'id', s.id,
    'class_id', s.class_id,
    'title', s.title,
    'description', s.description,
    'original_file_path', s.original_file_path,
    'created_at', s.created_at,
    'topics', COALESCE(
      (
        SELECT json_agg(
          json_build_object(
            'id', st.id,
            'topic_name', st.topic_name,
            'description', st.description,
            'expected_week', st.expected_week,
            'parent_topic_id', st.parent_topic_id
          )
          ORDER BY st.expected_week NULLS LAST, st.id
        )
        FROM public.syllabus_topics st
        WHERE st.syllabus_id = s.id
      ),
      '[]'::json
    )
  )
  INTO v_result
  FROM public.syllabi s
  WHERE s.id = p_syllabus_id;

  RETURN v_result;

EXCEPTION
  WHEN OTHERS THEN
    RAISE EXCEPTION 'Error fetching syllabus details: %', SQLERRM;
END;
$function$

Kullanım Örneği#

Projede Kullanım#

Dosya: lib/common/services/api/class_api.dart
Satır: ~219-222
Açıklama: Class API servisinde belirli bir müfredatın detaylarını çekmek için kullanılır.

BaseApiService.logApiCall('RPC', 'get_syllabus_details', params: {'p_syllabus_id': syllabusId});

final response = await _supabase
    .rpc('get_syllabus_details', params: {'p_syllabus_id': syllabusId});

SQL Örneği#

-- Müfredat detaylarını getir
SELECT get_syllabus_details(1);

-- JSON formatını güzelleştirerek göster
SELECT jsonb_pretty(get_syllabus_details(1)::jsonb);

-- Sadece başlık ve konu sayısını al
SELECT 
  (get_syllabus_details(1)::jsonb)->>'title' as title,
  jsonb_array_length((get_syllabus_details(1)::jsonb)->'topics') as topic_count;

Konu Hiyerarşisi#

Ana Konular#

parent_topic_id = NULL

Alt Konular#

parent_topic_id = [Ana Konu ID]

Örnek Hiyerarşi#

 Trigonometri (parent_topic_id: null)
   ├──  Sinüs Teoremi (parent_topic_id: 101)
   ├──  Kosinüs Teoremi (parent_topic_id: 101)
   └──  Trigonometrik Denklemler (parent_topic_id: 101)

 Fonksiyonlar (parent_topic_id: null)
   ├──  Doğrusal Fonksiyonlar (parent_topic_id: 103)
   └──  Kuadratik Fonksiyonlar (parent_topic_id: 103)

Konu Sıralama#

ORDER BY st.expected_week NULLS LAST, st.id
  1. Önce expected_week küçükten büyüğe
  2. expected_week NULL olanlar en sonda
  3. Aynı hafta içinde id küçükten büyüğe

Özellikler#

  • Hiyerarşik yapı: Ana konu-alt konu ilişkisi
  • Haftalık planlama: expected_week ile zamanlama
  • COALESCE: Konu yoksa boş array döner
  • Role-based access: Öğretmen/öğrenci yetki kontrolü
  • Soft-delete aware: deleted_at kontrolü

JSON Response Şeması#

interface SyllabusDetails {
  id: number;
  class_id: number;
  title: string;
  description: string | null;
  original_file_path: string | null;
  created_at: string; // ISO 8601
  topics: Topic[];
}

interface Topic {
  id: number;
  topic_name: string;
  description: string | null;
  expected_week: number | null;
  parent_topic_id: number | null; // Ana konularda null, alt konularda parent ID
}

Mobil Uygulama Kullanımı#

// Flutter/Dart örneği
final response = await supabase
    .rpc('get_syllabus_details', params: {'p_syllabus_id': 1})
    .execute();

final syllabus = response.data;
print('Müfredat: ${syllabus['title']}');
print('Konu Sayısı: ${syllabus['topics'].length}');

// Ana konuları filtrele
final mainTopics = (syllabus['topics'] as List)
    .where((topic) => topic['parent_topic_id'] == null)
    .toList();

// Alt konuları bul
final subTopics = (syllabus['topics'] as List)
    .where((topic) => topic['parent_topic_id'] == mainTopicId)
    .toList();

İlgili Tablolar#

  • public.syllabi
  • public.syllabus_topics
  • public.classes
  • public.class_members
  • public.users
  • public.roles

Veri Modeli#

syllabi (1) ----< (N) syllabus_topics
                          |
                          +-- parent_topic_id (self-reference)

Performans#

Subquery: Topics için bir subquery kullanılır, bu nedenle:

  • Tek bir SQL çağrısı
  • JSON formatında döner
  • Çok fazla konu varsa yavaşlayabilir

Optimize etmek için:

CREATE INDEX idx_syllabus_topics_syllabus_id ON syllabus_topics(syllabus_id);
CREATE INDEX idx_syllabus_topics_parent_id ON syllabus_topics(parent_topic_id);

İlgili Fonksiyonlar#

  • get_class_syllabi() - Sınıfın tüm müfredatlarını listele
  • get_syllabus_details() - Bu fonksiyon

Notlar#

İpucu: Alt konuları parent_topic_id ile filtreleyerek ağaç yapısı (tree structure) oluşturabilirsiniz.

Veri Analizi: expected_week ile haftalık ilerleme takibi yapılabilir.

UI Önerisi: Mobil uygulamada expandable list kullanarak ana konular ve alt konular gösterilebilir.


Örnek UI Kullanımı#

 2024-2025 Matematik Müfredatı
   
   Hafta 1: Trigonometri
      • Sinüs Teoremi
      • Kosinüs Teoremi
   
   Hafta 5: Fonksiyonlar
      • Doğrusal Fonksiyonlar
      • Kuadratik Fonksiyonlar