Source: personne/serviceGroupeRepository.js


'use strict'

const flow = require('an-flow')

// on ne peut pas mettre ces services en dépendance de $groupeRepository car ils sont déclarés après
let $ressourceRepository
let $personneRepository

module.exports = function (component) {
  component.service('$groupeRepository', function (EntityGroupe, $cacheGroupe) {
    /**
     * @typedef groupesCallback
     * @param {Error} [error]
     * @param {Groupe[]} groupes
     */

    /**
     * Supprime un groupe (ET modifie les ressources liées)
     * @param {string} nom
     * @param {errorCallback} next
     * @memberOf $groupeRepository
     */
    function deleteGroupe (nom, next) {
      // on affecte au 1er appel
      if (!$ressourceRepository) $ressourceRepository = lassi.service('$ressourceRepository')
      if (!$personneRepository) $personneRepository = lassi.service('$personneRepository')

      flow().seq(function () {
        // on efface d'abord le groupe des ressources
        $ressourceRepository.removeGroup(nom, this)
      }).seq(function () {
        // puis des personnes
        $personneRepository.removeGroup(nom, this)
      }).seq(function () {
        // on peut virer le groupe
        EntityGroupe.match('nom').equals(nom).purge(this)
      }).seq(function () {
        // et on vire du cache
        $cacheGroupe.delete(nom, next)
      }).catch(next)
    }

    /**
     * Récupère une liste de groupes
     * @param {string[]} noms
     * @param {groupesCallback} next
     */
    function fetchListByNom (noms, next) {
      if (!Array.isArray(noms) || !noms.length) return next(Error('noms invalides'))
      const groupes = []
      flow(noms).seqEach(function (nom) {
        $cacheGroupe.getByNom(nom, this)
      }).seq(function (cachedGroups) {
        const missing = []
        cachedGroups.forEach((groupe, index) => {
          if (groupe) groupes.push(groupe)
          else missing.push(noms[index])
        })
        if (!missing.length) return next(null, groupes)
        EntityGroupe.match('nom').in(missing).grab(this)
      }).seq(function (grps) {
        next(null, groupes.concat(grps))
      }).catch(next)
    }

    /**
     * Récupère une liste de groupes dont le oid fourni est gestionnaire
     * @param {string} oid
     * @param {groupeListCallback} next
     * @memberOf $groupeRepository
     */
    function fetchListManagedBy (oid, next) {
      EntityGroupe.match('gestionnaires').equals(oid).sort('nom').grab(next)
    }

    /**
     * Récupère un groupe d'après son oip
     * @param {string} groupeNom
     * @param {groupeCallback} next
     * @memberOf $groupeRepository
     */
    function load (oid, next) {
      $cacheGroupe.get(oid, function (error, groupe) {
        if (error) return next(error)
        if (groupe) return next(null, groupe)
        // pas en cache, on va chercher en bdd
        EntityGroupe.match('oid').equals(oid).grabOne(function (error, groupe) {
          if (error) return next(error)
          if (!groupe) return next()
          $cacheGroupe.set(groupe)
          next(null, groupe)
        })
      })
    }

    /**
     * Récupère un groupe d'après son nom
     * @param {string} nom
     * @param {groupeCallback} next
     * @memberOf $groupeRepository
     */
    function loadByNom (nom, next) {
      $cacheGroupe.getByNom(nom, function (error, groupe) {
        if (error) log.error(error)
        if (groupe) return next(null, groupe)
        // pas en cache, on va chercher en bdd
        EntityGroupe.match('nom').equals(nom).grabOne(function (error, groupe) {
          if (error) return next(error)
          if (!groupe) return next()
          next(null, groupe)
          $cacheGroupe.set(groupe)
        })
      })
    }

    /**
     * Récupère tous les groupes ouverts
     * @param {groupeCallback} next
     * @memberOf $groupeRepository
     */
    function loadOuvert (next) {
      EntityGroupe.match('ouvert').equals(true).grab(function (error, groupes) {
        if (error) return next(error)
        next(null, groupes)
      })
    }

    /**
     * Récupère tous les groupes publics
     * @param {groupeCallback} next
     * @memberOf $groupeRepository
     */
    function loadPublic (next) {
      EntityGroupe.match('public').equals(true).grab(function (error, groupes) {
        if (error) return next(error)
        next(null, groupes)
      })
    }

    /**
     * Enregistre une groupe en bdd (et met à jour le cache)
     * @param {EntityGroupe}       groupe
     * @param {entityPersonneCallback} next
     * @memberOf $groupeRepository
     */
    function save (groupe, next) {
      if (!groupe.nom) return next(Error('Impossible d’enregistrer un groupe sans nom'))
      if (!groupe.store) groupe = EntityGroupe.create(groupe)
      // la mise en cache est dans afterStore de l'entity
      groupe.store(next)
    }

    /**
     * Service d'accès aux groupes utilisé par les différents contrôleurs
     * @service $groupeRepository
     */
    const $groupeRepository = {
      delete: deleteGroupe,
      fetchListByNom,
      fetchListManagedBy,
      load,
      loadByNom,
      loadOuvert,
      loadPublic,
      save
    }

    return $groupeRepository
  })
}