refactor: rename database → storage

More semantically accurate: contains SQLite files, schema, fixtures, test data.
Updated all references in code, scripts, docs.
This commit is contained in:
Théophile Gervreau-Mercier
2026-02-12 12:12:58 +01:00
parent 0e4921583e
commit 7fca85d1c1
38 changed files with 131 additions and 131 deletions

View 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

View 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.

1375
storage/docs/SETUP.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,170 @@
# Fiche technique
## Différentes catégories / métadonnées
**• Titre du TFE**
**• Sous-titre (si applicable)**
**• Auteur·ice(s)**
**• Contact (optionnel) [mail/site/insta/etc.]**
**• Promoteur·ice(s)**
**• Année**
**• Orientation [liste prédéfinie]**
* Arts Numériques / Dessin / Cinéma d'animation / Installation-Performance / Peinture / Photographie / Sculpture / Vidéographie / Graphisme / Typographie / Design Numérique / Illustration / Bande-Dessinés / Sérigraphie / Gravure
**• AP [liste prédéfinie]**
* Narration Spéculative / Design et Politique du Multiple [DPM] / Atelier Pratiques Situées [APS] / Lieux, Interdisciplinarités, Écologie, Nécessité, Systèmes [L.I.E.N.S.]
**• Finalité du master [liste prédéfinie]**
* Approfondi / Enseignement /Spécialisé
**• Langue du TFE [liste prédéfinie + option de créer des nouvelles langues]**
* Français / Anglais / autre : [imput] —> possible d'en sélectionner plusieurs en même temps
**• Format [liste pré-définie + une case autre "fourre-tout"]**
* Site web / Audio / Vidéo / Performance / Objet éditorial / Installation / Etc. / Autre
* —> possible d'en sélectionner plusieurs en même temps
**• Mots-clés (max 10) [liste avec les mots clés déjà existants + option d'en créer des nouveaux]**
* spéculation / narration / urbanisme / patrimoine / intime / collectivité / film / cinéma / sociologie / anthropologie / éphémérité / queer / écriture / poésie / écologies affectives / technologies / autre : [imput]
**• Synopsis (environ 200 mots ; pas nécessairement de max à voir si c'est nécessaire côté technique)**
**• Durée du TFE (si applicable) [faire en choix entre minutes/pages : [imput]]**
**• J'autorise l'erg à archiver mon TFE de la manière suivante ;**
[]x Libre ;[] mon TFE est en libre accès à tout le monde sur la plateforme des TFE ainsi que dans la bibliothèque de l'erg.
[]x Interne ;[] mon TFE n'est accessible que sur place en physique. Une note descriptive est disponible sur le site.
[]x Interdit ;[] mon TFE n'est pas disponible en physique ni sur le site. Une note descriptive est disponible sur le site.
L'étudiant·e peut, à tout moment, décider de restreindre son propre choix. Iel ne peut par contre pas l'ouvrir.
**• Licence du TFE ; dropdown avec plusieurs choix pré-établis + ouverture pour en donner d'autres ?**
* Les options précises sont encore au travail.
**• Upload du TFE**
**• Upload des annexes éventuelles**
**• Upload de la partie écrite**
**• Système pour que læ président·e du jury puisse rajouter une note de max 150 mots qui contextualiserait le TFE.**
**• Points du jury**
[]/!\ Quand l'étudiant·e dépose le TFE, celui-ci ne doit pas immédiatement être publié. Il faut attendre que la soutenance ait eu lieu et que læ président·e puisse éventuellement y ajouter un texte ainsi que les points. []
[]—> trouver un système pour rendre ça le plus fluide possible pour læ présidant·e ainsi que l'étudiant·e.[]
## Design
• Prévoir un « onglet » Charte / à propos (texte à venir doit être facile à adapter sans avoir à coder).
• Prévoir un « onglet » licences (texte à venir doit être facile à adapter sans avoir à coder).
• Prévoir un « onglet » contact (texte à venir doit être facile à adapter sans avoir à coder).
• Il faut prévoir un espace ou quelque chose pour différencier les thèses (doctorats) des TFE.
## Points importants
• Important que le "back-office" soit accessible / pas trop complexe pour qu'on puisse adapter, supprimer, ajouter, corriger les données des TFE (relativement) facilement.
• Important que le texte des différents onglets soit éditable (relativement) facilement.
• Important que le statut de monstration "libre", "interne", "interdit" soit facilement changeable.
## Création Base de Données
• Engagement début décembre
* Min 5h/semaine à horaire libre
* On espère qu'un premier draft de base donnée arrivera mi-décembre pour pouvoir expérimenter avec. On vous enverra un fichier csv dès qu'on a une base solide.
• Collecte et assemblage des différentes années (au moins 2 ans idéalement tout [lol])
* —> il faudra demander aux ancien·nes étudiant·es s'iels sont d'accord que leurs données soient publiées. Un mail sera envoyé après la récolte.
* —> voir avec Karim ce qu'on a le droit de montrer s'il n'y a pas de réponse (fiche descriptive, TFE en physique ?)
• Établir une liste de mots clés prédéfinis / voir s'il y a des lacunes et/ou problèmes quelque part
• On est au travail pour la partie doctorats. On vous tient au courant dès qu'il y a plus d'informations à ce sujet.
## Technique
• Hébergement et intégration avec les outils existants à voir avec Joan.
## Retroplanning
• Mi-décembre ; envoi d'un semblant de base de donnée pour permettre à l'équipe posterg d'expérimenter
• Journées pédagogiques du 15 \& 16 janvier ; travail sur les TFE, la place du jury dans sa publication etc.
• Mi-février ; envoi d'un mail aux ancien·nes étudiant·es et aux profs en vue de la publication digitale des TFE
• Mi-février ; finalisation de la maquette du site Post-ERG
• Mi-mars ; base de donnée des ancien·nes étudiant·es finalisée (fichier .cvs)
• Mi-avril ; date de remise du projet site finalisé
• Début mai ; mise en ligne du site
• Mi-mai ; dépôt des TFE de 1e session (les TFE ne sont pas publiés publiquement à ce moment)
• Mi-juin ; publication publique des TFE (après éventuelle note du jury)