mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 11:09:18 +02:00
Nginx config, working deploy, basic theme, repo cleanup
This commit is contained in:
887
database/DATABASE_SPECIFICATION.md
Normal file
887
database/DATABASE_SPECIFICATION.md
Normal file
@@ -0,0 +1,887 @@
|
||||
# Post-ERG Database Specification
|
||||
|
||||
Complete technical specification of the Post-ERG thesis database schema.
|
||||
|
||||
**Version:** 1.0
|
||||
**Database:** SQLite
|
||||
**Last Updated:** February 5, 2026
|
||||
|
||||
---
|
||||
|
||||
## 📋 Table of Contents
|
||||
|
||||
1. [Overview](#overview)
|
||||
2. [Entity Relationship Diagram](#entity-relationship-diagram)
|
||||
3. [Core Tables](#core-tables)
|
||||
4. [Lookup Tables](#lookup-tables)
|
||||
5. [Junction Tables](#junction-tables)
|
||||
6. [Support Tables](#support-tables)
|
||||
7. [Views](#views)
|
||||
8. [Indexes](#indexes)
|
||||
9. [Triggers](#triggers)
|
||||
10. [Data Types Reference](#data-types-reference)
|
||||
11. [Business Rules](#business-rules)
|
||||
12. [Sample Queries](#sample-queries)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
### Purpose
|
||||
Database for managing and publishing ERG final thesis projects (TFE - Travaux de Fin d'Études) and doctoral theses.
|
||||
|
||||
### Key Features
|
||||
- Multi-author thesis support
|
||||
- Multiple supervisors per thesis
|
||||
- Flexible format types (web, audio, video, print, etc.)
|
||||
- Access control (public, internal, restricted)
|
||||
- File attachment management
|
||||
- Keyword tagging system
|
||||
- Full-text search capability
|
||||
- Academic metadata tracking
|
||||
|
||||
### Database Size Estimates
|
||||
- **Expected records**: 100-500 theses/year
|
||||
- **Growth rate**: ~10-15% annually
|
||||
- **Average record size**: ~5KB (metadata only)
|
||||
- **File storage**: External (linked via file paths)
|
||||
|
||||
---
|
||||
|
||||
## Entity Relationship Diagram
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌──────────────────┐ ┌─────────────┐
|
||||
│ authors │◄──────│ thesis_authors │──────►│ theses │
|
||||
└─────────────┘ 1:N └──────────────────┘ N:1 └─────────────┘
|
||||
│
|
||||
┌─────────────┐ ┌──────────────────┐ │
|
||||
│supervisors │◄──────│thesis_supervisors│──────────────┘
|
||||
└─────────────┘ 1:N └──────────────────┘ N:1
|
||||
|
||||
┌─────────────┐ ┌──────────────────┐
|
||||
│ keywords │◄──────│ thesis_keywords │──────────────┐
|
||||
└─────────────┘ 1:N └──────────────────┘ N:1 │
|
||||
│
|
||||
┌─────────────┐ ┌──────────────────┐ │
|
||||
│ languages │◄──────│ thesis_languages │──────────────┤
|
||||
└─────────────┘ 1:N └──────────────────┘ N:1 │
|
||||
│
|
||||
┌─────────────┐ ┌──────────────────┐ │
|
||||
│format_types │◄──────│ thesis_formats │──────────────┤
|
||||
└─────────────┘ 1:N └──────────────────┘ N:1 │
|
||||
│
|
||||
┌─────────────┐ │
|
||||
│orientations │──────────────────────────────────────────┤
|
||||
└─────────────┘ 1:N N:1 │
|
||||
│
|
||||
┌─────────────┐ │
|
||||
│ ap_programs │──────────────────────────────────────────┤
|
||||
└─────────────┘ 1:N N:1 │
|
||||
│
|
||||
┌─────────────┐ │
|
||||
│finality_types│─────────────────────────────────────────┤
|
||||
└─────────────┘ 1:N N:1 │
|
||||
│
|
||||
┌─────────────┐ │
|
||||
│access_types │──────────────────────────────────────────┤
|
||||
└─────────────┘ 1:N N:1 │
|
||||
│
|
||||
┌─────────────┐ │
|
||||
│license_types│──────────────────────────────────────────┤
|
||||
└─────────────┘ 1:N N:1 │
|
||||
│
|
||||
┌─────────────┐ │
|
||||
│thesis_files │──────────────────────────────────────────┘
|
||||
└─────────────┘ N:1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Core Tables
|
||||
|
||||
### `theses`
|
||||
**Purpose:** Main table storing thesis/dissertation information.
|
||||
|
||||
| Column | Type | Null | Default | Description |
|
||||
|--------|------|------|---------|-------------|
|
||||
| `id` | INTEGER | NO | AUTOINCREMENT | Primary key |
|
||||
| `identifier` | TEXT | YES | NULL | Unique identifier (e.g., "2025-002") |
|
||||
| `title` | TEXT | NO | - | Thesis title |
|
||||
| `subtitle` | TEXT | YES | NULL | Optional subtitle |
|
||||
| `year` | INTEGER | NO | - | Academic year of submission |
|
||||
| `is_doctoral` | BOOLEAN | NO | 0 | 0 = TFE (Master), 1 = Doctoral thesis |
|
||||
| `orientation_id` | INTEGER | YES | NULL | FK to `orientations` |
|
||||
| `ap_program_id` | INTEGER | YES | NULL | FK to `ap_programs` (Ateliers Pratiques) |
|
||||
| `finality_id` | INTEGER | YES | NULL | FK to `finality_types` |
|
||||
| `synopsis` | TEXT | YES | NULL | ~200 word summary |
|
||||
| `context_note` | TEXT | YES | NULL | Note by jury president (max 150 words) |
|
||||
| `remarks` | TEXT | YES | NULL | Internal administrative remarks |
|
||||
| `duration_minutes` | INTEGER | YES | NULL | For audio/video works |
|
||||
| `duration_pages` | INTEGER | YES | NULL | For written works |
|
||||
| `file_size_info` | TEXT | YES | NULL | Human-readable size (e.g., "128 pages + 45 minutes") |
|
||||
| `access_type_id` | INTEGER | YES | NULL | FK to `access_types` |
|
||||
| `license_id` | INTEGER | YES | NULL | FK to `license_types` |
|
||||
| `jury_points` | DECIMAL(4,2) | YES | NULL | Grade out of 20 |
|
||||
| `jury_note_added` | BOOLEAN | NO | 0 | Whether jury added a context note |
|
||||
| `submitted_at` | DATETIME | YES | NULL | Student submission timestamp |
|
||||
| `defense_date` | DATETIME | YES | NULL | Date of thesis defense |
|
||||
| `published_at` | DATETIME | YES | NULL | Public publication timestamp |
|
||||
| `is_published` | BOOLEAN | NO | 0 | Publication status |
|
||||
| `baiu_link` | TEXT | YES | NULL | Link to institutional repository (BAIU) |
|
||||
| `created_at` | DATETIME | NO | CURRENT_TIMESTAMP | Record creation time |
|
||||
| `updated_at` | DATETIME | NO | CURRENT_TIMESTAMP | Last update time |
|
||||
|
||||
**Indexes:**
|
||||
- `idx_theses_year` ON `year`
|
||||
- `idx_theses_published` ON `is_published`
|
||||
- `idx_theses_identifier` ON `identifier`
|
||||
- `idx_theses_orientation` ON `orientation_id`
|
||||
- `idx_theses_ap_program` ON `ap_program_id`
|
||||
- `idx_theses_access_type` ON `access_type_id`
|
||||
|
||||
**Constraints:**
|
||||
- `identifier` must be UNIQUE
|
||||
- `year` must be > 1950 (implicit validation)
|
||||
- `jury_points` must be between 0 and 20 (implicit validation)
|
||||
|
||||
---
|
||||
|
||||
### `authors`
|
||||
**Purpose:** Store student/author information.
|
||||
|
||||
| Column | Type | Null | Default | Description |
|
||||
|--------|------|------|---------|-------------|
|
||||
| `id` | INTEGER | NO | AUTOINCREMENT | Primary key |
|
||||
| `name` | TEXT | NO | - | Author full name |
|
||||
| `email` | TEXT | YES | NULL | Contact email |
|
||||
| `created_at` | DATETIME | NO | CURRENT_TIMESTAMP | Record creation time |
|
||||
| `updated_at` | DATETIME | NO | CURRENT_TIMESTAMP | Last update time |
|
||||
|
||||
**Indexes:**
|
||||
- `idx_authors_email` ON `email`
|
||||
|
||||
**Notes:**
|
||||
- Same author can have multiple theses
|
||||
- Email is optional (privacy)
|
||||
- No uniqueness constraint on name (same names possible)
|
||||
|
||||
---
|
||||
|
||||
### `supervisors`
|
||||
**Purpose:** Store thesis supervisor/promoter information.
|
||||
|
||||
| Column | Type | Null | Default | Description |
|
||||
|--------|------|------|---------|-------------|
|
||||
| `id` | INTEGER | NO | AUTOINCREMENT | Primary key |
|
||||
| `name` | TEXT | NO | - | Supervisor full name |
|
||||
| `created_at` | DATETIME | NO | CURRENT_TIMESTAMP | Record creation time |
|
||||
| `updated_at` | DATETIME | NO | CURRENT_TIMESTAMP | Last update time |
|
||||
|
||||
**Notes:**
|
||||
- Reusable across multiple theses
|
||||
- No email/contact info stored (administrative data)
|
||||
|
||||
---
|
||||
|
||||
## Lookup Tables
|
||||
|
||||
### `orientations`
|
||||
**Purpose:** Predefined list of artistic orientations.
|
||||
|
||||
| Column | Type | Null | Default | Description |
|
||||
|--------|------|------|---------|-------------|
|
||||
| `id` | INTEGER | NO | AUTOINCREMENT | Primary key |
|
||||
| `name` | TEXT | NO | - | Orientation name |
|
||||
| `created_at` | DATETIME | NO | CURRENT_TIMESTAMP | Record creation time |
|
||||
|
||||
**Predefined Values:**
|
||||
1. Arts Numériques
|
||||
2. Dessin
|
||||
3. Cinéma d'animation
|
||||
4. Installation-Performance
|
||||
5. Peinture
|
||||
6. Photographie
|
||||
7. Sculpture
|
||||
8. Vidéographie
|
||||
9. Graphisme
|
||||
10. Typographie
|
||||
11. Design Numérique
|
||||
12. Illustration
|
||||
13. Bande-Dessinée
|
||||
14. Sérigraphie
|
||||
15. Gravure
|
||||
|
||||
**Constraints:**
|
||||
- `name` must be UNIQUE
|
||||
|
||||
---
|
||||
|
||||
### `ap_programs`
|
||||
**Purpose:** Practical workshops programs (Ateliers Pratiques).
|
||||
|
||||
| Column | Type | Null | Default | Description |
|
||||
|--------|------|------|---------|-------------|
|
||||
| `id` | INTEGER | NO | AUTOINCREMENT | Primary key |
|
||||
| `name` | TEXT | NO | - | Program full name |
|
||||
| `code` | TEXT | YES | NULL | Short code/acronym |
|
||||
| `created_at` | DATETIME | NO | CURRENT_TIMESTAMP | Record creation time |
|
||||
|
||||
**Predefined Values:**
|
||||
1. Narration Spéculative (no code)
|
||||
2. Design et Politique du Multiple (DPM)
|
||||
3. Atelier Pratiques Situées (APS)
|
||||
4. Lieux, Interdisciplinarités, Écologie, Nécessité, Systèmes (LIENS)
|
||||
|
||||
**Constraints:**
|
||||
- `name` must be UNIQUE
|
||||
|
||||
---
|
||||
|
||||
### `finality_types`
|
||||
**Purpose:** Master degree finality types.
|
||||
|
||||
| Column | Type | Null | Default | Description |
|
||||
|--------|------|------|---------|-------------|
|
||||
| `id` | INTEGER | NO | AUTOINCREMENT | Primary key |
|
||||
| `name` | TEXT | NO | - | Finality type name |
|
||||
| `created_at` | DATETIME | NO | CURRENT_TIMESTAMP | Record creation time |
|
||||
|
||||
**Predefined Values:**
|
||||
1. Approfondi (Research-focused)
|
||||
2. Enseignement (Teaching)
|
||||
3. Spécialisé (Specialized)
|
||||
|
||||
**Constraints:**
|
||||
- `name` must be UNIQUE
|
||||
|
||||
---
|
||||
|
||||
### `languages`
|
||||
**Purpose:** Languages used in thesis.
|
||||
|
||||
| Column | Type | Null | Default | Description |
|
||||
|--------|------|------|---------|-------------|
|
||||
| `id` | INTEGER | NO | AUTOINCREMENT | Primary key |
|
||||
| `name` | TEXT | NO | - | Language name |
|
||||
| `created_at` | DATETIME | NO | CURRENT_TIMESTAMP | Record creation time |
|
||||
|
||||
**Predefined Values:**
|
||||
1. Français
|
||||
2. Anglais
|
||||
|
||||
**Notes:**
|
||||
- Expandable if needed (Dutch, etc.)
|
||||
- Thesis can be multilingual (junction table)
|
||||
|
||||
**Constraints:**
|
||||
- `name` must be UNIQUE
|
||||
|
||||
---
|
||||
|
||||
### `format_types`
|
||||
**Purpose:** Physical/digital format types.
|
||||
|
||||
| Column | Type | Null | Default | Description |
|
||||
|--------|------|------|---------|-------------|
|
||||
| `id` | INTEGER | NO | AUTOINCREMENT | Primary key |
|
||||
| `name` | TEXT | NO | - | Format type name |
|
||||
| `created_at` | DATETIME | NO | CURRENT_TIMESTAMP | Record creation time |
|
||||
|
||||
**Predefined Values:**
|
||||
1. Site web
|
||||
2. Audio
|
||||
3. Vidéo
|
||||
4. Performance
|
||||
5. Objet éditorial (printed matter)
|
||||
6. Installation
|
||||
7. Autre (other)
|
||||
|
||||
**Notes:**
|
||||
- Multiple formats per thesis allowed
|
||||
- "Autre" for edge cases
|
||||
|
||||
**Constraints:**
|
||||
- `name` must be UNIQUE
|
||||
|
||||
---
|
||||
|
||||
### `access_types`
|
||||
**Purpose:** Define thesis accessibility levels.
|
||||
|
||||
| Column | Type | Null | Default | Description |
|
||||
|--------|------|------|---------|-------------|
|
||||
| `id` | INTEGER | NO | AUTOINCREMENT | Primary key |
|
||||
| `name` | TEXT | NO | - | Access type name |
|
||||
| `description` | TEXT | YES | NULL | Detailed description |
|
||||
| `created_at` | DATETIME | NO | CURRENT_TIMESTAMP | Record creation time |
|
||||
|
||||
**Predefined Values:**
|
||||
|
||||
| ID | Name | Description |
|
||||
|----|------|-------------|
|
||||
| 1 | Libre | Full access online and in library |
|
||||
| 2 | Interne | Physical access only; descriptive note online |
|
||||
| 3 | Interdit | No access; descriptive note online only |
|
||||
|
||||
**Constraints:**
|
||||
- `name` must be UNIQUE
|
||||
|
||||
---
|
||||
|
||||
### `license_types`
|
||||
**Purpose:** Creative Commons and other license types.
|
||||
|
||||
| Column | Type | Null | Default | Description |
|
||||
|--------|------|------|---------|-------------|
|
||||
| `id` | INTEGER | NO | AUTOINCREMENT | Primary key |
|
||||
| `name` | TEXT | NO | - | License name (e.g., "CC BY-SA 4.0") |
|
||||
| `description` | TEXT | YES | NULL | License description |
|
||||
| `created_at` | DATETIME | NO | CURRENT_TIMESTAMP | Record creation time |
|
||||
|
||||
**Expected Values:**
|
||||
- CC BY 4.0
|
||||
- CC BY-SA 4.0
|
||||
- CC BY-NC 4.0
|
||||
- CC BY-NC-SA 4.0
|
||||
- CC0 1.0
|
||||
- All Rights Reserved
|
||||
- Custom (text description)
|
||||
|
||||
**Constraints:**
|
||||
- `name` must be UNIQUE
|
||||
|
||||
---
|
||||
|
||||
### `keywords`
|
||||
**Purpose:** Expandable keyword/tag list.
|
||||
|
||||
| Column | Type | Null | Default | Description |
|
||||
|--------|------|------|---------|-------------|
|
||||
| `id` | INTEGER | NO | AUTOINCREMENT | Primary key |
|
||||
| `keyword` | TEXT | NO | - | Keyword/tag text |
|
||||
| `created_at` | DATETIME | NO | CURRENT_TIMESTAMP | Record creation time |
|
||||
|
||||
**Notes:**
|
||||
- Keywords are case-insensitive (normalized to lowercase)
|
||||
- Maximum 10 keywords per thesis (enforced in application)
|
||||
- Auto-created when first used
|
||||
- Can be reused across theses
|
||||
|
||||
**Constraints:**
|
||||
- `keyword` must be UNIQUE
|
||||
|
||||
---
|
||||
|
||||
## Junction Tables
|
||||
|
||||
### `thesis_authors`
|
||||
**Purpose:** Many-to-many relationship between theses and authors.
|
||||
|
||||
| Column | Type | Null | Default | Description |
|
||||
|--------|------|------|---------|-------------|
|
||||
| `thesis_id` | INTEGER | NO | - | FK to `theses.id` |
|
||||
| `author_id` | INTEGER | NO | - | FK to `authors.id` |
|
||||
| `author_order` | INTEGER | NO | 1 | Display order (1, 2, 3...) |
|
||||
|
||||
**Primary Key:** (`thesis_id`, `author_id`)
|
||||
|
||||
**Cascade Rules:**
|
||||
- ON DELETE CASCADE (both FKs)
|
||||
|
||||
**Notes:**
|
||||
- Single author: `author_order = 1`
|
||||
- Multiple authors: ordered by `author_order`
|
||||
|
||||
---
|
||||
|
||||
### `thesis_supervisors`
|
||||
**Purpose:** Many-to-many relationship between theses and supervisors.
|
||||
|
||||
| Column | Type | Null | Default | Description |
|
||||
|--------|------|------|---------|-------------|
|
||||
| `thesis_id` | INTEGER | NO | - | FK to `theses.id` |
|
||||
| `supervisor_id` | INTEGER | NO | - | FK to `supervisors.id` |
|
||||
| `supervisor_order` | INTEGER | NO | 1 | Display order |
|
||||
|
||||
**Primary Key:** (`thesis_id`, `supervisor_id`)
|
||||
|
||||
**Cascade Rules:**
|
||||
- ON DELETE CASCADE (both FKs)
|
||||
|
||||
---
|
||||
|
||||
### `thesis_languages`
|
||||
**Purpose:** Many-to-many relationship between theses and languages.
|
||||
|
||||
| Column | Type | Null | Default | Description |
|
||||
|--------|------|------|---------|-------------|
|
||||
| `thesis_id` | INTEGER | NO | - | FK to `theses.id` |
|
||||
| `language_id` | INTEGER | NO | - | FK to `languages.id` |
|
||||
|
||||
**Primary Key:** (`thesis_id`, `language_id`)
|
||||
|
||||
**Cascade Rules:**
|
||||
- ON DELETE CASCADE (both FKs)
|
||||
|
||||
---
|
||||
|
||||
### `thesis_formats`
|
||||
**Purpose:** Many-to-many relationship between theses and format types.
|
||||
|
||||
| Column | Type | Null | Default | Description |
|
||||
|--------|------|------|---------|-------------|
|
||||
| `thesis_id` | INTEGER | NO | - | FK to `theses.id` |
|
||||
| `format_id` | INTEGER | NO | - | FK to `format_types.id` |
|
||||
|
||||
**Primary Key:** (`thesis_id`, `format_id`)
|
||||
|
||||
**Cascade Rules:**
|
||||
- ON DELETE CASCADE (both FKs)
|
||||
|
||||
---
|
||||
|
||||
### `thesis_keywords`
|
||||
**Purpose:** Many-to-many relationship between theses and keywords.
|
||||
|
||||
| Column | Type | Null | Default | Description |
|
||||
|--------|------|------|---------|-------------|
|
||||
| `thesis_id` | INTEGER | NO | - | FK to `theses.id` |
|
||||
| `keyword_id` | INTEGER | NO | - | FK to `keywords.id` |
|
||||
|
||||
**Primary Key:** (`thesis_id`, `keyword_id`)
|
||||
|
||||
**Indexes:**
|
||||
- `idx_thesis_keywords_thesis` ON `thesis_id`
|
||||
- `idx_thesis_keywords_keyword` ON `keyword_id`
|
||||
|
||||
**Cascade Rules:**
|
||||
- ON DELETE CASCADE (both FKs)
|
||||
|
||||
**Business Rules:**
|
||||
- Maximum 10 keywords per thesis (enforced in application layer)
|
||||
|
||||
---
|
||||
|
||||
## Support Tables
|
||||
|
||||
### `thesis_files`
|
||||
**Purpose:** Store file attachments for theses.
|
||||
|
||||
| Column | Type | Null | Default | Description |
|
||||
|--------|------|------|---------|-------------|
|
||||
| `id` | INTEGER | NO | AUTOINCREMENT | Primary key |
|
||||
| `thesis_id` | INTEGER | NO | - | FK to `theses.id` |
|
||||
| `file_type` | TEXT | NO | - | Type: 'main', 'annex', 'written_part', 'other' |
|
||||
| `file_path` | TEXT | NO | - | Relative path to file |
|
||||
| `file_name` | TEXT | NO | - | Original filename |
|
||||
| `file_size` | INTEGER | YES | NULL | Size in bytes |
|
||||
| `mime_type` | TEXT | YES | NULL | MIME type (e.g., 'application/pdf') |
|
||||
| `description` | TEXT | YES | NULL | File description |
|
||||
| `uploaded_at` | DATETIME | NO | CURRENT_TIMESTAMP | Upload timestamp |
|
||||
|
||||
**Cascade Rules:**
|
||||
- ON DELETE CASCADE on `thesis_id`
|
||||
|
||||
**File Types:**
|
||||
- **main**: Primary thesis document (PDF, HTML, etc.)
|
||||
- **annex**: Supplementary materials
|
||||
- **written_part**: Written component of practice-based thesis
|
||||
- **other**: Additional files
|
||||
|
||||
**Notes:**
|
||||
- Files stored in `/var/www/html/formulaire/data/theses/`
|
||||
- Cover images stored in `/var/www/html/formulaire/data/covers/`
|
||||
|
||||
---
|
||||
|
||||
### `pages`
|
||||
**Purpose:** Static content management (About, Licenses, Contact, etc.).
|
||||
|
||||
| Column | Type | Null | Default | Description |
|
||||
|--------|------|------|---------|-------------|
|
||||
| `id` | INTEGER | NO | AUTOINCREMENT | Primary key |
|
||||
| `slug` | TEXT | NO | - | URL-friendly identifier |
|
||||
| `title` | TEXT | NO | - | Page title |
|
||||
| `content` | TEXT | YES | NULL | Page content (Markdown/HTML) |
|
||||
| `is_published` | BOOLEAN | NO | 1 | Publish status |
|
||||
| `created_at` | DATETIME | NO | CURRENT_TIMESTAMP | Record creation time |
|
||||
| `updated_at` | DATETIME | NO | CURRENT_TIMESTAMP | Last update time |
|
||||
|
||||
**Predefined Pages:**
|
||||
- `charte` - Site charter/policy
|
||||
- `about` - About page
|
||||
- `licenses` - License information
|
||||
- `contact` - Contact page
|
||||
|
||||
**Constraints:**
|
||||
- `slug` must be UNIQUE
|
||||
|
||||
---
|
||||
|
||||
## Views
|
||||
|
||||
### `v_theses_full`
|
||||
**Purpose:** Complete thesis information with all relationships joined.
|
||||
|
||||
**Columns:**
|
||||
- All columns from `theses`
|
||||
- `orientation` (TEXT) - Orientation name
|
||||
- `ap_program` (TEXT) - AP program name
|
||||
- `finality_type` (TEXT) - Finality type name
|
||||
- `access_type` (TEXT) - Access type name
|
||||
- `license_type` (TEXT) - License name
|
||||
- `authors` (TEXT) - Comma-separated author names
|
||||
- `supervisors` (TEXT) - Comma-separated supervisor names
|
||||
- `languages` (TEXT) - Comma-separated language names
|
||||
- `formats` (TEXT) - Comma-separated format names
|
||||
- `keywords` (TEXT) - Comma-separated keywords
|
||||
|
||||
**Usage:**
|
||||
```sql
|
||||
SELECT * FROM v_theses_full WHERE id = 123;
|
||||
```
|
||||
|
||||
**Notes:**
|
||||
- Uses `GROUP_CONCAT` for many-to-many relationships
|
||||
- Results are comma-delimited strings
|
||||
- May need post-processing for proper arrays
|
||||
|
||||
---
|
||||
|
||||
### `v_theses_public`
|
||||
**Purpose:** Published theses only (for public website).
|
||||
|
||||
**Definition:**
|
||||
```sql
|
||||
SELECT * FROM v_theses_full WHERE is_published = 1;
|
||||
```
|
||||
|
||||
**Usage:**
|
||||
```sql
|
||||
SELECT * FROM v_theses_public ORDER BY year DESC, title;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Indexes
|
||||
|
||||
### Performance Indexes
|
||||
|
||||
| Index Name | Table | Columns | Purpose |
|
||||
|------------|-------|---------|---------|
|
||||
| `idx_theses_year` | `theses` | `year` | Filter by year |
|
||||
| `idx_theses_published` | `theses` | `is_published` | Public/private filtering |
|
||||
| `idx_theses_identifier` | `theses` | `identifier` | Unique lookup |
|
||||
| `idx_theses_orientation` | `theses` | `orientation_id` | Filter by orientation |
|
||||
| `idx_theses_ap_program` | `theses` | `ap_program_id` | Filter by AP program |
|
||||
| `idx_theses_access_type` | `theses` | `access_type_id` | Access control |
|
||||
| `idx_authors_email` | `authors` | `email` | Author lookup |
|
||||
| `idx_thesis_authors_thesis` | `thesis_authors` | `thesis_id` | Join optimization |
|
||||
| `idx_thesis_authors_author` | `thesis_authors` | `author_id` | Join optimization |
|
||||
| `idx_thesis_keywords_thesis` | `thesis_keywords` | `thesis_id` | Join optimization |
|
||||
| `idx_thesis_keywords_keyword` | `thesis_keywords` | `keyword_id` | Keyword search |
|
||||
|
||||
---
|
||||
|
||||
## Triggers
|
||||
|
||||
### Timestamp Update Triggers
|
||||
|
||||
**`update_theses_timestamp`**
|
||||
```sql
|
||||
AFTER UPDATE ON theses
|
||||
UPDATE theses SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id;
|
||||
```
|
||||
|
||||
**`update_authors_timestamp`**
|
||||
```sql
|
||||
AFTER UPDATE ON authors
|
||||
UPDATE authors SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id;
|
||||
```
|
||||
|
||||
**`update_supervisors_timestamp`**
|
||||
```sql
|
||||
AFTER UPDATE ON supervisors
|
||||
UPDATE supervisors SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id;
|
||||
```
|
||||
|
||||
**`update_pages_timestamp`**
|
||||
```sql
|
||||
AFTER UPDATE ON pages
|
||||
UPDATE pages SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Data Types Reference
|
||||
|
||||
### SQLite Data Types Used
|
||||
|
||||
| Type | SQLite Affinity | Description | Example Values |
|
||||
|------|----------------|-------------|----------------|
|
||||
| `INTEGER` | INTEGER | Signed integer | 1, 42, 2025 |
|
||||
| `TEXT` | TEXT | Variable-length text | "Title", "Name" |
|
||||
| `BOOLEAN` | INTEGER | 0 or 1 | 0 (false), 1 (true) |
|
||||
| `DATETIME` | TEXT | ISO8601 timestamp | "2025-02-05 12:00:00" |
|
||||
| `DECIMAL(4,2)` | REAL | Decimal number | 15.50, 18.75 |
|
||||
|
||||
### Boolean Convention
|
||||
- `FALSE` = 0
|
||||
- `TRUE` = 1
|
||||
- NULL = undefined/not set
|
||||
|
||||
---
|
||||
|
||||
## Business Rules
|
||||
|
||||
### Thesis Submission Workflow
|
||||
|
||||
1. **Draft Creation** (`is_published = 0`)
|
||||
- Student creates initial entry
|
||||
- Required fields: title, year, at least one author
|
||||
|
||||
2. **Complete Metadata**
|
||||
- Add orientation, AP program, finality
|
||||
- Upload files
|
||||
- Add keywords (max 10)
|
||||
- Set languages, formats
|
||||
|
||||
3. **Submission** (`submitted_at` set)
|
||||
- Student marks as ready for review
|
||||
- Email notification to administrators
|
||||
|
||||
4. **Defense** (`defense_date` set)
|
||||
- After thesis defense
|
||||
- Jury adds grade (`jury_points`)
|
||||
- Optional context note by jury president
|
||||
|
||||
5. **Publication** (`is_published = 1`, `published_at` set)
|
||||
- Administrator approves
|
||||
- Appears on public website
|
||||
- Respects `access_type` rules
|
||||
|
||||
### Data Validation Rules
|
||||
|
||||
**Required Fields (for publication):**
|
||||
- `title`
|
||||
- `year`
|
||||
- At least one author (via `thesis_authors`)
|
||||
- `orientation_id`
|
||||
- `access_type_id`
|
||||
|
||||
**Optional but Recommended:**
|
||||
- `synopsis` (~200 words)
|
||||
- `keywords` (3-10 recommended)
|
||||
- At least one file attachment
|
||||
- `license_id`
|
||||
|
||||
**Constraints:**
|
||||
- `year`: Must be ≥ 1950
|
||||
- `jury_points`: 0.00 to 20.00
|
||||
- `keywords`: Maximum 10 per thesis
|
||||
- `author_order`: Must be sequential (1, 2, 3...)
|
||||
- `identifier`: Unique across all theses
|
||||
|
||||
### Access Control Rules
|
||||
|
||||
| Access Type | Public View | Library Access | File Download |
|
||||
|-------------|-------------|----------------|---------------|
|
||||
| **Libre** | Full metadata + abstract | Yes | Yes |
|
||||
| **Interne** | Metadata + descriptive note | Physical only | No |
|
||||
| **Interdit** | Metadata + descriptive note | No | No |
|
||||
|
||||
---
|
||||
|
||||
## Sample Queries
|
||||
|
||||
### Common Queries
|
||||
|
||||
**Get all published theses from 2025:**
|
||||
```sql
|
||||
SELECT * FROM v_theses_public
|
||||
WHERE year = 2025
|
||||
ORDER BY title;
|
||||
```
|
||||
|
||||
**Find theses by author name:**
|
||||
```sql
|
||||
SELECT t.* FROM theses t
|
||||
JOIN thesis_authors ta ON t.id = ta.thesis_id
|
||||
JOIN authors a ON ta.author_id = a.id
|
||||
WHERE a.name LIKE '%Dupont%'
|
||||
AND t.is_published = 1;
|
||||
```
|
||||
|
||||
**Get thesis with all relationships:**
|
||||
```sql
|
||||
SELECT * FROM v_theses_full WHERE id = 42;
|
||||
```
|
||||
|
||||
**List theses by orientation:**
|
||||
```sql
|
||||
SELECT t.title, t.year, o.name as orientation
|
||||
FROM theses t
|
||||
JOIN orientations o ON t.orientation_id = o.id
|
||||
WHERE o.name = 'Arts Numériques'
|
||||
AND t.is_published = 1
|
||||
ORDER BY t.year DESC;
|
||||
```
|
||||
|
||||
**Full-text search in titles and synopses:**
|
||||
```sql
|
||||
SELECT * FROM v_theses_public
|
||||
WHERE title LIKE '%design%'
|
||||
OR synopsis LIKE '%design%'
|
||||
ORDER BY year DESC;
|
||||
```
|
||||
|
||||
**Get theses by keyword:**
|
||||
```sql
|
||||
SELECT DISTINCT t.* FROM theses t
|
||||
JOIN thesis_keywords tk ON t.id = tk.thesis_id
|
||||
JOIN keywords k ON tk.keyword_id = k.id
|
||||
WHERE k.keyword = 'écologie'
|
||||
AND t.is_published = 1;
|
||||
```
|
||||
|
||||
**Count theses per year:**
|
||||
```sql
|
||||
SELECT year, COUNT(*) as count
|
||||
FROM theses
|
||||
WHERE is_published = 1
|
||||
GROUP BY year
|
||||
ORDER BY year DESC;
|
||||
```
|
||||
|
||||
**Get theses with files:**
|
||||
```sql
|
||||
SELECT t.title, tf.file_name, tf.file_type
|
||||
FROM theses t
|
||||
JOIN thesis_files tf ON t.id = tf.thesis_id
|
||||
WHERE t.is_published = 1
|
||||
ORDER BY t.title;
|
||||
```
|
||||
|
||||
**Find theses without keywords:**
|
||||
```sql
|
||||
SELECT t.* FROM theses t
|
||||
LEFT JOIN thesis_keywords tk ON t.id = tk.thesis_id
|
||||
WHERE tk.thesis_id IS NULL
|
||||
AND t.is_published = 1;
|
||||
```
|
||||
|
||||
### Administrative Queries
|
||||
|
||||
**Recently submitted theses (pending review):**
|
||||
```sql
|
||||
SELECT title, submitted_at
|
||||
FROM theses
|
||||
WHERE submitted_at IS NOT NULL
|
||||
AND is_published = 0
|
||||
ORDER BY submitted_at DESC;
|
||||
```
|
||||
|
||||
**Theses missing required metadata:**
|
||||
```sql
|
||||
SELECT id, title, year
|
||||
FROM theses
|
||||
WHERE (orientation_id IS NULL
|
||||
OR access_type_id IS NULL
|
||||
OR id NOT IN (SELECT thesis_id FROM thesis_authors))
|
||||
AND is_published = 0;
|
||||
```
|
||||
|
||||
**Most used keywords:**
|
||||
```sql
|
||||
SELECT k.keyword, COUNT(*) as usage_count
|
||||
FROM keywords k
|
||||
JOIN thesis_keywords tk ON k.id = tk.keyword_id
|
||||
GROUP BY k.keyword
|
||||
ORDER BY usage_count DESC
|
||||
LIMIT 20;
|
||||
```
|
||||
|
||||
**Theses by supervisor:**
|
||||
```sql
|
||||
SELECT s.name as supervisor, COUNT(*) as thesis_count
|
||||
FROM supervisors s
|
||||
JOIN thesis_supervisors ts ON s.id = ts.supervisor_id
|
||||
JOIN theses t ON ts.thesis_id = t.id
|
||||
WHERE t.is_published = 1
|
||||
GROUP BY s.name
|
||||
ORDER BY thesis_count DESC;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Making Schema Changes
|
||||
|
||||
### How to Request Changes
|
||||
|
||||
When requesting schema changes, please specify:
|
||||
|
||||
1. **What needs to change**
|
||||
- Table name
|
||||
- Column name(s)
|
||||
- Relationship
|
||||
|
||||
2. **Type of change**
|
||||
- Add new table
|
||||
- Add new column
|
||||
- Modify existing column
|
||||
- Remove column/table
|
||||
- Change relationship
|
||||
|
||||
3. **Why it's needed**
|
||||
- Use case
|
||||
- Business requirement
|
||||
- Performance issue
|
||||
|
||||
4. **Example data**
|
||||
- Sample values
|
||||
- Expected format
|
||||
|
||||
### Example Change Request
|
||||
|
||||
```
|
||||
**Change Request:** Add support for thesis awards/distinctions
|
||||
|
||||
**Type:** Add new table + relationship
|
||||
|
||||
**Reason:** Need to track prizes and awards given to theses
|
||||
(e.g., "Best TFE 2025", "Jury Prize")
|
||||
|
||||
**Proposed Structure:**
|
||||
- Table: `awards`
|
||||
- id (INT, PK)
|
||||
- name (TEXT) - Award name
|
||||
- description (TEXT) - Award description
|
||||
- year (INT) - Year established
|
||||
|
||||
- Table: `thesis_awards`
|
||||
- thesis_id (INT, FK)
|
||||
- award_id (INT, FK)
|
||||
- awarded_date (DATETIME)
|
||||
|
||||
**Example Data:**
|
||||
- "Prix du Jury 2025"
|
||||
- "Meilleur TFE Arts Numériques"
|
||||
- "Prix de l'Innovation"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Version History
|
||||
|
||||
| Version | Date | Changes |
|
||||
|---------|------|---------|
|
||||
| 1.0 | 2026-02-05 | Initial specification document |
|
||||
|
||||
---
|
||||
|
||||
**For questions or change requests, reference this document and provide:**
|
||||
- Section name
|
||||
- Table/column affected
|
||||
- Desired outcome
|
||||
- Example use case
|
||||
Binary file not shown.
206
database/QUICK_SCHEMA_REFERENCE.md
Normal file
206
database/QUICK_SCHEMA_REFERENCE.md
Normal file
@@ -0,0 +1,206 @@
|
||||
# Database Quick Reference
|
||||
|
||||
Quick lookup for the Post-ERG database schema.
|
||||
|
||||
## 📊 Table Summary
|
||||
|
||||
| Table | Type | Records | Description |
|
||||
|-------|------|---------|-------------|
|
||||
| `theses` | Core | ~500/year | Main thesis records |
|
||||
| `authors` | Core | ~600 | Student/author info |
|
||||
| `supervisors` | Core | ~50 | Thesis supervisors |
|
||||
| `thesis_authors` | Junction | ~550/year | Thesis ↔ Authors |
|
||||
| `thesis_supervisors` | Junction | ~600/year | Thesis ↔ Supervisors |
|
||||
| `thesis_languages` | Junction | ~550/year | Thesis ↔ Languages |
|
||||
| `thesis_formats` | Junction | ~700/year | Thesis ↔ Formats |
|
||||
| `thesis_keywords` | Junction | ~3000/year | Thesis ↔ Keywords |
|
||||
| `thesis_files` | Support | ~800/year | File attachments |
|
||||
| `orientations` | Lookup | 15 | Art orientations |
|
||||
| `ap_programs` | Lookup | 4 | Workshop programs |
|
||||
| `finality_types` | Lookup | 3 | Master finalities |
|
||||
| `languages` | Lookup | 2+ | Languages |
|
||||
| `format_types` | Lookup | 7 | Media formats |
|
||||
| `access_types` | Lookup | 3 | Access levels |
|
||||
| `license_types` | Lookup | ~10 | Creative Commons |
|
||||
| `keywords` | Lookup | ~500+ | Tag system |
|
||||
| `pages` | Support | 4 | Static pages |
|
||||
|
||||
## 🔑 Key Relationships
|
||||
|
||||
```
|
||||
theses ──┬── 1:N ──► thesis_authors ──► N:1 ── authors
|
||||
├── 1:N ──► thesis_supervisors ──► N:1 ── supervisors
|
||||
├── 1:N ──► thesis_keywords ──► N:1 ── keywords
|
||||
├── 1:N ──► thesis_languages ──► N:1 ── languages
|
||||
├── 1:N ──► thesis_formats ──► N:1 ── format_types
|
||||
├── 1:N ──► thesis_files
|
||||
├── N:1 ──► orientations
|
||||
├── N:1 ──► ap_programs
|
||||
├── N:1 ──► finality_types
|
||||
├── N:1 ──► access_types
|
||||
└── N:1 ──► license_types
|
||||
```
|
||||
|
||||
## 📝 Core Fields Reference
|
||||
|
||||
### `theses` (Main Table)
|
||||
|
||||
**Identity:**
|
||||
- `id` - Primary key
|
||||
- `identifier` - Human-readable ID (e.g., "2025-002")
|
||||
|
||||
**Basic Info:**
|
||||
- `title` - Thesis title (required)
|
||||
- `subtitle` - Optional subtitle
|
||||
- `year` - Academic year (required)
|
||||
- `is_doctoral` - TFE (0) or Doctoral (1)
|
||||
|
||||
**Academic:**
|
||||
- `orientation_id` - Art orientation
|
||||
- `ap_program_id` - Workshop program
|
||||
- `finality_id` - Master finality type
|
||||
|
||||
**Content:**
|
||||
- `synopsis` - ~200 word summary
|
||||
- `context_note` - Jury note (max 150 words)
|
||||
- `duration_minutes` - For audio/video
|
||||
- `duration_pages` - For written works
|
||||
|
||||
**Access:**
|
||||
- `access_type_id` - Public/Internal/Restricted
|
||||
- `license_id` - Creative Commons, etc.
|
||||
|
||||
**Workflow:**
|
||||
- `submitted_at` - Student submission
|
||||
- `defense_date` - Defense date
|
||||
- `is_published` - Public visibility
|
||||
- `published_at` - Publication date
|
||||
- `jury_points` - Grade (0-20)
|
||||
|
||||
## 🏷️ Lookup Values
|
||||
|
||||
### Orientations (15)
|
||||
Arts Numériques, Dessin, Cinéma d'animation, Installation-Performance, Peinture, Photographie, Sculpture, Vidéographie, Graphisme, Typographie, Design Numérique, Illustration, Bande-Dessinée, Sérigraphie, Gravure
|
||||
|
||||
### AP Programs (4)
|
||||
- Narration Spéculative
|
||||
- Design et Politique du Multiple (DPM)
|
||||
- Atelier Pratiques Situées (APS)
|
||||
- Lieux, Interdisciplinarités, Écologie, Nécessité, Systèmes (LIENS)
|
||||
|
||||
### Finality Types (3)
|
||||
Approfondi, Enseignement, Spécialisé
|
||||
|
||||
### Languages (2+)
|
||||
Français, Anglais
|
||||
|
||||
### Format Types (7)
|
||||
Site web, Audio, Vidéo, Performance, Objet éditorial, Installation, Autre
|
||||
|
||||
### Access Types (3)
|
||||
- **Libre**: Full access online + library
|
||||
- **Interne**: Library only, note online
|
||||
- **Interdit**: No access, note only
|
||||
|
||||
## 🔍 Common Queries
|
||||
|
||||
### Get Published Theses
|
||||
```sql
|
||||
SELECT * FROM v_theses_public ORDER BY year DESC;
|
||||
```
|
||||
|
||||
### Get Thesis by ID
|
||||
```sql
|
||||
SELECT * FROM v_theses_full WHERE id = ?;
|
||||
```
|
||||
|
||||
### Search by Title
|
||||
```sql
|
||||
SELECT * FROM v_theses_public
|
||||
WHERE title LIKE '%keyword%'
|
||||
ORDER BY year DESC;
|
||||
```
|
||||
|
||||
### Filter by Year
|
||||
```sql
|
||||
SELECT * FROM v_theses_public
|
||||
WHERE year = 2025
|
||||
ORDER BY title;
|
||||
```
|
||||
|
||||
### Filter by Orientation
|
||||
```sql
|
||||
SELECT t.* FROM theses t
|
||||
JOIN orientations o ON t.orientation_id = o.id
|
||||
WHERE o.name = 'Arts Numériques'
|
||||
AND t.is_published = 1;
|
||||
```
|
||||
|
||||
### Get Author's Theses
|
||||
```sql
|
||||
SELECT t.* FROM theses t
|
||||
JOIN thesis_authors ta ON t.id = ta.thesis_id
|
||||
JOIN authors a ON ta.author_id = a.id
|
||||
WHERE a.name LIKE '%name%'
|
||||
AND t.is_published = 1;
|
||||
```
|
||||
|
||||
### Get Keywords for Thesis
|
||||
```sql
|
||||
SELECT k.keyword FROM keywords k
|
||||
JOIN thesis_keywords tk ON k.id = tk.keyword_id
|
||||
WHERE tk.thesis_id = ?;
|
||||
```
|
||||
|
||||
### Count by Year
|
||||
```sql
|
||||
SELECT year, COUNT(*) as count
|
||||
FROM theses
|
||||
WHERE is_published = 1
|
||||
GROUP BY year
|
||||
ORDER BY year DESC;
|
||||
```
|
||||
|
||||
## 📌 Important Constraints
|
||||
|
||||
- **Unique:** `theses.identifier`, `authors.email`, all lookup table names
|
||||
- **Required:** `theses.title`, `theses.year`, at least one author
|
||||
- **Max:** 10 keywords per thesis
|
||||
- **Range:** `jury_points` 0.00 - 20.00
|
||||
- **Cascade:** All junction tables DELETE CASCADE
|
||||
|
||||
## 🎯 Views
|
||||
|
||||
### `v_theses_full`
|
||||
Complete thesis data with all relationships (comma-separated).
|
||||
|
||||
### `v_theses_public`
|
||||
Only published theses (`is_published = 1`).
|
||||
|
||||
## 🔧 Making Changes
|
||||
|
||||
**Format for change requests:**
|
||||
|
||||
```
|
||||
Table: [table_name]
|
||||
Change: [add/modify/remove]
|
||||
Column: [column_name]
|
||||
Type: [data_type]
|
||||
Reason: [why needed]
|
||||
Example: [sample data]
|
||||
```
|
||||
|
||||
**Example:**
|
||||
|
||||
```
|
||||
Table: theses
|
||||
Change: add
|
||||
Column: external_url
|
||||
Type: TEXT
|
||||
Reason: Link to external project website
|
||||
Example: https://example.com/project
|
||||
```
|
||||
|
||||
## 📚 Full Documentation
|
||||
|
||||
See `DATABASE_SPECIFICATION.md` for complete details.
|
||||
@@ -1,244 +1,222 @@
|
||||
# Post-ERG Thesis Database Schema
|
||||
# Database Documentation
|
||||
|
||||
SQLite database schema for managing final thesis projects (TFE) and doctoral theses at ERG.
|
||||
Complete documentation for the Post-ERG thesis database.
|
||||
|
||||
## Overview
|
||||
## 📚 Available Documentation
|
||||
|
||||
This schema supports all requirements from the technical specifications (`posterg_fiche-technique.md`):
|
||||
### 1. **[DATABASE_SPECIFICATION.md](DATABASE_SPECIFICATION.md)** ⭐
|
||||
**Complete technical specification** - 25KB comprehensive document
|
||||
|
||||
- Multiple metadata categories (orientation, AP, finality, languages, formats, keywords)
|
||||
- Multiple authors and supervisors per thesis
|
||||
- Access control (Libre/Interne/Interdit)
|
||||
- Licensing management
|
||||
- File uploads (main TFE, annexes, written parts)
|
||||
- Jury notes and points
|
||||
- Publication workflow (submission → defense → publication)
|
||||
- Editable static pages (charte, about, licenses, contact)
|
||||
- Distinction between TFEs and doctoral theses
|
||||
**Contents:**
|
||||
- Complete table definitions with all columns
|
||||
- Entity relationship diagrams
|
||||
- Junction table specifications
|
||||
- Lookup table values
|
||||
- Business rules and workflows
|
||||
- Sample queries and use cases
|
||||
- Instructions for requesting schema changes
|
||||
|
||||
## Database Structure
|
||||
**Use when:** You need complete technical details about the database structure.
|
||||
|
||||
### Core Tables
|
||||
---
|
||||
|
||||
**`theses`** - Main thesis information
|
||||
- Basic metadata (title, subtitle, year, identifier)
|
||||
- Academic details (orientation, AP program, finality)
|
||||
- Content (synopsis, jury notes, duration/size)
|
||||
- Access control and licensing
|
||||
- Publication workflow status
|
||||
### 2. **[QUICK_SCHEMA_REFERENCE.md](QUICK_SCHEMA_REFERENCE.md)** 🚀
|
||||
**Quick reference guide** - 5KB at-a-glance reference
|
||||
|
||||
**`authors`** - Student/author information
|
||||
- Name and contact email
|
||||
**Contents:**
|
||||
- Table summary
|
||||
- Key relationships diagram
|
||||
- Core fields reference
|
||||
- Predefined lookup values
|
||||
- Common SQL queries
|
||||
- Constraint summary
|
||||
|
||||
**`supervisors`** - Thesis promoters
|
||||
- Name of supervisor/promoter
|
||||
**Use when:** You need quick lookup or common query examples.
|
||||
|
||||
**`thesis_files`** - Uploaded files
|
||||
- Main TFE, annexes, written parts
|
||||
- File metadata (path, size, MIME type)
|
||||
---
|
||||
|
||||
**`pages`** - Static content pages
|
||||
- Charte, about, licenses, contact pages
|
||||
- Easily editable content
|
||||
### 3. **[schema.sql](schema.sql)** 💾
|
||||
**The actual SQL schema** - Executable SQL file
|
||||
|
||||
### Reference Tables (Predefined Lists)
|
||||
**Contents:**
|
||||
- Complete CREATE TABLE statements
|
||||
- Indexes and triggers
|
||||
- Predefined data (orientations, AP programs, etc.)
|
||||
- Views for common queries
|
||||
|
||||
- `orientations` - Arts Numériques, Dessin, Cinéma d'animation, etc.
|
||||
- `ap_programs` - Narration Spéculative, DPM, APS, LIENS
|
||||
- `finality_types` - Approfondi, Enseignement, Spécialisé
|
||||
- `languages` - Français, Anglais, etc. (expandable)
|
||||
- `format_types` - Site web, Audio, Vidéo, Performance, etc.
|
||||
- `keywords` - Dynamic, expandable keyword list (max 10 per thesis)
|
||||
- `access_types` - Libre, Interne, Interdit
|
||||
- `license_types` - To be defined
|
||||
**Use when:** Setting up or resetting the database.
|
||||
|
||||
### Junction Tables (Many-to-Many)
|
||||
---
|
||||
|
||||
- `thesis_authors` - Links theses to authors
|
||||
- `thesis_supervisors` - Links theses to supervisors
|
||||
- `thesis_languages` - Multiple languages per thesis
|
||||
- `thesis_formats` - Multiple formats per thesis
|
||||
- `thesis_keywords` - Max 10 keywords per thesis
|
||||
## 🚀 Quick Start
|
||||
|
||||
## Key Features
|
||||
### View Database Schema
|
||||
```bash
|
||||
# Read the quick reference
|
||||
cat database/QUICK_SCHEMA_REFERENCE.md
|
||||
|
||||
### 1. Flexible Metadata
|
||||
- Multiple authors, supervisors, languages, formats, and keywords per thesis
|
||||
- Predefined lists with ability to add new entries
|
||||
- Proper normalization to avoid data duplication
|
||||
|
||||
### 2. Access Control
|
||||
Three levels of access as specified:
|
||||
- **Libre**: Freely accessible online and in library
|
||||
- **Interne**: Physical access only, descriptive note online
|
||||
- **Interdit**: No physical/online access, descriptive note only
|
||||
|
||||
**Important**: Access can be restricted but never opened (as per specs)
|
||||
|
||||
### 3. Publication Workflow
|
||||
The schema tracks the complete lifecycle:
|
||||
|
||||
1. **Submission** (`submitted_at`) - Student submits TFE
|
||||
2. **Defense** (`defense_date`) - Soutenance takes place
|
||||
3. **Jury Review** (`jury_note_added`, `jury_points`, `context_note`)
|
||||
4. **Publication** (`published_at`, `is_published = 1`)
|
||||
|
||||
**Important**: TFEs are NOT published immediately upon submission. They must wait for:
|
||||
- Defense to occur
|
||||
- Jury to add optional context note (max 150 words)
|
||||
- Jury points to be recorded
|
||||
|
||||
### 4. File Management
|
||||
Support for multiple file types per thesis:
|
||||
- Main TFE work
|
||||
- Annexes
|
||||
- Written part
|
||||
- Other supporting files
|
||||
|
||||
### 5. Views for Easy Querying
|
||||
|
||||
**`v_theses_full`** - Complete thesis information with all related data
|
||||
- Joins all tables
|
||||
- Concatenates multiple values (authors, supervisors, keywords, etc.)
|
||||
- Use for backend/admin interfaces
|
||||
|
||||
**`v_theses_public`** - Only published theses
|
||||
- Filtered to `is_published = 1`
|
||||
- Use for public-facing website
|
||||
|
||||
## Usage
|
||||
# Or full specification
|
||||
cat database/DATABASE_SPECIFICATION.md
|
||||
```
|
||||
|
||||
### Initialize Database
|
||||
|
||||
```bash
|
||||
sqlite3 posterg.db < schema.sql
|
||||
# Create test database from schema
|
||||
just init-test-db
|
||||
|
||||
# Create with sample data
|
||||
just create-fixtures
|
||||
```
|
||||
|
||||
### Example Queries
|
||||
### Query Database
|
||||
```bash
|
||||
# Open SQLite prompt
|
||||
just query-db
|
||||
|
||||
#### Get all published theses from 2025
|
||||
```sql
|
||||
SELECT * FROM v_theses_public WHERE year = 2025;
|
||||
# Show specific thesis
|
||||
just show-thesis 42
|
||||
```
|
||||
|
||||
#### Get theses by orientation
|
||||
```sql
|
||||
SELECT * FROM v_theses_full
|
||||
WHERE orientation = 'Vidéographie';
|
||||
## 📝 Making Schema Changes
|
||||
|
||||
### Step 1: Document Your Request
|
||||
|
||||
Format:
|
||||
```
|
||||
**Table:** [table_name]
|
||||
**Change Type:** [add/modify/remove]
|
||||
**What:** [description]
|
||||
**Why:** [reason/use case]
|
||||
**Example Data:** [samples]
|
||||
```
|
||||
|
||||
#### Get theses with specific keyword
|
||||
```sql
|
||||
SELECT t.* FROM v_theses_full t
|
||||
JOIN thesis_keywords tk ON t.id = tk.thesis_id
|
||||
JOIN keywords k ON tk.keyword_id = k.id
|
||||
WHERE k.keyword = 'performance';
|
||||
### Step 2: Specify Details
|
||||
|
||||
For **new columns**:
|
||||
- Column name
|
||||
- Data type (TEXT, INTEGER, BOOLEAN, DATETIME)
|
||||
- NULL/NOT NULL
|
||||
- Default value
|
||||
- Indexes needed?
|
||||
|
||||
For **new tables**:
|
||||
- Table name
|
||||
- All columns
|
||||
- Relationships to existing tables
|
||||
- Sample data
|
||||
|
||||
### Step 3: Provide Context
|
||||
|
||||
Include:
|
||||
- Use case scenario
|
||||
- Who will use it?
|
||||
- How will it be displayed?
|
||||
- Any constraints?
|
||||
|
||||
### Example Request
|
||||
|
||||
```
|
||||
**Table:** theses
|
||||
**Change Type:** add column
|
||||
**What:** Add column to track if thesis won an award
|
||||
**Why:** Need to highlight award-winning theses on homepage
|
||||
**Column Name:** has_award
|
||||
**Data Type:** BOOLEAN
|
||||
**Default:** 0 (false)
|
||||
**Example:** 1 for "Prix du Jury 2025" winner
|
||||
```
|
||||
|
||||
#### Get theses awaiting publication (submitted but not published)
|
||||
```sql
|
||||
SELECT * FROM theses
|
||||
WHERE submitted_at IS NOT NULL
|
||||
AND is_published = 0;
|
||||
## 🗂️ Database Structure Overview
|
||||
|
||||
```
|
||||
┌─────────────┐
|
||||
│ theses │ ◄── Main table (500+ records/year)
|
||||
└──────┬──────┘
|
||||
│
|
||||
├──► authors (via thesis_authors)
|
||||
├──► supervisors (via thesis_supervisors)
|
||||
├──► keywords (via thesis_keywords)
|
||||
├──► languages (via thesis_languages)
|
||||
├──► formats (via thesis_formats)
|
||||
├──► thesis_files (attachments)
|
||||
│
|
||||
└──► Lookup tables:
|
||||
• orientations
|
||||
• ap_programs
|
||||
• finality_types
|
||||
• access_types
|
||||
• license_types
|
||||
```
|
||||
|
||||
#### Update access type (can only restrict, not open)
|
||||
```sql
|
||||
-- Allowed: from Libre to Interne
|
||||
UPDATE theses SET access_type_id = 2 WHERE id = 1;
|
||||
## 📊 Key Statistics
|
||||
|
||||
-- Not allowed per specs: from Interdit to Libre
|
||||
-- This should be enforced in application logic
|
||||
- **Core tables:** 3 (theses, authors, supervisors)
|
||||
- **Junction tables:** 5 (many-to-many relationships)
|
||||
- **Lookup tables:** 7 (predefined values)
|
||||
- **Support tables:** 2 (files, pages)
|
||||
- **Views:** 2 (full data, public only)
|
||||
- **Indexes:** 11 (for performance)
|
||||
- **Triggers:** 4 (auto-update timestamps)
|
||||
|
||||
## 🔍 Common Scenarios
|
||||
|
||||
### Scenario 1: Student Submits Thesis
|
||||
1. Create record in `theses` (is_published=0)
|
||||
2. Add author to `authors`, link via `thesis_authors`
|
||||
3. Add supervisor(s) to `supervisors`, link via `thesis_supervisors`
|
||||
4. Set `orientation_id`, `ap_program_id`, `finality_id`
|
||||
5. Upload file to `thesis_files`
|
||||
6. Add keywords via `thesis_keywords`
|
||||
7. Set `submitted_at` timestamp
|
||||
|
||||
### Scenario 2: Admin Publishes Thesis
|
||||
1. Verify all required fields present
|
||||
2. Set `defense_date`
|
||||
3. Set `jury_points`
|
||||
4. Optional: add `context_note`
|
||||
5. Set `is_published = 1`
|
||||
6. Set `published_at = CURRENT_TIMESTAMP`
|
||||
|
||||
### Scenario 3: Public User Searches
|
||||
Query `v_theses_public` view with filters:
|
||||
- By year
|
||||
- By orientation
|
||||
- By keyword
|
||||
- By author name
|
||||
- Full-text search in title/synopsis
|
||||
|
||||
## 🛠️ Development Workflow
|
||||
|
||||
### Local Development
|
||||
1. Use `test.db` for development
|
||||
2. Create via `just init-test-db`
|
||||
3. Populate with `just create-fixtures`
|
||||
4. Test queries before deployment
|
||||
|
||||
### Schema Changes
|
||||
1. Update `schema.sql`
|
||||
2. Update `DATABASE_SPECIFICATION.md`
|
||||
3. Test on `test.db`
|
||||
4. Deploy to production (manual migration)
|
||||
|
||||
### Testing
|
||||
```bash
|
||||
# Run tests on local database
|
||||
just test-public-all
|
||||
|
||||
# Check database stats
|
||||
just stats-public
|
||||
```
|
||||
|
||||
## Data Import Notes
|
||||
## 📞 Need Help?
|
||||
|
||||
Based on `Database_TFE_test.csv`:
|
||||
1. **Quick lookup** → Read `QUICK_SCHEMA_REFERENCE.md`
|
||||
2. **Complete details** → Read `DATABASE_SPECIFICATION.md`
|
||||
3. **Schema changes** → Follow format in this README
|
||||
4. **SQL examples** → Check `QUICK_SCHEMA_REFERENCE.md`
|
||||
|
||||
### Current CSV Structure
|
||||
- Identifiant (e.g., "2025-002")
|
||||
- Titre, Sous-titre
|
||||
- Auteur·ice(s) - comma-separated if multiple
|
||||
- Contact - email
|
||||
- Promoteur·ice(s) - comma-separated if multiple
|
||||
- Format - comma-separated if multiple
|
||||
- Année
|
||||
- AP - abbreviation (DPM, LIENS, etc.)
|
||||
- Orientation - abbreviation (SC, VI, CA, etc.)
|
||||
- Finalité
|
||||
- Mots-clés - comma-separated, max 10
|
||||
- Synopsis
|
||||
- Contexte - jury context note
|
||||
- Remarques - internal notes
|
||||
- Langue - language(s)
|
||||
- Autorisation - access type
|
||||
- License - license type
|
||||
- taille - duration/size info
|
||||
- Points sur 20 - jury points
|
||||
- lien BAIU - institutional repository link
|
||||
## 🔗 Related Documentation
|
||||
|
||||
### Import Considerations
|
||||
|
||||
1. **Parse comma-separated values** for:
|
||||
- Authors (split and create entries in `authors` table)
|
||||
- Supervisors (split and create entries in `supervisors` table)
|
||||
- Formats (map to `format_types`)
|
||||
- Keywords (split and create/link in `keywords`)
|
||||
- Languages (split and map to `languages`)
|
||||
|
||||
2. **Map abbreviations**:
|
||||
- Orientations: SC → Sculpture, VI → Vidéographie, CA → Cinéma d'animation, etc.
|
||||
- AP: DPM, LIENS, APS (exact match)
|
||||
|
||||
3. **Handle missing data**:
|
||||
- Some fields in CSV are empty (AP, Orientation for some entries)
|
||||
- Use NULL in database
|
||||
|
||||
4. **Parse duration/size**:
|
||||
- Examples: "128 pages", "78 pages + ?? minutes", "68 minutes"
|
||||
- Extract numeric values for `duration_pages` and `duration_minutes`
|
||||
- Store original string in `file_size_info`
|
||||
|
||||
## Schema Design Decisions
|
||||
|
||||
### Why SQLite?
|
||||
- Self-contained, serverless
|
||||
- Easy to backup (single file)
|
||||
- Good performance for this use case
|
||||
- Simple to integrate with various tools
|
||||
|
||||
### Normalization Level
|
||||
- 3rd Normal Form (3NF) for most tables
|
||||
- Denormalized views for read performance
|
||||
- Balance between flexibility and simplicity
|
||||
|
||||
### Extensibility
|
||||
- New languages can be added via `languages` table
|
||||
- Keywords are dynamic and grow with content
|
||||
- License types can be defined later
|
||||
- Static pages can be added via `pages` table
|
||||
|
||||
### Constraints
|
||||
- CASCADE deletes on junction tables
|
||||
- UNIQUE constraints on lookup table names
|
||||
- NOT NULL on critical fields
|
||||
- Automatic timestamps via triggers
|
||||
|
||||
## Important Business Rules
|
||||
|
||||
1. **No immediate publication**: TFEs must go through defense before publication
|
||||
2. **Access restriction is one-way**: Can restrict but not open access
|
||||
3. **Max 10 keywords** per thesis (enforce in application)
|
||||
4. **Jury context note max 150 words** (enforce in application)
|
||||
5. **Synopsis ~200 words** (guideline, not hard limit)
|
||||
6. **Multiple selections allowed** for: languages, formats, authors, supervisors, keywords
|
||||
7. **Doctoral theses**: Use `is_doctoral = 1` to distinguish from TFEs
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Create import script to load CSV data
|
||||
2. Define license types
|
||||
3. Build backend API for CRUD operations
|
||||
4. Implement authorization checks
|
||||
5. Create admin interface for easy editing
|
||||
6. Build public-facing website using views
|
||||
- [Deployment Guide](../nginx/DEPLOYMENT_COMPLETE.md)
|
||||
- [Repository Structure](../REPOSITORY_STRUCTURE_ANALYSIS.md)
|
||||
- [Test Database Guide](../nginx/TEST_DATABASE_SETUP.md)
|
||||
|
||||
BIN
database/test.db
BIN
database/test.db
Binary file not shown.
Reference in New Issue
Block a user