Sfoglia il codice sorgente

Page addresse postal

Vincent GUFFON 4 anni fa
parent
commit
6d088f5980

+ 2 - 0
lang/field/fr-FR.js

@@ -1,5 +1,7 @@
 export default (context, locale) => {
   return ({
+    importAddress: 'Importer l\'adresse d\'une des personnes de votre structure',
+    addressCountry: 'Pays',
     legalInformation: 'Informations légales',
     agrements: 'Agréments',
     salary: 'Salariés',

+ 1 - 0
lang/form/fr-FR.js

@@ -1,5 +1,6 @@
 export default (context, locale) => {
   return ({
+    autocomplete_research: 'Aucun résultat ne correspond à votre recherche',
     save: 'Enregistrer',
     back: 'Retour',
     cancel: 'Annuler',

+ 9 - 4
models/Core/AddressPostal.ts

@@ -1,5 +1,4 @@
-import {Str, HasOne, Num, Model, Uid} from '@vuex-orm/core'
-import { Country } from '~/models/Core/Country'
+import {Attr, Str, Num, Model, Uid} from '@vuex-orm/core'
 
 export class AddressPostal extends Model {
   static entity = 'address_postals'
@@ -7,8 +6,14 @@ export class AddressPostal extends Model {
   @Uid()
   id!: number | null
 
-  @HasOne(() => Country, 'id')
-  addressCountry!: Country | null
+  @Str('', { nullable: true })
+  '@id'!: string
+
+  @Attr(null)
+  organizationAddressPostalId!: number | null
+
+  @Str('', { nullable: true })
+  addressCountry!: string
 
   @Str('', { nullable: true })
   addressCity!: string

+ 1 - 1
models/Core/Country.ts

@@ -1,4 +1,4 @@
-import {Str, Model, Uid} from '@vuex-orm/core'
+import {Str, Model, Uid, Attr} from '@vuex-orm/core'
 
 export class Country extends Model {
   static entity = 'countries'

+ 1 - 1
models/Organization/OrganizationAddressPostal.ts

@@ -7,7 +7,7 @@ export class OrganizationAddressPostal extends Model {
   @Uid()
   id!: number | null
 
-  @HasOne(() => AddressPostal, 'id')
+  @HasOne(() => AddressPostal, 'organizationAddressPostalId')
   addressPostal!: AddressPostal | null
 
   @Str('PRINCIPAL', { nullable: false })

+ 150 - 39
pages/organization/address/_id.vue

@@ -1,9 +1,8 @@
 <!-- Page de détails d'une adresse postale -->
-
 <template>
   <main>
     <v-skeleton-loader
-      v-if="loading"
+      v-if="organizationAddressPostalFetching.pending"
       type="text"
     />
     <LayoutContainer v-else>
@@ -18,23 +17,24 @@
         </v-toolbar>
 
         <UiForm :id="id" :model="model" :query="query()">
-          <template v-slot:form.input="{entry, updateRepository}">
-            <v-skeleton-loader
-              v-if="loading"
-              type="text"
-            />
-            <v-container v-else fluid class="container">
+          <template #form.input="{entry, updateRepository}">
+
+            <v-container fluid class="container">
               <v-row>
                 <v-col cols="12" sm="12">
-                  <UiInputAutocomplete
+                  <UiInputAutocompleteWithAPI
                     field="owner"
-                    label="addressOwner"
-                    item-value="@id"
-                    :item-text="['cp', 'city']"
-                    @update="updateAddressFromOwner"
+                    label="importAddress"
+                    :item-text="['person.givenName', 'person.name']"
+                    :searchFunction="accessSearch"
+                    @update="updateAccessAddress"
                   />
                 </v-col>
 
+                <v-col cols="12" sm="6">
+                  <UiInputText field="addressPostal.addressOwner" label="addressOwner" :data="entry['addressPostal.addressOwner']" @update="updateRepository" />
+                </v-col>
+
                 <v-col cols="12" sm="6">
                   <UiInputEnum field="type" label="addresstype" :data="entry['type']" enum-type="address_postal_organization" @update="updateRepository" />
                 </v-col>
@@ -42,31 +42,68 @@
                 <v-col cols="12" sm="6">
                   <UiInputText field="addressPostal.streetAddress" label="streetAddress" :data="entry['addressPostal.streetAddress']" @update="updateRepository" />
                 </v-col>
+
                 <v-col cols="12" sm="6">
                   <UiInputText field="addressPostal.streetAddressSecond" label="streetAddressSecond" :data="entry['addressPostal.streetAddressSecond']" @update="updateRepository" />
                 </v-col>
+
                 <v-col cols="12" sm="6">
                   <UiInputText field="addressPostal.streetAddressThird" label="streetAddressThird" :data="entry['addressPostal.streetAddressThird']" @update="updateRepository" />
                 </v-col>
+
+                <v-col cols="12" sm="6">
+                  <UiInputAutocompleteWithAPI
+                    field="addressPostal.postalCode"
+                    label="postalCode"
+                    :data="getAutoCompleteAddressItem"
+                    :item-text="['postcode']"
+                    :slotText="['postcode', 'city']"
+                    :searchFunction="addressSearch"
+                    :returnObject="true"
+                    @update="updateCpAddress($event, updateRepository)"
+                  />
+                </v-col>
+
                 <v-col cols="12" sm="6">
-                  <UiInputText field="addressPostal.postalCode" label="postalCode" :data="entry['addressPostal.postalCode']" @update="updateRepository" />
+                  <UiInputAutocompleteWithAPI
+                    field="addressPostal.addressCity"
+                    label="addressCity"
+                    :data="getAutoCompleteAddressItem"
+                    :item-text="['city']"
+                    :slotText="['postcode', 'city']"
+                    :searchFunction="addressSearch"
+                    :returnObject="true"
+                    @update="updateCpAddress($event, updateRepository)"
+                  />
                 </v-col>
+
                 <v-col cols="12" sm="6">
-                  <UiInputText field="addressPostal.addressCity" label="addressCity" :data="entry['addressPostal.addressCity']" @update="updateRepository" />
+                  <UiInputAutocomplete
+                    field="addressPostal.addressCountry"
+                    label="addressCountry"
+                    :data="getIdFromUri(entry['addressPostal.addressCountry'])"
+                    :items="countries"
+                    :isLoading="countriesFetchingState.pending"
+                    :item-text="['name']"
+                    @update="updateRepository(`/api/countries/${$event}`, 'addressPostal.addressCountry')"
+                  />
                 </v-col>
+
               </v-row>
             </v-container>
 
-            <UiMap :zoom="12" :address="addressItem" @updateAddress="updateAddress" />
+            <UiMap :zoom="12" :address="addressPostalItem()" @updateAddress="updateAddressFromMap" />
+
           </template>
 
-          <template v-slot:form.button>
+          <template #form.button>
             <NuxtLink :to="{ path: '/organization', query: { accordion: 'address_postal' }}" class="no-decoration">
               <v-btn class="mr-4 ot_light_grey ot_grey--text">
                 {{ $t('back') }}
               </v-btn>
             </NuxtLink>
           </template>
+
         </UiForm>
       </v-card>
     </LayoutContainer>
@@ -74,45 +111,66 @@
 </template>
 
 <script lang="ts">
-import { defineComponent, useContext, useFetch, ref, computed, Ref, ComputedRef } from '@nuxtjs/composition-api'
+import { defineComponent, useContext, useFetch, computed, ComputedRef } from '@nuxtjs/composition-api'
 import { Repository as VuexRepository } from '@vuex-orm/core/dist/src/repository/Repository'
 import { Model, Query } from '@vuex-orm/core'
 import { OrganizationAddressPostal } from '~/models/Organization/OrganizationAddressPostal'
+import {Country} from "~/models/Core/Country";
 import { QUERY_TYPE } from '~/types/enums'
 import { repositoryHelper } from '~/services/store/repository'
 import { queryHelper } from '~/services/store/query'
 import { AddressPostal } from '~/models/Core/AddressPostal'
+import {UseCountry} from "~/use/data/useCountry";
+import ModelsUtils from "~/services/utils/modelsUtils";
+import {UseAddressPostal} from "~/use/data/useAddresspostal";
+import {AnyJson} from "~/types/interfaces";
+import DataProvider from "~/services/data/dataProvider";
+import {UseAccess} from "~/use/data/useAccess";
 
 export default defineComponent({
   name: 'OrganizationAddress',
   setup () {
     const { route, $dataProvider } = useContext()
-    const loading: Ref<boolean> = ref(true)
     const id: number = parseInt(route.value.params.id)
 
     const repository: VuexRepository<Model> = repositoryHelper.getRepository(OrganizationAddressPostal)
-    const query: Query = repository.with('addressPostal', (query) => {
-      query.with('addressCountry')
-    })
-
-    useFetch(async () => {
+    const query: Query = repository.with('addressPostal')
+    const {fetchState: organizationAddressPostalFetching} = useFetch(async () => {
       await $dataProvider.invoke({
         type: QUERY_TYPE.MODEL,
         model: OrganizationAddressPostal,
         id
       })
-      loading.value = false
     })
 
-    const addressItem: ComputedRef<AddressPostal|null> = computed(() => {
-      const organizationAddressPostal = queryHelper.getFirstItem(query) as OrganizationAddressPostal
-      return organizationAddressPostal.addressPostal
+    const organizationAddressPostalItem: ComputedRef<OrganizationAddressPostal|null> = computed(() => {
+      return queryHelper.getFirstItem(query) as OrganizationAddressPostal
+    })
+
+    const addressPostalItem: ComputedRef<AddressPostal|null> = computed(() => {
+      return organizationAddressPostalItem.value.addressPostal
     })
 
-    const updateAddress = (address: AddressPostal) => {
-      const organizationAddressPostal = queryHelper.getFirstItem(query) as OrganizationAddressPostal
-      organizationAddressPostal.addressPostal = address
-      repositoryHelper.persist(OrganizationAddressPostal, organizationAddressPostal)
+    const updateAddressFromMap = (addressPostal: AddressPostal) => {
+      repositoryHelper.persist(AddressPostal, addressPostal)
+    }
+
+    const getAutoCompleteAddressItem = computed(() => {
+      if(addressPostalItem.value?.addressCity || addressPostalItem.value?.postalCode)
+        return {id:0, city: addressPostalItem.value?.addressCity, postcode: addressPostalItem.value?.postalCode}
+      return {}
+    })
+
+    const {countries, fetchState: countriesFetchingState} = new UseCountry().getAll()
+
+    const {searchFunction: addressSearch, updateCpAddress} = new UseAddressPostal().invoke()
+
+    const {getPhysicalByFullName: accessSearch} = new UseAccess().invoke()
+
+    const {updateAccessAddress} = accessOwnerResearch($dataProvider, organizationAddressPostalItem, addressPostalItem)
+
+    const getIdFromUri = (uri: string) => {
+      return ModelsUtils.extractIdFromUri(uri)
     }
 
     /** Computed properties needs to be returned as functions until nuxt3 : https://github.com/nuxt-community/composition-api/issues/207 **/
@@ -120,17 +178,70 @@ export default defineComponent({
       model: OrganizationAddressPostal,
       query: () => query,
       id,
-      loading,
+      organizationAddressPostalFetching,
       panel: 0,
-      addressItem,
-      updateAddress,
-      updateAddressFromOwner: (data: any) => {
-        console.log(data)
-      }
+      addressPostalItem: () => addressPostalItem,
+      countries,
+      countriesFetchingState,
+      addressSearch,
+      getIdFromUri,
+      getAutoCompleteAddressItem,
+      accessSearch,
+      updateAccessAddress,
+      updateAddressFromMap,
+      updateCpAddress
     }
-  }
+  },
+  beforeDestroy() {
+    repositoryHelper.cleanRepository(OrganizationAddressPostal)
+    repositoryHelper.cleanRepository(Country)
+    repositoryHelper.cleanRepository(AddressPostal)
+  },
 })
+
+/**
+ * Fonction permettant la mise à jour des champs de l'adresse suivant une adresse d'un Access
+ * @param $dataProvider
+ * @param organizationAddressPostalItem
+ * @param addressItem
+ */
+function accessOwnerResearch($dataProvider:DataProvider, organizationAddressPostalItem:ComputedRef<OrganizationAddressPostal>, addressItem:ComputedRef<AddressPostal>){
+  const updateAccessAddress = async (accessId: number) =>{
+    const response = await $dataProvider.invoke({
+      type: QUERY_TYPE.DEFAULT,
+      url: `api/access_addresses`,
+      id:accessId
+    })
+
+    //On ne conserve que l'adresse principale
+    const principalPersonalAddress = response.data.person.personAddressPostal.filter((personAddress: AnyJson) => {
+      return personAddress.type === 'ADDRESS_PRINCIPAL'
+    })
+
+    if(principalPersonalAddress.length > 0){
+      const personalAddress = principalPersonalAddress.pop()
+
+      //On créer la nouvelle adresse et on initialise les champs restants...
+      const addressPostal = new AddressPostal(personalAddress.addressPostal)
+      addressPostal.addressOwner = `${response.data.person.name} ${response.data.person.givenName}`
+      addressPostal['@id'] = ''
+
+      if(addressItem.value)
+        addressPostal.id = addressItem.value.id
+
+      //On l'associe à l'OrganizationAddressPostal qui est éditée, et on persist
+      organizationAddressPostalItem.value.addressPostal = addressPostal
+      repositoryHelper.persist(OrganizationAddressPostal, organizationAddressPostalItem.value)
+    }
+  }
+
+  return {
+    updateAccessAddress
+  }
+}
+
 </script>
+
 <style>
   .toolbarForm .v-toolbar__content{
     padding-left: 0 !important;

+ 26 - 14
pages/organization/index.vue

@@ -72,12 +72,11 @@ Contient toutes les informations sur l'organization courante
               <v-row>
                 <v-col cols="12" sm="12">
                   <UiSubList
-                    :query="repositories.addressRepository.with('addressPostal', (query) => {
-                      query.with('addressCountry')
-                    })"
+                    :query="repositories.addressRepository.with('addressPostal')"
                     :root-model="models.Organization"
                     :root-id="id"
                     :model="models.OrganizationAddressPostal"
+                    loaderType="image"
                   >
                     <template #list.item="{items}">
                       <v-container fluid>
@@ -100,7 +99,17 @@ Contient toutes les informations sur l'organization courante
                                 <span v-if="item.addressPostal.streetAddressSecond">{{ item.addressPostal.streetAddressSecond }} <br></span>
                                 <span v-if="item.addressPostal.streetAddressThird">{{ item.addressPostal.streetAddressThird }} <br></span>
                                 {{ item.addressPostal.postalCode }} {{ item.addressPostal.addressCity }}<br>
-                                <span v-if="item.addressPostal.addressCountry">{{ item.addressPostal.addressCountry.name }}</span>
+                                <span v-if="item.addressPostal.addressCountry">
+                                  <UiItemFromUri
+                                    :model="models.Country"
+                                    :query="repositories.countryRepository.query()"
+                                    :uri="item.addressPostal.addressCountry"
+                                  >
+                                    <template #item.text="{item}">
+                                      {{item.name}}
+                                    </template>
+                                  </UiItemFromUri>
+                                </span>
                               </template>
                             </UiCard>
                           </v-col>
@@ -123,6 +132,7 @@ Contient toutes les informations sur l'organization courante
                     :root-model="models.Organization"
                     :root-id="id"
                     :model="models.ContactPoint"
+                    loaderType="image"
                   >
                     <template #list.item="{items}">
                       <v-container fluid>
@@ -145,10 +155,10 @@ Contient toutes les informations sur l'organization courante
                                 <span v-if="item.emailInvalid" class="ot_danger--text"><v-icon class="ot_danger--text">mdi-alert</v-icon> <strong>{{ $t('emailInvalid') }}</strong> : {{ item.emailInvalid }} <br></span>
 
                                 <span v-if="item.telphone"><strong>{{ $t('telphone') }}</strong> : {{ formatPhoneNumber(item.telphone) }} <br></span>
-                                <span v-if="item.telphoneInvalid" class="ot_danger--text"><v-icon class="ot_danger--text">mdi-alert</v-icon> <strong>{{ $t('telphoneInvalid') }}</strong> : {{ item.telphoneInvalid }} <br></span>
+                                <span v-if="item.telphoneInvalid" class="ot_danger--text"><v-icon class="ot_danger--text">mdi-alert</v-icon> <strong>{{ $t('telphoneInvalid') }}</strong> : {{ formatPhoneNumber(item.telphoneInvalid) }} <br></span>
 
-                                <span v-if="item.mobilPhone"><strong>{{ $t('mobilPhone') }}</strong> : {{ item.mobilPhone }} <br></span>
-                                <span v-if="item.mobilPhoneInvalid" class="ot_danger--text"><v-icon class="ot_danger--text">mdi-alert</v-icon> <strong>{{ $t('mobilPhoneInvalid') }}</strong> : {{ item.mobilPhoneInvalid }} </span>
+                                <span v-if="item.mobilPhone"><strong>{{ $t('mobilPhone') }}</strong> : {{ formatPhoneNumber(item.mobilPhone) }} <br></span>
+                                <span v-if="item.mobilPhoneInvalid" class="ot_danger--text"><v-icon class="ot_danger--text">mdi-alert</v-icon> <strong>{{ $t('mobilPhoneInvalid') }}</strong> : {{ formatPhoneNumber(item.mobilPhoneInvalid) }} </span>
                               </template>
                             </UiCard>
                           </v-col>
@@ -324,6 +334,7 @@ import { repositoryHelper } from '~/services/store/repository'
 import UseValidator from '~/use/form/useValidator'
 import { UseNavigationHelpers } from '~/use/form/useNavigationHelpers'
 import I18N from '~/services/utils/i18n'
+import {Country} from "~/models/Core/Country";
 
 export default defineComponent({
   name: 'OrganizationParent',
@@ -343,23 +354,23 @@ export default defineComponent({
 
     const { panel } = UseNavigationHelpers.expansionPanels()
 
+    const formatPhoneNumber = (number: string): string => {
+      return I18N.formatPhoneNumber(number)
+    }
+
     return {
       repositories,
       id,
       organizationProfile,
-      models: { Organization, ContactPoint, BankAccount, OrganizationAddressPostal },
+      models: { Organization, ContactPoint, BankAccount, OrganizationAddressPostal, Country },
       datatableHeaders: getDataTablesHeaders(i18n),
       rules: getRules(i18n),
       siretError,
       siretErrorMessage,
       checkSiretHook,
+      formatPhoneNumber,
       panel
     }
-  },
-  methods: {
-    formatPhoneNumber (number: string): string {
-      return I18N.formatPhoneNumber(number)
-    }
   }
 })
 
@@ -402,7 +413,8 @@ function getRepositories () {
     organizationRepository: repositoryHelper.getRepository(Organization),
     contactPointRepository: repositoryHelper.getRepository(ContactPoint),
     bankAccountRepository: repositoryHelper.getRepository(BankAccount),
-    addressRepository: repositoryHelper.getRepository(OrganizationAddressPostal)
+    addressRepository: repositoryHelper.getRepository(OrganizationAddressPostal),
+    countryRepository: repositoryHelper.getRepository(Country)
   }
 }
 </script>

+ 12 - 5
plugins/Data/axios.js

@@ -1,12 +1,19 @@
 export default function ({ $axios, redirect, store }) {
   $axios.onRequest(config => {
-    $axios.setHeader('x-accessid', `${store.state.profile.access.id}`)
+    if(!config.params.noXaccessId){
+      $axios.setHeader('x-accessid', `${store.state.profile.access.id}`)
 
-    if (store.state.profile.access.switchId) {
-      $axios.setHeader('x-switch-user', `${store.state.profile.access.switchId}`)
-    }
+      if (store.state.profile.access.switchId) {
+        $axios.setHeader('x-switch-user', `${store.state.profile.access.switchId}`)
+      }
 
-    $axios.setToken(`${store.state.profile.access.bearer}`, 'Bearer')
+      $axios.setToken(`${store.state.profile.access.bearer}`, 'Bearer')
+    }else{
+      delete config.headers.common['Authorization']
+      delete config.headers.common['x-accessid']
+      $axios.setHeader('x-accessid', false)
+      $axios.setToken(false)
+    }
   })
 
   $axios.onResponse(response => {

+ 41 - 0
use/data/useAccess.ts

@@ -0,0 +1,41 @@
+import { AnyJson } from '~/types/interfaces'
+import {QUERY_TYPE} from "~/types/enums";
+import { useContext} from '@nuxtjs/composition-api'
+import DataProvider from "~/services/data/dataProvider";
+
+/**
+ * @category Use/data
+ * @class UseAccess
+ * Use Classe pour gérer l'alimentation des Accesses
+ */
+export class UseAccess {
+  private $dataProvider!: DataProvider
+
+  constructor() {
+    const {$dataProvider} = useContext()
+    this.$dataProvider = $dataProvider
+  }
+
+  public invoke(): AnyJson{
+    return {
+      getPhysicalByFullName: (research: string) => this.getPhysicalByFullName(research),
+    }
+  }
+
+  private async getPhysicalByFullName(research: string): Promise<Array<AnyJson>>{
+    if(research){
+      const response = await this.$dataProvider.invoke({
+        type: QUERY_TYPE.DEFAULT,
+        url: `api/access_people`,
+        listArgs: {
+          filters:[
+            {key: 'person.isPhysical', value: 1},
+            {key: 'fullname', value: research}
+          ]
+        }
+      })
+      return response.data
+    }
+    return []
+  }
+}

+ 75 - 0
use/data/useAddresspostal.ts

@@ -0,0 +1,75 @@
+import { AnyJson } from '~/types/interfaces'
+import {QUERY_TYPE} from "~/types/enums";
+import { useContext } from '@nuxtjs/composition-api'
+import DataProvider from "~/services/data/dataProvider";
+
+/**
+ * @category Use/data
+ * @class UseAddressPostal
+ * Use Classe pour gérer les deux champs postal code et adresseCity
+ */
+export class UseAddressPostal {
+  private $dataProvider!: DataProvider
+
+  constructor() {
+    const {$dataProvider} = useContext()
+    this.$dataProvider = $dataProvider
+  }
+
+  public invoke(): AnyJson{
+    return {
+      searchFunction: (research: string, field: string) => this.searchFunction(research, field),
+      updateCpAddress: (value:AnyJson, updateRepository: Function) => this.updateCpAddress(value, updateRepository),
+    }
+  }
+
+  /**
+   * Fonction de recherche qui utilise l'API gouvernematal pour autocompléter les CP et villes.
+   * @param research
+   * @param field
+   * @private
+   */
+  private async searchFunction (research: string, field: string): Promise<Array<AnyJson>>{
+    if(research){
+      const response = await this.$dataProvider.invoke({
+        type: QUERY_TYPE.DEFAULT,
+        url: `https://api-adresse.data.gouv.fr/search/?q=${research}&type=municipality&autocomplete=1&limit=20`,
+        params: {
+          noXaccessId: true
+        }
+      })
+      const apiResponse = response.data.features.map((data:AnyJson)=>data.properties)
+
+      // Par défaut on insère les valeurs que l'utilisateur a écrit, car un nom de ville ou de CP peut être absent de l'API
+      const defaultResponse = []
+      if(field === 'addressPostal.addressCity'){
+        defaultResponse.push({id:0, postcode: null, city: research})
+      }else{
+        defaultResponse.push({id:0, postcode: research, city: null})
+      }
+
+      return defaultResponse.concat(apiResponse)
+    }
+    return []
+  }
+
+  /**
+   * Fonction permettant de mettre à jour le repo par rapport à la réponse (objet) de l'autocomplete
+   * @param value
+   * @param updateRepository
+   * @private
+   */
+  private updateCpAddress(value:AnyJson, updateRepository: Function): void{
+    //Si une valeur est présente
+    if(value){
+      if(value.city)
+        updateRepository(value.city, 'addressPostal.addressCity')
+      if(value.postcode)
+        updateRepository(value.postcode, 'addressPostal.postalCode')
+    }else{
+      //Cas où on efface les valeurs des champs
+      updateRepository(null, 'addressPostal.addressCity')
+      updateRepository(null, 'addressPostal.postalCode')
+    }
+  }
+}

+ 42 - 0
use/data/useCountry.ts

@@ -0,0 +1,42 @@
+import { AnyJson } from '~/types/interfaces'
+import {QUERY_TYPE} from "~/types/enums";
+import {Country} from "~/models/Core/Country";
+import { useContext, useFetch, computed } from '@nuxtjs/composition-api'
+import DataProvider from "~/services/data/dataProvider";
+import {repositoryHelper} from "~/services/store/repository";
+
+/**
+ * @category Use/data
+ * @class UseCountry
+ * Use Classe pour gérer l'alimentation des Countries
+ */
+export class UseCountry {
+  private $dataProvider!: DataProvider
+
+  constructor() {
+    const {$dataProvider} = useContext()
+    this.$dataProvider = $dataProvider
+  }
+
+  /**
+   * Récupération des Country via l'API
+   */
+  public getAll(): AnyJson{
+    const {fetch, fetchState} = useFetch(async () => {
+      await this.$dataProvider.invoke({
+        type: QUERY_TYPE.MODEL,
+        model: Country
+      })
+    })
+
+    const countries =  computed(() => {
+      return repositoryHelper.findCollectionFromModel(Country)
+    })
+
+    return {
+      countries,
+      fetch,
+      fetchState
+    }
+  }
+}