---
# System prepended metadata

title: Notes Moana Dev

---

# Notes Moana Dev


Déplacé ici : https://pad.incubateur.net/cHKvNMeTR3WnfLf_2Jhdjw






























## A faire sur le sprint 70
- Toulon  - Sarah
- Anomalies - Sylvain
- Tracking - Charline
- bug email - Charline
- Metabase embeded - Sarah
- Douanes - Sylvain

## TODO config des alertes

- Logs 
- SSI XSS
- Cacher la modif de l'email
- Faire un ticket pour la restriction des compagnies
- Faire un ticket pour les TODO qu'on n'aura pas traités

## Page configuration des alertes

- Un utilateur peut accéder à la page mais sans les boutons de modification.


- Un utilisateur référent est la personne qui est autoriser à modifier les alertes.

- Permission dans le backoffice : L'administrateur des habilitations doit pouvoir autoriser un utilisateur référent à modifier à la page gestion des alertes.

- L'utilisateur référent peut désactiver/activer la notification par l'email et modifier l'email
- L'utilisateur référent peut ajouter/import la liste des IMO

- L'utilisateur référent peut supprimer les IMO individuelement.

- Pouvoir rechercher un IMO dans le tableau : recherche/filtre front-end.

- Avoir une pagination front pour les IMOs

- Consulter la liste des pavillion
- Ajouter le nom du pays dans le tableau des pavillions

- Éviter que les utilisateurs des compagnies maritimes puissent voir la page des alertes.

- Quand on modifie l'email de norification, on envoie d'une

- Pas de Sanity check de la liste de l'IMO : Numérique de 7 chars.

- SSI : XSS sur les formulaires


***


- [x] Front non-référent menu + en-tête - C
- [ ] Front non référent list IMOs - C
- [ ] Front non-référent pavillon - C


- [x] API current user + champ is_team_manager - S // C (si besoin)
- [ ] Permissions référent cokpit -S
- [ ] Ajout bandeaux affichés dynamiquement si reférent ou pas - C


- [ ] API modif email : si l'email est vide, c'est une désactivation - S
- [ ] Front modif e-mail - C
- [ ] Branchement API - C // S (si besoin)


- [ ] API suppression IMO - C
- [ ] API ajout IMO avec le parsing du champ list d'imo - S
- [ ] Front modif IMO - C
- [ ] Branchement API - C // S (si besoin)





## Mise en prod 12 aout

- [x] Met à jour prod 
- [x] Changer les variables d'env
- [x] Relance container
- [x] Partage VaulWarden
- [x] Mettre à jour les SIPs vigie sip 
- [x] Attendre lancement import de la pool 3
- [x] Remettre les utilisateurs dans la bonne tz
- [x] Audrey communique avec eux

## Gestion des droits / permissions / habilitations

On pourrait qui ne change pas trop ce que nous avons déjà :

### 1. Les équipes

On continue d'utiliser l'admin des équipes pour configurer les accès liés aux fonctionnalités de l'app Moana. Les sujets métier.

Il y a déjà des permissions existantes, avec des cases à cocher :
- Accès au téléchargements ROC/FPR
- Autoriser la connexion par email
- Accès à la page liste des bus scolaire
- [nouveau] Les notifications par mail ? Si on veut l'ajouter en champs oui / non en plus de l'adresse mail.


On pourrait déplacer :
- Accès à la page upload des voyages scolaire qui est actuellement géré ailleurs, avec les permissions Django au niveau utilisateur. Là, il y a du code à modifier.
- (Charline) : De la même façon un accès à la page de suivi des navires de Moana, pour ne pas que les compagnies y accèdent. [À faire plus tard]


Dans le futur, on pourra rajouter d'autres choses quand le besoin sera là, avec de nouvelles cases à cocher :

- Accès à la fonction d'import manuel
- Affichage de la liste des navires sensibles
- Accès à la fonction "Signalement d'un mouvement non présent"
- Affichage de la barre de recherche & bouton "Rechercher"
- Affichage des filtres de recherche
- Affichage de la recherche d'un mouvement par date
- Accès à la recherche par date pour les mouvements en cours & futurs
- Accès à la recherche par date pour les mouvements passés
- Accès aux mouvements "En cours"
- Visualiser le bouton de téléchargement des listes de "Passagers"
- Visualiser le bouton de téléchargement des listes "Équipage"
- Accès à la fonction de traitement des listes "Passagers" (FPR)
- Accès à la fonction de traitement des listes "Passagers" (ROC)
- Accès à la fonction de traitement de listes "Équipage" (FPR)
- Accès à la fonction de traitement de listes "Équipage" (ROC)
- Accès aux informations détaillés des mouvements
- Affichage du lien de redirection vers Marine Traffic d'un mouvement
- Affichage du lien de redirection vers Vessel Finder d'un mouvement
- Accès à la fonction de signalement d'un mouvement

Remarque :
On n'a pas vraiment de notion de groupe CF, Ciblage, Compagnies. Mais on pourrait avoir une organisation de l'interface d'admin, qui facilite la config des accès.


### 2. Organisation de l'admin

Dans la section équipe, on pourrait réoganiser l'admin pour facilité la config des accès. Les cases à cocher restent, mais on peut les grouper dans des sections commes :

À revoir au moment de code et à discuter avec l'équipe déploiement :
- Permissions de base
- Permissions spécifiques CF
- Permissions spécifiques Ciblage
- Permissions spécifiques Compagnie


### 3. Gestion des permissions de l'admin

Les utilisateurs, en plus d'être associé à une équipe "métier" peuvent être associés à un "groupe d'accès". Le groupe d'accès existe déjà actuellement. Les utilisateurs qui ne sont pas de l'équipe Moana, ne sont pas réellement concernés par la notion de groupe d'accès, puisqu'on gère les permissions métier via les équipes métier. Si besoin, on pourra tout de même avoir explicitement un groupe avec aucun accès.

Côté équipe Moana, on utilise la solution standard de Django pour donner accès aux différentes sections de l'admin.

On aura les groupes d'accès suivants :

- Moana Tech
- Moana Non Tech
- Moana Lecture Seule
- Aucun Accès Admin (?) => NON voir plus bas gestion utilisateur
- Téléchargement liste autorisé


Comportement par défaut : 
- Aucun accès admin 
- Téléchargement possible des listes

#### 4. Gestion de l'utilisateur. Permission d'accès à l'admin

- is_active : permet d'activer l'utilisateur. L'équipe déploiement peut utiliser ce champ pour désactiver un compte.
- is_staff : réservé à toutes personne qui peut accéder à l'admin.
- is_superuser : pas utilisé pour le moment




Charline : 
- Utilisateur Moana Aucun accès admin :  ça serait comme un utilisateur "démo" ou "andv" ça peut être utile. => VU
- Permissions spécifiques : il faut qu'on puisse les additionner, car certaines équipes sont CF + Ciblage. => OK
- L'équipe "Non Tech" de Moana : elle ne peut pas télécharger de liste, mais il faudrait quand même trouver un moyen pour activer "facilement" le téléchargement si besoin d'aider un utilisateur, ou de faire une démo de l'app => OK
- Juste pour être sûre l'idée c'est de garder la gestion des permissions au niveau de l'équipe mais d'utiliser la façon de faire "native" avec les permissions django ? Et ces permissions pourraient-être "surchagées" / "modifiées" au niveau de l'utilisateur ? => Non l'inverse ! 


### Problèmes

- Comment empécher les téléchargement de liste pour les personnes de l'équipe Moana - Tous les utilisateurs hors CF/Ciblage.
- Il faut éviter qu'un utilisateur qui a accès à l'admin puisse se donner les permissions de téléchargement de liste. Actuelemnt, le problème c'est que quand on accès à l'admin utilisteur, on peut se donner ces droits.
- Il faut pouvoir, au besoin, permettre à une personne de l'équipe Moana de télécharger les listes pour des investigation.


### Habilitation interne
Solution : Ajouter un section admin/modèle avec pour chaque utilisateur 
- une case à cocher "téléchargement liste O/N". Par défault elle est à "oui".
- Un case à cocher "autoriser l'import manuel des FAL". PAr défault elle est à "non". Il faudra rajouter ce champ dans l'endpoint de "current user" pour l'afichage front.
- Associer un utilisateur à un groupe d'admin [à déplacer]
- Case à cocher is_staff et is_superuser [à déplacer]


### Organisation générale

- utilisateurs << modifiable par non-tech
- équipe utilisateurs / métier << modifiable par non tech
- groupe d'administration / accès / interne / backoffice << les tech crée les groupes et les associations peuvent être faites par les non tech.
- habilitations concernant les données / Accès et altération données << réservé aux personnes qui gère l'habilitation




## Mises en prod pendant JOP

Contexte : 
- On ne doit pas faire de mises en prod pendant le JOP sauf si c'est un correctif
- On souhaite éviter d'avoir un tag "fourre-tout" avec tout notre travail du sprint, car pas possible de rool-back et on a une grosse features des habilitations

Process tech : 
- on merge toutes nos PRs dans main de façon "classique" sans faire le déploiement, on peut quand même créer les tags.
- si on a un fix à faire on passe par le process "hotfix"
- ensuite on rapatrie le correctif dans main (de la façon qu'on veut)

Process Hotfix : 
- on créer une branche à partir du tag qui est en prod "hotfixes/xxxx"
- une fois le correctif testé sur une app review 
- on écrase notre branche prod par cette branche "hotfixes/xxxx"

Lundi 12 aout : 
- On copie main dans prod

______

Process : 
- Pas de changement on prépare toutes les PR comme d'habitude à partir de la branche main
- On mettra tout en ligne le lundi 12 août, en séparant les mises en prod pour avoir des tags distincts
- On liste ici le plan de mise en prod des PRs pour le lundi

Exception! :  
- On finalise la branche sur les emails
- Une fois cette branche finalisée on part de cette branche pour créer la branche sur les habilitations qui va sans doute impacter beaucoup de code. 
- Au moment de la mis en prod on mergera dans l'ordre la branche emails puis la branche habilitation



### Ordre de mise en prod pour le lundi 12 août : 

Ici on note à chaque fois, si la version est majeure ou mineure et les PR associées
______


### Problème avec les scripts imports SIP qui prennent trop longtemps à s'exécuter

Dans l'admin, on configure des URLs d'api associées à un port. L'API contient les information des mouvements de navire qu'on importe pour mettre à jour notre DB.

Le problème de lenteur vient du fait qu'on peut avoir ~ 10 ports avec 10 URLs d'API à importer. C'est le cas Vigisip. En théorie, on peut imaginer qu'il y ait encore plus de ports configurés. L'implémentation actuelle ne peut pas passer à l'échelle.

L'implémentation actuelle :

```
For sip_url in SipVigiesip.objects.all():
    import(sip_url)
```

On pourrait changer cette implémentation :

- On prend en priorité les ports avec les dates de fin d'import les plus anciennes.
- On marque une date de début, puis une date de fin quand le script se termine correctement.
- Si le script se termine bien, on aura une date de fin récente, donc à la prochaine exécution, ce port-là ne sera pas prioritaire.
- Si le script ne termine pas l'import pour le port, sa date de fin restera plus ancienne, et ce port-là sera priorisé à la prochaine exécution.


```
For sip_url in SipVigiesip.objects.all().order_by("import_end_date")[:3]:
    - Mark import_start_date
    - import(sip_url) : XXX
    - Mark import_end_date
    - Mark import_success Y/N ?
```


Les Plus :
- On garde notre cron/schuduleur actuel chez Scalingo.

Les moins :
- On rajoute des champs date dans la db.
- Le script va tout de même régulièrement se terminer en erreur. Pour limiter cela, on pourrait décider de traiter les ports par lot de 3 par exemple.


#### Implémentation group d'exécution pour réduire les timemout cron job import sip

1. Ajouter le champ groupe d'execution
2. Dans le script d'import ajouter un paramettre pour prendre en compte le goupe d'execution
    - Par défaut on exécute tous les ports.
    - Si un groupe ou une liste de groupe est défini, on exécute chaque groupe.
3. Ajouter une date de fin et une date de début d'exécution.
4. Prendre en compte la date de fin dans le script. À chaque exécution : 
    - On récupère le port qui ont les dates de fin les plus anciennes.
    - On exécute tous les autre ports qui sont dans le groupe.
    - On met à jour les date de fin.
    - On s'arrête quand l'import groupe est terminé ou quand le script s'interromp après 10min.


### Possible ticket à qualifier

- Les TODO de school trips
- 

## Tests unitaire et recette

Avant de démarrer le dev d'une fonctionnalité
- On fait une kickoff pour parler des détail d'implémentation.
- On met dans le ticket le plan test de recette - modèle à définir.

Avant de mettre en prod : 
- On fait un point de validation des tests pour la mise en prod.
- S'il y a des bugs mais non bloquant on crée les tickets.


## Docker

> Faciliter l'installation de l'app en local

- [x] db => pas besoin car sqlite
- [ ] backend
- [ ] pipenv maintient des versions des packages
- [ ] dossier partagé entre docker et notre machine "hot reload"
- [ ] frontend
- [ ] doc readme pour l'installation du projet


## 7 mai - Delay

Objectif : 
- regrouper à un même endroit tous les champs / outils utilisés pour le calcul des listes en retard
-> PersonList
-> Ship
-> Log

App delay : 
- avoir les champs qui s'occupent des delay

list_delay

    ship.crew_list_delay_type
    ship.person_list_delay_type
    ship.travel_duration
    ship.list_expected_time
    passenger.delay_type
    crew.delay_type

***

delay type choices : 24h / after-arival / no-delay
references : listes des areas codes proche FR-Metro
travel duration choices : short / long 


***

travel_duration
    WithTravelDuration.travel_duration
    Option A: ship.day_minus_one_duration : relevant_time - 24h
    references : listes des areas codes proche FR-Metro
    travel duration choices : short / long

list_delay
    ship.crew_list_delay_type
    ship.person_list_delay_type

    Option B: ship.list_expected_time : relevant_time - 24h

***

Todo : 
- PR#1 App Travel_duration
    - [x] field duration short/long
    - [x] field duration in ship data log (pas dans data quality)
    - [x] field list_expected_time / time_at_d_1
    - [x] Tests
- PR#2 
    - [x] Ajoute le calcul delay 24h à la réception de la liste fal5/fal6
    - [x] Tests
- [x] Merge into ship reference
- [x] Migration pour rajouter les champs duration types à la table de référence
- PR#3 
    - [ ] Dans une autre PR Refacto pour tout mettre dans app List_delay



## 7 mai - N8N

Problèmes de Metabase / N8N : 
- ne pas avoir en doublon les anomalies
- ne pas créer d'entrées si l'anomalie est corrigée entre temps
- le trigger ne peut pas être à la création de l'entrée de Metabase


## 2 mai

- Préciser dans la variable que c'est 24h que en france métro
- On s'occupe pas de l'outer mer pour l'instant


1) PR #1 : traversée
- [x] Vérifier que c'est un mouvement FR-Métro
- [x] Flagguer un mouvement quand la traversée est de plus "24h" "court / longue" traversée
- [ ] Tests unitaires

Pour gérr 

2) PR #2 : calcul du délai réception
- [ ] Calculer un champ "estimated_list_reception"
- [ ] Au changement d'infos depuis import SIP ou autre re-calculer le champs etimated_list_reception
- [ ] À la réception de la liste on calcule le retard 
- [ ] Met à jour le champs retard dans les PersonList et le Ship
- [ ] Tests unitaires 

## CSP nonce

> /!\ c'est normal de ne pas voir les valeur de nonce dans la console. POUR DÉBUGGER IL FAUT VÉRIFIER L'EXÉCUTION DU SCRIPT OU DU STYLE DIRECTEMENT.

dossier /backend : 
- Configurer le nonce depuis les settings django : ajouter la génération dans le script et le style
``
CSP_INCLUDE_NONCE_IN = [
    "script-src",
    "style-src",
]
``
Le mettre avant les csp.
- Pour tous les template il ne faut plus utiliser de style inline. Deux options :(a) créer des balises style auxquelles on ajoute les csp. (b) créer un fichier de style que l'on charge via balise html "classique"

``` nonce="{{request.csp_nonce}}" ```

dossier /frontend :
- On peut ajouter la ligne directement depuis vue si-besoin
- CSP bloqe le plugin de legacy

## 8 avril

Test unitaires fail : 
- [x] Trouver si on met les fichiers à la racine ou des faux ?


Filtre france metro :

- [x] Modifier mention téléchargeable
- [x] Ajouter filtre backend au changement => en parler
- [x] Filtre front-end
- [x] Effacer filtre front-end
- [x] Filtre affiché à l'ouverture dropdown
- [x] Filtre sélectionné
- [x] Filtre au chargement page
- [x] Log
- [x] Tests unitaires


## TODO School trips app

SchoolTripGroup => SchoolTrip
can_access_upload_page


### Notes de déploiement

- [x] SCHOOL_TRIPS_ENABLED=True
- [x] Créer le groupe d'accès avec "Can access school trips upload page"
- [x] Se confirmer entre nous que la vue téléchargement bus scolaire côté PAF sera bien désactivée.
- [x] Hash style CSP


### Tests charline
- [x] Tester avec un ordi paramétré en anglais
- [x] Tester en-tête CSV supprimée
- [x] Restriction upload

### Tests recette à faire sur l'app review
- Review app: https://moana-staging-pr572.osc-fr1.scalingo.io/
- [ ] Redirections url
- [ ] Connexion par mail
- [ ] Informations sont biens envoyées et enregistrées
- [ ] On a bien les messages d'erreurs d'affichés si les champs sont incorrects
- [ ] Sécurité de l'upload : On ne doit pouvoir uploader que des CSV/fichier Text.

#### Retours victor:
- [x] Redirections url OK
- [x] Connexion par mail OK mail reçu
- [x] Informations sont biens envoyées et enregistrées
- [x] On a bien les messages d'erreurs d'affichés si les champs sont incorrects (OK mais c'est en FR)
- [x] Sécurité de l'upload : On ne doit pouvoir uploader que des CSV/fichier Text. (meme si je nomme un pdf en .csv "bad mime type" stylé)

### Tests Axel
- Review app: https://moana-staging-pr572.osc-fr1.scalingo.io/
- [X] Redirections url
- [X] Connexion par mail
- [X] Informations sont biens envoyées et enregistrées
- [X] On a bien les messages d'erreurs d'affichés si les champs sont incorrects
- [X] Sécurité de l'upload : On ne doit pouvoir uploader que des CSV/fichier Text.

##### Autres points non bloquants : 
- [x] pour le login :
    - [x] "Work email" je mettrais plutot "business email"
    - [x] Uniformiser le Titre de la page de Login et la page d'uploac -> "Data transmission for school trip"
    - [x] Objet du mail de connexion "lien email" est en FR -> passer en ENG "login link to access Moana"
    - [x] Page d'attente après avoir cliqué sur le lien magique est en FR. -> Passer en ENG si possible.
>     Veuillez patienter quelques instants Si vous n'êtes pas redirigé vers la page cliquez ici
>     -> Please wait a few moments. If you are not redirected to the page, click here
- [x] Fichier template
   - [x] Renomer le lien "Download List of travelers csv file template"
    - [x] Le template n'est pas le bon fichier (il faut le csv avec les entêtes et les lignes vides)
    - [x] Renomer le nom du fichier template "List of travelers template"
- [x] bouton "choisir un fichier" et Aucun fichier choisi en FR --> "upload a file" ("no file uploaded) => Système
- [x] info bulle quand on remplit mal les champs :  "veuillez sélectionner un fichier" et toutes les autres infos bulles ... sont en FR (pas très grave mais à noter). Propositions ici :
    - "Please fill this field"
    - "Please select a valide date and time"
    - "Please select a file to upload"
    - "Please check this if you want to continue"
    => C'est système ça Victor t'embête pas ;) ahaha je me fais chier ! merci
- [x] Petit texte à cocher je modifierais un poil
> I certify that all the information refers to an eligible school trip between the United Kingdom and France
In some cases, failure to comply with the requirements is an offence subject to legal proceedings.

- [x] page de Feedback je mettrais pas le terme "processed" qui induit que ça a été traité par la PAF de Dover... je nuancerais "Thank you. Your file has been sent !"

###### Propositions hors scope
- Passer la zone bleue d'informations à droite du formulaire. Permettrait d'éviter la zone vide à droite + de remonter les infos du formulaire en tête. A discuter avec Alice
- Simplification de la zone Bleue : 
    - Who uploads the data ? Ferry compagies operatinf from the port of Dover
    - Where ? -> On peut virer puisqu'on l'a juste au dessus
    - What Data ?  information about the scool trip and List of bus travelers
    - When ? Informations need to be submited at the latest 48h before the school trip
- Ajouter le template à télécharger à l'endroit du bouton d'upload


### Pack 1
- [x] Secure file upload to restric access to users that are allowed
- [x] Sanity check on file upload
- [x] Empty file_content on delete UploadFile - not needed.
- [x] Ajouter le template de la page de succès après l'upload
- [x] redirect unauthenticated users that hit the form page
- [x] @charline : Champ text responsable voyage
- [x] @charline : Check "I certify..."
- [x] Settings to enable shool trips for login and upload urls
- [x] redirect without the ending / will not work properly, for instance: /school-trips/login
- [x] @sylvain: Tracking on file upload
- [x] Home redirect /school-trips/ => /school-trips/upload/
- [x] @sylvain Remove CSV file header


### Pack 2
- [x] Style form
- [x] Gestion des erreurs
- [x] @charline : Champs obligatoire à définir
- [x] @charline : ajouter traduction page Wait.html
- [x] @charline : Trouver un moyen de distinguer les email de connection. On va avoir 2 textes différents.
- [x] Design de la nouevlle page de success redirect upload form
- [x] @charline : Fix issue with date => c'était ok !!
- [x] @charline : input time au click => support partiel pour le composant natif https://caniuse.com/input-datetime
- [x] @charline : Ajouter un bouton de logout 
- [x] @charline : Modifier le fichier template avec entete

### Pack 3
- [ ] Bug quand le fichier CSV ne contient qu'une ligne : ```content = file_bytes.split(b"\n", 1)[1]```
- [ ] Gérer les utilisateurs compagnies quand ils essaient d'accéder à Moana contrôle
- [ ] Add security check against CSV injection
- [ ] Secure file download, restrict to allowed users
- [ ] Secure API endpoint for listing school trips - only allowed users
- [ ] Tracking on file download
- [ ] @charline : Reload page should not 404
- [ ] @charline : Refesh results on time based ?
- [ ] @charline : Ajout coordonnées dans la vue tableau des agents

### Pack 4
- [ ] Voir comment ajouter un lien Team<->Permission/Group. On aurait donc 2 groupes : Permission Suivi les bus / Upload listes scolaires.
- [ ] Re-segmenter les templates django base dsfr et school trip pour ne pas utiliser les même header

### Pack 5 Refactoring
- [ ] Move account templates to main templates folder
- [ ] problèm with the fact the the team as to activate the email login
- [ ] (Optional) To ignore authentication in a view uses decorato @login_not_required for FBV or LoginNotRequiredMixin for CBV:
- [ ] use env.bool for settings boolean + Sometime the env file has "BLA=False" but the settings stays true. Check why.
- [ ] Refactoring : Use general purpose file validation instead of ShipFileValidation. 
    - This refactoring can be done may be as part for security update against CSV injection for FPR csv files.

### Pack 6 Améliorations
- [ ] Le bouton send du formulaire s'active une fois que tous les champs sont remplis
- [ ] Ajouter des vérifications sur la date ? Min / max
- [ ] Message d'erreur du fichier à afficher dans l'input
- [ ] Et ajouter le bandeau alert erreur pour dire qu'il y a des erreurs dans le formulaire
- [ ] Changer le style du mail de connexion


### Branches

    features/school-trips
    features/school-trips-csv-file << migrate school_trips zero



### API List 

```
[
    {
        "id": 1,
        "registration_plate": "1234",
        "trip_date": "2024-03-21T16:02:32+01:00",
        "bus_operator": "Test",
        "check_status": "not-processed",
        "file_url": "/path/to/file/1",
        "created": "2024-03-21T16:02:36.410659+01:00",
        "modified": "2024-03-21T16:02:36.410659+01:00"
    },
    {
        "id": 2,
        "registration_plate": "12345",
        "trip_date": null,
        "bus_operator": "",
        "check_status": "processed",
        "file_url": "/path/to/file/2",
        "created": "2024-03-21T16:02:46.568125+01:00",
        "modified": "2024-03-21T16:02:46.568125+01:00"
    }
]
```


## PRs à merger


Mercredi matin
- Liens admin
- SSI chars spéciaux 
    - [x] Correction de tests à faire @charlin
        - Rename add_log_on_name
        - move cleanup xml
    - [x] Validation PR @sylvain
  
Mercredi aprèm
- Refactoring modèle

Jeudi 1 matin
- Charline France métro
- Sylvain France-UK app, model

Jeudi 2
- Charline France-UK


## France - Uk

Ce qu'il faut faire : 

Phase 1
- Créer l'appli django des listes scolaires (BE) @sylvain 
    - Modèle
    - API
- ✅ Intégration front-end static (FE) @charlinelaportebeta 
    - ✅ Tableau front
    - ✅ avec le statut "liste traité" en GET 

Phase 2
- ✅ POST liste traitée (BE) @charline
- Formulaire de transmission ouvert à tous, sans auth (BE). Django template, pas obligé DSF. Sylvain
- Gestion du stokage du fichier uploadé et du CSV à télécharger

Phase 3
- ✅ Les utilisateurs de Douvres sont les seuls à voir le tableau @charline (static)
- ✅ Pour activer le mode "Voyage Scolaire" dans l'admin pour les utilisateur Douvres

Phase 4 
- Authentification spécifique pour les compagnies pour restreindre l'accès à Moana des compagnies.

Phase 5
- ajouter des logs au téléchargement
- ajouter des logs au traitement


Autres TODO pour 

- API : Filter les liste que à partir du jour - pas de liste passées.
- API : Ordre des liste date + plaque immatriculation des bus

## Francis

Hypothèses à confirmer :
- Séparer nos bases loose referency et tables de miroir
- Avoir du pre-processing
- L'organisation des bases de données

Choisir une bonne requête : 
- Un board Metabase problématique (confiance, lenteur)
- Impactant (objectif de comité, ou consulté quotidiennement)
- Qui n'a pas de pré-processing en place, mais sûrement à venir
- Qui n'est pas en cours en code / d'amélioration
- Qui n'est pas "trop grosse" dans sa compléxité 
> Charline : j'ai rajouté le dernier point, car discuté avec Francis ça doit quand même être rapide à débugger / comprendre pour lui dans un premier temps


## Refactoring ShipMovement Models

ShipBaseModel : Les info de bases communes à ShipMovement, CrewList, PassengerList et les ShipData dans les logs.
ShipMovementBaseModel : Pour les Mouvement et les logs. Pas utilisé pour les PersonList.


1. Déplacer ces champs de ShipBaseModel => ShipMovementBaseModel, car ces champs ne concernent pas les CrewList et PassengerList:


    swing_crew_list_id = models.CharField(
        "swing crew list id", max_length=256, blank=True
    )
    swing_passengers_list_id = models.CharField(
        "passengers crew list id", max_length=256, blank=True
    )
    sip_fal5_available = models.BooleanField(
        "Liste équipage disponible dans le SIP",
        default=False,
    )
    sip_fal6_available = models.BooleanField(
        "Liste passagers disponible dans le SIP",
        default=False,
    )



2. Déplacer de ShipMovement => ShipMovementBaseModel, car ces champs concernent aussi les ShipData dans les logs.

    agent_fax = models.CharField("agent fax", max_length=256, blank=True)
    name_of_master = models.CharField("name of master", max_length=256, blank=True)
    registry_location_name = models.CharField(
        "registry location name", max_length=256, blank=True
    )
    registry_location_code = models.CharField(
        "registry location code", max_length=256, blank=True
    )
    brief_particulars_of_voyage = models.CharField(
        "brief particulars of voyage", max_length=256, blank=True
    )

3. Déplacer de ShipMovement => alerts.ship_relation.AlertOnShip, car ces champs ont à voir avec les alertes.
   On peut aussi décider de les déplacer dans ShipMovementBaseModel si on considère que les logs ShipData devraient avoir cette info.

    fal5_counter = models.PositiveSmallIntegerField(
        "Nombre de FAL 5 reçus", null=False, blank=False, default=0
    )
    fal6_counter = models.PositiveSmallIntegerField(
        "Nombre de FAL 6 reçus", null=False, blank=False, default=0
    )


4. Supprimer la duplication du champ gross_tonnage 



Refactor 1

ShipBaseModel
    Abstract

ShipMovementBaseModel(ShipBaseModel)
    Abstract

WithFalCounters()
    fal5_counter
    fal6_counter
    Abstract

ShipMovementReferenceBaseModel(ShipMovementBaseModel, WithFalCounters)

ShipMovement(ShipMovementReferenceBaseModel, ...)
    Concret

logs.ShipData(ShipMovementBaseModel)

data_processing.FalCoverage(ShipMovementBaseModel)

data_processing.ShipMovementReference(ShipMovementReferenceBaseModel)


Plan d'action 1 : SOFT

1. Refactor abstract models
2. Add new ShipMovementReference model
4. Update metabase
4. Identify and remove obsolete fields
5. Add history on ShipMovementReference

Plan d'action 2 :  HARD

1. Refactor abstract models
1.a Add history on ShipMovementReference
3. Identify and remove obsolete fields
4. Add new ShipMovementReference model << Risque de dégradé l'app << Comment gérer historique ??
5. Update Metabase

Plan d'action 3 : COMPROMIS

1. Refactor abstract models
2. Add new ShipMovementReference model
3. Add history on ShipMovementReference
4. Update metabase
5. Identify and remove obsolete fields


**Plan d'action 4 : Du Bonheur**

1. Refactor abstract models
2. Add new ShipMovementReference model
3. ... Leave it until the end of comity ...
5. Metabase V2 
6. Archives V1 => dump DB at a time, is not populated anymore

Plan de passation des DBs :
_De ajd à mai :_
stats.moana : logs, data_processing => DB 1 : Mysql stats
stats-futur.moana : tracking, data_processing => DB 2 : Postgres stats
    postgres stats : TrackingActionLog, ShipData light, ShipMovementReference

_À partir de mai :_
stats-old.moana : logs, data_processing => DB 1 : Mysql stats
stats.moana : tracking, data_processing => DB 2 : Postgres stats

Bonus : 
Decomissionner le addons Mysql de l'app Scalingo moana-prod
Utiliser un nouvel ID shipCallID-Way pour identifier le mouvement et faire la jointure avec la table référence. Cet ID pourra aussi être utilisé dans le code partout où on récupère le ShipMovement avec get(ship_call, way)


#### Petite discussion avec Julien D qui m'indique que :

- On confirme l'utilisation d'un 2nd app scalingo pour les stats :
    - DB stats postgres
    - Cron de data processing
    - Toutes les info de stats sont disponibles et cette app est autonome.
- On confirme l'arch de l'app scalingo du produit :
    - DB postgres de l'app
    - Cron de copie des données
    - Dans leur cas, le tracking est géré en premier sur l'app produit et est copié et annominsée sur l'app stats.
- Il font une réplication des tracking pour avoir des tracking annonimisés dans la base de stats.
- Il ont recours sur Tchap à un S3 intermédiare entre l'app et les stats


## Mise en Prod : 
- Data quality add switch firstname-lastname for unknown value #539
- Add agent name and type of list in data quality logs #538
- Change geographic area #537
=> App review intermédiaire

À tester : 
- Add log when user reports a missing ship #541 TEST OK charline
- Fix S-Wing API response handling #540

À review : 
- Enabled user creation from file import #544

À voir après : 
- Create a ship data referential to facilitate acces from other logs in Metabase #542



# 22 janvier : Plan de refactoring data analysis


### Hosting

Actuellement :
moana-prod
moana-staging
moana-prod-stats
moana-staging-stats


Évolution 1:
moana-prod-data-processing : lance les scripts de data processing, mais cible la DB mysql de moana-prod.
Déploiement auto de la branche data-processing.

Branches
    staging
    prod
    data-processing


Évolution 2:
moana-prod-db-stats # actuellement le rôle de la DB mysql. ça pourrait être une DB postgres.




### Code repo


Option 1 :
backend
    - logs : tracking, anomalies, stats
frontend
data_processing
    - fal coverage
    - person list analysis


Options 2: (Trop compliqué de déplacer logs pour l'instant)
backend
frontend
data_processing
    - logs : tracking, anomalies, stats ?
    - fal coverage
    - person list analysis


### App backend


Option 3 Structure globale : 

- logs 
- data_processing     # C'est l'application commune pour les sujet data analysis.
    |_ mixins
    |_ ...
    |_fal_coverage
        |_ models
            |_ FalCoverage
        |_ managment/commands/
            |_ analyze_fal_coverage
    |_person_list
        |_ models
            |_ PersonList <=
        |_ managment/commands/
            |_ analyze_crew_import_actions
            |_ analyze_crew_checks_actions
            |_ analyze_passenger_import_actions
            |_ analyze_passenger_checks_actions


Option 1
from data_processing.fal_coverage.models import FalCoverageAnalysis
from data_processing.person_list.models import PersonlistAnalysis

SQL : 
fal_coverage_falcoverageanalysis
person_list_personlistanalysis


Option 2
from fal_coverage_analysis.models import FalCoverageAnalysis
from person_list_analysis.models import PersonListAnalysis

SQL : 
fal_coverage_analysis_falcoverageanalysis
person_list_analysis_personlistanalysis


Option 3
from fal_coverage.models import FalCoverage
from person_list_analysis.models import PersonListAnalysis

SQL : 
fal_coverage_falcoverage
person_list_analysis_personlistanalysis


*** 

Les problèmes :

1. Il faut que le code soit bien organisé avec les nouvelles app data processing.
2. Le process de mise en prod pour le data processing doit être plus simple et plus rapide.
4. L'app "logs" fait plusieurs choses :
    - Activité utilisateurs
    - Détection des anomalies de données
    - Activité de l'appli
    - Analyse liste de personnes - qu'on voudrait déplacer.

    Possible split de l'app "logs" :
        Tracking user
        Tracking app
        Data quality
        data processing
            - fal coverage
            - person list


***

À faire : 
- Déplacer le modèle logs.PersonListAnalyze => person.
- Supprimer le script inutilisé "analyze_person_list_checks".
- Déplacer les commands de data_analysis => person_list_analyze.
- Le code en commun entre fal_coverage person_list_analyze devrait être mis dans un mixin commun dans data_analysis.
- Voir s'il faut renomer l'app "data_analysis" en "data_processing" ou "data_engeneering" ou "data_crunching"


## 11 janvier

> 🎯 Redesign des filtres

Toutes les "grandes" étapes qui doivent être faites : 
1) Boutons en haut de page
- [x] enlève actualiser les mouvements
- [x] garde le refresh automatique
- [x] déplace le bouton "liste des navires sensibles"

2) Onglets
- [x] enlever l'ancien fonctionnement au chargement de la page
- [x] Enlever la surcouche de CSS des onglets précédent
- [x] Ajouter les boxes navires dans les onglets
- [x] Ajouter la pagination dans les onglets
- [x] Ajouter une surcouche de code CSS pour les nouveaux onglets (buggy mais pas trop le choix, car border codées bizarrement)
- [x] chaque onglet indique le nombre de mouvements correspondant à la recherche
- [x] Vérifier refresh automatique dans l'onglet historique
- [x] Vérification du cache

3) Pas de mouvement
- [x] Message affiché si pas de mouvement au démarrage même message.
- [x] Message affiché si pas de mouvement à la recherche
=> J'ai mis un message pour les deux, voir avec Alice si ok
=> Plus call to action vers le bouton "signaler"

4) Debug 
- [x] À l'auto reload on perd les mouvements
- [x] Séparateur de date a un fond bleu
- [x] Sticky des dates separator => enlevé

5) Filtres actuels : arrivé et type et recherche
- [x] Déplace barre de recherche
- [x] Ajoute les tags cliquables
- [x] Ajoute les listes déroulantes custom
- [x] Sélection des filtres
- [x] Dé-sélection des filtres
- [x] Afficher les résultats
- [x] Effacer la sélection
- [x] Ajouter le store mutation 'resetNumberOfShips'
- [x] Logs activation des filtres
- [x] Logs efface la sélection
- [x] Style css shadow
- [x] Unit test à corriger
- [x] Nouveaux tests unitaires si filtre vide

6) Debug
- [x] On ne peut plus ouvrir les mouvement ou signaler une erreur
- [x] Vérifier le 'fr-text--bold'

7) Nouveau filtre navires sensibles
- [x] Activation on/off en 1 clic sur le tag
- [x] Filtre fonctionne
- [x] Reset number ships
- [x] Logs
- [x] Vérifier le rouge à prendre
=> J'ai laissé l'ancien modèle de fonctionnement des logs mais possible de le refaire si besoin en groupant en 1 log. Voir avec Etienne

8) Nouveauté filtre par port
- [x] Liste déroulante en front-end
- [x] On récupère les ports de notre équipe
- [x] Ajouter la sélection multiple dans le back-end
- [x] Filtrer en front-end
- [x] Scroll à partir de 5 ports
- [x] Scroll top liste déroulante
- [x] Barre de recherche locale si plus de 6 ports
- [x] Pas de filtre ports si équipe 1 port
- [x] Logs
- [x] Tests unitaires associés

9) Nouveauté filtre par provenance
- [x] Ajouter le paramètre dans le back-end (filtre par pays)
- [x] Tests unitaires associés
- [x] Filtre front-end
- [x] Json local avec les options possible des pays pour les filtres
- [x] Créer un nouveau log
=> Est-ce qu'on reset la barre de recherche quand on ré-ouvre le dropdown ?

10) Débugging
- [x] Pagination : à bouger dans la nouvelle structure
- [x] Reset filter pas à la jour avec la nouvelle structure du store
- [x] Manque couleur hover filtre navire sensible
- [x] Background tabs content
- [x] Ajouter un loader au filtre
- [x] Espacement entre barre de recherche et liste options
- [x] Lorsque cherche nombre de ships pour l'autre onglet, mettre la page à 0
- [x] Message si pas de mouvements

11) Code review
- [x] Voir si y'a un composant multiplechoice sans choices => custom
- [x] Tests unitaires
- [x] Commentaire regex

12) Navire sensible
- [x] Le nombre affiché est le nombre total toute temporalité confondu
=> Questionner Alice car comportement bizarre
- [x] Tests unitaires 

13) Refactoring
- [x] Effacer anciens composants : FiltersAndSearch + FilterAlertsSensitive
- [x] HomeTitle => HomeHeaderContainer ?
- [x] HomeFilters => HomeFiltersContainer 

14) Refactoring 2
- [x] Découper le composant tagItem en 3 sous-composant ?

15) Debugging
- [x] Reset de la pagination au changement de tab

16) Fitre navires sensibles
- [x] Liste déroulante
- [x] Logs
- [x] Nombre visible dans l'onglet

17) Debugging icone
- [x] Couleur tag type navire bleu => normal pas cliquable ! 
- [x] Couleur départ / arrivée icone
- [x] Invalid prop: prop "name" is required. => Je ne le trouve pas

18) Vérification générales
- [ ] Cache
- [ ] Dark mode / light mode
- [ ] Accessibilité
- [ ] Responsive
- [ ] Logs

19) Tests
- [x] Mettre dans le doc de recettage
- [ ] En attente du filtre navire sensible pour doc recettage


## 10 janvier

> 🎯 Mise à jour du référentiel type navire

Étapes :
- [x] Exporter 2 fichiers CSV : ship-types, ship-types-mapping
- [x] Les mettre dans le dossier data
- [x] Renommer le ship-type-mapping en ship-types-mapping-original
- [x] `./manage.py clean_ship_types_mapping_file data/ship-types-mapping-original.csv`
- [x] Un nouveau fichier mapping est généré 
- [x] On vérifie les changements réalisés, présents dans le fichier `ship-types-mapping-cleaned-to-review.txt`
- [x] La liste des doublons effacé est présente dans le fichier `ship-types-mapping-removed.txt`
- [x] On le remplace par celui que l'on avait exporté
- [x] `python manage.py import_ship_types data/ship-types.csv`
- [ ] `python manage.py import_ship_types_mapping data/ship-types-mapping.csv`
- [ ] On efface les doublons du mapping : `./manage.py clean_ship_types_mapping_db`
- [ ] C'est fini !!



## Pour l'homologation

- Faire un revue des fonctionnalité avant le prochain sprint pour être sûr qu'on dev les fonctionnalités qui nous paraissent essentielles pour l'audit.
- Corriger les bugs remontés par David pour le lancement en local de Moana
- Préparer la réu de présentation du code pour voir s'il manque de la doc.
    - Créer les comptes utilisateurs  avec différentes équipes
    - Créer la config dans la whitelist always data de la collecte staging
    - Leur donner des fichiers d'exemple de FAL : 1,5,6,NCA
    - Désativer le déploiement automatique de la branche staging

## refactoring des models de la DB metabase / mysql

### Archi actuelle

logs
    - models logs/tracking
    - models data analysis
    - data quality
data_analysis
    - scripts pour l'analyse

### Archi alternative

stats
    - config pour les stats

tracking
    - action log => action tracking
    - data quality ?

data analysis
    - person analysis


## 2 janv


- Ajouter la table comité date début, date fin. [AnalysisPeriod].
- Ajouter FK AnalysisPeriod sur la table Person Analyze.
- À propos des équique: Option 1 pour l'instant.
    - Option 1 : Garder le sélection par défaut
    - Option 2 : Modifier la table équipe pour y ajouter : Type d'équipe PPF oui/non. Faire une FK sur la table d'analyse personne.
    - Optionn 3: Ajouter une colonne PPF oui/non en "flat" dans la table d'analyse personne.
    - Option 4 : Ne garder que les équipes PPF dans la table d'analyse. Il faudra donc quand même rajouter la colonne PPF oui/non dans la table Team pour que le script d'analyse puisse être informer.
- OBSOLETE Faire une copy/sync de la table équipe dans la DB mysql.
- OBSOLETE Faire une nouvelle table d'analyse des équipe avec les critères comité.
- UsageNotPPF : FK AnalysisPeriod, Equipe, # connection


En questionnement :
- Ajouter une table de Config Suivi de Comité : Equipe, usage constaté, usage cible. [TeamFolowup]


Orga des apps:

logs => logs, tracking, data analysis


stats config
    - comité
    - suivi comité
    - equipe sync



Tracking



## 20 décembre

> 🎯 Ajouter un tracking sur les filtres et la recherche

Le problème c'est qu'il faut créer des logs qui soient compatibles avec notre version actuelle, et la prochaine. 

```
Logs que l'on a déjà : 
- filter alert ship-watchlist on
- filter alert ship-watchlist off
- filter alert ship-country on
- filter alert ship-country off
- edit ship-watchlist
- show comment
```

La norme d'écriture des traces front est la suivante : 
`[verbe d'action] [quoi] [catégorie (optionnel)] [on | off (optionnel)]`


### A. Afficher la liste des navires sensibles

- action : `show list-sensitive-ship`
- quand l'utilisateur clic sur le bouton "Liste des navires sensibles"
- même comportement actuellement et après

### B. Filtres

#### Fonctionnement du front actuellement sur les filtres : 
Le front actuel ne permet pas d'avoir la même logique de code que le front à venir sur les filtres. Nous avons 2 grosses probélamtiques qui demandent d'ajouter des vérifications en plus : 

**1) Des requêtes sont envoyées au back à chaque clic sur une case**
À chaque fois que l'utilisateur clic sur une case ou entre une lettre sur la recherche une requête est envoyée au back-end, il n'y a pas d'action de "valider" la recherche et/ou les filtres complets.
Pour pallier cette problématique l'idée serait de mettre en place un watcher qui attend que les changement des filtres soient fini : 
- au moment du 1er fetch
- on enregistre la requête envoyée au back
- on lance un timer de X secondes
- si un nouveau fetch est envoyé avant la fin du timer, on efface le timer, on enregistre la nouvelle requête, on relance un timer
- etc, etc.
- jusqu'à ce que le timer arrive à la fin sans nouvelle requête fetch envoyée
- à ce moment alors on enregistre la trace de la dernière requête envoyée au back

**2) Quand un filtre est non actif c'est qu'il a toutes ses cases de cocher**
Une autre problématique, c'est qu'il n'y a pas de bouton pour "effacer" les filtres. Pour chacun d'entre eux il va aussi falloir vérifier si toutes les valeurs ne sont pas "cochées". Sauf pour les ports où il y a un champs "all" dans la liste déroulante.

#### Fonctionnement du front avec les nouveaux filtres : 
Il n'y aura plus besoin d'avoir de timer pour les filtres, car pour chacun d'entre eux nous aurons un bouton de confirmation : "afficher les résultats". Pareil pour les traces de désactivation du log, on aurons un bouton "effacer le filtres".

Le fontionnement pour tous les filtres sera alors le suivant : 
- au clic sur "afficher ..." : on enregistre une trace "filtre xxx on"
- au clic sur "effacer" : on enregistre une trace "filtre xxx off"

#### Traces à enregistrer : 

##### Filtre par port
- ation ON : `filter port-of-call on`
- ation OFF : action : `filter port-of-call off`
- target : nombre de ports sélectionnés dans le filtre
- data : liste des locodes des ports

##### Filtre par direction
- action ON : `filter way arrival on`
- action ON : `filter way departure on`
- action OFF : `filter way off`

##### Filtre par type
- action ON : `filter ship-type cargo on`
- action ON : `filter ship-type ferry on`
- action ON : `filter ship-type cruise on`
- action ON : `filter ship-type other on`
- action OFF : `filter ship-type off` 

Questions : 
- Est-ce qu'il faut faire une variante pour chaque type en "off" ou un commun omme au dessus c'est bon ?
- Est-ce qu'on regroupe toutes les traces sur un même log type `filter ship-type on` et on met la valeur du filtre dans la data ? Comme pour le filtre par port.


### C. Filtre par timeline

Aujourd'hui les mouvements en cours et l'historique étant des onglets on peut les tracer différemment : 

`filter timeline past on`
- ACTUEL : quand il clic sur l'onglet historique des mouvements
- APRÈS : comme un filtre
 
`filter timeline recent on`
- ACTUEL : quand il clic sur l'onglet historique des mouvements
- APRÈS : comme un filtre

Remarques : 
- /!\ Pas de log quand on arrive ou quand onrecharge la page
- Je garde un log pour le filtre sur timeline recent car ça sera automatique dans le code
- Nous ne pourrons jamais avoir de log `filter timeline off` (logique !)

### D. Recherche 

À chaque changement dans la barre de recherche une requête est envoyée au back. Pour ne pas avoir "l'historique" des lettres tapées et avoir uniquement le mot final. Nous pouvons enregistrer la trace soit : 
- au "focus out" de la barre de recherche
- au bout de X secondes d'inactivité dans la barre de recherche.

Les traces seront construites comme pour les filtres : 
- ation : `filter research on`
- data : le ou les mots qui ont été cherchés

Remarques : 
- on utilise le verbe d'action `filter` non `search` car la recherche est considérée comme un filtre


## 29 novembre

> 🎯 Mise à jour des packages front et back

- [ ] Front-end utiliser la commander de création vue-dsfr, finalement j'ai préférer faire la migration manuelle et en plus pour ne pas dépendre de leur package.
- [ ] Django migration
    - [ ] Il faudra tester que les horaires respecte bien les timezone. Il y a un changemet dans la gestion des timezone.
    - [ ] Il faudra vérifier que les import SIP se passe bien.
    - [ ] Pour Django 5, je pense qu'on va devoir attendre. Il y a une incompatibilité avec django-celery-beat. https://github.com/celery/django-celery-beat/issues/698
- [ ] Metabase

**✅ Principale todo de la migration :** 
- [x] Suivre le guide de migration vue-cli vers Vite : https://vueschool.io/articles/vuejs-tutorials/how-to-migrate-from-vue-cli-to-vite/
- [x] Trouver un package pour la compatibilité Firefox 52 : [@vitejs/plugin-legacy](https://github.com/vitejs/vite/tree/main/packages/plugin-legacy)
- [x] Migrer Yarn 1 vers 4 : https://yarnpkg.com/migration/guide
- [x] Ajout du proxy de l'api
- [x] Enlever le vue config
- [x] Changer les require(assets) et les mettre dans static
- [x] Mise à jour vite dernière version
- [x] Créer une app review
- [x] Le dossier .yanrc doit-il être versionné ou non ? 
- [x] Tester build old browser à partir de l'app review
- [x] Trouver le bon CSP_Script policy pour faire fonctionner le legacy code `* 'unsafe-inline' 'unsafe-eval'`
- [x] Est-ce qu'on a besoin de cette config `"start": "vite --port $PORT"` & `host: "0.0.0.0",` => NON
- [x] Passage à Yarn 3 pour garder upgrade-interactive ?
- [x] Upgrade les packages à leur dernière version
- [x] Date écrite en anglais
- [x] Figer les versions des packages "importants" => tous sont en `^`
- [x] Vérifier la config prettier
- [x] Enlever la config du linter `"vue/no-mutating-props": "off"`
- [x] Changer les recommandations d'extensions avec Vue => Enlève Vetur on et Volar à la place
- [x] Prettier ne fonctionne pas sur Sass que faire ?? Si on enlève Sass, enlever l'extension associée => Passage à Scss
- [x] Mise à jour du ReadMe
- [x] Utilisation des sass module pourle styling vue: pas nécessaire le BEM fonctionne bien pour nous.
- [x] Version engine.yarn n'a pas l'air de fonctionné dans le déploiement scalingo ` !     You don't need to specify Yarn engine. Scalingo will install the latest Yarn 1.x, so that per project version can be used. More information here: https://yarnpkg.com/getting-started/install#global-install http://doc.scalingo.com/languages/javascript/nodejs`
- [x] Fix vue escale
- [x] Fix date time séparationv irgule s'il n'y a pas de jour : bug créé en local en front pas de fixe nécessaire
- [x] Vérifier et corriger les erreurs du linter Vue

**🏗️ Sous-branches à merger :**
- [x] (PR 1) `features/migrate-vite-prettify` : Lancer un prettier 
- [x] (PR 3) `features/migrate-vite-legacy` : Éviter une modification des hashs dans un changement de version mineur du plugin https://www.npmjs.com/package/@vitejs/plugin-legacy 

**✅ Moment is deprecated :**
- [x] Voir sil faut trouver une nouvelle lib
- [x] Tester DateTime JS
- [x] => Tester Moment sur Firefox 52

**🆘 Sentry non fonctionnel :**
Problème de CSP sur la prod et le front en staging mais je ne vois pas où les régler. J'ai mis à jour le packet sentry/vue.
- [x] Ajout : `CORS_ALLOW_HEADERS = env("CORS_ALLOW_HEADERS", default=[""])` dans les settings prod et local django. => ne change rien
- [x] Ajout tracePropagationTargets => ne change rien
- [x] Tester erreur sentry sur staging : non fonctionnel
- [x] Tester erreur sentry sur la prod : non fonctionnel
- [ ] => Résoudre la config CSP https://docs.sentry.io/product/security-policy-reporting/
- [ ] Ajouter tracking des composants sur Sentry

**🚀Mise en prod :**
- [ ] env variable : CSP_SCRIPT_SRC = `'self' 'sha256-MS6/3FCg4WjP9gwgaBGwLpRCY6fZBgwmhVCdrPrNf3E=' 'sha256-tQjf8gvb2ROOMapIxFvFAYBeUJ0v1HCbOcSmDNXGtDo=' 'sha256-VA8O2hAdooB288EpSTrGLl7z3QikbWU9wwoebO/QaYk=' 'sha256-+5XkZFazzJo8n0iOP4ti/cLCMUudTf//Mzkb7xNPXIc='`
- [x] AVANT ajoute les env `VITE_`
- [ ] APRÈS enlève les env `VUE_APP_`
- [ ] Rebuild pour vérifier que tout est ok en déploiement manuel


## 27 novembre


- Ticket pas de nationalité ?
- Ticket harmonisation des logs : par ex le champ target.


### Nationalités

Des choses à faire, suite à notre session avec Victor :

- Ajouter le compteur des extra schengen
- Rajouter les compteurs dans les logs
- Pour les nationalités qui ne sont pas dans le référentiel, on créer un log d'anomalie.
- Log d'anomalie pour les nationalités vide  - creer une carte séparée pour ça

## 21 novembre

> 🎯  Ajouter les informations relatives aux documents d’identité présentes dans les FAL5/6 pour nos listes MOANA

Appli back : 
- [x] Ajouter les informations des FALs dans la liste associée (5 ou 6)
- [x] Nettoyage des parsers ? Avec les héritages de classes ? 
- [x] Enlever les caractères spéciaux, probème d'affichage du ROC

Tests: 
- [x] Les logs sont crées si un champs est manquant
- [x] Un log n'est pas crée si le champ optionnel est manquant

Appli front : 
- [x] Rajouter dans la liste des signalements l'erreur correspondante 'Problème sur les documents d'identité'

Logs : 
- [x]  Ajout des logs quand les champs sont manquants : Natureofidentity + Numberofidentity
- [ ] Mettre à jour la doc log qualité de données
- [ ] Créer un board ? 


## Récap réu du 15 nov - Questionnement gestion des secrets, paramètres, etc.

Avec : Richard, David, Charline, Sylvain

Ce dont on a parlé : 

- Gestion des secrets
    - Team Moana envoie la mini doc pour savoir ce qu'on met dans l'admin et ce qu'on met dans le var Scalingo.
- Workflow GIT, branches, process de déploiement
    - Team Moana envoie le process de déploiement
- Présentation du code
- Gestion du Gitlab
- Process et rituels
    - On a évoqué les docs que nous avons sur Resana, sur Notion.
    - On a parlé un peu des rituels et on s'est dit que ça vaudrait une nouvelle discussion si on veut aller plus dans les détails.


## Gestion des secrets

### Variable de configuration

> 💡 Où enregistrer ma variable de configuration ? Dans l'admin Django ? Dans l'admin Scalingo ? Voici les questions à se poser pour trouver le bon emplacement.

#### Différences entre les admin

Avec l'admin Scalingo : 
- on accède à tous les réglages car accès à la DB
- seule l'équipe équipe tech peut y accéder

Avec l'admin Django :
- on accède uniquement aux réglages de l'app
- tous les membres de Moana peuvent y accéder

#### Choisir le bon Admin 

**Ce qu'on met dans dans Scalingo :**
- Clés d'accès aux serveurs
- Les configurations qui changent peu
- Les configurations qui sont associées avec le code
- Les configurations sensibles qui ne doivent pas être altérées par inadvertance ou sans discussion d'équipe

**Ce qu'on met dans l'admin Django :**
- Config qui doit être gérable par l'équipe déploiement
- La config est plus complexe qu'une simple "variable", par exemple un fichier
- Les configurations qui sont spécifiques à des équipes utilisatrices


## Implémentation counteur de nationalité

Quand on importe une liste de personne, dans le "parser", pour chaque personne de la liste, on va faire ceci :
- On prend la nationalité, le code alpha2, par exemple "DE"
- On regarde le tableau de référence des pays, avec le code alpha2
- En fonction du pays, on va incrémenter un des compteurs suivants
    - count france
    - count intra eu
    - count extra eu soumis visa france
    - count extra eu sousmis visa ue


Table de référence :
- alpha_2 # exemple DE => Germany
- nom du pays
- france
- intra eu
- extra eu soumis visa france
- extra eu sousmis visa ue



## Brainstorm atelier point de qualif

- Faire un atelier au forum avec un retour d'expé sur les points de qualif
- L'objectif serait se mettre en contact avec des équipes qui ont de l'intéret pour notre expérience, par exemple par ce que : 
    - Ils ne font pas de réu de qualif
    - Les réu de qualif sont laborieuse
    - Les réu de planifications sont laborieuse
    - Les sujets à mettre en priorité sont trop vagues
    - L'équipe n'est pas assez impliquée


## 6 novembre 2023

Mises en prod avant audit : 
- #1040 Corriger les locodes mal référencés pour l'outre mer
- Rajouter les cron pour l'analyse de données

A discuter : 
- Détail implémentation nationnalité

Charline : 
- Commencer à regarder pour les tests unitaires front
- Écrire à Alice pour le design (en parler en daily avant)

## 26 septembre 2023

> 🎯 Rendre administrable le moyen de connexion par agent : mail / sso

Questions : 
- Est-ce que Cheops est géré par équipes "individuellement" ou pour toutes les équipes "de type PAF" ? (on a pas ce type d'équipe actuellement)
- Faut-il ajouter un message lorsque les utilisateurs sont "ré-authoriser" à se connecter avec l'e-mail ? Ou même pour les nouveaux qui ne comprendront pas pourquoi le bouton n'est pas affiché => Avoir un message dans l'admin
- Est-ce qu'il faut juste "cacher" la connexion par email, ou bien vérifier à chaque connexion si la methode est autorisée pour l'utilisateur en question ? => pas possible car il est pas connecté

Implémentation : 
- On laisse l'utilisateur se connecter (méthode de son choix)
- Une fois connecté on vérifie si la méthode de connexion est bonne
- si oui > redirige vers l'app Vue + log de connexion
- si non > redirige vers le login avec un message type " vous devez vos co avec Cheops"

Vérification : 
- je pensais qu'on aurait pu la faire dans le signals.py mais je n'arrive pas à faire la redirection vers la home en ajoutant un message (je vidais la session)
- si pas possible ici je pensais ajouter une page intermédiaire qui aurait juste géré cette vérif et redirection (comme on a sur Cheops actuellement)


Sylvain:

- Est-ce qu'on va devoir faire une nouvelle étape dans le process de login pour que l'utilisateur commence par mettre son email, puis redirection soir vers l'auth cheops soit vers magicauth ?
- 

## Petit brainstorming à propos des revues de code

- On pourrait documenter un mini process de revue de code
- Documenter le fait qu'on recommende de faire systématiquement un point tech pour discuter des détails d'implémentation.
- On essaye d'avoir un espace de note tech commun
- 


## 25 septembre 2023

> 🎯 Améliorer la détection des caractères spéciaux

- [x] Redéfinir le cleanup et le bad_encoding le format c'est du remplacement, le bad encoding juste de l'analyse
- [x] Garde la liste dans les settings mais documenter le tout dans le Grist (avec un lien vers le repo ?)
- [x] On met dans les settings la string_cleanup_list
- [x] Ajouter le "?" dans les bad encoding ? `Questionnement`
- [x] Dans les logs afficher tout le nom prénom et non pas que le caractère trouvé


## Bug N/A : détail d'implementation


- dans la fonction `format_name` du parser, on va remplacer N/A par "inconnu"
- On a déjà une fonction `check_unknown_values` qui permet d'indiquer dans nos tracking quand le nom comporte une valeur comme "unknown" ou "inconnu"
- On va donc utiliser cette fonction existante pour nous signaler les non inconnus
- Les logs qu'on déclanchera pour les N/A seront donc :
    - Log "name formatting"
    - Log "unknown name" => avant on avait plutôt "empty name"

Du coup, avec cette proposition, on ne met pas XX mais plutôt "inconnu"



## Prios


Mardi
- [x] Agents Maritimes: déploiement
- [x] Bugfixe Agent Maritimes
- [x] Ajout champs texte signalement d'une erreur: Revue + déploiement

Mercredi
- [ ] Pagination: coder le front - à faire en //
    - [ ] Le résultat des ships est mainteant dans data.results et non directement dans le data
    - [ ] Changer le compteur de mouvement qui est maintenant dispo dans l'API
    - [ ] Intégrer le composant pagination de DSFR : https://vue-dsfr.netlify.app/?path=/docs/composants-dsfrpagination--docs

- [ ] Le cas 1970: coder le fix - à faire en //
- [ ] Mouvement non présent: finialisation back-end + rebase à partir PR champs texte + branchement front et back avec la mise en place du post api + revue + déploiement

Jeudi
- Sentry : revue de process
- Process et visibilité des emails non inscrits chéops


## 4 septmebre 2023

> 🎯 Signaler un mouvement non présent

**GET :** 
* [x] Créer le endpoint to GET
* [x] En query params passer le type d'issue que l'on veut
* [x] Récupérer la team depuis l'utilisateur connecté
* [x] Retourner les issues 
* [x] Tableau vide si pas d'issues

**FRONT :** 
* [x] Afficher le nombre d'issues
* [x] Si pas d'issue mettre un zéro
* [x] Si issues mettre le tableau
* [x] Refresh des issues signalées au post d'une nouvelle
* [x] Le champs détails ne s'enregistre pas avec le composant DSFR
* [x] REFACTO : cleanIssueData

**POST :**
* [x] Créer une route API
* [x] Ajouter le type d'issue en dur
* [x] Ajouter le texte
* [x] Ajouter le message de feedback

**Refacto :**
* [x] Déplacer le formulaire pour signaler une erreur

**Matter :**
```
**Signaler un mouvement non présent :**
App review : https://moana-staging-pr423.osc-fr1.scalingo.io/
PR : https://gitlab.mim-libre.fr/andv/demonstrateur-moana/moana/-/merge_requests/423

Pas de gros changements dans le front que j'avais montré avant. J'ai juste simplifié le tableau des signalement en enlevant le champs "type" car ce sont toutes les mêmes.

Ce qu'il faut tester : 
* [ ] Je peux créer un nouveau signalement pour une mouvement non présent
* [ ] Le nouveau signalement s'affiche dans l'admin 
* [ ] Je vois que les signalement de mon équipe
* [ ] Les informations que j'ai renseignées s'affichent bien 

```

## Pagination Septembre 2023


Doc DRF : https://www.django-rest-framework.org/api-guide/pagination/




* * *


## 28 août 2023

> 🎯 Résoudre le bug où le prénom ou le nom a pour valeur "N/A" et crée un bug dans le FPR #984

Questions : 
- Le problème est uniquement pour le FPR ou ROC aussi ? Et faut-il le mettre à vide également pour le ROC ?

Todo : 
- Ajouter les valeurs "N/A" et "n/a" dans la liste `char_cleanup_list` de la fonction `format_name`
- On change l'ordre des fonctions, d'abord formattage puis check empty

```
OLD

Façon A : 
- Détecter la valeur "N/A" ou "n/a" dans les champs noms et prénoms
- La remplacer par une chaîne de caractères vide
- Créer un log ""

Ordre des fonctions de cleanup des listes : 
- log vide : NON
- formattage : on crée des noms ou prénoms vides
- log formatage : OK
=> demander si besoin de plus ? Etienne ? 
- si c'est un problème on fait la vérification du formattage de nom avant celle des champs vides.
```

Tests : 
- Si on a le champs on remplace bien la valeur
- "N/A" ou "n/a"
- Vérifier si c'est aussi le cas pour les annexes

## 10 août 2023 

> 🎯 Réunion DFDS

### Participants:

* Christopher Mabille : analyst & super user (he makes the link between IT and business)
* Mads Guhle : IT team business analyst, 
* Benoit Jones : head of crewing (in charge of fal 5)

### Technical discussion

- Documentation: they don't read the documentation (already sent). 
    - Sending the documentation again(inc Mads Guhle)
- Applications: Seabook (FAL6) and Adonis (FAL5) for Calais / Dieppe. It's gonna be one system that send FAL5/6 (to be confirmed)
- New Haven / Dieppe: 4-5 hours.
- E-mail adress: should it be the same email adress for all users ? Yes it's a unique email adress. DFDS will create a generic e-mail.
- Developpers: it will be Mads Guhle's team. They've already make a similar process for UK. It seems "very simple" for their team, the documentation is good enough to start working. 
- Deadline: is there a deadline ? The sooner the better.
- Calais / Dieppe / Dunkerque: for Dunkerque it will be an other system. The GUMP will solve this problem (multiple systems)
- Postman: 
    - Sending the Postman models
- Test: first a test with Dieppe and then Calais. It should be "very easy" to replicate the system with Calais
- Calais: "They didn't ask us anything"
- Fiche organisation
    - Mme Berthelot va envoyer la fiche organisation pour modification
- Ms Berthelot vacation: 1st - 24th september


### Next steps:

- Resent the "fiche organisation" completed
- Read the documentation
- Chose an e-mail adress
- Create a PISTE account / Wait for escaleport validation
- Test with the POSTMAN environment
- 1h meeting with webconf to test with Ms Berthelot (before Ms Berthelot vacation - to be confirmed by e-mail)


## 9 août 2023 

> 🎯 Metabase board anomalies ship_type est vide

Rappel de ce qu'on veut : 
* connaitre le volume de mouvements n'ayant pas de ship type par mois

C'est quoi un volume :
* le nombre de mouvements avec l'anomalies / nombre de mouvement analysés dans le mois

Bugs à corriger  : 
- [ ] dans la liste des logs remontés on a aussi la liste des actions utiisateurs
- [ ] les mouvements sont doublés car parfois ils n'ont pas le même geographic_area
- [ ] Est-ce qu'on prend les arrivées et départs ou juste arrivée

Points de vigileance : 
* Si une information est fausse mais est corrigée ensuite (par SIP ou nouvel envoi fal), on a toujours le log qui existe alors que l'information n'est pas fausse

## 8 août 2023

> 🎯 Réu Stena Irish


### Participants:

Stena:
- Tali Oliver domain architect, system integrator
- Costi Miriam: product owner Stena

Irish:
- Javier Ganaza irish ferry developer
- Lysiane Bardin business analyst
- Ray Slattery: operation manager

Escaleport:
- Guido collegue of Nathalie Berthelot project manager
- Nathalie Berthelot

Moana:
- Sylvain T:
- Charline L
- Etienne

### Technical

- Stena already has the Swagger link (available in the documentation).
- Stena uses two different systems for FAL5/6 (SLOOP and CREW_SF), but a single application will be developed for sending FALs.
- Irish uses BOOKIT which contains passengers and crew
- Guida and Nathalie will provide:
    - Postman templates: They need to share the collection or share their workspace with us.
        - TODO : link
    - The code snippet for authentication token.
    - A diagram illustrating the request flow.
- Miriam needs clarity on whom to contact in case of technical or transmission issues. - It would be good to reassure her on this matter.

### Questions:
- Is the organization code unique? Yes.
- Whom to contact if there's an issue? E-scaleport and Moana.
- Is it possible to share the Postman template used by Mrs. Berthelot? Yes.
- Is there an interface where we can see if our sendings are correct ? No

### Next steps:
- Companies: Set up a PISTE account (choose a unique email + nom appli) and test on the sandbox environment.
- Nathalie will send the document "Fiche organisation" to Stena and Irish

- POSTMAN how to share environnement : https://learning.postman.com/docs/collaborating-in-postman/sharing/


- Irish/Stena: Define the unique email for account and an app name
- Irish/Stena: Create a PISTE Account
- E-scaleport: Will get automaticcaly an email, once she has the register email she can validate the account
- Irish/Stena: Then you'll have access to api 
- Irish/Stena: Based on the postman template you'll add your personnal information
- Irish/Stena: When you are ready for your test, call Nathalie to organize the test with her via visio
- Irish/Stena: When testing is validated, create the app in e-scaleport prod env
- Irish/Stena/ANDV: When lists will be sended in prod ask the ANDV if they received it


## 4 août 2023

> 🎯 Revue de code SQL Metabase

1. On a tous les deux trouvé ça instructif, on y a passé plus d'un heure.

2. On a regardé le nouveau dashboard pour le suivi des équipes non PPF,

3. Remaruque : Les équipes non PPF sont sélectionnées par les cases à cocher, par défaut dans la config du filtre "team". Donc il faudra bien penser à changer cette sélection lorsque de nouvelles équipes non PPF sont rajoutées.
    - Pour faire évoluer ceci, on pourrait rendre dispo l'information, par exemple PPF/ non PPF ou "type d'équipe": PAF/Douane/Gendarmerie
    - On pourrait aussi envisager de créer une nouvelle table référentielle côté Mysql qui listerait les équipes avec leur type d'équipe.

4. Fait : un snippet a été ajouté avec les e-mails des membres de l'équipe.

5. Fait : Les requêtes ont été simplifiées en retirant les sous-requêtes.

6. Remarque : Depuis la base de données LOGS dans Metabase, nous n'avons pas accès aux tables de référentiels qui sont dans la base de données Postgresql. Dès lors, il est difficile de faire des liens, par exemple pour rechercher les utilisateurs qui sont "staff". Metabase ne permet pas de faire des liens entre 2 bases de données. Ce même problème est rencontré pour obtenir le référentiel équipe, par exemple.
    - Une solution serait de dupliquer les tables référentielles dans la DB Mysql.
    - Une autre solution serait de systématiquement ajouter dans les entrées de logs, les champs sur lesquels on a besoin de filtrer. Par exemple on aurait le champ "is_staff" dans l'entrée de logs. Ou bien le champ "type d'équipe". Un solution pas très élégante.

7. On a regardé un autre board, à propos du gross tonnage dans la table "data quality". Cette information est manquante dans la table des "data quality Ship data". C'est un peu le même problème pour le champ "agent name" et probablement d'autres informations qui ne sont présentes que dans les FAL1. Comment palier à ce manque ?
    - Ce problème rejoint peut-être celui des référentiels.
    - Une solution serait de faire des "requêtes référentiel" depuis la table ShipData qui elle, contient l'information. On a donc un référentiel constitué dynamiquement au moment de l'affichage de la requête finale. On pourrait alors faire le lien entre ce référentiel et la table "data quality ship data". Cette solution n'est certainement pas très performante et il faut bien réfléchir à comment constituer le référentiel dynamique.
    - Une autre solution serait de créer une nouvelle table référentielle que l'application Moana, en backend, serait responsable de maintenir et de mettre à jour régulièrement. Par exemple dans ce cas, on aurait une table avec des ship_call_id et un gross tonnage qui serait associé par l'app Moana. La logique de cette association serait à définir. Avec cette nouvelle table présente dans la DB mysql, il sera plus facile de récupérer l'information du gross tonnage partout où nous en avons besoin.
 
## 2 août 2023

> 🎯 Plan de refactoring front

Mises à jour:
- upgrade yarn
- upgrade dsfr
- maj yarn tracking sentry

Correctifs : 
- ajout serializers manquants
- geographic area vue détail 
- variables d'environnement non utilisée(s)

Nettoyage :
- enlever le référentiel agent maritime qui est maintenant obsolète
- renommer / simplifier / découper certains composants front
- ajouter un store pour gérer l'affichage des modales 

Devops : 
- ajouter une commande shell pour effacer tous les mouvements
- ajouter de la documentation ? (auto)
- ajouter des tests front ? <3 


## 1er août 2023

> 🎯 Plan de refactoring


- Upgrade django
- Packaging pipy de Filesify
- Packaging de Trackman
- app `fpr` deevrait être divisée en fpr + roc
- Migration des settings de scalingo env vers l'admin:
    - Liste des pays pour lesquels on a une alert pavillon
    - ... À définir
- Génération automatique de la doc ?
- Renaming : ```ARRIVING = "arriving"
DEPARTING = "departing" => arrival/departure ?``` 
- Renaming
    - ata_to_port_of_call => ata
    - eta_to_port_of_call => eta
    - atd_from_port_of_call => atd
    - etd_from_port_of_call => etd

## 31 juillet 2023

> 🎯 Utiliser les ATA / ATD au même titre que les ETA/ETD


ShipMovement : 
```
- attrib arrival_time : ata or eta
- attrib departure_time : atd or etd
- attrib relevant_time() : arrival_time or departure_time
- def departure_stopover_time() : if is_arrival and has related_movement: related_movement.relevant_time else : self.relevant_time
- def arrival_stopover_time() : if is_departing and has related_movement: related_movement.relevant_time : self.relevant_time
```


Todo : 
- [x] Ajouter les 3 nouveaux champs + migrations
- [x] Faire les fonctions post-save pour calculer les valeurs des 3 champs
- [x] Modifier les anciennes fonctions estimated_time(), departure_time() arrival_time()
- [x] Faire un test / validation : c’est-à-dire l'affichage de relevant_time, arrival_stopover_time et departure_stopover_time
- [x] Ajouter les champs arrival_time, departure_time, relevant_time dans les logs Metabase (ShipBaseModel)
- [x] Enlever "Estimé" dans le front
- [x] L'API SIP s-wing envoie l'info arrivalState : estimated/real et departureState: estimated/real. Il faudrait confirmer que quand c'est "real", les timestamps qui sont envoyés dans les champs "arrival" et "departure" sont bien des ata/atd. Si c'est le cas, il faudra modifier notre import SIP s-wing pour différentier les estimation des horaire "actual/real", puisque actuellement, on met les horaires dans les champs estimations eta/etd.
- [x] La même chose est faire pour Vigiesip.
    - 🫸 On a décidé de ne pas le faire finalement, puisqu'on a pas ATA/ATD dans l'API qu'on utilise - cette info est présente dans une autre API navire à quai.
- [x] Mettre à jour le filtre par timeline (past ou present) qui vérifie actuellement en fonction de l'eta ou etd, il faut que ça soit arrival_time ou departure_time
- [x] Changer l'annotation eta_or_etd qui doit maintenant utilise le nouveau champ "relevant_time".
- [x] Le script remove_data doit lui aussi utiliser le nouveau champ "relevant_time"
- [x] Le code autour du filtrage initial n'est pas très bien documenté
- [x] La vue `ships.views.ShipMovementViewMixin` doit aussi utiliser le "relevant_time"
- [x] Dans l'admin, les champs calculés devraient apparaître en readonly
- [x] Dans l'admin, il y a des filtres à changer, car ils se basent sur l'ancienne logique eta/etd.
- [x] Vérifier s'il faut faire des modifications dans les tests unitaires
- [x] Vérifier l'évolution du nombre de requêtes dans le debug tool
- [x] Analyse plus systématique de la pertinence de l'ATA/ATD :
    - Vérifier dé-priorisation des ATA/ATD des fal5/6 = est-ce que l'ATA/ATD du FAL1 est systématiquement ok, quand on le compare à l'ATA/ATD du FAL5/6.


```
    ***
    
    
    ***
    
    - attrib arrival_ae_time : ata or eta
    - attrib departure_ae_time : atd or etd
    - attrib ae_time() : arrival_ae_time or departure_ae_time
    - def departure_time() : if is_arrival and has related_movement: related_movement.ae_time else : self.ae_time
    - def arrival_time() : if is_departing and has related_movement: related_movement.as_time : self.ae_time
            
            
    arrival_ae_time, departure_ae_time and ae_time sont des champs de la DB qui sont calculés au moment de l'import
    
    priority_time
    primary_time
    prefered_time
    favorite_time
    main_time
    selected_time
    relevant_time
    proper_time
    
    eta/ata => relevant ?
    arrival/departure => relevant ?
    
    
    - def estimated_time()  # display_time ?
        if self.is_arriving:
            resulting_time = self.arrival_relevant_time
        if self.is_departing:
            resulting_time = self.departure_relevant_time
        return resulting_time
    
    - def arrival_time()
        if self.is_arriving:
            resulting_time = self.estimated_time
        if self.is_departing:
            if self.related_movement:
                resulting_time = self.related_movement.estimated_time
            else:
                resulting_time = self.estimated_time
        return resulting_time
    
    - def departure_time()
        if self.is_departing:
            resulting_time = self.etd_from_port_of_call
        if self.is_arriving:
            if self.related_movement:
                resulting_time = self.related_movement.estimated_time
            else:
                resulting_time = self.etd_from_port_of_call
        return resulting_time
    
    
    
    - def actual_or_estimated_time()  # relevant_time ?
        if self.departing: atd ou etd
        if self.arriving: ata ou eta
        
        
    - is_arriving or is_departing ? | import, on le sait | affichage, on le sait
    - ata ou eta ? | import, on le sait | affichage, on le sait
    - related_movement ? | import on ne sait pas | affichage, on le sait.
    
        
        
        
```

## 26 juillet 2023

> 🎯 Accéder à sa liste d' IMO mis en surveillance

**End-point :** 
- GET : récuper la liste des IMO en surveillance
- URL: /api/alerts/watchlist/

```
- on récupère automatiquement l'équipe avec le user de session de la requête
```

## 17 juillet 2023

> 🎯 Signalement erreur depuis l'app

=> Un signalement est une "issue"

**issues/model.py :**
- Équipe (Team)
- Utilisateur (User)
- Mouvement (Ship)
- Type d'erreur (choice depuis settings)
    - Erreur sur la liste
    - Charactères spéciaux
        - issue-crew-char-encoding
        - issue-passengers-char-encoding
    - Problème de type navire
    - Mauvais horaires
    - Autres..
    - => Types à redéfinir
- Status du traitement (Pour les admin : choice depuis settings - en cours / résolu / etc...)
- Note (Pour les admins : pour documenter le travail effectué - wysiwyg)

Question : La liste d'erreur est elle modifiable depuis l'admin ?
    - Il faudra une API pour les lister
    => On fait une liste hard codé


**End-point :** 
- POST : envoyer un signalement 
- URL: /api/ships/<id>/report-issue/

``` 
{
    issue_type: "crew-encoding-issues",
}

- Le champ "team" est rajouté en backend avec l'utilisateur de la session.
- Le status est par défaut "en cours" ou "nouveau".
- Ajouter un log à chaque signalement d'erreur
```


V1 : pas besoin d'un end-point GET

```
- On rajoute les donnée des "issues" dans l'API GET /api/ships/
{
    
    issues: [
        {
            utilisateur:  , 
            type erreur: ,
            date du signalement: ,
            status du traitement: ,
            note: ,
        }
    ]
}
```

**UX / UI :** 
- Signaler l'erreur depuis le mouvement
- Sélectionner le type d'erreur à partir d'une liste de choix ordonnés
- Afficher le nombre de signalements déjà fait
- Revoir le wording "Signaler une erreur"
- Gérer l'affichage des signalements précédents


**Étapes dev :**
1. Faire le modèle
2. Rajouter les info du signalement dans l'API ships GET
3. Afficher dans le front dynamiquement
4. Implémenter le POST
5. Faire des logs back-end pour les signalements
6. S'occuper du compteur de signalement
   

    
**Étapes backend :**

- [x] App infra / Boilerplate
- [x] Test issue boilerplate that fails on checking if issue data is available in GET ship list
- [x] Add model
- [x] GET API : Add data in ships data
    - [x] ship_relation : model mixin with relation for ships.issues
    - [x] Issue model serializer
    - [x] ship_relation : serializer mixin that adds issues to ship serializer
- [x] POST API : add a post endpoint
    - [X] ship_relation : view mixin that can be used in ships api view and add a post 
    - [X] add missing issue types choices fields
    
    

    
## 17 juillet 2023


> 🎯 Rendre l'historique paramétrable par équipe jusqu'à 60 jours

- [x] Mettre l'historique en effacement à 60 jours max au lieu de 7
- [x] Ajouter un champ dans les équipes pour personnaliser, type nombre libre `historic_duration`
- [x] Dans le filtre timeline past, ajouter une vérification : ETA/ETD est supérieur à ```aujourd'hui moins durée de l'historique```
- [x] Tests unitaires
- [x] Documentation Readme : historique + purge app + variable de configuration Scalingo
- [ ] Documentation Grist


## 29 juin 2023

> 👀 Filesify

- [ ] Secret
- [ ] Est-ce qu'on versionne le pipfile ?
- [ ] Il manque l'installation des packets
- [ ] Ajouter les DS_Store dans le gitignore
- [ ] Mettre en marche les tests

## 27 juin 2023

> 🎯 Avoir un script pour effacer les données sensibles lors de la copie de base prod > staging

Améliorer l'étape 8, pour rendre le nettoyage automatique
- [x] Effacer les utilisateurs non Moana
- [x] Effacer les listes Équipage
- [x] Effacer les listes Passagers

Voir si de options sont possibles : 
- [ ] Ne pas effacer certains membres ?

## 22 juin 2023

> 🎯 Changer les règles d'import FAL 5/6

Todo : 
- [x] Ne pas importer les informations LAST_PORT / eta / etd dans les FAL5/6
- [x] Si ETA/ETD/LAST_PORT sont vides il faut alors les importer
- [x] Mettre à jour les tests
- [x] Créer les nouveaux tests

## 21 juin 2023

### Réunion Anais
[Ticket routes API](https://gitlab.mim-libre.fr/sndv-maritime/equipe/-/issues/831)

**Utilisation API :**
- Est-ce qu'il y a une doc ? 
- Est-ce qu'ils ont pu avancé sur l'ouverture de l'API / ces limites ?

> Nous disent quand dispo
> Ils mettent en place un client python pour l'api

**Lien Anais <> Moana :**
- Est-ce possible pour lui d'ajouter un bout de code vers chez nous ? 
- À l'inverse Moane > Anais, il faut envoyer le MMSI ?

> Ok pour le faire 
> Ils l'ont pour Marine Traffic
> Peuvent personnaliser l'affichage du bouton chez eux
> MMSI + (ETA + Provenance) => (pas forcément à jour)

**Précédentes escales :**
J'ai trouvé cette route : https://api.anais.beta.gouv.fr/ships/[mmsi]/portcalls/[timestamp_from]/[timestamp_to] 
- est-ce bien la bonne ? 
- Ou est-ce qu'il existe une autre avec un retour JSON "plus simple" qui donne les précédents ports directement. 

> OK bonne route
> From - To : avec date 
> Et pas de X anciens car y'a des on/off dans certains ports
> Récupérer le mmsi depuis le end-point imo
> Attention ça reste du calculé il faut le préciser

**Type navires :**
Quand on interroge l'API juste via son IMO (https://api.anais.beta.gouv.fr/ships/imo/9805336) ou MMSI (https://api.anais.beta.gouv.fr/ships/228443600/), on récupère dans le JSON une valeur cargo: 60 ou cargo: 36 . 
- Ces nombres correspondent à des identifiants ?
- Et aussi quelle route ensuite interroger pour avoir le détail de cet identifiant

> Champs AIS : renseigné par le capitaine / table de type propre à > l'AIS.

**Registre Llyods :**
Pour mettre en place un lien Moana > SeaSercher, il nous faudrait "un numéro de référence interne Loyd’s"
- Est-ce que vous avez ça ? 

> Ils ont l'ID interne de Llyods   
> Va nous faire un référentiel IMO / MMSI / ID LLOYDS / AIS  
> Oui ça va vite.

**Feedback alertes:**
- Ça se passe bien ?

> Ça a été demandé très vite
> La boite de pandorre est emmerde
> Horreur à tester
> Couter beaucoup de dev 
> Pas sûre si utilisé vraiment
> Faire attention au nombre max d'alertes
> Voir le prix du pack sendinblue ??

**ETA**
- Essayer de savoir à quelle heure arrive un bateau sur notre port, pour comprendre si c'est conforme avec notre ETA
> Dans les AIS - type 5
> Capitaine qui met à jour, reste du déclaratif.


## 15 juin 2023 
### Add Front tracking

> 🎯 Pouvoir depuis le front-end logger des actions utilisateurs.
> 💡 Mettre en place une route API


#### Questions :

1) Est-ce qu'on met la route d'API dans l'appli réutilisable trackman ou bien dans moana.logs ?

Pros avec trackman
    - Mettre en commun le point d'API.

Cons avec trackman
    - Sécuriser en authorisant que les POST.
    - Récupérer la en front team
    - Récupérer en front le ship data
    - Backend : il faut faire l'équivalent de `add_ship_data_to_action_log`


API dans trackman :
```
POST api/tracking/add/

action_details = {
    "actor": "",
    "team": "PAF Sète",
    "action": "activate ships alert filter", "filter ship by alert"
    "object": "",
    "target": "",
    "description": "",
    "data": "",
    shipData: {} // Optional
}

```



#### TODO
- [ ] Sanyty check du nom de l'action ?
- [ ] Vérifier que le POST des action front n'introduit pas de problème de sécurité de type intrusion de scrpits.
- [ ] Faut-il utiliser un "model serializer"


#### Proposition :

Trackman fournit un mixin d'api TrackmanApiMixin

Work plan :
- [x] Add a mixins.py with simple empty @post action
- [x] Add create log code to post
- [ ] Add ability to customize the logic that's triggered on
- [ ] Provide some sample doc or extend this mixin in moana.logs



#### Si API dans logs.Moana : 


API dans moana.logs :
```
- POST api/tracking/add/
- {action: xxx-xxx, shipId: xxx}
- action : à renseigner
- shipId: optionnel
```


Log :
```
create_user_action_log()
- actor: vide
- team: à renseigner
- action: à renseigner
- object: optionnel
- target: optionnel
- description: optionnel
- data: optionnel
- ship: optionnel
```

Actions :
```
- filtre par navire - ON
- filtre par navire - OFF
```
