# Demande de logement

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

## Form status

Le champs form_status est un champs calculé par le back qui permet de savoir si le formulaire est complet ou non.
Il peut prendre les valeurs suivantes

- "invalid" => le formulaire ne satisfait pas les regles de validations
- "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

### 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        |
| "COMPLETE"                           | INCOMPLETE | INCOMPLETE | INCOMPLETE  | COMPLETE                 |

### 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

## 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
            ]}
        }
    }

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}

## 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}

## 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.
        },
        {...},
        ...
    ]

## Renseigner les dependants

    housing_request.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 »,
        },
        ...
      ]

## 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}}

## 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 :

Un champs `applicant_verified` dans la housing_request, par défault true pour toutes les nouvelles créations et qui est passe à true lors de la validation du code pour les demandes existantes.
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

Si la demande applicant_verified: true => alors elle peut être mise à jour par le sne.
Si la demande applicant_verified: false => On doit fournir le code comme pour l'appel /api/dmo/nuds/:nud/authentify_with_pin_code sinon on a une erreur.
Pour générer un email/code pour une demande on peut appeler la route /api/dmo/nuds/:nud/send_new_pin_code

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

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

    POST api/dmo/housing_request_entity_form_levels

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

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

Avec en body pour les 2 requêtes :

    {
      "data": {
        "attributes": {
          "entity_id": 'id',
          "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/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/housing_request_entity_form_levels?entity_siret=siret

Pour afficher un niveau spécifique :

    GET api/dmo/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
        }
      }
    }

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}

## 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"
                                                    }
                                                ],
                                                ...
                                                }

## Affectation de nud invalide

lors de la création d'un numéro unique pour une demande, ou de l'affectation d'un numéro unique existant a une demande ou de son passage à "is_active", une vérification est effectuée afin d'exclure la possibilité d'affecter a une demande active un numéro unique déja affecté a une autre demande active

## 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

## Recherche d'offre par channel

il est possible de rechercher des offres par channel

    /api/dmo/housing_request?housing_channel_keys="votre channel key"

## Récupération du nombre de demande éligible et notre possible de nombre éligible

Sur l'object `housing_offer`, il y a 2 options qui permet de recalculé les champs eligible_requests_nb et possible_eligible_requests_nb:

- `eligible_requests_nb` donne le total de demande actuelement éligible
- `possible_eligible_requests_nb` donne le total de demande qui pourrait être éligible indépendamment de leur status (active et non satisfaite)  
  Sur les appels suivant :
- GET /api/dmo/housing_offers?[filtres]&options[]=eligible_requests_nb
- GET /api/dmo/housing_offers?[filtres]&options[]=possible_eligible_requests_nb
- GET /api/dmo/housing_offers?[filtres]&options[]=eligible_requests_nb&options[]=possible_eligible_requests_nb
- GET /api/dmo/housing_offers/:id?options[]=eligible_requests_nb
- GET /api/dmo/housing_offers/:id?options[]=possible_eligible_requests_nb
- GET /api/dmo/housing_offers/:id?options[]=eligible_requests_nb&options[]=possible_eligible_requests_nb

## Vérifier si un utilisateur à un housing_request_initializer en attente de code

    GET /api/dmo/nuds/pending_for_current_user

    Retourne soit une 404 ou alors l'housing_request_initializer avec les attributs unique_number, pin_code_created_at, email, done, expired
    L'attribut expired vaut vrai quand on trouve une housing_request_initializer qui correspond mais qui est plus ancienne que 24h.

## Changements du champs motivation

avec la version 4 du cerfa sne, les champs de type string "motivation1", "motivation2" et "motivation3" sont remplacés par un champs de type array "motivations"

    ex :
    housing_request.motivations = ["valeur1", "valeur2", ...]

## Nouveaux champs liés au cerfa V4

Le cerfa V4 introduit de nouvelles données, la correspondance aidera les fronts a communiquer avec hermes. l'anglais n'est pas parfait mais il aidera les francophones du projet a s'y retrouver facilement.

| Balise xlm            | Nom du champ sur hermes                | Nom du champ front                                                  | type                                                                                                               |
| --------------------- | -------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| 10095                 | 10095                                  | 10095                                                               | 10095                                                                                                              |
| ressourcesMensuelles  | housing_request.have_monthly_income    | Percevez-vous des ressources mensuelles ?                           | Booléen                                                                                                            |
| periodeChomage        | applicant.unemployment_period          | Chômage de plus d’un an                                             | Booleen                                                                                                            |
| dateFinPeriodeChomage | applicant.unemployment_period_date_end | Date de fin de période de chômage                                   | Date aaaa-mm-jj                                                                                                    |
| compDateCommandement  | applicant.command_to_leave_date        | Date du commandement si commandement de quitter les lieux           | Date aaaa-mm-jj                                                                                                    |
| nombreHandicap        | housing_request.disabled_person_number | Nombre de personnes en situation de handicap                        | Numérique (1)                                                                                                      |
| telDomicilePro        | applicant.pro_or_home_tel_number       | tel Domicile ou professionnel                                       | String (la sec demande Numérique (10) mais nous preferons utiliser une string pour harmoniser avec les autres tels |
| 10106                 | 10106                                  | 10106                                                               | 10106                                                                                                              |
| infoProprietaire      | housing_request.owner_info_needed      | Je souhaite être informé sur la possibilité de devenir propriétaire | Booléen                                                                                                            |

## CerfaV4

l'objet housing_request a désormais un champ String "cerfa_version"
si une demande à été extraite d'un cerfa V4 récupéré en xml sur le sne, alors :

    housing_request.cerfa_version = "4"

## Gestion des renouvellement sne

Voici les nouveaux champs ajouté sur l'housing_request :

sne_created_at : date creation sne (correspond au dateCreationDemande, attribut déjà existant)
next_renewal_date_set_by_sne : valeur récupérer du sne
last_sne_renewal_date : date du dernier renouvellement (correspond au dateRenouvellement, peut être nul)
next_sne_renewal_date: champs calculé pour être next_renewal_date_set_by_sne ou ((last_sne_renewal_date ou sne_created_at) + 1 an)
soon_need_to_be_renewed : booléen vrai si la next_sne_renewal_date est dans moins d'un mois
need_to_be_renewed : booléen vrai si la next_sne_renewal_date est dépassée

Un batch est appelé tout les jours pour mettre à jour les valeurs des booleans

## Cotations

Quand une demande avec un nud au provider IMHOWEB est importée ou mise à jour ou un candidature est créée, l'API lance un appel pour récupérer les champs `cotations`, `supplement_can_apply` et `supplement_status` chez sopra.

Le `cotations` de `housing_request` est reportée sur son `housing_application` active

Possibilité de trier par cotations sur les demandes et candidatures en ajoutant le code insee de la commune (Exemple pour la commune 33000)

    GET /api/dmo/housing_requests?sort[cotations.33000]=-1
    GET /api/dmo/housing_applicationss?sort[cotations.33000]=-1

Possibilté de trier par cotations sur les demandes eligibles et candidatures d'une offre le code insee est déduit de l'offre

    GET /api/dmo/housing_offers/:id/eligible_requests?sort[cotations]=-1
    GET /api/dmo/housing_offers/:id/all_applications?sort[cotations]=-1

Lors de création d'une candidature si la demande est bloquée par ihmoweb, voici le message d'erreur

    POST /api/dmo/housing_applications
    {
        attributes: {
            housing_request_id: id
        }
    }

    Réponse 422

    {
        "errors"=>[
            {
                "status"=>422,
                "source"=>{"pointer"=>"/data/attributes/housing_request_id"},
                "detail"=>"this housing_request is not allowed to apply"
            }
        ]
    }

## RFR dynamique

Ajout d'une route pour afficher les valeurs qui sont en config pour la date de bascule et la date à prendre en compte :

    GET /api/dmo/housing_requests/config_change_minus_two
        {
            change_minus_two_date: '2022-01-15',
            change_minus_two_year: 2020
        }

Suivant les valeurs des champs et si on a dépassé la date, on utilise différentes valeurs (year_minus_one, amount_year_minus_one, year_minus_two, amount_year_minus_two) pour calculer le reference_tax_revenues et créer les pièces obligatoires (impot sur le revenu)

Les champs ci-dessous sont sur l'applicant, pour avoir les valeurs en prenant en compte la config :

      dynamic_year_minus_two
      dynamic_year_minus_one
      dynamic_amount_minus_two
      dynamic_amount_minus_one

## Mise à jour next_renewal_date_set_by_sne

    Route pour mettre à jour directement next_renewal_date_set_by_sne et next_sne_renewal_date

        PUT PUT /housing_requests/:id/update_next_renewal_date_set_by_sne
        {
            next_renewal_date_set_by_sne: '2022-01-01'
        }

## Calcul du champs entity_status

Le champs entity_status est calculé de la manière suivante :

- Vide <= Si il n'y a pas d'entity_id
- ANNULE <= Si l'entity_status est ANNULEE
- REFUSE <= Si l'entity_refused est true
- SALARIE LOGE <= Si entity_validated = true et request_status = SATISFAITE
- DOSSIER PRESENTE <= Si entity_validated = true et le status de l'application active est TRANSMIS BAILLEUR, RETENUE EN CAL SOUS CONDITIONS ou RETENUE EN CAL SOUS RESERVE
- DOSSIER ACCEPTE <= Si entity_validated = true et le status de l'application active est RETENUE EN CAL
- EN COURS <= Si entity_validated = true
- A VALIDER <= Si le request_statue est COMPLETE ou SATISFAITE
- EN COURS DE SAISIE <= Si l'entity_status etait vide et que le request status est INCOMPLETE ou EN ATTENTE DE NUD
- Si on est dans aucun de ces cas on laisse l'entity_status à la même valeur

## Savoir si une offre est eligible à une demande

    GET /api/dmo/housing_requests/:als_id/is_eligible_offer/:offer_id

    Retour
    {
      is_eligible: true|false
    }

## Contourner le blocage de candidture

Pour forcer la création d'une candidature sans avoir de vérification du blocage de la candidature. Il faut utiliser l'option skip_check lors de l'appel :

    POST /api/dmo/housing_applications
    {
      data: { attributes: { ... }},
      options: ['skip_check']
    }

## Maximum de candidature active

Il est possible de restreindre le nombre de candidature active sur une candidature via la valeur en config `max_allowed_applications`.
Cette valeur peut être 0 ou 1.

Si on essaye de créer ou de mettre à jour une candidature, qui passerait le nombre de candidatures active au dessus de la valeur max_allowed_applications. On reverra une erreur 422, exemple:

    POST /api/dmo/housing_applications
    {
        data: {
            attributes: {
                housing_request_id: id,
                housing_offer_id: id,
                status: 'EN ATTENTE',
            }
        }
    }
    Retour :
    422
     {
        "errors":[
            {
                "status":422,
                "source":{"pointer"=>"/data/attributes/housing_request_id"},
                "detail":"this housing_request has the maximum of housing_application 0"
            }
        ]
    }

## Motifs non retenu

Ajouter/modifier un motif via le champs `motive_code` :

    PUT /api/dmo/housing_applications/:id
    {
      data: {
        attributes: {
          motive_code: "IV01",
        }
      }
    }

Dans le résultat, le champs `motive_label` permet de faire le lien entre le code et ce que l'on a en config.

    GET /api/dmo/housing_applications/:id
    {
      data: {
        attributes: {
          ...
          motive_code: "IV01",
          motive_label: "Dossier incomplet",
          ...
        }
      }
    }

```json
  ...
  "motive_label": {
    "IV01":	"Dossier incomplet",
    "IV02": "Document(s) non conforme(s) à votre situation déclarative",
    "IV03":	"Non retenu",
    "IV04":	"Non retenu",
    "IV05": "Demande hors périmètre Action Logement Services, voir CGU. <a href=\"/#/legal-notice\">voir CGU</a>",
    "IV06":	"Désistement du candidat",
    "IV07":	"Non retenu",
    "IV08":	"Non retenu",
    "IV09":	"Le logement n'est plus disponible à la location",
    "IV10": "Le logement n'est plus disponible à la location",
    "IV11": "Non retenu",
  }
  ...
```

Si le mapping du code n'existe pas en config, on renvoie nul.

Pour ajouter un lien, il suffit de renseigner le lien en html avec un lien relatif. Attention au \ avant les "

## Maximum de candidature active

Il est possible de restreindre le nombre de candidature active sur une candidature via la valeur en config `max_allowed_applications`.
Cette valeur peut être 0 ou 1.

Si on essaye de créer ou de mettre à jour une candidature, qui passerait le nombre de candidatures active au dessus de la valeur max_allowed_applications. On reverra une erreur 422, exemple:

    POST /api/dmo/housing_applications
    {
        data: {
            attributes: {
                housing_request_id: id,
                housing_offer_id: id,
                status: 'EN ATTENTE',
            }
        }
    }
    Retour :
    422
     {
        "errors":[
            {
                "status":422,
                "source":{"pointer"=>"/data/attributes/housing_request_id"},
                "detail":"this housing_request has the maximum of housing_application 0"
            }
        ]
    }

## Fix sur les timezones avec plusieurs périodes

Pour les dates 08 Oct 1914 et 08 Oct 1944, il existe plusieurs periodes sur les timezones qui se chevauchent.
Ce qui créé une erreur AmbiguousTime lors de la sauvegarde d'une date de naissance d'un applicant.
Pour corriger cela, on prend maintenant la première période quand il y a un conflict.

## Fonctionnement des points entreprises

Voici l'appel pour pour attriber des points à une entreprise
Il existe 3 champs sur chaque entreprise :

- annual_stock : le total de points que l'entreprise a
- total_spent : total de points dépensés
- available_points : total de points restant

      PATCH /api/dmo/housing_requests/:id
      {
          data: {
              attributes: {
                  priority_points_indexes: [100, 80, 30]
          }
      }

  Et 3 champs qui détaillent le total_spent :

- spent_on_completed_requests : pour les demandes à l'entity_status SALARIE LOGE
- spent_on_ongoing_requests : pour les demandes avec un entity_status ['EN COURS DE SAISIE', 'A VALIDER', 'EN COURS', 'DOSSIER PRESENTE', 'DOSSIER ACCEPTE' ]
- spent_on_other : pour les autres demandes

Le total de points d'une demande est calculé via la somme du champs priority_points_indexes
Ce total est ajouté/supprimé de l'entreprise quand l'entity_id de la demande est modifiée

Il n'est plus possible de modifié directement ces champs dans l'API.
Il faut utiliser les appels suivant :

Pour modifier le stock d'une entreprise :

      PUT /entities/:id/update_annual_stock
      {
        annual_stock: 2000
      }

## Configuration RFR

Il est possible de modifier la configuration rfr en accédant à la route : `/admin/rfr_settings`

Cette page comprend tous les paramètres de configuration pour le calcul du rfr et l'affichage du message front.

Cette configuration n'a pas besoin de redémarrage pour être prise en compte.

Les valeurs de l’ancienne configuration (`/admin/settings` > `hermes_config`) sont récupérées pour alimenter la nouvelle, puis l’ancienne config est supprimée via une migration automatique.

Le front peut utiliser la route suivante pour récupérer les valeurs de la configuration :

GET /api/dmo/housing_requests/get_rfr_settings

```json
{
    "change_minus_two_date": "2022-01-15", # Date de bascule
    "change_minus_two_year": "2020", # Année utilisé pour le N-2
    "should_show_rfr_message": true, # Valeur en configuration si on veut afficher le message
    "show_warning_message": false, # Valeur à utiliser pour afficher le message (calculé en fonction de la date de bascule + durée du message)
    "message_duration": "90", # Durée d'affichage du message
    "rfr_message_title": "Mise à jour requise", # Titre du message
    "rfr_message": "Message", # Message à afficher
}

```

Suivant les valeurs des champs change_minus_two_date et change_minus_two_year et si on a dépassé la date, on utilise différentes valeurs (year_minus_one, amount_year_minus_one, year_minus_two, amount_year_minus_two) pour calculer le reference_tax_revenues et créer les pièces obligatoires (impot sur le revenu)

Les champs ci-dessous sont sur l'applicant, pour avoir les valeurs en prenant en compte la config :

      dynamic_year_minus_two
      dynamic_year_minus_one
      dynamic_amount_minus_two
      dynamic_amount_minus_one

Pour les dates 08 Oct 1914 et 08 Oct 1944, il existe plusieurs periodes sur les timezones qui se chevauchent.
Ce qui créé une erreur AmbiguousTime lors de la sauvegarde d'une date de naissance d'un applicant.
Pour corriger cela, on prend maintenant la première période quand il y a un conflict.

# Validation entreprise et attribution de points

Nous allons mettre une route à disposition du front permettant d’ajouter et supprimer
des points entreprises sur une demande ou plusieurs demandes, qu’elles soient
rattachées à une entreprise mère ou une filiale.

### Requête

```
PATCH /api/dmo/housing_requests/entity_validation
{
    "data": [
        {
            "id": "xxxxxx",
            "attributes": {
                "priority_points_indexes": [1, 2, 3],
                "entity_validated" : true/false,
                "entity_refused": true/false,
            }
        },
        {
            "id": "xxxxxx",
            "attributes": {
                "priority_points_indexes": [1, 2, 3],
                "entity_validated" : true/false,
                "entity_refused": true/false,
            }
        },

    ]
}
```

Les valeurs passées dans l’appel sont aussi bien les valeurs existantes qui ne changent, pas que les valeurs modifiées. Par exemple, pour une demande déjà validée dont on modifie les points, on renverra entity_validated=true, entity_refused=false et les nouvelles valeurs de priority_points_indexes.

### Retour

Si toutes les réponses sont en 200 :

```
CODE : 200

{
    "data":[
        {
            "id": "xxxxxx",
            "attributes": {
                "priority_points_indexes": [1, 2, 3],
                "entity_validated" : true/false,
                "entity_refused": true/false,
            }
        },
        {
            "id": "yyyyyy",
            "attributes": {
                "priority_points_indexes": [1, 2, 3],
                "entity_validated" : true/false,
                "entity_refused": true/false,
            }
        }
    ]
}
```

Si au moins une des réponses n’est pas en 200 :

```
CODE : 207
{
    "data":[
        {
            "id": "xxxxxx",
            "response":{
                "return_code" : "200",
                "details" : "Opérations effectuées"
            },
            "attributes": {
                "priority_points_indexes": [1, 2, 3],
                "entity_validated" : true/false,
                "entity_refused": true/false,
            }
        }, {
            "id": "yyyyyy",
            "response": {
                "return_code" : "422",
                "details" : "Opérations incohérentes"
            },
            "attributes": {
                "priority_points_indexes": [1, 2, 3], //
                "entity_validated" : true/false,
                "entity_refused": true/false,
            }
        }
    ]
}
```

### Liste exhaustive des codes retour

| erreur                                                                                                                                        | code retour | details                                         |
| --------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ----------------------------------------------- |
| Opération effectuée                                                                                                                           | 200         | Opération effectuée                             |
| La demande n’existe pas                                                                                                                       | 404         | Demande introuvable                             |
| La demande n’est pas active                                                                                                                   | 422         | Demande obsolète                                |
| L’utilisateur n’a pas de droits permettant d’agir sur la demande                                                                              | 403         | Droits insuffisants                             |
| Plus de 3 valeurs nous sont envoyées dans priority_points_indexes                                                                              | 422         | Trop de points envoyées                         |
| Il manque une valeurs dans les paramètres                                                                                                     | 422         | Paramètre manquant                              |
| La requête indique de passer la demande à entity_validated=true et entity_refused=true, ou ni entity_validated ni entity_refused ne sont true | 422         | Opérations incohérentes                         |
| Tentative d’attribution de points alors que la demande n’est pas validée                                                                      | 422         | Attribution de points à une demande non validée |
| Tentative d’attribution de points alors que l’entité à laquelle elle est rattachée n’a pas un solde depoints suffisant                        | 422         | Points disponibles insuffisants                 |

# Annulation d'une demande

Il est possible d'annuler une demande en effectuant un appel sur la route suivante :

    PATCH /api/dmo/housing_requests/:id/cancel_request

Voici les retours possibles :

| http_code | retour                                                        | raison                              |
| --------- | ------------------------------------------------------------- | ----------------------------------- |
| 200       | json de la demande mise à jour                                | Success                             |
| 403       | erreur missing_rights_to_update                               | Droits insuffisants                 |
| 404       | erreur housing_request_not_found                              | Demande introuvable                 |
| 422       | erreur housing_request_already_canceled                       | Demande déjà annulée                |
| 422       | erreur has_active_application                                 | Demande avec une candidature active |
| 422       | erreur cancel_aborted_error_XXXXX (avec le code erreur sopra) | Erreurs retournées par sopra        |

Format des erreurs :

```json
{
  "errors": [
    {
      "title": "translation missing: fr.error_messages.housing_request_not_found.title",
      "status": 422,
      "code": "translation missing: fr.error_messages.housing_request_not_found.code"
    }
  ]
}
```

Cet appel déclenche un appel radierDemande vers sopra.
Si l'appel est un succès, la demande est mise à jour avec le status "ANNULEE", is_active à false et le champs form_status à "cancelled"


# Gestion des pièces justificatives

  Ajout d'un champs has_pending_documents sur la housing_request. Ce booléen sera par défaut à false lors de la création d’une demande et sur les demandes existantes. Sa valeur ne sera pas modifiée lors d’une mise à jour par le demandeur via front. Elle ne doit être modifiée que par des appels d’AL’in Gestion (décrits ci-après) lorsque AL’in Gestion notifie AL’in qu’une demande a des pièces en attente.

    POST /api/dmo/housing_requests/:id/has_pending_documents
      {
        “has_pending_documents”: true/false
      }

  Usage limité aux comptes ayant un rôle “Administrator” plugandwork.

Codes retours :
  * Succès : 204
  * Échec :
    * 404 : housing_request_not_found
    * 422 :
      * has_pending_documents_missing
      * has_pending_documents_wrong_value
      * has_pending_documents_already true/false
    * 401 : user_not_permitted
  

  Format de retour en cas d’échec (exemple avec l’erreur 404) :

    {
      "errors": [
        {
          "title": "translation missing: fr.error_messages.housing_request_not_found.title",
          "status": 404,
          "code": "translation missing: fr.error_messages.housing_request_not_found.code"
        }
      ]
    }
