github.com/benoitkugler/goacve@v0.0.0-20201217100549-151ce6e55dc8/server/frontend/bv/src/pages/espace_perso/logic/controller.ts (about)

     1  import { BaseController } from "@/shared/logic/controller";
     2  import {
     3    Aide,
     4    CampPlus,
     5    Participant,
     6    Personne,
     7    PublicDocument,
     8    SchemaPaiement,
     9    StatutAttente,
    10    Sexe,
    11    MessageKind,
    12    ContenuSondage,
    13    PseudoMessage
    14  } from "@/shared/logic/types";
    15  import { age } from "../../../shared/logic/utils";
    16  import { Data } from "./data";
    17  
    18  // ATTENTION : cet app suppose qu'elle est déployée sur une url de la forme
    19  // origin/espace_perso/<key>
    20  
    21  export interface CompletionFicheSanitaire {
    22    medecinNoms: string[];
    23    medecinTels: string[];
    24    telsAdditionnels: string[];
    25  }
    26  
    27  export class ControllerEspacePerso extends BaseController {
    28    data: Data;
    29  
    30    constructor() {
    31      super();
    32      this.data = new Data(this);
    33    }
    34  
    35    isPersonneMajeur(personne: Personne) {
    36      const ageP = age(new Date(), personne.date_naissance);
    37      return ageP >= 18;
    38    }
    39  
    40    needValidationFicheSanitaire(personne: Personne) {
    41      return (
    42        !this.isPersonneMajeur(personne) &&
    43        !this.isFsUpToDate(personne.id_crypted)
    44      );
    45    }
    46  
    47    isFsUpToDate(idPersonneCrypted: string) {
    48      let isOk = false;
    49      this.data.participants
    50        .filter(p => p.id_personne_crypted == idPersonneCrypted)
    51        .forEach(p => {
    52          isOk = isOk || p.is_fiche_sanitaire_up_to_date;
    53        });
    54      return isOk;
    55    }
    56  
    57    getCamp(participant: Participant): CampPlus | undefined {
    58      return this.data.camps[participant.id_camp];
    59    }
    60  
    61    getPersonneById(idCrypted: string) {
    62      return this.data.personnes[idCrypted];
    63    }
    64  
    65    getPersonne(participant: Participant) {
    66      return this.getPersonneById(participant.id_personne_crypted);
    67    }
    68  
    69    isModificationLocked(part: Participant) {
    70      const camp = this.getCamp(part);
    71      if (camp == null) return true;
    72      const dt = new Date(camp.date_debut);
    73      const intervalle = (dt.getTime() - Date.now()) / (1000 * 60 * 60);
    74      if (this.data.metas == null) return true;
    75      return intervalle < this.data.metas.update_limitation;
    76    }
    77  
    78    updateDocumentAide(doc: PublicDocument, aide: Aide) {
    79      if (this.data.finances == null || this.data.finances.aides == null) return;
    80      const index = this.data.finances.aides.findIndex(
    81        a => a.id_crypted == aide.id_crypted
    82      );
    83      this.data.finances.aides[index].document = doc;
    84    }
    85  
    86    documentsARemplir() {
    87      let total = 0;
    88      Object.values(this.data.personnes).forEach(personne => {
    89        (personne.documents || []).forEach(contrainte => {
    90          if ((contrainte.docs || []).length == 0) {
    91            total += 1;
    92          }
    93        });
    94      });
    95      return total;
    96    }
    97  
    98    /** Renvoie un nom de page contenant les camps concernés par le dossier */
    99    pageTitle() {
   100      const camps = Object.values(this.data.camps)
   101        .map(c => c.label)
   102        .join(" - ");
   103      return "Espace de suivi : " + camps;
   104    }
   105  
   106    /** Renvoie `true` si au moins un des séjours demande un acompte. */
   107    get withAcompte() {
   108      for (const part of this.data.participants) {
   109        const camp = this.getCamp(part);
   110        if (camp && camp.schema_paiement == SchemaPaiement.SPAcompte) return true;
   111      }
   112      return false;
   113    }
   114  
   115    /** Renvoie `true` si tous les participants sont en liste d'attente */
   116    get onlyAttente() {
   117      for (const part of this.data.participants) {
   118        if (part.liste_attente.statut == StatutAttente.Inscrit) return false;
   119      }
   120      return true;
   121    }
   122  
   123    get salutations() {
   124      if (this.data.responsable == null) return "Bonjour";
   125      const resp = this.data.responsable;
   126      if (resp.prenom == "") {
   127        return "Bonjour";
   128      }
   129      if (resp.sexe == Sexe.SFemme) {
   130        return `Chère ${resp.prenom}`;
   131      }
   132      return `Chere ${resp.prenom}`;
   133    }
   134  
   135    /** renvoie les camps ouverts au sondage */
   136    campsSondages() {
   137      const tmp: { [key: number]: CampPlus } = {};
   138      this.data.messages
   139        .filter(message => message.kind == MessageKind.MSondage)
   140        .map(message => message.contenu as ContenuSondage)
   141        .forEach(contenu => {
   142          const camp = this.data.camps[contenu.id_camp];
   143          if (camp) {
   144            tmp[contenu.id_camp] = camp;
   145          }
   146        });
   147      return Object.values(tmp).sort((a, b) => a.label.localeCompare(b.label));
   148    }
   149  
   150    isMessageFactureRappel(message: PseudoMessage) {
   151      const d = new Date(message.created).valueOf();
   152      const otherFacs = this.data.messages
   153        .filter(m => m.kind == MessageKind.MFacture && m.id != message.id) // autre factures
   154        .filter(m => new Date(m.created).valueOf() < d); // envoyée avant
   155      return otherFacs.length > 0;
   156    }
   157  
   158    /** renvoie les informations potentiellement partageable entre 2 participants */
   159    hintsFichesSanitaires(): CompletionFicheSanitaire {
   160      const medecinNoms: { [key: string]: boolean } = {};
   161      const medecinTels: { [key: string]: boolean } = {};
   162      const telsAdditionnels: { [key: string]: boolean } = {};
   163  
   164      Object.values(this.data.personnes).forEach(pers => {
   165        if (pers.fiche_sanitaire.medecin.nom) {
   166          medecinNoms[pers.fiche_sanitaire.medecin.nom] = true;
   167        }
   168        if (pers.fiche_sanitaire.medecin.tel) {
   169          medecinTels[pers.fiche_sanitaire.medecin.tel] = true;
   170        }
   171        if (pers.fiche_sanitaire.tel) {
   172          telsAdditionnels[pers.fiche_sanitaire.tel] = true;
   173        }
   174      });
   175  
   176      return {
   177        medecinNoms: Object.keys(medecinNoms),
   178        medecinTels: Object.keys(medecinTels),
   179        telsAdditionnels: Object.keys(telsAdditionnels)
   180      };
   181    }
   182  }
   183  
   184  // Singleton responsable des données
   185  // et des requêtes serveurs.
   186  export const C = new ControllerEspacePerso();