
# Documentation paw-HERMES
Cette documentation ajoute des précisions sur les différents appels de Flux réalisés, elle vient en complément de la documentation swagger disponible sur 
## liens utiles
[swagger du projet](/api/swagger/index.html)

[changelog](/api/dmo/changelog)

### Liste des hosts accessibles pour la solution :

intitulé|host par vpn|host externe
--------|------------|------------
environnement de développement|[https//dev.hermes.openstack.local](https://dev.hermes.openstack.local)|[https://doc-alshermes-int.be-idys.com](https://doc-alshermes-int.be-idys.com)
environnement de recette|[https://test.hermes.openstack.local](https://test.hermes.openstack.local)|[https://als-hermes-scoring-rec.be-idys.com](https://als-hermes-scoring-rec.be-idys.com)
environnement de démo|[https://demo.hermes.openstack.local](https://demo.hermes.openstack.local)|[https://als-hermes-demo-api.be-idys.com](https://als-hermes-demo-api.be-idys.com)

### url des clients frontends ALS:
intitulé|url
--------|------------
environnement de développement|[https://als-hermes-int.be-idys.com/](https://als-hermes-int.be-idys.com/)
environnement de recette|[http://als-hermes-entreprise-rec.be-idys.com/](http://als-hermes-entreprise-rec.be-idys.com/)

## url GED

[https://ged-test.dev.hermes.openstack.local](https://ged-test.dev.hermes.openstack.local)

als-hermes-int.be-idys.com
## Utilitaires de recherche

### Utilitaire de tri

Pour trier un retour dans notre application, utilisez le paramètre de recherche « sort » :

	?sort[champ1]=-1&sort[champ2]=1 …

La valeur « -1 » demande un tri décroissant, la valeur « 1 » demande un tri croissant.

Par exemple, pour trier sur la date de création de manière décroissante (du plus récent au plus ancien) :

	?sort[creation_date]=-1

###  Utilitaires de restriction logique

À votre disposition - pour tous les champs qui peuvent être recherchés sur tous les modèles, les opérateurs logiques suivants :

####  De grandeur

 - $gt : strictement plus grand que
 - $gte : plus grand ou égal à
 - $lt : strictement plus petit que
 - $lte : plus petit ou égal à

#### D’équité / d’iniquité

 - $ne : n'est pas 
 - $nin : n’est pas contenu dans 
 - $eq : est exactement 
 - $in : est contenu dans

#### D’expression régulière

 - $regex : avec une expression régulière sans les « / » de début et de
   fin

#### D'opération logique

 - **$or** et **$and** : une liste de listes associatives, chacune étant un nouveau filtre acceptant toutes les options précédement citées

    ex : ?$or[][field1]=value1&$or[][field2]=value2

équivaut à :

    {
      "$or": [
        {
          "field1": "value1",
          "field2": "value2
        }
      ]
    }

Il est aussi possible d'utiliser des index pour scinder les éléments de liste :

    ex: ?$or[0][field1]=value1&$or[1][field2]=value2

équivaut à :

    {
      "$or": [
        { "field1": "value1" },
        { "field2": "value2" }
      ]
    }

#### Complément d'info :
Ces opérateurs sont cumulables.

Ils s’utilisent de la façon suivante dans une requête :			  

    ?champ1[operateur1]=value&champ2[operateur2]=value&champ1[operateur2]=value …

L’exemple : 

    ?created_at[$lt]=2018-03-12T22:30&is_active[$ne]=true

Veut dire : _qui a été créé avant le 12 mars 2018 à 22h30 non inclue (strictement plus petit que) et qui n’est pas actif._

Exception faite sur les paramètres $in et $nin qui n’acceptent que des liste donc :

    ?title[$in][]=titre1&title[$in][]=titre2&status[$nin][]=PRET&status[$nin][]=PARTEZ

Veut dire : _qui a un titre contenue dans **[titre1, tritre2]** et un statut non contenu dans **[PRET, PARTEZ]**_

**ATTENTION:** *Si deux critères envoyés sont contradictoires il n’y aura aucun résultat.*

## Flux 3 accès aux candidatures transmises aux bailleurs

Pour répondre à ce besoin deux routes accessiblent via l'API :
* GET api/dmo/housing_offers/with_validated_applications
* GET api/dmo/housing_offers/with_validated_applications/{id}

### Paramètre obligatoire : "from"

Pour ces deux appels est nécessaire le paramètre **"from"**.

    {uri}?for={yyyy}-{mm}-{dd}T{hh}:{mm}:{ss}

Paramètre de filtrage pour limiter la date minimale de passage au statut "TRANSMIS BAILLEUR".

### Paramètres de recherche accessibles

Il est possible d'employer tous les champs et utilitaires de recherche accessibles pour les offres.

### Autre paramètre optionnel : "to"

Pour ces deux appels, est possible l'utilisation du paramètre **"to"**.

    {uri}?to={yyyy}-{mm}-{dd}T{hh}:{mm}:{ss}

Paramètre de filtrage pour limiter la date maximale de passage au statut "TRANSMIS BAILLEUR".

### Liste des offres ayant des candidatures au statut "TRANSMIS BAILLEUR"

uri :

    GET api/dmo/housing_offers/with_validated_applications?from={yyyy}-{mm}-{dd}T{hh}:{mm}:{ss}

Affiche la liste des offres ayant une ou plusieurs candidatures au statut **"TRANSMIS BAILLEUR"**, et qui ont pris ce statut depuis **"from"**.

### Liste des candidatures ayant l'état "TRANSMIS BAILLEUR" pour une offre donnée

uri :

    GET api/dmo/housing_offers/with_validated_applications/{id}?from={yyyy}-{mm}-{dd}T{hh}:{mm}:{ss}:{msms}

Le paramètre de chemin **"id"** étant l'id de l'offre souhaitée.
Affiche la liste des candidatures au statut **"TRANSMIS BAILLEUR"** pour une offre donnée, et qui est passée à ce statut depuis **"from"**.

## FLux 4 Gestion des statuts d'une offre

### route spécifique bailleurs

    POST     /api/dmo/housing_applications/update_status/
    
    {  
    "data":{     
      "attributes":{
                 "unique_number":"0690412654321G3U05",
                 "external_ref":"CVL-000014",
                 "status":"Visite proposée",
                 "last_status_update_date":"01/01/0001",
                 "lessor_event_informations ":"0"
        }
      }
    }
     

### Explication rapide du concept de "status"

Pour gérer au niveau du moteur le cycle de vie d'un objet, nous employons le concept de **"status"**.
Ceux-ci permettent de discriminer des objets entre eux en fonction de l'état "métier" dans lequel ils se trouvent.

Pour gérer ces statuts il y a deux méthodes accessibles :
- 1. Modifier un champ "status" sur une offre
- 2. Produire un "status" détaillé par la route : **POST api/dmo/statuses**

### Changement de "status" simple

Dans le cas des offres, les champs accessibles pour gérer ces changements non-détaillés de "status" sont les suivants :
- **lessor_status:** status fournit par le bailleur
- **offer_status:** status fournit par SOPRA ou produit par effet de bord
Changer la valeur d'un de ces champs vers la valeur adéquate, permet au moteur de produire les effets souhaités.

### Changement de "status" détaillé

uri :

     POST api/dmo/statuses

Il s'agit ensuite de fournir un corps de requête adéquat.
Pour le détail fonctionnel des champs présents dans notre swagger [https://als-hermes-scoring-rec.be-idys.com/api/swagger/index.html](https://als-hermes-scoring-rec.be-idys.com/api/swagger/index.html):
- **status_label:** complément de status indiquant à quel concept ce status est associé (ex: *lessor*, *offer*, *request*, *entity*, ...)
- **motive:** description du motif de passage à ce status
- **title:** intitulé du status. IMPORTANT : La validité parfaite de sa valeur est essentielle => ce champs détermine - pour le moteur, l'état métier actuel de l'objet associé.
- **object_id:** id de l'objet associé
- **performer_id:** dans le cas d'une possibilité de "status" concurrents, il est essentiel d'indiquer ici l'id du déclencheur de ce status. *(non utile dans le cas du bailleur)*

### Correspondance des évènements aux status

**NOUS AVONS BESOIN DE FAIRE UN POINT SUR CETTE CORRESPONDANCE.**

évènement|label de status|valeur PAW
---------|---------------|----------
||

## Flux 5 Mise à jour des bien MAD

Ce flux se déclenche lors d'une mise à disposition d'un bien, ou lors de la modification d'une offre en état MAD.
Son déclenchement implique la mise à jour de l'objet SOPRA associé.

## Flux 6A, 6B, 6C et 39 infos générales

uri globale : 

    GET api/dmo/housing_offers/${id}/eligible_request

Avec pour ${id} l’id de l’offre choisie.

Mapping des valeurs :

 - Numéro interne demande ALS => **als_id** 
 - Score =>  **profile_epci_score** 
 - Rang initial => **eligible_position** 
 - Rang actuel (estimation ou réél si positionné) => **applicated_position**
 - Taux d’effort => **effort_rate**
 - Nombre de candidatures du demandeur => **applications_nb**

###  Flux 6A Instruction d'une offre - Onglets candidatures Affichage de la liste des propositions en cours d'instruction

Utilisez le paramètre de recherche « ids » contenant la liste des demandes éligibles à étudier :

    ids[]=${id1}&ids[]=${id2}&ids[]=${id3} …

Pour obtenir les demandes éligibles à une offre portant les ids saisis.

Ou

    ?als_id[$in][]=${id1}& als_id[$in][]=${id2}& als_id[$in][]=${id3} …

Pour Obtenir les demandes éligibles à une offre portant les als_id saisis.

### Flux 6B et 6C infos générales

Trier par scoring, exemple : 

    ?sort[profile_epci_score]=(-1 || 1)

Disponible aussi - comme pré-décrit, sur tous les autres champs des demandes.

#### Flux 6B Instruction d'une offre - Affichage de la liste des candidatures et de leurs scoring respectifs

Ajouter le paramètre 

    housing_offer_ids=${id} 

${id} étant l’id de l’offre en question, pour obtenir toutes les demandes positionnées sur l’offres.

#### Flux 6C Instruction d'une offre - Demandes éligibles Affichage de la liste des demandeurs éligibles (non positionnés sur l'offre) et de leurs scoring respectifs

Ajouter le paramètre 

    housing_offer_ids[$ne]=${id}

${id} étant l’id de l’offre en question, pour obtenir toutes les demandes non positionnées sur l’offres.

#### récuperer l'ensemble des candidatures liées a une offre donnée :
la demande liée à la candidature sera dépliée dans la réponses (champs housing_reqquest + main_applicant)

    GET /api/dmo/housing_offers/{id}/all_applications
    
### Flux 39 Affichage de la demande et de la liste des offres éligibles pour cette demande

Utilisez ensuite les utilitaires de recherche (cf : Utilitaires de recherche) sur les champs souhaités pour filtrer les demandes éligibles selon les critères définis.

##  Flux 7 Liste des offres à traiter par les différents rôles (COL, ROL, CDL-C)

    GET api/dmo/housing_offers

Utilisez le paramètre **« ids[] »** ou **« als_id[$in] »** pour rechercher un lot spécifique d’offre.

Mapping des champs :

 - Nombre de demande éligibles par orientation => **eligible_requests_nb_detailed**
	 - Contient potentiellement (absent ou à 0 si aucune demande correspondante) :
		 - **priority_public** (dalo inclut)
		 - **single_parent** (monoparentale)
		 - **mutation**
		 - **entities** (objet de forme) :
			 - **id_paw1** : quantité
			 - **id_paw2** : quantité
			 -  ...
- Nombre de candidats positionnés sur l’offre => **applicated_nb**
- Nombre de photos => **pictures_nb**

## Flux 10 gestion des photos

[https://als-hermes-scoring-rec.be-idys.com/api/swagger/index.html#operations-API_DMO_HOUSING_OFFERS-post_api_dmo_housing_offers__housing_offer_id__pictures](https://als-hermes-scoring-rec.be-idys.com/api/swagger/index.html#operations-API_DMO_HOUSING_OFFERS-post_api_dmo_housing_offers__housing_offer_id__pictures)

Les photos sont systématiquement ratachées à une housing_offer.

Le nombre maximal de photos par housing offer est de 5. Au-dela la création est bloquée.
Dans ce cas, il faut alors soit :
- Éditer une photo
- En supprimer une, puis rajouter celle souhaitée

Formatage du json pour une picture :

    {
	    "id" :"5dc5975b88cb110b0543a829",
	    "type" : "pictures",
	    "attributes" : {
		    "responsible" : {
			    "id" : "5dc5975a88cb110b0543a822",
			    "first_name" : "Martin",
			    "last_name" : "Durand"
		    },
		    "readers" : [],
		    "writers" : [],
		    "read_level" : "write",
		    "created_at" : "2019-11-08T17:27:07.560+01:00",
		    "updated_at" : "2019-11-08T17:27:08.538+01:00",
		    "thumb240" : “urlDeLaMiniature240pixel.png”,
		    "thumb1000" : “urlDeLImageEn1000pixelDeLarge.png”,
		    "full_size" : “urlDeLImageEnTailleOriginale.png”,
		    "housing_offer_id" : "5dc5975b88cb110b0543a828"
	    }
    }

#### image par défaut
lorsqu'aucune image n'est fournie, l'api fournit une image par défault réalisée a partir de google map.
un booléen is_default=true est ajouté au json de l'image en question
    
    housing_offer => {
    ...
    ...
      "department" => "30",
                                             "pictures" => [
                    [0] {
                                "id" => nil,
                              "type" => "pictures",
                        "attributes" => {
                                  "is_default" => true,
                                    "thumb240" => "https://maps.googleapis.com/maps/api/streetview?size=240x240&location=14+rue+edgard+quinet+30100+&key=AIzaSyB44UtIXYeMCKhtwUWeUdO16KVDMUAHHqQ",
                                   "thumb1000" => "https://maps.googleapis.com/maps/api/streetview?size=1000x1000&location=14+rue+edgard+quinet+30100+&key=AIzaSyB44UtIXYeMCKhtwUWeUdO16KVDMUAHHqQ",
                                   "full_size" => "https://maps.googleapis.com/maps/api/streetview?size=1500x1500&location=14+rue+edgard+quinet+30100+&key=AIzaSyB44UtIXYeMCKhtwUWeUdO16KVDMUAHHqQ",
                            "housing_offer_id" => "5ee8720088cb11fea71b2c57"
                        }
                    }
                ],
                                          "pictures_nb" => 0,
                                  "ordered_picture_ids" => [],
                                         "main_picture" => {
                            "id" => nil,
                          "type" => "pictures",
                    "attributes" => {
                              "is_default" => true,
                                "thumb240" => "https://maps.googleapis.com/maps/api/streetview?size=240x240&location=14+rue+edgard+quinet+30100+&key=AIzaSyB44UtIXYeMCKhtwUWeUdO16KVDMUAHHqQ",
                               "thumb1000" => "https://maps.googleapis.com/maps/api/streetview?size=1000x1000&location=14+rue+edgard+quinet+30100+&key=AIzaSyB44UtIXYeMCKhtwUWeUdO16KVDMUAHHqQ",
                               "full_size" => "https://maps.googleapis.com/maps/api/streetview?size=1500x1500&location=14+rue+edgard+quinet+30100+&key=AIzaSyB44UtIXYeMCKhtwUWeUdO16KVDMUAHHqQ",
                        "housing_offer_id" => "5ee8720088cb11fea71b2c57"
                    }
                },
                                 "publication_end_date" => nil,
                                 ...
                           }      

#### Création

    POST /api/dmo/housing_offers/{housing_offer_id}/pictures  

avec un file dans les formDatas  
  
renvoie les infos sur la picture créée

####  Recuperation des images liées à une offre

uri :

    GET /api/dmo/housing_offers/{housing_offer_id}

Renvoie 3 champs concernant les pictures

    {
        "ordered_picture_ids": ["id1","id2"] ,
        /*(éditable) liste ordonnée des ids de pictures liées a l’offre
        * (max 5) la première de l’array est la picture principale*/
	    

        "main_picture": {…} 	,
        /*objet contenant les infos de l’image principale
        * première picture de l'array "ordered_pictures"
        * (non éditable directement)*/

	    "pictures": [ 
		    {…},
		    {…}
	    ]
        /*liste d’objets du type picture
        * (non editable directement)*/
    }

### Edition

    PUT ou PATCH     /api/dmo/housing_offers/{housing_offer_id}/pictures/{picture_id}  

avec un champ "file" contenant le fichier image dans dans les formDatas

### Suppression

    DELETE     /api/dmo/housing_offers/{housing_offer_id}/pictures/{picture_id}   

### Changement d’ordre dans les pictures

pour changer l’ordre des photos, il faut éditer le champ « ordered_picture_ids » de l’housing offer, la premiere de l’array en deviendra la picture princiaple (main_picture).

    PUT ou PATCH sur /api/dmo/housing_offers/{housing_offer_id}

  avec en params : 

    "data":{
	    "attributes":{
		    "ordered_picture_ids":[
			    “picture3.id”,
			    “picture1.id”,
			    “picture2.id”
		    ]
	    }
    }

### changement de la main picture

pour changer la main picture il faut réordonner les pictures afin que la picture souhaitée se retrouve au début du tableau « ordered_picture_ids »

## Flux 11 Rendre l'offre au bailleur (entrant)

Modifier la valeur du "offer_status" dans la "housing_offer": 

    PATCH/PUT sur /api/dmo/housing_offers/{housing_offers_id}
    
avec en params du body: 
    
        "data":{
    	    "attributes":{
    		   "offer_status": "RETIRE PAR LE BAILLEUR" 
    	    }
        }

## Flux 12 Reprise offre par le bailleur (sortant sopra)
Transmission au back sopra via un appel de WS du status d'une offre donnée (housing_offer) lorsque celle ci à son status qui passe à reprise par le bailleur ('RBA')



## Flux 13 Confirmer la reprise de l'offre par le bailleur

https://code.plugandwork.net/plugandwork.app/hermes/commit/cbe458dd5376cd92d934fbb07319c9225e011f9a
c'est une édition d'une entité offre, elle s'appele sur la route : 

    PATCH/PUT sur /api/dmo/housing_offers/{housing_offer_id}
    
avec en params du body: 
    
        "data":{
    	    "attributes":{
    		   "lessor_status" : "RETIRE" ,
    		    "offer_status" : "RETIRE PAR LE BAILLEUR"
    	    }
        }


## Flux 14 Gérer l'orientation d'une offre

L'orientation d'une offre est composée par les champs suivants :

  - **priority_public**: Boléen statuant sur l'accessibilité à l'offre par les publiques prioritaires uniquement
  - **mutation**: Boléen statuant sur l'accessibilité à l'offre par les demandes en situation de mutation uniquement
  - **single_parent**: Boléen statuant sur l'accessibilité à l'offre par les familles monoparentales uniquement
  - **reserved**: Boléen statuant sur l'accessibilité à l'offre par les demandeurs des entreprises liées à l'offre
  - **entity_ids**: Liste des ids des entreprises liées à l'offre

Pour modifier l'orientation d'une offre il s'agit donc de mettre à jour les champs indiqués plus haut au niveau de l'offre souhaitée.

## Flux 15 Gérer la publication d'un offre

L'offre doit passer au statut : "LOGEMENT PUBLIE".
Pour ce faire :

    PATCH /api/dmo/housing_offers/{id}

body :

    {
      "data":{
        "attributes":{
          "details": "string", // description du bien
          "dpe_ges": "string", // étiquette GES
          "dpe_conso": "string" // étiquet DPE
        }
      }
    }

## Flux 16 Commercialiser l'offre sans publication

c'est une édition d'une entité offre, elle s'appele sur la route : 

    PATCH/PUT sur /api/dmo/housing_offers/{housing_offer_id}
    
avec en params du body: 
    
        {
          "data":{
            "attributes":{
                    "offer_status": "COMMERCIALISE SANS PUBLICATION",
                    "lessor_status": "PUBLIE",
                    "publication_end_date": Date
            }
          }
        }


## Flux 17 Commercialiser une offre avec publication


c'est une édition d'une entité offre, elle s'appele sur la route : 

    PATCH/PUT sur /api/dmo/housing_offers/{housing_offer_id}
    
avec en params du body: 
    
        "data":{
    	    "attributes":{
    	            "offer_status": "LOGEMENT PUBLIE",
                    "lessor_status": "PUBLIE",
                    "publication_end_date": Date
    	    }
        }

- les offres avec le champ is_public à true sont des offres qui resortirons pour les candidats quelque soit les critères d'eligibilité
- les offres avec le status offer_status=='LOGEMENT PUBLIE' seront visible en mode visiteur

## Flux 18 Dépublier une offre


c'est une édition d'une entité offre, elle s'appele sur la route : 

    PATCH/PUT sur /api/dmo/housing_offers/{housing_offer_id}
    
avec en params du body: 
    
        "data":{
    	    "attributes":{
    		   offer_status : "EN COURS DE DESIGNATION" 
    		    lessor_status : "EN DESIGNATION"
    	    }
        }

## Flux 19 Suite à l'action 'Transmettre au bailleur", envoi des candidats choisis pour une offre donnée

### Transmission au front als des demandes retenues

    POST sur /api/dmo/housing_offers/{housing_offer_id}/selected_applications

  avec en params du body: 

    "data":{
	    "attributes":{
		   "als_request_ids":[
			    “als_request_id1”, //id de demande tels que présent dans le back
			    “als_request_id2”,
			    “als_request_id3”,
			    ...
		    ]
	    }
    }
    
   Entraine une modification du statut de la candidature à "TRANSMIS BAILLEUR" et renvoie la liste des candidatures ainsi éditées avec en embed les demandes associées

### recupération des candidatures enregistrées sur le front avec un status à TRANSMIS BAILLEUR pour une offre donnée
pour une offre donnée, récupération des candidature dont le statut est à « TRANSMIS BAILLEUR » avec pour chacune la housing_request associée en embed dans le json

    GET api/dmo/housing_offers/${id}/selected_applications

Avec pour ${id} l’id de l’offre choisie.  
  
il est possible d’ajouter des options de recherche et une pagination à cette requete comme pour les autres requêtes ; documentation accesible sur notre [swagger](https://als-hermes-scoring-rec.be-idys.com/api/swagger).

## Flux 20 Annuler la commercialisation d’une offre 


c'est une édition d'une entité offre, elle s'appele sur la route : 

    PATCH/PUT sur /api/dmo/housing_offers/{housing_offer_id}
    
avec en params du body: 
    
        "data":{
    	    "attributes":{
    		   "offer_status" : "EN ATTENTE COMMERCIALISATION",
    		   "lessor_status" : "EN ATTENTE PUBLICATION"
    	    }
        }

## Flux 21 Envoi d'une candidature au back sopra (sortant sopra)
Ce flux se déclenche lors de la création d'une candidature pour une offre ( au create d'une
housing_application ). Il envoie une requête  vers Sopra indiquant l'offre concerné et la demande concernée ainsi que la date de positionnement.
      
      
## Flux 30 Envoi d'une demande (sortant sopra)
ce flux se déclanche a la création ou a l'update d'une housing_request et permet de renseigner le back sopra sur les modifications d'une demande de logement.

## Flux 32 Envoit d'un NUD au FRONT

Pour créer un Nud :

uri:

    POST /api/dmo/nuds

body :

    {
      "data": {
        "attributes": {
          "housing_request_id": ,// String, id PAW de la demande concernée (utilisez aussi l'als_id si vous preferez)
          "als_id":             ,// String, als_id de la demande concernée (connue sous le nom de ref_interne chez sopre
          "department":         ,// String, code du département rattaché au nud
          "creation_date":      ,// DateTime, date de création rattaché au nud
          "unique_number":      ,// String, numéro unique du nud
          "is_active":           // Boolean, true si toujours d'actualité, false pour désactiver la validité
        }
      }
    }

Cette méthode API gère aussi les doublons :
Si la paire **"unique_number"** <==> **"housing_request_id"**, est déjà réferencée, alors l'objet portant cette correspondance sera récupéré et mit à jour.

Vous pouvez vous référer au [swagger](https://als-hermes-scoring-rec.be-idys.com/api/swagger/index.html) pour connaitre le reste de ses fonctionnalités classiques.

## Flux 36 Validation d'une demande par une entreprise (sortant sopra)
ce flux se déclenche quand entity_validated est modifié

## Flux 37 Dès détection d'une modification de l'orientation sur une demande suite au traitement automatique de détermination

	GET api/dmo/housing_requests/clp_details?als_ids[]=${id1}&als_ids[]=${id2}…

Le paramètre **_« als_ids »_** est ici obligatoire. C’est l’équivalent du paramètre **_« ids »_** mais pour la correspondance avec le champ « als_id » porté par une demande.

Ce paramètre n’existe que pour cette action !!! Autrement il faut utiliser **« als_id[$in] »** pour reproduire son effet.

Mapping des champs :

 - Nombre de candidatures => **applicantions_nb** Date dernière
  - candidature => **last_application_date** Nombres d’offres éligibles
  - détaillé => **eligible_offers_nb_detailed** Objet qui contient les
  - clefs : Nombre non commercialisées => **non_commercialized** Nombre
	  - commercialisées et non publiées => **commercialized_non_pubicated**
		 -  Nombre commercialisées et publiées => **commercialized_publicated**

## Flux 38 Gérer l'orientation d'une demande

### rappel généraux
Dans notre solution une demande est un objet composite formé :

  - d'un demandeur principal **Applicant**
  - d'une demande de logement **HousingRequest**
  - d'aucun à plusieurs co-titulaire **Applciant**

Les informations présentes sur chacun de ces objet produit l'orientation d'une demande.

Champs concernés pour :

  - Le demandeur principal et les co-titulaire :
    - **entity_id**: entreprise du demandeur principal ou du co-titulaire
  
  - La demande de logement :
    - **entity_validated**: validation entreprise (pour l'instant ne prend en compte que la validation de l'entreprise du demandeur principal)
    - **single_parent** (automatique): Boléen calculé en fonction de la composition familiale de la demande et statuant sur l'état "monoparental" ou non du foyer de la demande
    - **mutation**: Boléen statuant sur l'état "mutation" de la demande
    - **priority_public**: Boléean statuant sur l'état "publique prioritaire" de la demande

Pour modifier l'orientation d'une demande il s'agit donc de mettre à jour les champs indiqués plus haut au niveau de la demande souhaitée, excepté pour **single_parent** qui est produit par plusieurs composantes :

  - situation familiale du demandeur principale
  - si le foyer inclut ou non des enfants à charge

### application au flux 38 

    PATCH/PUT sur /api/dmo/housing_requests/{housing_request_id}
    
avec en params du body: 
    
        "data":{
    	    "attributes":{
    		   "priority_public" : Boolean
    	    }


## Flux 40 Notification du changement de statut d'une candidature (entrant)

Modifier la valeur du "status" dans la "housing_application": 

    PATCH/PUT sur /api/dmo/housing_applications/{housing_application_id}
    
avec en params du body: 
    
        "data":{
    	    "attributes":{
    		   "status": "A L'ETUDE ALS" 
    	    }
        }

## Flux 50 à 56 Communication d'évènements candidature (sortant sopra)

Ce flux se déclenche lors de la modification du statut d'une candidature (champ "status" d'une housing_application).   
Il envoie une requête indiquant l'évènement vers Sopra avec un code évènement tel que décrit ci dessous.
      
### Statuts des candidatures
Cette liste peut être amenée à évoluer car certaines corrrespondances avec les précédents statuts ne sont pas encore bien établies.

A présent il est indispensable de séparer les statuts de commissions des statuts de visite, il existe donc deux champs sur le modèle HousingApplication qui sont `status` et `visit_status`

Actuellement la correspondance avec le code évènement fonctionne avec les anciens et les nouveaux statuts.   
Si un ancien statut est utilisé alors il sera converti suivant ce tableau.  
Le code évènement sera renvoyé avec les anciens et nouveaux statuts (si correspondance)

|status|visit_status|Ancienne correspondance|Code évènement renvoyé|
|---|---|---|---|
|EN ATTENTE||Waiting||
|PLO||PLO||
|TRANSMIS BAILLEUR||Inscription CAL|INSCAL|
|ACCEPTEE EN CAL||Attribution lot avec rang|DESCAL|
|REFUSEE EN CAL||Refus attribution|DESCAL03|
|NON RETENUE||Refus lot demandeur|REFLOG|
|NON RETENUE EN CAL||Radiation attribution|RADATT|
|DESISTEMENT SALARIE AVANT CAL||||
|ANNULEE BAILLEUR||||
|DESISTEMENT||||
|ANNULEE||||
|A L’ETUDE ALS||||
|DESISTEMENT APRES CAL||||
|**ACCEPTEE EN CAL**|VISITE PROPOSEE|Visite proposée|VISPRO|
|**ACCEPTEE EN CAL**|VISITE EFFECTUEE|Visite effectuée|VISEFF|
||DESISTEMENT APRES VISITE|||
||ACCORD APRES VISITE|||
|**ACCEPTEE EN CAL**||Attribution lot|DESCAL01|
|**ACCEPTEE EN CAL**||Attribution sous condition|DESCAL02|

### Déclanchement des effets de bords

A la suite de certaines modifications sur les statuts d'une HousingApplication, cela peut déclencher une série d'évènements.

|status|visit_status|Effet|Impact|
|---|---|---|---|
|si inclut le mot 'DESISTEMENT'|VISITE EFFECTUEE|Re-calcul du scoring|- 35 points|
|ACCEPTEE EN CAL|NA|Re-calcul du scoring|+ 35 points|

### Affichage de l'historique des statuts pour un candidat

Un candidat peut afficher la liste des statuts de ses candidatures via la requête suivante : 

    GET /api/dmo/statuses/applications_history

La notion d'historisation est liée au filtrage par 2 paramètres disponibles, `start_date` et `end_date`, que l'on peut ajouter à la requête soit l'un ou l'autre, soit les deux : 

    GET /api/dmo/statuses/applications_history?start_date=01/01/2020&end_date=31/12/2020

Le requête est alors filtrée sur les statuts dont la date de mise à jour (`updated_at`) est comprise entre les bornes datées.

## Affichage des offres de logements publiques

Le front-end peut lancer des requêtes afin de récupérer l'ensemble des offres de logements publiques (housing_offer avec le champ "is_public" à true)

Il n'est pas nécessaire d'être identifié pour y avoir accès (pas besoin de token).

    GET /api/dmo/public_housing_offers

Les paramètres de tri et de pagination possibles sont décris dans le swagger : 

[https://als-hermes-scoring-rec.be-idys.com/api/swagger/index.html#operations-tag-API_DMO_PUBLIC_HOUSING_OFFERS](https://als-hermes-scoring-rec.be-idys.com/api/swagger/index.html#operations-tag-API_DMO_PUBLIC_HOUSING_OFFERS)

Une expliquation plus détaillée de l'utilisation des query params pour préciser la recherche se trouve au premier chapitre de cette documentation.

Il est aussi possible de réaliser une requête pour récupérer le détail d'une seule housing_offer dont le champ is_public est à true sans être identifié (pas besoin de token) :

    GET /api/dmo/public_housing_offers/{id}
    

## Envoi d'email

Pour demander à l'api  d'envoyer un email, on doit réaliser la requete 

    POST /api/d2/docs
    
avec dans le body json de la requête : 
 
    {
        "to": "String",
        "cc": "String",
        "bcc": "String",
        "from": "String"
        "data":{
            "attributes":{
                "type": "email",  //doit etre égal à "email" pour que l'envoi soit réalisé
                "title": "String", //objet du mail
                "body": "String"   //contenu du mail
            }
        }
    }
    
    
## Gestion Documents 

A la création d'une Demande (housing_request), ainsi qu'aux updates, un objet housing_request_folder representant le dossier demande est créé ou mis a jour.
Des objets de type "required_document" sont générés après un calcul sur les pieces a fournir pour un dossier donné.
le calcul est automatisé par notre API, et il n'y a plus qu'a afficher la liste des pieces a fournir.
Si les pieces existent déja pour un applicant donné, alors elles sont récupérés directement.
Si la demande évolue et entraine une modification des pieces à fournir, alors les required_documents sont mis a jours automatiquement

### Récupération de la liste des pieces à fournir pour une demande

    GET api/dmo/housing_requests/${id}/housing_request_folder
    
cette requete renvoie un JSON ressemlant à ceci :

    {
        "data" : {
                    "id" : "5de12f9b88cb11400c9dcdfe",
                  "type" : "housing_request_folders",
            "attributes" : {
                        "created_at" : "2019-11-29T15:47:55.045+01:00",
                        "updated_at" : "2019-11-29T15:47:55.045+01:00",
                            "nud_status" : "Dossier validé", //status du dossier de demande pour obtention d'un nud
                            "consultation_status" : "Dossier validé", //status du dossier de demande pour consulter les offre
                            "application_status" : "Dossier incomplet", //status du dossier de demande pour candidater aux offre
                        "completion" : 0, //pourcentage de completion du dossier
                    "validity_limit" : "2021-11-29T15:47:55.045+01:00",
                    "is_still_valid" : true,
     "file_upload_from_sne_complete" : true, //booléen, true si la recherche des pieces justificatives dans le sne à été executée
                "housing_request_id" : "5de12f9a88cb11400c9dcdf9",
                "required_documents" : [{
                                                "id" : "5de12f9b88cb11400c9dcdfa",
                                        "created_at" : "2019-11-29T15:47:55.048+01:00",
                                        "updated_at" : "2019-11-29T15:47:55.048+01:00",
                                            "nature" : "Pièce d'identité"
                                              "type" : "Carte nationale d’identité ou passeport",
                                             "label" : "Veuillez déposer une copie recto-verso de votre carte d'identité ou en cours de validité. 
                                                          Attention, ce document doit impérativement faire figurer 
                                                          Nom d’usage, Nom de naissance, Prénom (uniquement le premier),Date de naissance,Lieu de naissance,Pays de naissance, Date d’émission, Date d’expiration, Signature et photo. 
                                                          Ce document doit être lisible et complet.""validity_limit" : "2021-11-29T15:47:55.045+01:00", //limite de validité si la piece n'est valable qu'un certain temps
                                    "is_still_valid" : true,
                                            "status" : "pièce non fournie", //status de la piece à fournir
                                 "validation_errors" : nil, //tableaucontenant la liste des erreurs de validations constatées sur une piece
                                         "tagset_id" : nil, //reference de l'espace de travail contenant la piece
                                    "tagsetLocation" : nil, //url du serveur hebergeant les documents et les especes de travail
                                             "files" : [ 
                                                          {
                                                              "doc_id": "5e9ee989dfbd97202c2eaa88",
                                                              "filename": "5df7a2a222ec795c2ba50465.pdf",
                                                              "url": "/api/dmo/hermes/gedfile/send/79f5b03574a4dc7535d025e793326418/5e4fe6f922ec792b1717a092.pdf", // fin de l'url, à concatener avec l'url du serveur hermes utilisé
                                                              "preview_url": "", // fin de l'url, à concatener avec l'url du serveur hermes utilisé
                                                              "doc_data": {...}
                                                             }
                                                         ],
                                          "category" : "SPI",  //code de catégorie du document
                      "is_required_for_nud" : false,  //true si requis pour obtenir un nud
                      "is_required_for_consultation" : false,  //true si requis pour consulter les offres
                       "is_required_for_application" : true,   //true si requis pour postuler aux offres
                             "is_for_main_applicant" : false,  //true si le document est requis pour le main applicant
                               "dependent_infos" : {           //n'est renseigné que si la piece doit etre au nom du dépendent
                                              "last_name" : "GOUBILLze",
                                             "first_name" : "CHRIS",
                                             "birth_date" : "2017-03-23T00:00:00.000Z",
                                               "rel_type" : "P",
                                                    "sex" : "M"
                                         },
                                         disability_index: nil //rensigné si la piece est liée au handicap
                                          //le document justificatif doit concerner cet applicant (demandeur)
                                         "applicant" : {             
                                                       "id" : "5de12f9a88cb11400c9dcdf7",
                                               "created_at" : "2019-11-29T15:47:54.930+01:00",
                                               "updated_at" : "2019-11-29T15:47:55.071+01:00",
                                                      "nud" : nil,
                                             "temporary_id" : nil,
                                "sne_profile_creation_date" : nil,
                                                    "ss_id" : nil,
                                               "first_name" : "Océane",
                                                "last_name" : "Vincent",
                                                "full_name" : "Océane Vincent",
                                                ...
                                                        }            
                                        },
                                        {...},
                                        {...}
                                    ]
                                      
            }
        }
    }
    
#### notion de "piece A OU piece B"

les required_documents ont désormais un champs 

      or_required_document_types : Array

dans lequel est inscrit un tableau avec la liste des types des pieces avec lesquelles ils sont en "OU"
     
 ex :
  
      required_documents : [
      {
             type: "quittance de loyer",
             ...,
             ...,
      or_required_document_types: ["Attestation du bailleur indiquant que vous êtes à jour de vos loyers et charges, ou tout moyen de preuve des paiements effectués"]},
            {
             type: "Attestation du bailleur indiquant que vous êtes à jour de vos loyers et charges, ou tout moyen de preuve des paiements effectués",
           ...,
           ...,
             or_required_document_types: ["quittance de loyer"]}
             ]
             
 lorsque l'une des deux piece a le status 'Pièce validée' ou 'A contrôler' alors l'autre n'est plus requise dans le calcul de la completude du dossier (meme si elle reste presente  au status "piece Manquante" ou autre)
#### Statuts des dossiers de demande

pour la conception de l'UX il sera important de prendre en considération les deux status des housing_request_folders
nud_status, consultation_status et application_status

nud_status, consultation_status et application_status pourront prendre les valeurs suivantes : 
    
   - "Dossier incomplet"
   - "Erreurs de validation dans les pieces fournies"
   - "Dossier complet prêt pour traitement"
   - "Dossier complet en cours de traitement"
   - "Dossier validé"
   - "Date de validité dépassée"

#### Statuts des pièces à fournir

à ce jour les required_documents.status pourront prendre les valeurs suivantes : 
    
   - "Pièce manquante" -> la piece n'a pas eté fournie
   - "Prêt pour traitement" -> la piece a été fournie mais necessite un traitement KYC avant d'etre validée
   - "Contrôle en cours" -> la piece est en cours de controle kyc
   - "Pièce invalide" -> le controle KYC declare la piece invalide
   - "A contrôler" -> La piece a été déposée, elle ne écéssite pas de controle KYC, mais elle n'a pas encore été validée par un collaborateur offre logement.
   - "Pièce validée" -> le traitement KYC ou un collaborateur offre logement a déclaré la piece valide 
   - "Date de validité dépassée" -> la date de validité de la piece est dépassée 
   
#### Impact sur le status de la housing_request

par défaut : housing_request.request_status = "INCOMPLETE"

nud_status == "Dossier validé" => housing_request.request_status = "EN ATTENTE DE NUD" (puis "EN ATTENTE DE PIECES" lorsque le nud est arrivé)

consultation_status == "Dossier validé" => housing_request.request_status = "ELIGIBLE"
application_status == "Dossier validé" => housing_request.request_status = "COMPLETE"

***Lorsque `housing_request.request_status = "ELIGIBLE"` :***

housing_request.entity.auto_request_validation == `true` => housing_request.entity_status = "EN COURS"
housing_request.entity.auto_request_validation == `false` => housing_request.entity_status = "A VALIDER"

#### personne concernée par la piece a fournir

il faut pour cela aller regarder dans la partie "applicant" du json pour pouvoir recuperer cette information
   
### Page d'accès publique à la liste des documents à fournir
SWAGGER: **API_DMO_HOUSING_REQUEST_SHARES**

Requete GET

    GET /api/dmo/housing_request_shares/:id?code=xxxxxxx

Requete POST

    POST /api/dmo/housing_request_shares

    {
        "data":{
            "id":"5ec29dfdd195548c7d716cff",
            "type":"housing_request_shares",
            "attributes":{
                "responsible":{
                    "id":"5ec29dfcd195548c7d716cf2",
                    "first_name":"Thomas",
                    "last_name":"Clemént"
                },
                "readers":null,
                "writers":null,
                "read_level":"guest",
                "created_at":"2020-05-18T16:38:53.244+02:00",
                "updated_at":"2020-05-18T16:38:53.244+02:00",
                "housing_request_id":"5ec29dfcd195548c7d716cf6",
                "lessor_id":"5ec29dfdd195548c7d716cfe",
                "code":"okplrdytdqrd",
                "expire_at":"2020-06-01T00:00:00.000+02:00",
                "public_url":"/api/dmo/housing_request_shares/5ec29dfdd195548c7d716cff?code=okplrdytdqrd"
            }
        }
    }

Lorsqu'une demande passe en candidature appliqué, (status: 'COMPLETE' ||'EN ATTENTE DE PIECES' ||'EN ATTENTE DE NUD'). Un enregistrement de type HousingRequestShare sera créé et un code de validation sera généré.

Il est aussi possible pour un utilisateur authentifié de créer manuellement un HousingRequestShare en fournissant un `:housing_request_id` et un `:lessor_id`

Pour accèder à la page publique de la liste des documents, il faut renseigner un id de HousingRequestShare ainsi que le code de validation qui est associé. Si l'id et le code sont valide, alors un objet HousingRequest avec les required_documents nesté sera retourné.

Il est possible de retrouver un objet `HousingRequestShare` grace l'id d'une `HousingRequest` mais *Attention : Il faut obligatoirement que le current_user est*
- soit le auth_role `superadministrateur`
- soit le auth_role `bailleur` auquel cas, il faut que le lessor_id de l'`HousingRequestShare` recherché soit le même que le lessor_id du current_user

Voici comment est attribué le lessor_id sur un objet `HousingRequestShare` :
- `housing_request_share.lessor_id = housing_request.main_applicant.entity.lessor.id`

Voici comment est vérifié l'accès pour un utilisateur avec le rôle bailleur :
- `housing_request_share.lessor_id == current_user.lessor_id`

Si une des deux conditions est respecté est que la `HousingRequest` en question possède bien une `HousingRequestShare` alors l'`HousingRequestShare` sera retourné

Requete GET

    GET /api/dmo/housing_request_shares/find_by_housing_request_id?housing_request_id=5ec29dfcd195548c7d716cf2

**Attention, après sa création, le code est valable pendant 15 jours**
## housing_request form_status

Afin que le frontend puisse informer le back de l'avancement et de la complétude du formulaire, un champs "form_status" est ajouté a la housing request.
il peut prendre les valeurs suivantes :

 - "empty" => valeur initiale
 - "invalid" => le formulaire ne satisfait pas les regles de validations
 - "in progress" => le formulaire satisfait les regles de validations mais n'a pas été validé par l'utilisateur
 - "complete" =>le formulaire satisfait les regles de validations et à été validé par l'utilisateur (seul status pris en compte par le back)
 - "cancelled" => demande annulée
l'envoi de flux 3O vers le SNE via sopra (en création comme en édition) est conditionné au fait que le form_status soit à "complete"

### modifications du request_status par rapport au form_status

voici les régression entrainées par l'evolution du form_status sur le request_status renvoyé enjson lors de la requete : 
        
| request_status de base \ form_status | empty | invalid | in progress | complete |
|--|--|--|--|--|
|"INCOMPLETE" | INCOMPLETE| INCOMPLETE| INCOMPLETE|**EN ATTENTE DE LA CNI**|
|"EN ATTENTE DE NUD" | INCOMPLETE| INCOMPLETE| INCOMPLETE|EN ATTENTE DE NUD|
|"EN ATTENTE DE PIECES" | INCOMPLETE| INCOMPLETE| INCOMPLETE|EN ATTENTE DE PIECES|
|"ELIGIBLE" | INCOMPLETE| INCOMPLETE| INCOMPLETE|ELIGIBLE|
|"COMPLETE" | INCOMPLETE| INCOMPLETE| INCOMPLETE|COMPLETE|

 
### Upload des document pour renseigner une piece à fournir (en ajout initial ou update)

    POST api/dmo/required_documents/${id}/send_files
    
    
Retour 200 avec le required document en body

cette requete peut etre executée pour mettre à jour une piece a fournir comme pour l'ajout initial. 
Le ou les fichiers nécessaires doivent etre envoyés en un seul et meme envoi sus la forme d'un formData contenant un ou plusieurs fichiers

retours erreurs possibles : 
 - 404 required document non trouvé
 - 422 "not_writers" => vous n'avez pas les droits d'écriture sur l'objet
 - 422 "no_file_in_the_request" => il n'y a pas de fichiers envoyés ac la requete

### Supression des fichiers liés a une piece 

    DELETE api/dmo/required_documents/${id}/files


Retour 200 avec le required document en body

retours erreurs possibles : 
 - 404 required document non trouvé
 - 422 "not_writers" => vous n'avez pas les droits d'écriture sur l'objet
 - 422 "object_is_locked_with_application_because_current_application_existing" =>une candidature est en cours et le dossier ne peut etre modifié


### Récupérer Historisations des statuts 

    GET api/dmo/required_documents/:id/historical_status 

    params: :id 
    
    {status: "success", code: 200, message: {'statuses' => statuses}} 

    5 statuts sont renvoyé de bases pour avoir la totalité il faut ajouter

    params: :id, more: true 
    

### Lancer un traitement de vérification du dossier

pour lancer la kycisation du dossier (l'idéal est de lancer cela lorsque l'un des trois status est à "Dossier complet prêt pour traitement")

    POST api/dmo/housing_requests/${id}/housing_request_folder/start_treatment

(a pour résultat temporaire de faire passer les pieces a "en attente de traitement" au status "piece validée")
## Securisation de la récupération des documents sur le SNE

### Demande d'envoi d'une clef d'authentification par mail :

    POST api/dmo/nuds/${numero_unique_departemental}/send_pin_code_on_mail
    
Lorsque une requete est envoyée sur ce point d'entré, une recherche d'existence du NUD est faite. si elle permet de remonter à un NUD existant, alors on evoie sur le mail qui lui est asscié un code à 6 caractères.

La récupération des demandes a partir du numéro unique etant débouchonnée, il faut désormais contacter Sopra (christophe.sebisch@soprasteria.com) pour obtenir des numéros uniques valides. 
Output :
-	200 – OK
-	400 – NUD non trouvé / incorrect
- 422 - voir le message d'erreur :

    - unique_number_not_covered_by_sne => le numéro unique n'est pas couvert dans la liste des départements
    - recuperation_of_housing_request_from_sne_already_done => le numéro unique a déja été utilisé pour créer une housing_request

Exemple d'une réponse avec un status 200

    {
      "email": "c*****************@soprasteria.com"
    }

note : provisoirement, l'email est 
- envoyé depuis l'adresse : securite@masolutionlogement.fr
- expédié sur l'adresse : recette.hermes@actionlogement.fr et comptetestals@gmail.com

### Envoi par l'utilisateur du code pin reçu sur son mail

    POST api/dmo/nuds/${numero_unique_departemental}/authentify_with_pin_code
    
    //avec en body de la requête : 
    {
      "pin_code": "A9i74M"
    }
    
Requete à envoyer lorsque l'utilisateur saisis le code qu'il vient de recevoir sur sa boite mail.
    
-	400 – aucune association trouvée ou association expirée
-	200 – OK, la réponse doit renvoyer une demande initialisée avec les infos issues du SNE si existantes sinon vide,
elle renvoie donc un objet du type "housing_request" dont le format est décrit plus haut dans cette documentation
- 422 - voir le message d'erreur :

    - unique_number_not_covered_by_sne => le numéro unique n'est pas couvert dans la liste des départements
    - recuperation_of_housing_request_from_sne_already_done => le numéro unique a déja été utilisé pour créer une housing_request
    - unable_to_send_mail_with_pin_code => un probleme est survenu lors de l'envoi
    
## gestion des codemandeurs

### Ajout d'un codemandeur

    PATCH api/dmo/housing_requests/{id}
    //avec en body de la requête : 
    {"data":
        {"attributes":
            {"coapplicants":[
                //laisser les autres codemandeurs si il y en a
                {
                    "rel_type":"P", //type de relation avec le demandeur principal
                    "id": applicant.id //id d'un objet applicant qu'on souhaite ajouter
                }
            ]}
        }
    }
    
### Supression d'un codemandeur

pour le retirer de la demande de logement :

    PATCH api/dmo/housing_requests/{id}
avec en body de la requête : 

    {"data":
        {"attributes":
            {"coapplicants":[
                //laisser les autres codemandeurs si il y en a
            ]}
        }
    }
 ou
 
    {"data":
        {"attributes":
            {"applicant_ids":[
                //laisser les autres applicant_ids si il y en a
            ]}
        }
    }
    
le fait de supprimer l'objet applicant entraine aussi la supression dans la liste des codemandeurs des demandes ou il est inscrit, mais cela peut avoir des conséquences facheuse si cet applicant est inscrit sur d'autres demandes.

    DELETE /api/dmo/applicants/{id}


## ajout d'un objectif bailleur

    POST /api/dmo/lessor_objectives
avec en attribut de la requete :

    {
        "data": {
            "attributes": {
                  "lessor_id": "string", //id du bailleur auquel est rataché l'objectif
                  "activation_date": "Date", //date d'activation
                  "district": "string", //ville sur laquelle s'applique l'objectif 
                                        // (attention, la facon dont est rempli ce champs doit correspondre directement au champs housing_offer.district 
                                        // pour que l'assignation se fasse - sensible a la casse )
                  "department": "string", //département sur lequel s'applique l'objectif 
                                          //(à renseigner si la ville est renseigné, 
                                          // attention, la facon dont est rempli ce champs doit correspondre directement au champs housing_offer.departement 
                                          // pour que l'assignation se fasse - sensible a la casse )
                  "threshold_type": "string", //norme
                  "priority_public": true, //public prioritaire
                  "new_offer": true, //Mise à l’habitation
                  "target_by_typologies": {  
                                            "T2": 30 //renseigner ici l'objectif attendu pour un type de logement donné
                                                     // valeurs possibles : "T1" ,"T2", "T3" etc...  utilisez "all" si l'objectif est pour tout les types de logements
                                            }
                   "agency_id": "string" //Entity_id de la filiale concernée
            }
      }
    }

format json de l'objet retourné :

                     {
                                 ...    
                            "department" : "String",
                              "district" : "String",
                        "threshold_type" : "String",
                       "priority_public" : "String",
                             "new_offer" : "String",
                    "present_typologies" : ["T1"],   //liste des Typologies présentes sur l'objectif
                             "lessor_id" : "String", //ID bailleur
                             "agency_id" : "String", //entity ID
                           "agency_name" : "String", //title de l'entity fournie 
                        "operation_name" : "String",  
                  "target_by_typologies" : {T1: 200}, //objectif initial
                "realized_by_typologies" : {T1:50}, //réalisé
    "objective_difference_by_typologies" : {T1:150} //reste à faire
         "targeted_offers_count" : 200 //nombre d'offre ayant la capacité de valider l'objectif si elles sont "LOUE"
         "lessor_objective_history_ids" : ["6DYZFHDUUS", ".....] id des objet lessor_objective_history concernés
                    }   
 
### detail des evenements d'objectif bailleurs

recuperer toute l'historique d'un objectif donné :

    GET /api/dmo/lessor_objective_histories?lessor_objective_id={:id}

recuperer un evenement particulier à partir de son id :

    GET /api/dmo/lessor_objective_histories/{:id}

rechercher toutes les offres qui ont validé un objectif donné

    GET /api/dmo/housing_offers?target_objective_ids={objective_id}&lessor_status="LOUE"

rechercher toutes les offres qui pouraient valider un objectif donné si elles passaient à LOUE 

    GET /api/dmo/housing_offers?target_objective_ids={objective_id}&lessor_status[$ne]="LOUE"

## récuperer toutes les opération_name des offres d'un bailleur

    GET /api/dmo/lessor/{:id}/current_operation_names
    
retour json

    [
        "Nom d'opération 1",
        "Nom d'opération 2",
        ...
    ]

## lier ou dé-lier un utilisateur à un bailleur
Permet de pouvoir identifier le Lessor d'un utilisateur courant (dans les cas ou le bailleur veut lier plusieurs utilisateurs à son compte bailleur, donc en plus du champ `:user_id` du modèle `Hermes::Lessor`)

    Put /api/dmo/lessor/{:id}/add_user
    Put /api/dmo/lessor/{:id}/remove_user

avec en attribut de requete :

    {
        "data": {
            "attributes": {
                "user_id": "string" // id de l'utilisateur à lier au compte bailleur
            }
        }
    }
    
retour json

    "user updated"

## Filtrer les demandes enregistrées par numéro siret

### Pour les entreprises

Utilisez le paramètre de recherche « main_employer_siret » contenant la liste des sirets (des employeurs des candidats) que l'on souhaite filtrer  :

    GET api/dmo/housing_requests?main_employer_siret[]=${siret1}&main_employer_siret[]=${siret2} 

### Pour les bailleurs

Utilisez le paramètre de recherche « siret » contenant la liste des sirets (des bailleurs) que l'on souhaite filtrer  :

    GET api/dmo/lessors?siret[$in][]=${siret1}&siret[$in][]=${siret2} 

## housing_request renseigner le champs seeked_localisation_list

    seeked_localisation_list' : [
        '{
            "nom": String,
            'code': String, //requis code insee de la commune (doit correspondre au code insée
            'codesPostaux' : [String], //requis liste des codes postaux de la commune (si elle a plusieurs code postaux
            "codeDepartement": "83", //requis
            'departement': String,
            ...  //l'api sauvegarde tout les couples clef valeurs voulus pour l'affichage front, le champs est libre.
        },
        {...},
        ...
    ]
    
## housing_request renseigner les dependants

    housing_request.dependents' : [
        '{
            'monthly_incomes': {pokemon_selling: 5, 'autre activité' : 33.45}, //nous ne nous occupons que de faire la somme des valeurs, le nom des clefs n'a pas d'importance coté back
            'monthly_charges': {unicorn_food: 10}, //nous ne nous occupons que de faire la somme des valeurs, le nom des clefs n'a pas d'importance coté back
            "last_name":"GALLET", 
            "first_name":"ANTONY", 
            "birth_date":"2017-03-23T00:00:00.000Z", 
            "rel_type":"E", 
            "sex":"M",
            "coparentality":"G", // G,D, ou null
            ...  //l'api sauvegarde tout les couples clef valeurs voulus pour l'affichage front, le champs est libre.
        },
        {...},
        ...
    ]
#### unborn_children
    
      housing_request.unborn_children : [
        {
          nb_child_birth: 1
          anticipated_birth : « DATE »,
        },
        ...
      ]

    
## récuperer la liste des départements valide pour le SNE

    GET /api/dmo/nuds/sne_department_list
    
retour :

    ["01", "02","04","05", ... ,  "971","972","973" ]

## Bailleur

### housing_offer

Création d'une nouvelle offre

    POST /api/dmo/housing_offers

Mise à jour d'une offre

    PUT /api/dmo/housing_offers/{housing_offer_id}

Champs interdits pour le role `'bailleur'`

    :als_siren
    :dalo
    :status
    :status_updated_at

### housing_request

Retrouver toute les housing_requests relative au current_user (si celui-ci à le role `'bailleur'`)

    GET /api/dmo/housing_requests?available=true

### Gestion de la requalification

Un bailleur peut reserver un logement qu'il a integré à la plate forme pour requalification, la requalification consiste à rapprocher une demande du SNE avec le logement existant dans Hermes.
Pour cela, le bailleur doit saisir les champs suivants lors de la création/mise à jour de son offre :

    {
        "offer_status": 'REQUALIFICATION'
    }

Grace à ce status, l'offre passera en `requalification: true`, il sera alors possible de la récupérer en utilisant le filtre de recherche adéquat.

Ensuite, il pourra directement lier l'offre à un candidat donné. Pour cela le bailleur doit fournir l'id de l'offre en question ansi que l'id du candidat. Si celui-ci n'est pas connu ou qu'il n'existe pas encore sur la plateforme, alors le bailleur peut utilisé le NUD ainsi que la date de naissance du candidat en question. Cette dernière sera utilisé à des fins de vérification.

**Utilisation avec applicant_id** [se reporter au swagger si besoin](/api/swagger/index.html)

    POST /api/dmo/housing_applications/attribution
    {
        "data": {
            "attributes": {
                "housing_offer_id": "5dc30a5ba70bf23b53a26475",
                "applicant_id": "5dc3c9bfa70bf25732aaa55b"
            }
        }
    }

**Utilisation avec NUD** [se reporter au swagger si besoin](/api/swagger/index.html)

Attention la date de naissance doit être sour le format `'YYYY-MM-DD'`

    POST /api/dmo/housing_applications/attribution
    {
        "data": {
            "attributes": {
                "housing_offer_id": "5dc30a5ba70bf23b53a26475",
                "nud": "123456789012345678",
                "birth_date": "1992-06-24"
            }
        }
    }

|status|raison|
|---|---|
|201|Attrribué avec succès|
|404|NUD inconnu|
|422|date de naissance invalide|

## Modèles geolocalisables
|field|type|info|
|---|---|---|
|`:address`|`string`||
|`:postal_code`|`string`||
|`:district`|`string`||
|`:country`|`string`||
|`:latitude`|`float`||
|`:longitude`|`float`||

Pour utiliser le géocodage dans un modèle, il faut inclure le concern `include ::Concerns::Geolocalizable`

Les modèles concernés sont `Hermes::Entity`, `Hermes::Applicant` et `Hermes::HousingOffer`, ils utilisent la [gem geocoder](https://github.com/alexreisner/geocoder)
et peuvent donc utiliser toute les méthodes de recherche qu'elle fournit.

- A chaque création de l'un de ces modèles, le geocode ou reverse_geocode est appelé
- A chaque mise à jour de l'un de ces modèles, si l'un des champs ci-dessus est modifié alors le geocode ou reverse_geocode est appelé

**Attention** Afin de ne pas être blocant, l'appel api pour le geocodage est executé dans une tache paralèlle, les données ne seront donc pas retournées immédiatement après la création/modification d'un enregistrement geocodable, cela implique donc une seconde requete (GET) pour recevoir ces informations

## Rôles utilisateurs

  Il existe 2 types de rôle : 
   - Administratif qui sont stocké sur le champs `roles` : 
     - `Administrator`, 
     - `SuperAdmin`, 
     - `Manager`
   - Métier qui sont stocké sur le champs `auth_roles` : 
     - `superadministrateur`, 
     - `demandeur`, 
     - `bailleur`, 
     - `entreprise`, 
     - `cre`, 
     - `rdsl`, 
     - `reservataire`, 
     - `collaborateur offre logement`, 
     - `collaborateur entreprises`
  
  Le role `superadministrateur` permet d'outrepasser les droits 

## Réservataire

    Création d'un Porteur de reservation via POST /api/dmo/reservation_holder
    
    Ajout d'un attribut reservation_holder_id sur les offres et demandes pour donner les droits aux utilisateurs avec le auth_roles 'reservataire' et le reservation_holder_id correspondant

## Filtrer les offres publiques par dates

    GET api/dmo/public_housing_offers

Ajouter les paramètres 

    date_publication_start[$gte]=${date limite inférieure} // au format YYYY-MM-DD
    publication_end_date[$lte]=${date limite supérieure} // au format YYYY-MM-DD

La requête va retourner toutes les offres publiques dont les dates de publication sont comprises entre les 2 paramètres.

## Récupération de l'historique des décomptes bailleurs par n° d'offre

    GET api/dmo/housing_offers/{id de l'offre}/history

La requête va retourner le tableau d'historique des décomptes bailleurs pour une offre, si l'utilisateur est le reservataire ou le bailleur de cette offre.

Le champ `created_at` est le timestamp du moment où un objectif a été réalisé.  
Les `target_by_typologies` et `realized_by_typologies` sont les copies des "attendus" et "réalisés" à ce moment.

```
  [  
    {
      "id": "5e4fdc8b3604e9cfbf4d055e",
      "type": "lessor_objective_history",
      "attributes": {
        ...
        "created_at": "2020-02-21T14:35:07.613+01:00",
        "lessor_objective_id": "5dc3c9bfa70bf25732aaa55b",
        "lessor_id": "5dc2d6b6a70bf24cc5b33594",
        "housing_offer_id": "5dc30a5ba70bf23b53a26475",
        "target_by_typologies": {
          "T3": 25,
        },
        "realized_by_typologies": {
          "T3": 3,
        }
      }
    }
  ]
```

## Récupération du score détaillé par n° d'offre pour un demandeur donné


Si l'utilisateur est demandeur sur l'offre, la requête va retourner son score détaillé.

    GET api/dmo/housing_offers/{id de l'offre}/detailed_score

Si l'utilisateur est au moins lecteur de l'offre, le paramètre `applicant_id` est **obligatoire**. La requête ne retourne le score pour ce demandeur que si l'utilisateur est également au moins lecteur du demandeur.

    GET api/dmo/housing_offers/{id de l'offre}/detailed_score?applicant_id={id de l'applicant}




## Renseigner la date de visite pour une candidature

    PATCH/PUT api/dmo/housing_applications/{housing_application_id}

avec en body de la requête : 

    {
      "data": {
        "attributes": {
          "visit_conducted_date": 'DD/MM/YYYY' // date de la visite
        }
      }
    }

  
## Fonctionnement de la création/update/auto_delete des offres 

Lorsqu'on crée un offre, un recherche est effectuée sur le champs lessor_id et external_ref.
Si une offre correspondante existe, elle est mise a jour avec les infos transmises lors de l'update.

A chaque modifications de l'offre via l'api, si l'offre a le champs housing_offer.auto_destroy_next_day à true, un compte à rebour de 36h se déclenche.
A l'issue de ce compte à rebours, si aucune requête de création ou d'update n'a été faite sur l'offre par le bailleur, le offer_status passe à "RETIRE PAR LE BAILLEUR"
et les actions suivantes sont exécutées :

 - envoi du flux 12 pour informer sopra de la reprise par le bailleur (status "RBA").
 - à spécifier
 - à spécifier
 


## Centre de Notifications
- Endpoint notifications: `/api/dmo/{targetable_type}/{targetable_id}/notifications`
- Endpoint subscriptions: `/api/dmo/{targetable_type}/{targetable_id}/subscriptions`
- [Collection postman](https://www.getpostman.com/collections/2d165c413a89f7df87f9)

### Utilisation
Lors de de certaines actions une notification peut être créé. Cette notification est un
enregistrement en base de donnée qui relie une entité **notifiable** et une entité **targetable**. Par exemple, lorsqu'un
nouveau logement est disponible et est éligible pour un salarié donné, **HousingOffer** est le **notifiable** et Applicant le **targetable**.

Par défaut un **Applicant** sera notifié par email lorsqu'une nouvelle notification lui sera destiné mais il est possible
de créer un abonnement à un type de notification et de spécifier si oui ou non les emails doivent être envoyés lors de
la création d'une nouvelle notification.
Si l'email est envoyé, celui-ci contient un message informant d'une nouvelle notification, et d'un lien permettant de
redirigé vers l'entité notifiable en question.

L'api fournit une série de routes permettants la gestion des notifications et abonnements.

### Clés d'abonnement aux notifications disponible
|Modèle|Clé|Création|
|---|---|---|
|Hermes::HousingRequest|housing_request.status.change|Si le status d'une HousingRequest est modifié, alors on notifie le candidat|
|Hermes::HousingOffer|housing_offer.new.eligible|Si un candiat est éligible à un nouveau logement lors de la création d'un score, celui-ci est notifé|

### Exemple pour la gestion des notifications d'un Applicant

**Objet Notification**

    {
    "data": {
        "id": "5e848a63d19554699b8358d0",
        "type": "notifications",
        "attributes": {
            "responsible": {
                "id": "5dd39e0ca70bf2255538a2eb",
                "first_name": "Pierre",
                "last_name": "DUPONT"
            },
            "readers": null,
            "writers": null,
            "read_level": "guest",
            "created_at": "2020-04-01T14:34:45.221+02:00",
            "updated_at": "2020-04-01T15:01:42.704+02:00",
            "title": "Notification title",
            "body": "Notification body",
            "opened_at": "2020-04-01T15:01:42.703+02:00",
            "key": "housing_offer.new_eligible",
            "sender_type": "Hermes::Lessor",
            "sender_id": "5dd26f45a70bf26eeed14b3a",
            "notifiable_type": "Hermes::HousingOffer",
            "notifiable_id": "5dfa69c122ec79668b6c1077",
            "subscription_id": "5e848a5dd19554699b8358cf"
        }
    }
}

**Récupération de la liste de ses notifications**

    GET /api/dmo/applicants/5dcd4a32a70bf24770e869b2/notifications

    status: 200

**Marquer une notification comme lue**

    PUT /api/dmo/applicants/5dcd4a32a70bf24770e869b2/notifications/5e5d2534d195540cc306cec2/open

    status: 200

**Ouvrir toute les notifications**
Il est possible d'utiliser le query param `:limit` afin d'ouvrir (x) notifications

    PUT /api/dmo/applicants/5dcd4a32a70bf24770e869b2/notifications/open_all

    status: 200

**Supprimer une notification**

    DELETE /api/dmo/applicants/5dcd4a32a70bf24770e869b2/notifications/5e5d2534d195540cc306cec2

    status: 204
### Exemple pour la gestion des abonnements d'un Applicant

**Objet abonnement**

    {
        "data": {
            "id": "5e848a5dd19554699b8358cf",
            "type": "subscriptions",
            "attributes": {
                "responsible": {
                    "id": "5dd39e0ca70bf2255538a2eb",
                    "first_name": "Pierre",
                    "last_name": "DUPONT"
                },
                "readers": null,
                "writers": null,
                "read_level": "guest",
                "created_at": "2020-04-01T14:34:37.391+02:00",
                "updated_at": "2020-04-01T14:34:37.391+02:00",
                "keys": [
                    {
                        "name": "housing_request.status.change",
                        "email": true,
                        "slack": false
                    },
                    {
                        "name": "housing_offer.new.eligible",
                        "email": true,
                        "slack": false
                    },
                ],
                "subscriber_type": "Hermes::Applicant",
                "subscriber_id": "5dd39e0ca70bf2255538a2eb"
            }
        }
    }

**Récupération de la liste des abonnements**

    GET /api/dmo/applicants/5dcd4a32a70bf24770e869b2/subscriptions/5e848a5dd19554699b8358cf

    status: 200

**S'abonner**

    PUT /api/dmo/applicants/5dcd4a32a70bf24770e869b2/subscriptions/5e848a5dd19554699b8358cf/subscribe

body

    {
        "provider": "email",
        "key": "housing_offer.new.eligible"
    }

    status: 200
    

**Se désabonner**

    PUT api/dmo/applicants/5dcd4a32a70bf24770e869b2/subscriptions/5e848a5dd19554699b8358cf/unsubscribe

body

    {
        "provider": "email",
        "key": "housing_offer.new.eligible"
    }

    status: 200

### HousingRequest notifications personalisés
Il est possible d'envoyé une notification personnalisé au candidat principal d'une demande et de sélectionner
le cannal de diffusion parmis les cannaux disponibles (email, sms, slack).

    POST api/dmo/housing_requests/5ec8f699d195547125211a45/notify

Avec en body :

    {
      "data": {
        "attributes": {
          "title": "Titre de la notification",
          "body": "Corps de la notification",
          "channels"?: ["sms"]
        }
      }
    }

Réponse : 

    {
        "data": {
            "id": "5ec8f699d195547125211a4f",
            "type": "notifications",
            "attributes": {
            "responsible": {
                "id": "5ec8f699d195547125211a42",
                "first_name": "Kylian",
                "last_name": "Giraud"
            },
            "readers": null,
            "writers": null,
            "read_level": "guest",
            "created_at": "2020-05-23T12:10:33.956+02:00",
            "updated_at": "2020-05-23T12:10:33.956+02:00",
            "title": "Titre de la notification",
            "body": "Corps de la notification",
            "opened_at": null,
            "key": "housing_request.custom.notification",
            "channels": [confiant
            "sender_type": "User",
            "sender_id": "5ec8f699d195547125211a43", // current_user
            "notifiable_type": "Hermes::HousingRequest",
            "notifiable_id": "5ec8f699d195547125211a45",
            "targetable_type": "Hermes::Applicant",
            "targetable_id": "5ec8f7aad195547356fef879", // main_applicant
            "subscription_id": "5ec8f699d195547125211a50"
            }
        }
    }

### Notifications journalière des nouvelles offres (Email)
Chaque jours, à 6h00 une notification mail sera envoyé à tout les demandeurs actif (qui ont une demande active) afin de leur informer de la liste des nouveaux logements auquels ils sont éligibles depuis le précédent email. Le mail sera envoyé uniquement si au moins un nouveau logement est présent sur la plateforme.

Pour que le mail soit envoyé tout les jours de manière automatique, il faut passer via l'interface Plugandwork, sur la route /admin/batchs et procédé de la manière suivante :

- Cliquer sur "Nouveau lot de travaux"
- Donner un nom (exemple daily_offers_notifier)
- Dans le champ **Recurrence (format crontab ou 1d, 30s ...)** ajouter `0 6 * * *` ou `1d`
- Selectionner une date et heure de premier lancement
- Cliquer sur Ajouter
- Vous serez alors redirigé vers la liste des batchs
- Cliquer sur `Editer` du batch que vous venez de créer
- Cliquer sur l'icone apparu juste à côté du champ `Script`
- Coller le code suivant à l'interieur `Hermes::Applicant.daily_offers_notifier`
- Cliquer sur Enregistrer

Si toutes les étapes ont bien étaient respectées, alors le script sera executer tout les jours à l'heure selectionné

## Désactiver ou supprimer une demande
  Impossibilité de désactiver/supprimer un demande si elle a des candidatures

    PATCH/PUT api/dmo/housing_requests/{id}

Avec en body : 

    {
      "data": {
        "attributes": {
          "is_active": false
        }
      }
    }

  ou 

    DELETE api/dmo/housing_requests/{id}

## Points managing on housing requests 

    Add points to entity  User must be collaborateur offre logement
    POST /api/dmo/entities/:entity_id/add_points

        params: entity_id: , points_to_add:
        {status: "success", code: 200, message: {"message" => "successfullly modified", "value" => entity.available_points}}

    Add points from an entity to an housing request user must be entreprise

    POST api/dmo/housing_requests/{id}/add_points_to_housing_request

        params: id: , points: , entity_id:

        {status: "success", code: 200, message: {'message' => 'points successfully added', 'points_added' => points}}


    List the points that are waiting 
    GET api/dmo/housing_requests/{id}/waiting_points

        params: id: 

        {status: "success", code: 200, message: {'waiting_points' => waiting_points}}

    List the points that have been spent
    GET api/dmo/housing_requests/{id}/spent_points
        
        params: id: 

        {status: "success", code: 200, message: {'spent_points' => spent_points}}

    List all the entity account request

    GET api/dmo/housing_requests/{id}/entity_requests
        params: id: 
        {status: "success", code: 200, message: {'entity_requests_account' => entity_requests_account}}


## Gestion des entity note / internal note 

    lire entity note d'une request 

    GET  api/dmo/housing_requests/{id}/entity_note
        params:  id:
        {status: "success", code: 200, message: entity_note}

  lire internal note d'une request 

    GET  api/dmo/housing_requests/{id}/internal_note
        params:  id:
        {status: "success", code: 200, message: internal_note}
        
        

    Modifier entity note 

        PUT api/dmo/housing_requests/{id}/update_entity_note
        params: id:, entity_note:

        {status: "success", code: 200, message: {"message" => "successfullly modified", "value" => entity_note}}


    Modifier internal note 

        PUT api/dmo/housing_requests/{id}/update_internal_note
        params: id:, internal_note:

        {status: "success", code: 200, message: {"message" => "successfullly modified", "value" => internal}}

## Changer le manual mode d'une entity / lessor

    Le user doit avoir comme rôle Superadmin
    Si l'entity / lessor à un manual mode en true elle changera en false et vice versa

    PUT /api/dmo/entities/{id}/switch_manual_mode
    params: id:

    PUT /api/dmo/lessors/{id}/switch_manual_mode
    params: id:

   {status: "success", code: 200, message: "manual mode switch to true / false"}




## Trier les offres par codes postaux souhaités en premiers

    GET api/dmo/housing_offers

Ajouter en paramètre un array de codes postaux dans l'ordre souhaité

    postal_codes[]={code postal souhaité 1} (e.g. 75100)
    postal_codes[]={code postal souhaité 2} (e.g. 34200)

La requête va retourner en premier les offres dont les codes postaux sont "75100" puis les offres dont les codes postaux sont "34200" puis toutes les autres offres.

**Pour afficher le positionnement d'un candidat par rapport à sa localisation**


Si l'utilisateur courant est demandeur sur l'offre :

    GET api/dmo/housing_offers/{id de l'offre}/score_position

Si l'utilisateur courant n'est pas demandeur :

  Pour avoir le score d'un applicant, vous pouvez ajouter le paramètre `applicant_id` :

    GET api/dmo/housing_offers/{id de l'offre}/score_position?applicant_id={id de l'applicant}

  Si le score est trouvé, la requête retourne alors le positionnement de l'utilisateur courant (s'il est demandeur) ou du candidat renseigné via l'`applicant_id` : 

    {
      "position_by_department": 4,
      "total_by_department": 10,
      "position_by_postal_code": 4,
      "total_by_postal_code": 10
    }

  Sans le paramètre `applicant_id` vous recevrez juste les totaux :
  
    {
      "total_by_department": 10,
      "total_by_postal_code": 10
    }

Avec "total_by_department/postal_code", le nombre de scores de l'offre pour le departement/code postal du candidat.  
Et "position_by_department/postal_code", la position sur l'offre pour le departement/code postal du candidat.

## Trier les offres par localisation

    GET api/dmo/housing_offers?longitude=44.55127&latitude=4.75386&distance=130

|fields|type|default|
|---|---|---|
|:longitude|:float|`null`|
|:latitude|:float|`null`|
|:distance|:integer|`20`|
|:unit|`km | meter`|`km`|

Le filtre sur la localisation étant apliqué en dernier, les conditions de récupération des offres reste exactement les mêmes.

Si les paramètres `:longitude` et `:latitude` sont fournis, alors le filtre sur la localisation sera appliqué.

## Fonctionnement du scoring
  Pour chaque offre un score est créé pour chaque demandeur éligible qui contient ses informations (accessible sur l'offre/candidature) :
    - eligible_position
    - applicated_position
    - eligible_requests_nb
    - applicated_nb

## Fonctionnement REX

  Liens de parenté via le champs parent_id dans les entities/lessors
  id_rex et cristal_id qui donne les ids correspondant dans les différents services

  Tous les appels retourne les données en fonctionne de l'habillitation de l'utilisateur.
  Pour ses 2 appels, on peut spécifier le parmètre for_lessor=true pour n'avoir que les bailleurs

  Retourne l'id et le nom des élements à la racine des arborescence: 
    
    GET /api/dmo/rex/root_elements?for_lessor=true|false

    {
        "data"=>[
            {
                "id"=>"5ebe3c03a6f7e901dbbed1d4", 
                "type"=>"hermes-entities", 
                "attributes"=>{
                    "title"=>"etpA1"
                }
            }, {
                "id"=>"5ebe3c04a6f7e901dbbed1f0", 
                "type"=>"hermes-entities", 
                "attributes"=>{
                    "title"=>"etpB1"
                }
            }
        ]
    }

  Retourne l'arborescence compléte pour une entreprise/bailleur: 
    
    GET /api/dmo/rex/{entity_id/lessor_id}?for_lessor=true|false
  
    {
        data: {
            from_element: {
                id: entity_id,
                ... # information de l'entreprise/bailleur qui correspond à entity_id/lessor_id
            },
            tree: [
                {
                    ... # information de l'enfant 1 dans l'arbrorescence REX
                    children: [
                        {
                            ... # information de l'enfant de l'enfant 1 dans l'arbrorescence REX
                        }
                    ]
                },
                {
                    ... # information de l'enfant 2 dans l'arbrorescence REX
                }
            ]
        }
    }

  Retourne les filliales pour une liste de parents
    
    GET /api/dmo/rex/subsidiaries?parent_ids[id1]&parent_ids[id2]&for_lessor=true|false



## Règles de dépublication d'une offre

### Pour administrateurs uniquement en CRUD complet

Exemple de création d'un nouveau réglage de dépublication : 

    POST api/dmo/housing_offer_expiration_settings

Avec en body 

    {
      "data": {
        "attributes": {
          "department": '34',
          "max_applicants": 10,          // seuil de candidatures max
          "minimal_publication_days": 3, // durée de vie minimale de l'offre en jour
          "expiry_days": 7,              // nombre de jours avant dépublication
          "lessor_id": {id du bailleur} 
        }
      }
    }

### Automatisation de la dépublication

Une offre **publiée**, créée ou éditée, récupère automatiquement le `max_applicants` et le `minimal_publication_days` (par défaut 3) du réglage correspondant à son département et lessor_id.

La date de dépublication (`publication_end_date`) est alors automatiquement calculée et enregistrée à `date_start_publication + expiry_days` (par défaut 7).

Lorsqu'une offre dépasse son seuil de candidatures **et** sa durée minimale de vie, elle est automatiquement dépubliée (offer_status: 'COMMERCIALISATION NON PUBLIEE')

### Remarques

Si le `max_applicants` n'est pas renseigné, l'offre n'a pas de seuil de candidatures.

Si un `expiry_days` est set à la création ou à l'édition d'une offre, il prend le pas sur celui du réglage (`housing_offer_expiration_setting`)  
- Exemple : si j'enregistre une offre avec `expiry_days = 20` et qu'il existe un réglage avec `expiry_days = 11`, ma date de dépublication sera de `publication_start_date + 20`

Si une date de dépublication (`publication_end_date`) est set à la création ou à l'édition d'une offre, c'est elle qui sera prise en compte quelque soit le réglage et/ou le `expiry_days` existant(s).

## Mailing form 

Faire une demande de code captcha :

    GET /api/dmo/public_forms/captcha

Réponse type :

    {status: "success", code: 200, message: {'captcha' => str', 'form_mailer_token' => "mailer_data_#{form_mailer_token}"}}

Le code captcha que vous recevez est une opération comme 1+2 ou 2-1

    POST /api/dmo/public_forms/confirm

Pour pouvoir envoyer un mail, confirmez le captcha sur l'endpoint ci-dessus avec en body de la requête :

        {
            res => resultat du captcha 
            form_id => id du form pour origine du mail 
            email => mail du destinataire
            content => contenu du mail 
            form_mailer_token => token reçu dans dans le GET du /captcha 

        }

Réponse type :

        {status: "success", code: 200, message: "mail delivered"}

## Zones détendues : untensed_area

Objectif :  Pouvoir definir des zones pour lesquelles le dossier de cadidature est allégé en termes de pieces justificatives a fournir.

Les administrateurs de l'application ont la possibilité de venir créer/modifier/supprimer/voir les zones détendues grace à un CRUD classique similaire aux autres objets de l'application :

Le modèle untensed_area est classique : 

    POST /api/dmo/untensed_areas  ->creation
    GET /api/dmo/untensed_areas  ->liste des zones détendues (on peut utiliser tout les modificateurs classiques de recherche)
    GET /api/dmo/untensed_areas/{id}  ->lecture d'une untensed_area
    PUT/PATCH /api/dmo/untensed_areas/{id}  ->modification
    DELETE /api/dmo/untensed_areas/{id}   ->supression

la donnée est affichée et modifiable sous ce format (l'idéal etant de renseigner ou le code comune ou le département, si le code commune et le département sont renseignés en meme temps, l'algorithme considerera que tout le département est en zone détendue) :

    data : {
        attributes : {
                           insee_code: 'String', // code insee de la commune à inclure dans les zones détendues
                           department: 'String', // departement à considerer comme zone détendue
                       }
     }
     
Lorsqu'une nouvelle zone détendue est ajoutée, modifiée, ou supprimée, l'ensemble des demandes concernées sont mises a jour et se voient attribuer le booleen "is_untensed_area" à true ou a false en fonction des communes choisies dans "seeked_localisation_list".

Le dossier de pieces justificatives des demandes avec le booléen "is_untensed_area" est automatiquement recalculé et seules les pieces liées a l'identitée du demandeur principal sont requises.

Ce recalcul est aussi effectué lorsque les "seeked_localisation_list" de la housing_request sont créées ou modifiées.

## Gestion des filières logements

Les filières logements sont gérées via 2 modèles : `HousingChannel` (filière logement) et `HousingChannelSetting` (filtrage des filières par département).
La lecture et l'écriture de ces 2 modèles sont uniquement accessibles au role **Administrator**.

### Pour administrateurs uniquement

1. **HousingChannel (filière logement)**

Requête pour créer une nouvelle filière logement : 

    POST api/dmo/housing_channels

Requête pour mettre à jour une filière logement : 

    PUT api/dmo/housing_channels/{id de l'housing_channel}

Avec en body pour les 2 requêtes : 

    {
      "data": {
        "attributes": {
          "key"(required): 'string', // e.g. 'public_priority'
          "label": 'string',         // e.g. 'Offre Public prioritaire'
          "request_name": 'string'   // e.g. 'Demande Publique prioritaire validés'
          "code_ikos": 'string'      // e.g. 'PUBPR'
        }
      }
    }

Pour supprimer une filière : 

    DELETE api/dmo/housing_channels/{id de l'housing_channel}

Pour afficher la liste des filières logement (utilitaires de tri disponibles $in, $nin, $ne, $eq, $all) : 

    GET api/dmo/housing_channels

Pour afficher une filière logement spécifique : 

    GET api/dmo/housing_channels/{id de l'housing_channel}

2. **HousingChannelSetting (filtrage des filières par département)**

Un utilisateur **Administrator** peut créer un filtrage de filière (`HousingChannelSetting`) pour un département donné. Il renseigne alors dans le tableau `housing_channel_keys`, les clés des filières logement qu'il souhaite associer à ce département.

**Attention, les clés ajoutées dans le tableau `housing_channel_keys` doivent correspondre au champ `key` de filières `HousingChannel` préalablement créées.**

Requête pour créer un nouveau filtrage : 

    POST api/dmo/housing_channel_settings

Requête pour mettre à jour un filtrage : 

    PUT api/dmo/housing_channel_settings/{id de l'housing_channel_setting'}

Avec en body pour les 2 requêtes : 

    {
      "data": {
        "attributes": {
          "department"(required): '34',
          "insee_code": '34001',
          "housing_channel_keys": ['priority_public', 'dalo'] 
        }
      }
    }

Pour supprimer un filtrage : 

    DELETE api/dmo/housing_channel_settings/{id de l'housing_channel_setting}

Pour afficher la liste des filtrages (utilitaires de tri disponibles $in, $nin, $ne, $eq, $all) : 

    GET api/dmo/housing_channel_settings

Pour afficher un filtrage spécifique : 

    GET api/dmo/housing_channel_settings/{id de l'housing_channel}

### Ajout et validation des filières logements pour une HousingRequest

Une `HousingRequest` porte dorénavant 3 nouveaux champs de type `array` : 

- • `housing_channel_pending_keys` : correspond aux clés des filières logement en attente de validation pour une demande de logement.
- • `housing_channel_keys` : correspond aux clés des filières logement validées pour une demande de logement.
- • `housing_channel_chosen_keys` : correspond aux mêmes clés des filières ajoutées dans le tableau "pending". Cependant ce tableau de clés "chosen" est immuable.

  --- 

  **Attention, la mise en attente de validation puis la validation des clés de filières est désactivée, cf. point 4 ci-dessous**

  --- 

1. **Ajout d'une filière logement en attente de validation**

Pour ajouter une clé de filière logement sur une HousingRequest :

    POST api/dmo/housing_requests/{id de l'housing_request}/add_housing_channel

Avec en body 

    {
      "keys"(required): ['dalo']
    }

**Attention, la clé ajoutée doit correspondre à une filière `HousingChannel` existante.**

La clé est alors ajoutée dans le tableau `housing_channel_pending_keys` **et** dans le tableau `housing_channel_chosen_keys` d'une demande de logement.   
Si le nom de la clé correspond à un champ booléen d'`HousingRequest` (comme 'dalo' ou 'priority_public'), celui-ci passe à `false`.

    GET api/dmo/housing_request/{id de l'housing_request}

    {
      "data": {
        "id": "5dc27c71a70bf201ccee9d39",
        "type": "housing_requests",
        "attributes": {
          ...
          "housing_channel_chosen_keys": [
            'dalo'
          ],
          "housing_channel_pending_keys": [
            'dalo'
          ],
          "housing_channel_keys": [],
          "dalo": false
        }
      }
    }


2. **Validation d'une filière logement**

Pour valider une clé de filière logement sur une HousingRequest :

    POST api/dmo/housing_requests/{id de l'housing_request}/validate_housing_channel

Avec en body 

    {
      "keys"(required): ['dalo']
    }

**Attention, la clé ajoutée doit correspondre à une filière `HousingChannel` existante.**   
**Elle doit également être présente au préalable dans le champ `housing_channel_pending_keys` de l'housing_request.**

La filière validée passe alors de `housing_channel_pending_keys` à `housing_channel_keys`. Le tableau `housing_channel_chosen_keys` reste inchangé.   
Si le nom de la clé correspond à un champ booléen d'`HousingRequest` (comme 'dalo' ou 'priority_public'), celui-ci passe à `true`.

    GET api/dmo/housing_request/{id de l'housing_request}

    {
      "data": {
        "id": "5dc27c71a70bf201ccee9d39",
        "type": "housing_requests",
        "attributes": {
          ...
          "housing_channel_chosen_keys": [
            'dalo'
          ],
          "housing_channel_pending_keys": [],
          "housing_channel_keys": [
            'dalo'
          ],
          "dalo": true
        }
      }
    }

3. **Filtrage par département**

S'il existe un filtrage de filières (`HousingChannelSetting`) pour un des départements recherchés (`truly_seeked_departments`), on ne peut ajouter à la demande de logement que des filières logement dont les clés sont incluses dans le filtrage.

Exemple : 

Soit le filtrage (`HousingChannelSetting`) suivant : 

    {
      "department": "34",
      "insee_code": null,
      "housing_channel_keys": [
        "dalo"
      ]
    }

Et la demande de logement suivante : 

    {
      "data": {
        "id": "5dc27c71a70bf201ccee9d39",
        "type": "housing_requests",
        "attributes": {
          ...
          "truly_seeked_departments": [
            '34'
          ],
          "housing_channel_chosen_keys": [],
          "housing_channel_pending_keys": [],
          "housing_channel_keys": []
        }
      }
    }

Je ne peux ajouter pour cette demande que la filière "dalo", car c'est la seule disponible pour le département '34'.

4. **Bypass de la validation**

Actuellement, seule la requête api suivante est disponible pour une HousingRequest : 

    POST api/dmo/housing_requests/{id de l'housing_request}/add_housing_channel

Avec en body 

    {
      "keys"(required): ['dalo']
    }

Elle n'ajoute pas la clé dans le tableau `housing_channel_pending_keys` mais directement dans le tableau final `housing_channel_keys` sans passer par l'étape de validation.

- • les clés sont toujours dupliquées dans le tableau `housing_channel_chosen_keys`.
- • le filtrage par département est toujours actif et fonctionnel.

5. **Supression d'une clé de filière sur la demande**

Pour retirer une housing_channel d'une HousingRequest : 

    POST api/dmo/housing_requests/{id de l'housing_request}/remove_housing_channel

Avec en body 

    {
      "keys"(required): ['cle_à_supprimer']
    }


### Ajout et suppression de clés de filières logement pour une HousingOffer

Une `HousingOffer` porte dorénavant un nouveau champ `housing_channel_keys`.

**Les requêtes API sont disponibles uniquement pour :**

- • les utilisateurs 'bailleur' qui sont au moins lecteurs du `lessor_id` porté par l'offre.
- • les utilisateurs 'reservataire'/'collaborateur offre logement' dont le `reservation_holder_id` correspond au `reservation_holder_id` de l'offre.

Pour ajouter une clé de filière :  

    POST api/dmo/housing_offers/{id de l'housing_offer}/add_housing_channel

Avec en body 

    {
      "keys"(required): ['cle_à_ajouter'] // e.g. 'dalo'
    }

**Attention, la clé ajoutée doit correspondre à une filière `HousingChannel` existante.**

Pour supprimer une clé de filière :  

    POST api/dmo/housing_offers/{id de l'housing_offer}/remove_housing_channel

Avec en body 

    {
      "keys(required): ['cle_à_supprimer']
    }


## Mise a jour de la demande avec les infos du SNE.

### Fonctionnement :
A chaque GET sur une housing_request, une routine qui ne se déclenche au maximum qu'un fois toutes les 24h vient verifier la dateFichier du retour XML de la demande récupérée par rapport au updated_at de la housing_request en bdd.

si la date de la demande sur le sne est plus récente que celle sur hermes, le booléen "is_sne_update_available" est passé à true et est visible dans le json de la housing_request.

### Chemin API :

pour mettre à jour les informations de la housing_request et des applicants a partir des informations contenues dans le SNE, il faut appeller :

    POST /api/dmo/housing_requests/{id}/update_from_sne
    
cette requete écrasera toutes les informations de la demande avec celles contenues dans le SNE.

## Recupération des retours erreurs des appels asynchrones vers le SNE/Sopra par le frontend :

Il faut se connecter avec un client faye js(websocket) sur le channel 

    /logs/users 
et filtrer les messages par code et par user_id


Les messages renvoyé dans ce channel comportent les infos suivantes :

    { 
      "code" : (le code erreur), 
      "log_id" : (l'id du log), 
      "id" : (l'id du user)
    }

donc si on traite les messages dont l'id du user est bien celui de l'utilisateur connecté il reste à vérifier le code erreur, si celui çi doit être affiché avec plus d'information. Il faut ensuite aller chercher le log sur 
      
      GET /api/d2/logs/ID_DU_LOG 
      
 l'id du log etant log_id dans le message websocket/faye

Exemple de librairie websocket faye angular : https://github.com/monterail/angular-faye

### fonctionnement

Lorsqu'une erreur se produit lors de l'appel d'un flux sopra, un log emmetant un evenement websocket est produit. ce log contient l'url appelée ainsi que le retour erreur du webservice sopra .

## Entreprises

### Compteur de demandes

La route permet grace à un `:entity_id` donné de pouvoir récupérer la liste des demandes en cours de saisie `in_process` ou de délégation `delegations` d'une entreprise.

      GET /entities/:id/housing_requests_count

      {
        "delegations": 10,
        "in_process": 20
      }

### Validation des matricules

**Ce modèle est nommé `EntityValidation`**

La validation de matricule est le fait pour une entrprise de valider qu'un salarier travaille bien pour elle et que le contrat est toujours actif.

Pour ce qui est des validations via matricule, cela concerne surtout les demandes et non les requalifications.
Le matricule n'étant pas un champ SNE, on ne l'aura pas pour une requalification, donc on passe forcément par l'attente d'une validation manuelle (cas par défaut).

La mise à jour de la date de fin de contrat declenche un job (à date) qui enlèvera l'entreprise de la demande et invalidera la candidature en cours

#### Impact score

Lors du calcul de score, si un candidat a une EntityValidation avec les champs `:validation` et `:active` à `true` alors **210 points** seront attributés


#### Liste des champs

|Name|Type|Editable|Format|Default|Infos
|---|---|---|---|---|---|---|
|entity_id|:srting|false|`"5e4fdc8b3604e9cfbf4d055e"`|auto|Entreprise lié à l'utilisateur courant|
|applicant_id|:srting|true|`"5e4fdc8b3604e9cfbf4d055e"`|null|Obligatoire lors de la création|
|identification_number|:srting|true|`"5e4fdc8b3604e9cfbf4d055e"`|null|Obligatoire lors de la création|
|civility|:srting|true|`"Mr", "Mme", "Mlle"`|null|Récupéré sur le candidat si aucun de [civility, first_name, last_name, birth_date] n'est fournit à la création|
|first_name|:srting|true|`"Jhon"`|null|Récupéré sur le candidat si aucun de [civility, first_name, last_name, birth_date] n'est fournit à la création|
|last_name|:srting|true|`"DOE"`|null|Récupéré sur le candidat si aucun de [civility, first_name, last_name, birth_date] n'est fournit à la création|
|birth_date|:srting|true|`"2020-08-24"`|null|Récupéré sur le candidat si aucun de [civility, first_name, last_name, birth_date] n'est fournit à la création|
|validation|:booleen|true|`true, fasle`|entity.auto_validation ou true|création/mise à jour|
|contract_start_date|:srting|true|`"2020-08-24"`|null|création/mise à jour|
|contract_end_date|:srting|true|`"2020-08-24"`|null|création/mise à jour|
|active|:booleen|false|`true, fasle`|auto|`true` si contract_start_date <= Date.today et contract_end_date > Date.today|
Lorsqu'une erreur se produit lors de l'appel d'un flux sopra, un log emmetant un evenement websocket est produit. ce log contient l'url appelée ainsi que le retour erreur du webservice sopra.

### Validation des demandes

**Attention à ne pas confondre avec la validation de matricule**

Par défaut, chaque entreprise est créée avec un champ `:auto_request_validation` à `true` ce champ est utilisé pour valider de manière automatique chaque demande émise par les salariers de l'entreprise `housing_request.entity_validated`.

Le champ `:auto_request_validation` peut êtrer modifié par les utilisateurs ayant un droit d'écriture sur l'entreprise.

*Voir **Validation du salarié par l'entreprise** pour les validations manuelles unitaire*

#### Impact score

Lors du calcul de score, si un demande a un `:entity_validated` à `false` les points liés à l'entreprise (`entity_points`) seront de `0`.

## Charges eau et chauffage individualisé pour taux d'effort

  Si le `heating_type` est défini sur une offre à une des valeurs suivante : 'Individuel gaz', 'Individuel PAC Electrique', 'Collectif autre', 'Individuel autre', 'Individuel électrique'. On ajoute des charges correspondantes pour l'eau et le chauffage pour le calcul du taux d'effort.
    
## Gestion des codes de rattachement candidat à une entreprise

Les codes sont gérés via le modèle `Hermes::EntityCode` uniquement disponible en lecture et écriture pour les utilisateurs role 'entreprise'.   
Le code est **généré automatiquement** s'il n'est pas renseigné à la création d'un nouvel entity_code. S'il est renseigné, celui-ci doit être **unique**.

### Vérification de la validité d'un code

    POST api/dmo/entity_codes/check_entity_code_validity

Avec en body : 

    {
      "code"(required): 'ZV39HP0P' // i.e. code à vérifier
    }

Si le code existe et est non expiré, la requête retourne la réponse suivante :

    {
      success: true,
      code: 'ZV39HP0P',
      message: 'Code valide et non expiré.'
    }

### Pour role 'entreprise' uniquement

Requête pour créer un nouvel entity_code : 

    POST api/dmo/entity_codes

Avec en body : 

    {
      "data": {
        "attributes": {
          "entity_id"(required): "ID de l'entity",
          "applicant_id": "ID de l'applicant",
          "code": "string",
          "expire_at": "JJ/MM/AAAA" // par défaut date du jour + 7 jours
        }
      }
    }

Si le code n'est pas renseigné à la création, il est alors généré aléatoirement :

    {
      "data": {
        "id": "5ea06c273604e93b0995accf",
        "type": "entity_codes",
        "attributes": {
          ...
          "code": "ZV39HP0P",
          "applicant_id": "123",
          "entity_id": "456"
        }
      }
    }

**Remarque** : un `EntityCode` est unique entre un candidat et une entreprise. Tant qu'il existe un `EntityCode` **non expiré** entre un applicant_id donné pour un entity_id donné, on ne peut pas en recréer un.

Pour supprimer un entity_code : 

    DELETE api/dmo/entity_codes/{id de l'entity_code}

Pour afficher la liste des entity_codes : 

    GET api/dmo/entity_codes

Pour filtrer sur un applicant id donné : 

    GET api/dmo/entity_codes?applicant_id={ID de l'applicant}

### Validation du code

    POST api/dmo/housing_requests/{id de l'housing_request}/validate_code

Avec en body : 

    {
      "code"(required): 'ZV39HP0P' // i.e. entity_code.code
    }

• Si le code correspond à un `EntityCode` existant non expiré, alors le candidat (`housing_request.main_applicant_id`) est rattaché à l'entreprise (entity_id) de l'entity_code.

• Si la validation est en succès, le code est enregistré dans le champ `last_entity_code` de la demande à titre informatif.

• Si le code est expiré, une erreur est retournée.


## Consentement et délégation

### Définition des niveaux de constement pour une Entity : `HousingRequestEntityFormLevel`

Ce modèle permet de définir les niveaux de constement pour un `entity_id` donné.

Requête pour créer un nouveau niveau de constement : 

    POST api/dmo/entities/{ID de l'entity}/housing_request_entity_form_levels

Requête pour mettre à jour le niveau de consentement : 

    PUT api/dmo/entities/{ID de l'entity}/housing_request_entity_form_levels/{id de l'entity_form_level'}

Avec en body pour les 2 requêtes : 

    {
      "data": {
        "attributes": {
          "consent_fields": ['champ_1', 'champ_2'],  // tableau des champs consentis
          "description": 'string',
          "level": integer,                          // e.g. 1, 2, 3....
          "delegation": true/false
        }
      }
    }

Pour supprimer le consentement : 

    DELETE api/dmo/entities/{ID de l'entity}/housing_request_entity_form_levels/{id de l'entity_form_level}

Pour afficher la liste des niveaux de consentement (utilitaires de tri disponibles $in, $nin, $ne, $eq, $all) : 

    GET api/dmo/entities/{ID de l'entity}/housing_request_entity_form_levels

Pour afficher un niveau spécifique : 

    GET api/dmo/entities/{ID de l'entity}/housing_request_entity_form_levels/{id de l'entity_form_level}

### Choix du consentement pour un demandeur : `HousingRequestEntityForm`

Ce modèle permet pour un candidat de choisir son niveau de consentement.

Requête pour créer un nouveau niveau de constement : 

    POST api/dmo/housing_request_entity_forms

Requête pour mettre à jour le niveau de consentement : 

    PUT api/dmo/housing_request_entity_forms/{id de l'entity_form'}

Avec en body pour les 2 requêtes : 

    {
      "data": {
        "attributes": {
          "consent_fields": ['champ_1', 'champ_2'],  // tableau des champs consentis
          "delegation": true/false,
          "housing_request_id": 'string',
          "entity_form_level_id": 'string' // ID de l'entity_form_level créé par l'entreprise
        }
      }
    }

**Attention :** Le champ `housing_request_id` est **obligatoire** en création et **unique** par consentement créé.  

Pour supprimer le consentement : 

    DELETE api/dmo/housing_request_entity_forms/{id de l'entity_form}

Pour afficher la liste des niveaux de consentement (utilitaires de tri disponibles $in, $nin, $ne, $eq, $all) : 

    GET api/dmo/housing_request_entity_forms

Pour afficher la liste des niveaux de consentement actifs (utilitaires de tri disponibles $in, $nin, $ne, $eq, $all) : 

    GET api/dmo/housing_request_entity_forms/actives

Pour afficher un niveau spécifique : 

    GET api/dmo/housing_request_entity_forms/{id de l'entity_form}

Une entreprise a également accès en lecture à la liste des champs consentis pour un niveau spécifique :

    GET api/dmo/housing_request_entity_forms/{id de l'entity_form}/show_request

Retourne en réponse le tableau des champs consentis : 

    [
      "champ_1",
      "champ_2",
      ...
    ]

### Filtrer les demandes de logement par niveau de consentement

Ajouter le param `consent_level` dans l'url de la requête. Exemple : 

    GET api/dmo/housing_requests?consent_level=4

Cela va retourner toutes les demandes de logement pour lesquelles il existe un niveau de consentement (`HousingRequestEntityForm`) de level 4.

On peut également ajouter un `entity_id` dans l'url de la requête pour filtrer les demandes de logement selon le niveau de consentement **et** selon l'entity : 

    GET api/dmo/housing_requests?consent_level=4&entity_id={id de l'entity}


## Validation du salarié par l'entreprise

Au changement d'entreprise du salarié demandeur principal, le booléen `housing_request.entity_validated` passe à `true` ou `false` en fonction du champ `auto_request_validation` de la nouvelle entreprise.
Seuls les utilisateurs avec des droits en écriture sur l'objet `entity` du salarié peuvent modifier ce booleen.

        PATCH/PUT api/dmo/housing_requests/{:id}
         body : {
           "data": {
             "attributes": {
               "entity_validated": true
               }
             }

Seuls les utilisateurs avec des droits en écriture sur le `main_applicant` de la `housing_request` ou sur son `entity` (entreprise) peuvent venir repasser le main_employer_siret de l'applicant à nil et supprimer la relation entre un demandeur et une entreprise.  
Pour créer cette relation, il faut passer par un code.

## Connexion "en tant que"

### Pour les utilisateurs "cre", "collaborateur offre logement" et "superadministrateur"
    
    POST api/dmo/users/{ID de la target}/switch

- • L'ID de la target peut être un ID de user ou un ID d'applicant.
- • Un "superadministrateur" qui switch peut le faire sur tous types de compte.
- • Pour un "collaborateur offre logement" qui switch, la target doit correspondre à un user 'demandeur', 'bailleur' ou 'entreprise', sinon la requête est en erreur.

En cas de succès, la réponse retourne un token de connexion "en tant que" l'utilisateur target.

```
  {
    "success": true,
    "info": "Enregistré",
    "email": "email de l'utilisateur target",
    "login": "login de l'utilisateur target",
    "jwt_token": "nouveau_token_genere_pour_le_log_as"
  }
```

La connexion "en tant que" donne accès à toutes les requêtes API dont l'utilisateur target a accès.

### Pour les utilisateurs "entreprise" uniquement dans le cadre de la délégation

Le params `entity_id` est **obligatoire** dans le body de la requête : 
    
    POST api/dmo/applicants/{ID de l'applicant}/switch

Avec en body : 

    {
      entity_id: "ID de l'entity"
    }

La réponse est en succès uniquement si :
  - • L'utilisateur "entreprise" qui switch est **au moins** lecteur de l'`entity_id`.
  - • Il existe une délégation entre l'`entity_id` et l'`applicant_id` renseigné dans la requête API.
  - • La délégation est signée.

En cas de succès, la réponse retourne un token de connexion pour l'utilisateur dont le `main_applicant_id` correspond à l'`applicant_id` renseigné dans la requête ou dont l'`email` correspond à l'`email` de l'applicant renseigné dans la requête.

Un utilisateur entreprise connecté "en tant que" grâce à la délégation n'aura seulement accès qu'aux requêtes API de la demande de logement (`api/dmo/housing_requests/...`)

## Réservation par une entreprise

Pour créer une réservation pour une entreprise

    POST /api/dmo/entity_reservations

      data: {
        attributes: {
          entity_id: entity_id,
          housing_offer_id: housing_offer_id,
          from: date,
          to: date,
        }
      }

Une fois créer si cette réservation est active à ce jour, l'offre liée devient réservée et un statut `Réservé par` est ajouté. 
Lorsque l'offre n'est plus réservée par cette réservation un status `Fin de réservation pour`.

Les routes suivantes sont également accessibles pour gérer ses réservations :

    GET /api/dmo/entity_reservations
    GET /api/dmo/entity_reservations/:id
    POST /api/dmo/entity_reservations
    PATCH /api/dmo/entity_reservations/:id
    DELETE /api/dmo/entity_reservations/:id

On peut récupérer l'historique des statuts d'une offre pour une entreprise via la requête suivante:

    GET /api/dmo/housing_offers/:id/entity_statuses?entity_id=id

Les deux champs `active_reservations` et `active_reservations_rex_ids` sur les offres contiennent respectivement les id hermes et id rex des entreprises ayant des réservations actives sur cette offre
    
## Operations, secteurs de gestions et contact bailleur

  Pour créer une operation, un secteur de gestion ou un contact bailleur: 

      POST /api/dmo/operations
      POST /api/dmo/management_areas
      data:{
        attributes:{
          name: 'name', # requis
          code: 'code', # non requis, unique et ALSOP|ALSSG par défault
          lessor_id: 'id' #requis si non superadmin
        }
      }

      POST /api/dmo/lessor_contacts
      data:{
        attributes:{
          name: 'name', # requis
          email: 'email', # non requis
          phone: 'phone', # non requis
          lessor_id: 'id' #requis si non superadmin
        }
      }

  Les comptes superadministateur peuvent créer toutes les operations/secteurs/contacts (avec/sans lessor_id)
  Les autres comptes doivent avoir des droits d'accés au bailleur pour pouvoir ajouter des operation/secteur/contact liés

  Pour récupérer la liste des operations/secteurs/contacts :

      GET /api/dmo/operations
      GET /api/dmo/management_areas
      GET /api/dmo/lessor_contacts

  Retourne toutes les opérations/secteurs sans lessor_id + ceux avec un lessor_id dont l'utilisateur a les droits d'accés.
  Possiblité de filtrer par lessor_id en ajoutant &lessor_id=id


## Vérification si une référence existe

    GET /api/dmo/housing_offers/reference_exist?external_ref=reference

## Besoin front sprint 25

5411 -a Pour qu'on puisse récupérer les candidatures d'une offre il faut soit ajouter les ID de candidatures actives sur une offre, soit permettre de requêter des objets candidature par housing_offer_id + status "EN ATTENTE ou "TRANSMIS BAILLEUR" ou "ACCEPTEE EN CAL"
pour récuperer les candidatures souhaités :

    GET /api/dmo/housing_applications&housing_offer_id=<id>&status[$in][]="ACCEPTEE EN CAL"&status[$in][]="TRANSMIS BAILLEUR"&... etc

5411 -b Il nous manque sur l'objet candidature les infos suivantes :
        - l'ID de l'offre chez le bailleur (external_ref de l'offre)
        - nom et prénom du candidat (main_applicant de la demande)
        - nur/nud (nud de la demande)
        - numéro de la demande (als_id de la demande)
        
du coup au niveau de la vue json j'ai rajouté ces champs : 

      housing_application: {
          ...
          "unique_numbers" => [
          [0] "AL056473357466383880"
          ],
          "offer_external_ref" => "EXTERNALREF01",
          "main_applicant_first_name" : "martin",
          "main_applicant_last_name" : "Matin",
          "request_als_id" : "0000000002",
          "rank" : 2,
          ...
      }

Pour trier via score, il faut utiliser le paramètre `offer_id`

GET /api/dmo/housing_applications?offer_id={housing_offer_id}&sort[applicated_position]=1

## Création d'utilisateur
  Les rôles suivant peuvent créer des utilisateurs : 

    Administrator
    SuperAdmin
    Manager
    superadministrateur
    entreprise
    bailleur
    rdsl
    cre

  Les `superadministrateur` ne peuvent être créés que par des utilisateurs ayant les rôles suivant :

    Administrator
    SuperAdmin
    Manager
    superadministrateur

  Pour créer ou mettre à jour un utilisateur

      POST | PATCH /api/dmo/users 
        data: {
          attributes: {
            first_name: 'John', 
            last_name: 'Doe', 
            email: 'johndoe@mail.com',
            phone_number: '1234567890',
            gender: 'M',
            auth_roles: ['cre'],
          }
        }

  Lors de la création ou mise à jour d'un compte utilisateur, le compte utilisateur beiam lié est créé ou mis à jour.

## Affectations d'habilitation sur les entreprise et bailleurs
  3 types de droit sur une entreprise/bailleur :
  * `reader`
    * voir l'entreprise/bailleur dans son arborescence REX
  * `user`
    * les droits de `reader`
    * peut modifier les informations de l'entreprise
  * `administrator` :
    * les droits de `user`
    * créer des habilitation sur les entreprises/bailleurs dont il a les droits

  Pour créer une habilitation sur une entreprise ou bailleur :

      POST /api/dmo/user_rights
        data: {
          attributes: {
              right: 'administrator',
              type: 'entity',
              entity_id: entity_id,
              user_id: user_id,
            }
          }
        }

  Pour supprimer une habilitations 

    DELETE /api/dmo/user_rights/:id

  Pour récupérer les habilitations, il existe 2 méthodes :

  * Sur les entity et lessor un champs `current_user_right`
  * Une route GET /api/dmo/user_rights avec la possibilité de filtrer par entity_id, lessor_id, user_id, right, type
  
  
## Indicateur vérifiant si l'offre a été vue par un collaborateur offre logement

il y a un booléen  viewed_by_colaborator_offre_logement sur l'objet housing request qui passe a false lorsque :
->le cerfa change.
->le status de la requete change.
->une piece justificative est déposée.

il peut etre repassé à true via une requete put/patch classique.
ce champs est recherchable

## Dashboard Administrateur

Il est possible gérer les resources suivantes sur le dashboard administrateur

|Resource|path|
|---|---|
|`Hermes::Threshold`|/admin/thresholds|
|`Hermes::UntensedArea`|/admin/areas|

## Recherche superadministrateur

Recherche sur les entreprises qui retrouve les utilisateurs liés à ces entreprises :

    GET /api/dmo/entities/admin_search
    # avec les paramètres suivant disponibles
    {
      entity_params: {
        id: 'id',
        id_cristal: 'id_cristal',
        siren: 'siren',
        siret: 'siret',
        title: 'title',
      },
      user_params: {
        id: 'id',
        first_name: 'first_name',
        last_name: 'last_name',
        email: 'email',
        auth_roles: 'auth_roles',
      }
    }
    #retour
    data: [
      {
        right: 'administrator',
        user_id: 'user_id',
        user_email: 'user_email',
        user_first_name: 'user_first_name',
        user_last_name: 'user_last_name',
        user_auth_roles: 'user_auth_roles',
        user_phone_number: 'user_phone_number',
        entity_id: 'entity_id',
        entity_als_id: 'entity_als_id',
        entity_title: 'entity_title',
        entity_siret: 'entity_siret',
        entity_siren: 'entity_siren',
        entity_id_cristal: 'entity_id_cristal',
      }
    ]

Recherche sur les bailleurs qui retrouve les utilisateurs liés à ces bailleurs :

    GET /api/dmo/lerrors/admin_search
    # avec les paramètres suivant disponibles
    {
      lessor_params: {
        id: 'id',
        id_cristal: 'id_cristal',
        siren: 'siren',
        siret: 'siret',
        title: 'title',
      },
      user_params: {
        id: 'id',
        first_name: 'first_name',
        last_name: 'last_name',
        email: 'email',
        auth_roles: 'auth_roles',
      }
    }
    #retour
    data: [
      {
        right: 'administrator',
        user_id: 'user_id',
        user_email: 'user_email',
        user_first_name: 'user_first_name',
        user_last_name: 'user_last_name',
        user_auth_roles: 'user_auth_roles',
        user_phone_number: 'user_phone_number',
        lessor_id: 'lessor_id',
        lessor_als_id: 'lessor_als_id',
        lessor_title: 'lessor_title',
        lessor_siret: 'lessor_siret',
        lessor_siren: 'lessor_siren',
        lessor_id_cristal: 'lessor_id_cristal',
      }
    ]

Recherche sur les demandes qui retourne les infos sur les demandeur et entreprises liés :

    GET /api/dmo/housing_requst/admin_search
    # avec les paramètres suivant disponibles
    {
      entity_params: {
        id: 'id',
        id_cristal: 'id_cristal',
        siren: 'siren',
        siret: 'siret',
        title: 'title',
        als_id: 'als_id',
      },
      applicant_params: {
        id: 'id',
        first_name: 'first_name',
        last_name: 'last_name',
        email: 'email',
      }
    }
    #retour
    data: [
      {
        id: 'id',
        nud: 'nud',
        als_id: 'als_id',
        user_id: 'user_id',
        applicant_id: 'applicant_id',
        applicant_email: 'applicant_email',
        applicant_first_name: 'applicant_first_name',
        applicant_last_name: 'applicant_last_name',
        entity_id: 'entity_id',
        entity_als_id: 'entity_als_id',
        entity_title: 'entity_title',
        entity_siret: 'entity_siret',
        entity_siren: 'entity_siren',
        entity_id_cristal: 'entity_id_cristal',
      }
    ]

    Avec des inforamtions de paginations stockées dans meta pour les 3 types de recherche:

      meta: {
        pagination: {
          per_page: per_page,
          total_pages: total_pages,
          total_objects: count,
        }
      }
## Hermes config

il faut aller dans parametres -> hermes_config

apres edition, il faut cliquer sur "mettre a jour", puis lancer sur tout les serveurs de prod la commande

    sudo /opt/scripts/bin/restart_paw

modele du json : 

    {
      "google_street_view": {
        "key": "XXXXXXXXXXXXXXXXXXXXXXXX"
        "signature": "XXXXXXXXXXXXXXXXXXXXXXXX"
        },
    	"ged": {
    		"url": "https://ged-test.dev.hermes.openstack.local",
    		"X-Auth-User-Token": "XXXXXXXXXXXXXXXXXXXXXXXX"
    	},
    	"kyc": {
    		"url": "https://integration-api.preventgo.io/v2",
    		"login": "XXXXXXXXXXXXXXXXXXXXXXXX",
    		"password": "XXXXXXXXXXXXXXXXXXXXXXXX"
    	},
    	"identity_provider_key": "als_hermes_salarie",
    	"DEP_PROVIDERS":
    	 {  
    	 "IMHOWEB": [
               "240"
               ],
    	 "SNE" : [
            "01",
            "02",
            "04",
            "05",
            "06",
            "07",
            "08",
            "09",
            "10",
            "11",
            "12",
            "13",
            "18",
            "19",
            "20",
            "23",
            "24",
            "26",
            "27",
            "28",
            "2A",
            "2B",
            "30",
            "32",
            "33",
            "34",
            "36",
            "38",
            "39",
            "40",
            "41",
            "42",
            "45",
            "46",
            "47",
            "48",
            "51",
            "52",
            "54",
            "55",
            "57",
            "59",
            "60",
            "62",
            "64",
            "65",
            "66",
            "69",
            "70",
            "71",
            "73",
            "74",
            "75",
            "76",
            "77",
            "78",
            "80",
            "81",
            "82",
            "83",
            "84",
            "87",
            "89",
            "90",
            "91",
            "92",
            "93",
            "94",
            "95",
            "971",
            "972",
            "973",
            "974",
            "111"
          ]
    }

## renvoi du flux 30
    
### par batch asynchrones 
pour renvoyer le flux 30 sur un ensemble de housing request données, utilisez la route en lui passant des ids OU des als_ids (si ya les deux ca prendra que les ids):

    POST api/dmo/housing_requests/send_flux_thirty
    avec en body :
      {
        ids : array, // tableau d'id (string) des housing_requests concernées 
        als_ids : array,  // OU tableau d'als_id (string, avec les 0000.. devant) des housing_requests concernées
      }

### unitairement de manière synchrone

    POST api/dmo/housing_requests/{id}/send_flux_thirty_sync
    
## notion de provider de nud

lors de la création d'un nud, l'api hermes recherche parmis la liste des providers dans les settings pour attribuer le provider du departement concerné a un nud donné.
cette information pourra ensuite se retrouver dans le json de la housing request :
    
    housing_request : {
                            ...
                            unique_numbers : ["0110418041931AL004", "0030418041931AL006"]
                            providers : ["SNE", "IHOWEB"],
                            unique_numbers_complete : [
                                                    {
                                                      unique_number: "0110418041931AL004", 
                                                      provider: "SNE"
                                                    },
                                                    {
                                                      unique_number: "0030418041931AL006", 
                                                      provider: "IHOWEB"
                                                    }
                                                ],
                                                ...
                                                }
                            

## rapatriement des demandes par collaborateurs

    POST api/dmo/nuds/{unique_number}/hydrate_housing_request_from_sne

params : 

       {
        user_id: "vivementLeWeekend"
       }

codes retours 

-> 200 ok (avec la housing request ds le json)
-> 401 l'utilisateur n'est pas collaborateur
-> 400 le numéro unique est déja pris
-> 422 l'utilisateur n'a pas pu etre trouvé a partir de l'user_id fourni

# Demande info sur l'utilisateur qui a fait derniere modification

  Voici les champs qui sont mis à jour quand un utilisateur modifie une demande. Ces champs peuvent être utilisé en paramètre sur la route /api/dmo/housing_requests pour filtrer/trier.

    last_update_user_id
    last_update_user_last_name
    last_update_user_first_name

# Informations de l'offre dans le candidature

  Sur les routes `GET /api/dmo/housing_applications` et `GET /api/dmo/housing_applications/:id` le paramètre `join_housing_offer` permet d'include l'offre dans l'application

