# Implémentation des parcours du BUT dans ScoDoc

Cette page est *destinée aux développeurs* et à tous ceux qui souhaitent
comprendre le fonctionnement du logiciel. Elle ne concerne que les formations
BUT, dites dans ScoDoc "APC" (pour *approches par compétences*).

ScoDoc est livré avec les référentiels de compétences de tous les parcours de
toutes les spécialités de BUT. En effet, ces référentiels sont nationaux,
publiés par le ministère (voir
[https://www.enseignementsup-recherche.gouv.fr/fr/bo/22/Special4/ESRS2211617A.htm](https://www.enseignementsup-recherche.gouv.fr/fr/bo/22/Special4/ESRS2211617A.htm))
et ne sont pas susceptibles d'adaptations locales.

Nous nous sommes basés sur les versions exportées du logiciel Orébut.

!!! note
    Les objets notés `CommeCeci` sont des modèles (classes SQLAlchemy)
    implémentés par des tables SQL.

## Structure des formations

Pour les formation en APC, on a d'une part le *programme de formation*, et de
l'autre le *référentiel de compétences*.

Pour le BUT, le référentiel de formation n'est pas fixé nationalement. Une part
est publiée (2/3) par le ministère, le reste est défini localement par les
universités (*adaptation locale*).

Les formations ScoDoc (`Formation`) sont constituées de

- UE : `UniteEns`
  - Modules (ressources, SAÉ, autres): `Module`

La formation définit les UE et modules pour l'ensemble
des semestres d'un ou plusieurs parcours. De cette façon, on peut utiliser les
mêmes éléments dans plusieurs parcours, et grouper les étudiants de plusieurs
parcours dans le même semestre si on le souhaite.


## Unités d'enseignement

Les UE sont des UE "LMD" habituelles; associées à des crédits ECTS,
capitalisables. Pour chaque UE on calcule une note (moyenne d'UE) et on attribue
une décision de jury (validée, ajournée, ...).

### ECTS et parcours

Les ECTS sont toujours associés aux UEs, et non au semestre ou aux modules.

Dans ScoDoc, il est obligatoire de spécifier le nombre d'ECTS des de chaque UE
(sauf les UE bonus qui n'ont jamais d'ECTS).

Le nombre d'ECTS est généralement fixe, mais il peut varier selon le parcours

!!! note "ECTS variable selon le parcours"
    Ce cas a été soulevé à propos du BUT MMI, qui préconiserait par exemple, au S4,
    une compétence "développer" avec 10 ECTS dans le parcours "Web", et 5 ECTS dans le
    parcours "Crea".
    Cette possibilité est prévue pour ScoDoc version 9.4.72
    Chaque UE a un attribut ECTS qui donne la valeur par défaut. On a aussi une
    valeur ECTS dans la table d'association `UEParcours`qui lie `UniteEns` et
    `ApcParcours`.
    Si cette valeur est présente, l'attribut ECTS de l'UE est ignoré.

## Modules et parcours

Les modules: on appelle ici "module" tout dispositif pédagogique évalué, dans le
BUT ce sont les *ressources* et les *SAÉ*.

Chaque module peut être associé à un ou plusieurs parcours, via la table 
d'association `ApcParcours` <-> `Module` (`parcours_modules`, many-to-many).

Via *Formation*/*Modification du module*:<br>
 <img src="/screens/module_choix_parcours.png" width="50%">

On peut ainsi vérifier que les parcours couvrent les AC, et faciliter les
inscriptions des étudiants aux modules (par ex. page présentant les modules
auxquels inscrire un groupe).

### Cas des modules présents dans plusieurs parcours

Il est fréquent qu'un module peut être utilisé dans plusieurs parcours de la
même formation BUT. Il peut contribuer à une UE de tronc commun, ou un
sous-ensemble d'UEs. Dans certains spécialités, le coefficient d'un module vers
une UE varie selon le parcours: dans ce cas, il faudra créer plusieurs UEs
associées au même niveau de compétence, et renseigner les coefficients
correspondants. les étudiants seront inscrits à l'une ou l'autre des UEs suivant
leur parcours.

## Coefficients modules / UEs

Les coefficients sont des réels (non nullables), `ModuleUECoef`.

Édition via *Formation*/*Édition des coefficients des modules vers les UEs*:<br>
 <img src="/fig/formation_edit_coefs.png" width="30%">

## Formation

Le programme de formation est constitué des classes suivantes (en BUT et dans
tous les types de formation. La notion de "matière" n'est pas utilisée en BUT).

- `Formation` (ex: "BUT R&T")
  - `UniteEns` (UE, ex: "Administrer les réseaux")
      - `Modules` (ressources, SAÉs) *<-> `ApcAppCritique`*, *<-> `ApcAnneeParcours`*

On voit que les modules ont toujours une UE de rattachement. Cependant, en BUT,
un module peut intervenir dans le calcul des notes de plusieurs UE, via une
matrice de coefficients.

!!! example "Méthodes de Formation"
    - `Formation.query_ues_parcour(parcour: ApcParcours)`->(query) les UEs d'un
    parcours de la formation.

## Référentiel de compétences

Le référentiel de compétences (`ApcReferentielCompetences`) défini les
compétences à valider (décomposées en niveaux) et les parcours BUT
(`ApcParcours`). Il est structuré ainsi:

- `ApcReferentielCompetences`
  - `ApcCompetence`
    - `ApcSituationPro`
    - `ApcComposanteEssentielle`
    - `ApcNiveau` (année (BUT1, BUT2, ...), ordre (1,2) ou (1,2,3)) *<-> `UE`*
      - `ApcAppCritique` *<-> `Module`*
  - `ApcParcours`
    - `ApcAnneeParcours` (ordre=1,2,3) *<-> `Module`*
  - *`ApcCompetence`* <- `ApcParcoursNiveauCompetence` (niveau 1, 2, 3) -> *`ApcAnneeParcours`*

Notons:

- Le lien (*one-to-one*) entre `UniteEns`(UE) et Niveau de compétence (`ApcNiveau`).

- Le lien entre Compétence et Année de Parcours à travers la table
 (*many-to-many*) `ApcParcoursNiveauCompetence` qui indique le niveau ce
 compétence concerné.

- Le lien *many-to-many* UE et `Parcours`, qui permet de spécifier les ECTS de
  l'UE dans un parcours donné et est utilisé pour vérifier la formation
  (couverture de tous les niveau en suivant un parcours donné, somme des ECTS).

- Le lien entre les apprentissages critiques (`ApcAppCritique`) et les
modules, qui permet d'établir les critères d'évaluation de chaque module.

### Niveaux de compétences et UEs

Une compétence est constituée de plusieurs niveaux (`ApcNiveau`), typiquement 2
ou 3. En BUT, chaque niveau correspond à deux UEs sur deux semestres de la même
année d'un parcours.

- Chaque parcours de BUT est défini par un ensemble de compétences.

- Une compétence est décomposée en deux ou trois *niveaux*, chacun constitué de
 deux UE consécutives (sur semestres pair et impair de la même année
 scolaire).

Lors des jurys, on enregistre les validations d'UE. Les UE sont liées à des
niveaux de compétences. Lorsque les deux UEs sont validées, le niveau est
validé: c'est le RCUE (*regroupement cohérents d'UEs*).

Pour valider un diplôme de BUT, il faut avoir validé tous les niveaux de toutes
les compétences du parcours choisi.

Une UE est associée à un et un seul niveau de compétence. Elle peut être
associée à un nombre quelconque de parcours.

Remarques:

- Certains niveaux (et donc UEs) sont présents dans tous les parcours: ce sont
  les niveaux de *tronc commun*.
- Une UE associée à un niveau peut avoir des ECTS différents selon le parcours
  (voir [note ci-dessus](#ects-et-parcours))
- Dans certaines spécialités, les coefficients des modules vers la même UE
  peuvent varier selon le parcours. Dans ce cas, on créera une UE par parcours
  (UE associée au même niveau), afin de pouvoir spécifier des coefficients
  distincts.

#### Vérifications effectués par ScoDoc

En plus des contraintes strictes liées aux relations modélisées,
ScoDoc vérifiera que

- Dans une formation, chaque niveau d'un parcours soit associé à deux et
  seulement deux UEs de ce parcours de la même année scolaires (BUT1, BUT2 ou
  BUT3).
- Le nombre total d'ECTS de chaque parcours soit bien 180 (3 années de 60 ECTS).
- Toutes les UEs sont bien associée à un niveau.


## FormSemestres

La formation est mise en œuvre dans des `FormSemestre` (date début, fin,
enseignants responsables, ...) constitués de `ModuleImpl` (module avec enseignant,
évaluations, ...).

- `FormSemestre`
  - `ModuleImpl`
    - `Evaluation`

On a vu que la formation pouvait comporter plusieurs parcours. Un `FormSemestre`
peut implémenter un ou plusieurs parcours. On a en effet une table d'association
Parcours <-> FormSemestre (`parcours_formsemestre`, many-to-many).

Via *Semestre*/*Modifier le semestre*:<br>
 <img src="/fig/formsemestre_choix_parcours.png" width="50%">

!!! example "Méthodes de FormSemestre"
    - `FormSemestre.query_ues(with_sport=False) ->` liste des UEs de ce semestres
    (tous parcours confondus).
    - `FormSemestre.query_ues_parcours_etud(etudid: int) -> `(query) UEs que suit
    l'étudiant dans ce semestre BUT en fonction du parcours dans lequel il est
    inscrit.

## Inscriptions des étudiants

Les étudiants sont inscrits:

- à des `FormSemestre` (`FormSemestreInscription`, avec:
  - un état, "inscrit", "démission" ou "défaillant";
  - un `ApcParcours`;
  - un code étape Apogée.

- dans un ModuleImpl (`ModuleImplInscription`)

Un formsemestre est associé à un ensemble de parcours. L'étudiant peut être
inscrit à l'un d'entre eux. Certaines formations commencent par une année de
tronc commun, durant laquelle l'étudiant n'a pas encore choisi son parcours. On
considérera que si l'étudiant n'est pas inscrit à un parcours, il est
implicitement inscrit à tous les parcours du semestre.

## Associations (nouvelles pour le BUT)

Pour la gestion des parcours BUT, on a introduit les associations suivantes,
qui n'existaient pas dans ScoDoc 9.2:

- `UniteEns` }o--o{ ensemble de `ApcParcours` : choix sur la page `ue_edit`
- `UniteEns` }o--|| `ApcNiveau` : choix sur la page `ue_edit`
- `Module` ||--o{ ensemble de `ApcParcours`
- `Module` ||--o{ `ApcAppCritique` : choix sur la page `module_edit`
- `FormSemestre` ||--o{ `ApcParcours` : choix sur la page
 `formsemestre_editwithmodules`
- `FormSemestreInscription` ||--|| `ApcParcours` : inscription au parcours, géré
  via la partition `Parcours`.

```mermaid
erDiagram
  UniteEns }o--o{ ApcParcours : UEParcours
  UniteEns }o--|| ApcNiveau : ""
  Formation ||--o{ UniteEns : ""
  FormSemestre }o--|| Formation : ""
  UniteEns }o--|{ Module : ModuleUECoef 
```

## Cas d'usage

### UEs à afficher sur les bulletins individuels

#### En ScoDoc 9.3.55 (ssi ref. comp. associé)

On part de `ResultatsSemestreBUT.ues`, qui est la version cachée de
`formsemestre.query_ues()` (toutes les UE du semestre) que l'on filtre 
avec `ResultatsSemestreBUT.etud_ues_ids(etudid)`: liste des id d'UE auxquelles 
l'étudiant est inscrit (sans bonus).

`etud_ues_ids()` accède à `ResultatsSemestreBUT.ues_inscr_parcours_df`, la
matrice d'inscriptions `(etuds, ue)`. 

### UEs à afficher sur les tableaux récap. de semestre

TODO

### UEs à valider en jury BUT

TODO

### Niveau de compétence d'un formsemestre

Le formsemestre est lié à un ensemble d'`ApcParcours`.

La liste des niveaux (`ApcNiveau`) associés aux UEs:

```py
[ ue.niveau_competence 
  for ue in formsemestre.query_ues() if ue.niveau_competence ]
```

### Inscription d'un étudiant aux ModuleImpls

L'inscription reste libre (chaque individu peut être inscrit à un sous-ensemble
quelconque des `ModuleImpl` du `FormSemestre`), mais il sera commode de pouvoir:

- Créer des groupes de parcours (via `edit_partition_form`)

- Inscrire les étudiants d'un groupe à tous les modimpls du parcours:
Les modimpls d'un parcours sont donnés par la méthode `modimpls_parcours` de
`FormSemestre`.

### Comment ScoDoc détermine-t-il les modules d'un parcours ?

Un parcours étant associé à des compétences, et les niveaux compétences à des
UE, on peut déterminer, pour un semestre de rang donné, l'ensemble des UEs
associées à un parcours.

Par ailleurs, chaque niveau de compétence est associé à un ensemble d'AC
(`ApcAppCritique`), et chaque module est aussi associé à son ensemble d'AC.

Pour chaque parcours d'un `FormSemestre`, on déterminera l'ensemble des `ModuleImpl`
de ce semestre ayant des AC communs avec ceux des niveaux de compétences
associés aux UE du semestre (sic). Notons que les niveaux de compétences sont
annuels, mais que les `ModuleImpl` sont semestriels.

### Vérifier que les ModuleImpls d'un parcours couvrent l'ensemble de ses ACs

Vérification utile en fin de formation.

#### En fin de formation, pour un étudiant

Soit un étudiant inscrit à un parcours. En fin de formation (S6), on peut
facilement vérifier que les AC ont été couverts:

- Lister les `ModuleImpl` auxquels l'étudiant a été inscrit dans ses semestres
 (S1 à S6);
- En déduire l'ensemble des AC évalués pour cet étudiant (indépendamment de sa
 réussite);
- Comparer aux AC du parcours tels que décrits dans le référentiel de compétence.

#### Au moment de la définition d'une formation

Le parcours du ref. de compétence indique un ensemble d'AC pour chaque niveau
(année). On pourra vérifier que les `Module`s de chaque année suffisent à
couvrir le parcours. Mais si les `Module`s ne sont pas associés à un parcours,
on ne peut pas aller plus loin.

### Lister les UEs d'un parcours d'une formation

```py
# Soit un parcours:
parcour = formation.referentiel_competence.parcours.filter_by(code="ROM").first()
# Listes UEs de ce parcours:
formation.query_ues_parcour(parcour)
# Liste des UEs du semestre 3:
formation.query_ues_parcour(parcour).filter_by(semestre_idx=2)
```

### Lister les regroupements d'UE d'un étudiant (RCUE)

Pour une année donnée: l'étudiant est inscrit dans ScoDoc soit dans le semestre
impair, soit pair, soit les deux (il est rare mais pas impossible d'avoir une
inscription seulement en semestre pair, par exemple suite à un transfert ou un
arrêt temporaire du cursus).

 1. Déterminer l'*autre* semestre: semestre précédent ou suivant de la même
    année, formation compatible (même référentiel de compétence) dans lequel
    l'étudiant est inscrit.
  
 2. Construire les couples d'UE (regroupements cohérents): apparier les UE qui
    ont le même `ApcParcoursNiveauCompetence`.

Un `RegroupementCoherentUE` est simplement un couple d'UE du même niveau dans le
cursus (BUT1, BUT2 ou BUT3).

### Déterminer si un étudiant peut passer dans l'année suivante

Note: on peut bien sûr toujours forcer le passage, pour traiter les cas
particuliers (décision de jury manuelle).

**Rappel:** le passage est de droit si

- [x] plus de la moitié des niveaux de compétences de l'année sont validés
- [x] aucun regroupement d'UE (niveau de compétence) de l'année < 8 /20
- [x] pour le passage en S5, avoir validé toutes les UE du BUT 1 (S1 et S2).

Il faut donc:

 1. Construire les regroupements d'UE et calculer la moyenne des moyennes d'UE
    (a priori de même poids, cela n'est pas spécifié dans les textes).

 2. Vérifier les conditions ci-dessus.

 3. Pour le passage en S5, construire l'ensemble des semestres de formations
    relevant du même référentiel de compétences dans lesquels a été inscrit
    l'étudiant, et vérifier que les UE de S1 et S2 sont validées.

## Enregistrement des validations de compétences

### Rappel: validations en formations classiques

Pour toutes les formations, ScoDoc enregistre les validations de semestres et
d'UE, via la classe `ScolarFormSemestreValidation`, dont les instances stockent:

- `etudid, formsemestre_id, code, event_date`

et pour les validations de semestres:

- `assidu, compense_formsemestre_id`

ou pour les validations d'UE

- `ue_id, is_external`

Les codes sont définis dans `sco_codes_parcours.py`, avec les valeurs: `ADC,
ADJ, ADM, AJ, ATB, ATJ, ATT, CMP, DEF, NAR, RAT` (voir [Gestion des Jurys
DUT](GestionJury.md)).

### Validation des niveaux de compétences

Pour le BUT, il faut enregistrer la validation des *niveaux de compétences*,
constitués de *regroupements cohérents d'UE* ("RCUE"), qui sont les UEs de la
même année de parcours associées à la même compétence.

On va stocker les validation des RCUE dans `ApcValidationRCUE`:

- `etudid`
- `formsemestre_id` (dernier déclenchant cette validation).
- `ue_1`, `ue_2` : les deux UE associées à ce niveau.
- `ApcParcours` : optionnel, le parcours dans lequel se trouve la compétence.
- `datetime` de la validation.
- `code` de validation: `ADM`, `CMP`, `AJ`.

Rappel: chaque UE est associé à un niveau de compétence
(`ue.niveau_competence`), qui doit ici être le même.

### Validation des années du BUT

Pour le BUT, ScoDoc enregistre les validations d'années `ApcValidationAnnee`

- `etudid`
- `ordre`: 1, 2, 3 pour BUT1, BUT2, BUT3.
- `formsemestre_id` (dernier déclenchant cette validation, None si extérieure)
- `annee_scolaire` (int, année de début, eg 2021 pour "2021-2022")
- `datetime` de la validation.
- `code` de validation: `PASD`, `PAS1NCI`, `RED`, `REO`, `DEM`, `EXC`, `ABAN`, `ABL`.

### Codes préconisés par l'AMUE pour le BUT

On associe lors du jury un code de décision:

- À chaque UE: `VAL`, `COMP`, `AJ`, `UESBL`.
- À chaque niveau de compétence (RCUE): `VAL`, `AJ`, `CODJ`.
- À chaque année: 

  - `PASD`: Passage en Année Supérieure de Droit (+ de 50% des UE VAL et RCUE Ajourné(s) >=8)
  - `PAS1NCI`: Passage en Année Supérieure avec au moins 1 Niveau de Compétence Insuffisant (RCUE<8)
  - `RED`: Redoublement de l'année
  - `REO`: REOrientation - décision automatique (revient à une exclusion), plus de 4 semestres RED ou décision de Jury 
  - `DEM`: DEMission (lettre de l'étudiant). 
  - `EXC`: EXClusion, décision réservée à des décisions disciplinaires
  - `ABAN`: ABANdon constaté (sans lettre de démission)
  - `ABL`: Année BLanchie
- Au diplôme: `ADM`

#### Correspondance avec les codes de ScoDoc

ScoDoc utilise des codes [documentés ici](GestionJury.md).

- Pour les semestres: `ADM`, `ADC`, `ADJ`, `ATT`, `ATB`, `ATJ`, `AJ`, `NAR`. En
BUT, pas besoin de codes semestriels. On ajoutera un code `JSD` (*Jury Sans
Décision*) pour simplement indiquer que le jury s'est tenu. Ce code ne sera pas
exporté vers Apogée.

- Pour les UEs: **codes d'état d'UE**

ScoDoc    | BUT AMUE | &nbsp;
----------|-----|-----
ADM       | VAL | UE validée automatiquement |
CMP       | COMP| UE validée par compensation|
AJ        | AJ  | UE ajournée (échec) |
 | UESBL | blanchissement (non dispo en ScoDoc 9) |

- Pour les RCUE:

 ScoDoc    | BUT AMUE | &nbsp;
----------|-----|-----
ADM       | VAL | validée automatiquement |
CMP       | CODJ| Niveau validée par "compensation" ???|
AJ        | AJ  | RCUE ajournée (échec) |

Rappel: les codes exportés vers Apogée sont configurables (table de transcodage dans la
config générale).

## Diagramme de classes

(dessin réalisé automatiquement en Mermaid; toutes les classes ScoDoc ne
figurent pas ici).

```mermaid
erDiagram
  FormSemestre ||--|{ ModuleImpl : contient
  ModuleImpl ||--o{ Evaluation : contient
  Module ||--o{ ModuleImpl : ""
  Formation ||--o{ UE : ""
  UE ||--|{ Module : ""

  Formation {
    str titre
    str acronym
    str code
  }
  
  ApcReferentielCompetences ||--|{ Formation : ""

  Etudiant {
    str nom
  }

  FormSemestre {
    int dept_id
    str titre
    date date_debut
    date date_fin
  }

  Etudiant }|..|{ ModuleImpl : ModuleImplInscription
  Etudiant }|..|{ FormSemestre : FormSemestreInscription
  FormSemestreInscription ||..o{ ApcParcours : "optionnel"

  Formation ||--o{ FormSemestre : ""

  ApcReferentielCompetences ||--o{ ApcCompetence : ""
  ApcCompetence ||--o{ ApcNiveau : ""
  ApcCompetence ||--o{ ApcSituationPro : ""
  ApcCompetence ||--o{ ApcComposanteEssentielle : ""
  ApcNiveau ||..o{ UE : ""
  ApcNiveau ||--o{ ApcAppCritique : ""
  ApcAppCritique }o..o{ Module : "optionnel"

  ApcReferentielCompetences ||--o{ ApcParcours : ""
  ApcParcours ||--o{ ApcAnneeParcours : ""

  ApcAnneeParcours {
    int ordre "année BUT"
  }

  ApcCompetence }o--o{ ApcAnneeParcours : "ApcParcoursNiveauCompetence (1,2,3)"

  Module }o--o{ ApcParcours : "parcours_modules"
  FormSemestre }o--o{ ApcParcours : "parcours_formsemestre"
  UE }o--o{ ApcParcours : "avec en option ECTS"
```

!!! note "Voir aussi"

    - [Informations pour les développeurs](GuideDeveloppeurs.md)
    - [API ScoDoc 9](ScoDoc9API.md)
    - [Le Bachelor Universitaire de Technologie (BUT)](BUT.md)
    - [Contacts](Contact.md)
