diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index bb71762235a1187989c66f732efe2aa222b128a2..8396a9ed144b0d4185a8bfd0dd085c5ceac7eade 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -46,6 +46,7 @@ test:
     - export GHOST_HOST_AND_PORT=http://localhost:2368
     - export GHOST_ADMIN_API_KEY=60142bc9e33940000156bccc:6217742e2671e322612e89cac9bab61fcd01822709fe5d8f5e6a5b3e54d5e6bb
     - export SALT=$TEST_SALT
+    - export ELASTICSEARCH_NODE=http://localhost:9200
   script:
     - npm i
     - npm run test:cov
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a59f202c1f017b324006555b280e9291176e900f..e1023255dc6824c6d6fdd32e3aef538476ceeae4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,33 @@
 
 All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
 
+## [1.8.0](https://forge.grandlyon.com///compare/v1.7.0...v1.8.0) (2021-05-06)
+
+
+### Features
+
+* add auto-migrate for production ([f0568dc](https://forge.grandlyon.com///commit/f0568dcb3959db84a96c78915a7cd135d163b1b4))
+* add migration for date format ([cae255e](https://forge.grandlyon.com///commit/cae255efe9c174457ae66c94a41e941bf7b2165c))
+* **structures:** add elastic search stack for better search handling ([bbf608b](https://forge.grandlyon.com///commit/bbf608b6e90afaea9ae84ee9121e11ade7dd32c0))
+* add enpoint for couting newsletter ([27cd278](https://forge.grandlyon.com///commit/27cd278781187a3734d06f16331fa9119da7adf4))
+* add new endpoint for structures, data is formated (jointure on modules) ([509f30f](https://forge.grandlyon.com///commit/509f30f9a2c36b18ed093d25fa37c3b9b3849165))
+* add notification mail to admin for structure ([d241ed8](https://forge.grandlyon.com///commit/d241ed8c4597a0151d5a916ae9c0f6aefe0e3092))
+
+
+### Bug Fixes
+
+* better naming ([2f837e7](https://forge.grandlyon.com///commit/2f837e78add9bacece2c8a03aa90c828ab7a832f))
+* change freeWorkshop back to notempty ([ad09120](https://forge.grandlyon.com///commit/ad0912014ce7e1da5c94565f4dd05ca14884adb6))
+* changes after review ([b627628](https://forge.grandlyon.com///commit/b62762851345e08d09cde924bc961ecca3123f16))
+* changes on email template (wording...) ([0d18670](https://forge.grandlyon.com///commit/0d18670ca6d889628150d3d04ef1257ef06c3a51))
+* docker-compose missing var + add admin verification on ES index reset ([0af581d](https://forge.grandlyon.com///commit/0af581d8a9d06d0de5b00a65915694cec6d270d2))
+* fix number of results for ES and filters count ([416654e](https://forge.grandlyon.com///commit/416654e6165072314f91d7db3924dd730dbe471b))
+* hide some fiel on endpoint and create migration for opening hours ([ec6d2ac](https://forge.grandlyon.com///commit/ec6d2acfd96a69ffd38e08310ec6f1863332a306))
+* remove mandatory field on structure + update local email sending conf ([7603e47](https://forge.grandlyon.com///commit/7603e47f335aee3ade21ec5d49e7927d7b6eaaa8))
+* remove useless import ([2253581](https://forge.grandlyon.com///commit/2253581b1ebc5a0dd2c0826ed97d9e549bba9402))
+* remove useless improt ([421806d](https://forge.grandlyon.com///commit/421806d13befac5092d87d4864358692938ccfd3))
+* **migration:** fix remove field bug in script ([d6a0f77](https://forge.grandlyon.com///commit/d6a0f775e2cbe6ca9e98d30dc6d136206b587667))
+
 ## [1.7.0](https://forge.grandlyon.com///compare/v1.6.1...v1.7.0) (2021-04-12)
 
 
diff --git a/docker-compose.yml b/docker-compose.yml
index e95e22ec421be34eadca84b2076cc2b029fd0cb0..94915f69117f8fbfab0d0965a2f7895797b79beb 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -8,10 +8,24 @@ services:
       - ${SERVICE_API_BIND_PORT}:3000
     extra_hosts:
       - 'sen.grandlyon.com:10.128.16.229'
+    volumes:
+      - ./.migrate:/app/.migrate
     environment:
       MONGO_NON_ROOT_USERNAME: ${MONGO_NON_ROOT_USERNAME}
       MONGO_NON_ROOT_PASSWORD: ${MONGO_NON_ROOT_PASSWORD}
       MONGO_DB_HOST_AND_PORT: ${MONGO_DB_HOST_AND_PORT}
+      JWT_SECRET: ${JWT_SECRET}
+      SALT: ${SALT}
+      MAIL_URL: ${MAIL_URL}
+      MAIL_TOKEN: ${MAIL_TOKEN}
+      NODE_ENV: ${NODE_ENV}
+      APTIC_TOKEN: ${APTIC_TOKEN}
+      GHOST_HOST_AND_PORT: ${GHOST_HOST_AND_PORT}
+      GHOST_ADMIN_API_KEY: ${GHOST_ADMIN_API_KEY}
+      GHOST_CONTENT_API_KEY: ${GHOST_CONTENT_API_KEY}
+      ELASTICSEARCH_NODE: ${ELASTICSEARCH_NODE}
+      ELASTICSEARCH_USERNAME: ${ELASTICSEARCH_USERNAME}
+      ELASTICSEARCH_PASSWORD: ${ELASTICSEARCH_PASSWORD}
     restart: unless-stopped
     depends_on:
       - database-ram
@@ -67,6 +81,43 @@ services:
     volumes:
       - db-ghost
 
+  es01:
+    image: elasticsearch:7.6.1
+    restart: unless-stopped
+    environment:
+      node.name: es01
+      cluster.name: es-docker-cluster
+      discovery.type: single-node
+      xpack.security.enabled: ${ELASTIC_SECURITY}
+      ELASTIC_PASSWORD: ${ELASTICSEARCH_PASSWORD}
+    volumes:
+      - db-elastic
+    networks:
+      - elastic
+    ports:
+      - ${ELASTICSEARCH_PORT}:9200
+
+  kib01:
+    image: docker.elastic.co/kibana/kibana:7.6.1
+    restart: unless-stopped
+    container_name: kib01
+    ports:
+      - ${KIBANA_PORT}:5601
+    environment:
+      ELASTICSEARCH_URL: http://es01:9200
+      ELASTICSEARCH_HOSTS: '["http://es01:9200"]'
+      ELASTICSEARCH_USERNAME: elastic
+      ELASTICSEARCH_PASSWORD: ${ELASTICSEARCH_PASSWORD}
+    depends_on:
+      - es01
+    networks:
+      - elastic
+
 volumes:
   db-ram:
   db-ghost:
+  db-elastic:
+
+networks:
+  elastic:
+    driver: bridge
diff --git a/package-lock.json b/package-lock.json
index d787d4c561026f1861332126e9218bc649e0b94c..7ce909f59ffedfe49c41f1c143c68e1840da7a8c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "ram_server",
-  "version": "1.7.0",
+  "version": "1.8.0",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
@@ -636,6 +636,40 @@
         "minimist": "^1.2.0"
       }
     },
+    "@elastic/elasticsearch": {
+      "version": "7.12.0",
+      "resolved": "https://registry.npmjs.org/@elastic/elasticsearch/-/elasticsearch-7.12.0.tgz",
+      "integrity": "sha512-GquUEytCijFRPEk3DKkkDdyhspB3qbucVQOwih9uNyz3iz804I+nGBUsFo2LwVvLQmQfEM0IY2+yoYfEz5wMug==",
+      "requires": {
+        "debug": "^4.3.1",
+        "hpagent": "^0.1.1",
+        "ms": "^2.1.3",
+        "pump": "^3.0.0",
+        "secure-json-parse": "^2.3.1"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "4.3.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
+          "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
+          "requires": {
+            "ms": "2.1.2"
+          },
+          "dependencies": {
+            "ms": {
+              "version": "2.1.2",
+              "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+              "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+            }
+          }
+        },
+        "ms": {
+          "version": "2.1.3",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+          "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+        }
+      }
+    },
     "@eslint/eslintrc": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.1.tgz",
@@ -1356,6 +1390,26 @@
         }
       }
     },
+    "@nestjs/config": {
+      "version": "0.6.3",
+      "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-0.6.3.tgz",
+      "integrity": "sha512-JxvvUpmH0/WOrTB+zh8dEkxSUQXhB7V3d/qeQXyCnMiEFjaq89+fNFztpWjz4DlOfdS4/eYTzIEy9PH2uGnfzA==",
+      "requires": {
+        "dotenv": "8.2.0",
+        "dotenv-expand": "5.1.0",
+        "lodash.get": "4.4.2",
+        "lodash.has": "4.5.2",
+        "lodash.set": "4.3.2",
+        "uuid": "8.3.2"
+      },
+      "dependencies": {
+        "uuid": {
+          "version": "8.3.2",
+          "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+          "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
+        }
+      }
+    },
     "@nestjs/core": {
       "version": "7.5.1",
       "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-7.5.1.tgz",
@@ -1370,6 +1424,11 @@
         "uuid": "8.3.1"
       }
     },
+    "@nestjs/elasticsearch": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/@nestjs/elasticsearch/-/elasticsearch-7.1.0.tgz",
+      "integrity": "sha512-3ixmu9MkTh0DS+LKAKcWHLyf/1DPQTXoy+aVClVI14DJQU208oHR3V0e9klApC+GXCYW+BDhNReh4HRyekjTrw=="
+    },
     "@nestjs/jwt": {
       "version": "7.2.0",
       "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-7.2.0.tgz",
@@ -4921,6 +4980,11 @@
       "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
       "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw=="
     },
+    "dotenv-expand": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz",
+      "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA=="
+    },
     "dotgitignore": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/dotgitignore/-/dotgitignore-2.1.0.tgz",
@@ -5060,7 +5124,6 @@
       "version": "1.4.4",
       "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
       "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
-      "dev": true,
       "requires": {
         "once": "^1.4.0"
       }
@@ -6941,6 +7004,11 @@
       "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
       "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg=="
     },
+    "hpagent": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-0.1.1.tgz",
+      "integrity": "sha512-IxJWQiY0vmEjetHdoE9HZjD4Cx+mYTr25tR7JCxXaiI3QxW0YqYyM11KyZbHufoa/piWhMb2+D3FGpMgmA2cFQ=="
+    },
     "html-encoding-sniffer": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz",
@@ -8183,6 +8251,7 @@
       "version": "12.0.0",
       "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-12.0.0.tgz",
       "integrity": "sha512-+8K35LlboWiPuCnXSyiid7rFdxNlpCWWM20WEYe6IZH6psfUWKZmSpSRQ5tk0C0cBeDsvsnIzcef5mYhyJsbug==",
+      "dev": true,
       "requires": {
         "mkdirp": "^1.0.4",
         "strip-ansi": "^5.2.0",
@@ -8193,17 +8262,20 @@
         "ansi-regex": {
           "version": "4.1.0",
           "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-          "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
+          "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+          "dev": true
         },
         "mkdirp": {
           "version": "1.0.4",
           "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
-          "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
+          "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+          "dev": true
         },
         "strip-ansi": {
           "version": "5.2.0",
           "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
           "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+          "dev": true,
           "requires": {
             "ansi-regex": "^4.1.0"
           }
@@ -8211,7 +8283,8 @@
         "uuid": {
           "version": "3.4.0",
           "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
-          "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
+          "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
+          "dev": true
         }
       }
     },
@@ -9288,6 +9361,16 @@
       "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
       "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0="
     },
+    "lodash.get": {
+      "version": "4.4.2",
+      "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
+      "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
+    },
+    "lodash.has": {
+      "version": "4.5.2",
+      "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz",
+      "integrity": "sha1-0Z9NwQlQWMzL4rDN9O4P5Ko3yGI="
+    },
     "lodash.includes": {
       "version": "4.3.0",
       "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
@@ -9334,6 +9417,11 @@
       "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
       "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
     },
+    "lodash.set": {
+      "version": "4.3.2",
+      "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz",
+      "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM="
+    },
     "lodash.sortby": {
       "version": "4.7.0",
       "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
@@ -11158,7 +11246,6 @@
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
       "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
-      "dev": true,
       "requires": {
         "end-of-stream": "^1.1.0",
         "once": "^1.3.1"
@@ -11806,6 +11893,11 @@
         "ajv-keywords": "^3.4.1"
       }
     },
+    "secure-json-parse": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.4.0.tgz",
+      "integrity": "sha512-Q5Z/97nbON5t/L/sH6mY2EacfjVGwrCcSi5D3btRO2GZ8pf1K1UN7Z9H5J57hjVU2Qzxr1xO+FmBhOvEkzCMmg=="
+    },
     "semver": {
       "version": "7.3.2",
       "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
@@ -14176,7 +14268,8 @@
     "xml": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz",
-      "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU="
+      "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=",
+      "dev": true
     },
     "xml-name-validator": {
       "version": "3.0.0",
diff --git a/package.json b/package.json
index 79114f2ed061d6b141ac421bafe63a3df12d5d55..0f20477d4039d2e01f2852231f0d219bcf5c5288 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "ram_server",
   "private": true,
-  "version": "1.7.0",
+  "version": "1.8.0",
   "description": "Nest TypeScript starter repository",
   "license": "MIT",
   "scripts": {
@@ -11,7 +11,7 @@
     "start": "ts-node -r tsconfig-paths/register src/main.ts",
     "start:dev": "nodemon",
     "start:debug": "nodemon --config nodemon-debug.json",
-    "start:prod": "node dist/main",
+    "start:prod": "npm run migrate:up && node dist/main",
     "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
     "release": "standard-version",
     "init-db": "node ./scripts/init-db.js",
@@ -25,8 +25,11 @@
     "migrate:down": "migrate --migrations-dir=\"./src/migrations/scripts\" --compiler=\"ts:./src/migrations/migrations-utils/ts-compiler.js\" down"
   },
   "dependencies": {
+    "@elastic/elasticsearch": "^7.12.0",
     "@nestjs/common": "^7.6.13",
+    "@nestjs/config": "^0.6.3",
     "@nestjs/core": "^7.5.1",
+    "@nestjs/elasticsearch": "^7.1.0",
     "@nestjs/jwt": "^7.2.0",
     "@nestjs/mongoose": "^7.1.0",
     "@nestjs/passport": "^7.1.5",
diff --git a/scripts/init-ghost.js b/scripts/init-ghost.js
index 350b0376602770cb6b9112cdb8afde728f6a13fe..345ed027d3792a0966ff63452cb05fddeb406fe1 100644
--- a/scripts/init-ghost.js
+++ b/scripts/init-ghost.js
@@ -81,8 +81,9 @@ function processImagesInHTML(html) {
   // Find images that Ghost Upload supports
   let imageRegex = /="([^"]*?(?:\.jpg|\.jpeg|\.gif|\.png|\.svg|\.sgvz))"/gim;
   let imagePromises = [];
+  let result;
 
-  while ((const result = imageRegex.exec(html)) !== null) {
+  while ((result = imageRegex.exec(html)) !== null) {
     let file = result[1];
     // Upload the image, using the original matched filename as a reference
     imagePromises.push(
diff --git a/src/admin/admin.controller.spec.ts b/src/admin/admin.controller.spec.ts
index 84dbf424a36ea0a54a4e59cf28ff657f8d546082..dc0bdef307a30973ed3864fa428e46aca34c8dea 100644
--- a/src/admin/admin.controller.spec.ts
+++ b/src/admin/admin.controller.spec.ts
@@ -1,12 +1,14 @@
-import { HttpException, HttpModule, HttpStatus } from '@nestjs/common';
+import { HttpModule } from '@nestjs/common';
 import { getModelToken } from '@nestjs/mongoose';
 import { Test, TestingModule } from '@nestjs/testing';
 import { ConfigurationModule } from '../configuration/configuration.module';
 import { MailerService } from '../mailer/mailer.service';
 import { NewsletterSubscription } from '../newsletter/newsletter-subscription.schema';
 import { NewsletterService } from '../newsletter/newsletter.service';
+import { SearchModule } from '../search/search.module';
 import { Structure } from '../structures/schemas/structure.schema';
 import { StructuresService } from '../structures/services/structures.service';
+import { StructuresSearchService } from '../structures/services/structures-search.service';
 import { User } from '../users/schemas/user.schema';
 import { UsersService } from '../users/users.service';
 import { AdminController } from './admin.controller';
@@ -17,10 +19,11 @@ describe('AdminController', () => {
 
   beforeEach(async () => {
     const module: TestingModule = await Test.createTestingModule({
-      imports: [ConfigurationModule, HttpModule],
+      imports: [ConfigurationModule, HttpModule, SearchModule],
       providers: [
         UsersService,
         StructuresService,
+        StructuresSearchService,
         NewsletterService,
         MailerService,
         {
@@ -47,21 +50,35 @@ describe('AdminController', () => {
   });
 
   it('should get pending attachments', async () => {
-    const result = [{name: "MJC Route de vienne", address: "14 chemin des platanes"}, {name: "Mairie Lyon 7eme", address: "21 boulevard martin"}];
+    const result = [
+      { name: 'MJC Route de vienne', address: '14 chemin des platanes' },
+      { name: 'Mairie Lyon 7eme', address: '21 boulevard martin' },
+    ];
     jest.spyOn(controller, 'getPendingAttachments').mockImplementation(async (): Promise<any> => result);
     expect(await controller.getPendingAttachments()).toBe(result);
   });
 
   it('should validate pending structure', async () => {
-    const result = [{name: "MJC Route de vienne", address: "14 chemin des platanes"}];
-    const structure: PendingStructureDto = {userEmail:"martin@mjc.fr", structureId: "1", structureName:"MJC Route de vienne"};
+    const result = [{ name: 'MJC Route de vienne', address: '14 chemin des platanes' }];
+    const structure: PendingStructureDto = {
+      userEmail: 'martin@mjc.fr',
+      structureId: '1',
+      structureName: 'MJC Route de vienne',
+    };
     jest.spyOn(controller, 'validatePendingStructure').mockImplementation(async (): Promise<any> => result);
     expect(await controller.validatePendingStructure(structure)).toBe(result);
   });
 
   it('should refuse pending structure', async () => {
-    const result = [{name: "MJC Route de vienne", address: "14 chemin des platanes"}, {name: "Mairie Lyon 7eme", address: "21 boulevard martin"}];
-    const structure: PendingStructureDto = {userEmail:"martin@mjc.fr", structureId: "1", structureName:"MJC Route de vienne"};
+    const result = [
+      { name: 'MJC Route de vienne', address: '14 chemin des platanes' },
+      { name: 'Mairie Lyon 7eme', address: '21 boulevard martin' },
+    ];
+    const structure: PendingStructureDto = {
+      userEmail: 'martin@mjc.fr',
+      structureId: '1',
+      structureName: 'MJC Route de vienne',
+    };
     jest.spyOn(controller, 'refusePendingStructure').mockImplementation(async (): Promise<any> => result);
     expect(await controller.refusePendingStructure(structure)).toBe(result);
   });
diff --git a/src/admin/admin.controller.ts b/src/admin/admin.controller.ts
index 03442f8e55e2210e3bf1fc52f96e0c4617ff3add..999c6d949ba0026bdc654d172dc703459030ed50 100644
--- a/src/admin/admin.controller.ts
+++ b/src/admin/admin.controller.ts
@@ -2,6 +2,7 @@ import { Body, Delete, Param } from '@nestjs/common';
 import { Controller, Get, Post, UseGuards } from '@nestjs/common';
 import { ApiOperation, ApiParam } from '@nestjs/swagger';
 import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
+import { NewsletterSubscriptionDocument } from '../newsletter/newsletter-subscription.schema';
 import { NewsletterService } from '../newsletter/newsletter.service';
 import { StructuresService } from '../structures/services/structures.service';
 import { Roles } from '../users/decorators/roles.decorator';
@@ -111,6 +112,13 @@ export class AdminController {
     else return this.newsletterService.findAll();
   }
 
+  @UseGuards(JwtAuthGuard, RolesGuard)
+  @Roles('admin')
+  @Get('countNewsletterSubscriptions')
+  public async countNewsletterSubscriptions(): Promise<number> {
+    return this.newsletterService.countNewsletterSubscriptions();
+  }
+
   @UseGuards(JwtAuthGuard, RolesGuard)
   @Roles('admin')
   @Delete('newsletterSubscription/:email')
diff --git a/src/app.module.ts b/src/app.module.ts
index ed6a03004e4e90edc2decf97c41b7f3478ca4f69..3cd15b2b24ef294009ddb6c3a55989789bd9bfd4 100644
--- a/src/app.module.ts
+++ b/src/app.module.ts
@@ -29,7 +29,7 @@ import { NewsletterModule } from './newsletter/newsletter.module';
     AdminModule,
     PostsModule,
     TempUserModule,
-    NewsletterModule
+    NewsletterModule,
   ],
   controllers: [AppController],
 })
diff --git a/src/categories/categories.module.ts b/src/categories/categories.module.ts
index bc6f3c86841008cb9bed60f0c70bbd517b947403..3373d355f83e81b4d19fa7ebcf1f2ca1b4487c87 100644
--- a/src/categories/categories.module.ts
+++ b/src/categories/categories.module.ts
@@ -19,7 +19,10 @@ import { CategoriesAccompagnement, CategoriesAccompagnementSchema } from './sche
     ]),
   ],
   controllers: [CategoriesFormationsController, CategoriesAccompagnementController, CategoriesOthersController],
-  exports: [CategoriesFormationsService],
+  exports: [CategoriesFormationsService, CategoriesAccompagnementService, CategoriesOthersService],
   providers: [CategoriesFormationsService, CategoriesAccompagnementService, CategoriesOthersService],
 })
-export class CategoriesModule {}
+export class CategoriesModule {
+  id: string;
+  text: any;
+}
diff --git a/src/configuration/config.ts b/src/configuration/config.ts
index 0506dc2ae8a5b211ad5883852d50858f71e84fda..97ab675e89c54d4e224c3ebec86ed372bbb45ce9 100644
--- a/src/configuration/config.ts
+++ b/src/configuration/config.ts
@@ -4,9 +4,9 @@ export const config = {
   host: 'localhost',
   protocol: 'http',
   port: '4200',
-  from: 'inclusionnumerique@grandlyon.com',
+  from: 'noreplyinclusionnumerique@grandlyon.com',
   from_name: 'Réseau des acteurs de la médiation numérique',
-  replyTo: 'inclusionnumerique@grandlyon.com',
+  replyTo: 'noreplyinclusionnumerique@grandlyon.com',
   templates: {
     directory: './src/mailer/mail-templates',
     verify: {
@@ -53,5 +53,13 @@ export const config = {
       ejs: 'structureErrorReport.ejs',
       json: 'structureErrorReport.json',
     },
+    structureModificationNotification: {
+      ejs: 'structureModificationNotification.ejs',
+      json: 'structureModificationNotification.json',
+    },
+    structureDeletionNotification: {
+      ejs: 'structureDeletionNotification.ejs',
+      json: 'structureDeletionNotification.json',
+    },
   },
 };
diff --git a/src/mailer/mail-templates/adminStructureClaim.ejs b/src/mailer/mail-templates/adminStructureClaim.ejs
index 8eff0993341c0655469c5cd2dfbe1aa50a9180ff..1e7e162f39e671fdf5d6beb2e1765a7d284e37e5 100644
--- a/src/mailer/mail-templates/adminStructureClaim.ejs
+++ b/src/mailer/mail-templates/adminStructureClaim.ejs
@@ -1,4 +1,4 @@
-Bonjour<br />
+Bonjour,<br />
 <br />
 Une nouvelle structure a été revendiquée. Pour valider ou refuser la demande, merci de vous rendre sur
 <a href="<%= config.protocol %>://<%= config.host %><%= config.port ? ':' + config.port : '' %>/admin">ce lien</a>.
diff --git a/src/mailer/mail-templates/adminStructureCreate.ejs b/src/mailer/mail-templates/adminStructureCreate.ejs
index 47b79daa15b999739415094be15f42e9f641ede0..0fa351673b20ec097f09119ed1aefb97c9746382 100644
--- a/src/mailer/mail-templates/adminStructureCreate.ejs
+++ b/src/mailer/mail-templates/adminStructureCreate.ejs
@@ -1,8 +1,8 @@
-Bonjour<br />
+Bonjour,<br />
 <br />
-Une nouvelle structure a été créé:
+Une nouvelle structure a été créée:
 <a href="<%= config.protocol %>://<%= config.host %><%= config.port ? ':' + config.port : '' %>/acteurs?id=<%= id %>"
-  ><strong><%= name %></strong></a
+  ><strong><%= structureName %></strong></a
 >
 <br />
 Il est possible que la structure ne soit pas immédiatement visible sur la carto. L'utilisateur doit valider son compte
diff --git a/src/mailer/mail-templates/apticStructureDuplication.ejs b/src/mailer/mail-templates/apticStructureDuplication.ejs
index 53d99ec48ecccb22849a867d2579fac919ec78f9..0b30ee72bff6faf595b43702914c0e7bb204b269 100644
--- a/src/mailer/mail-templates/apticStructureDuplication.ejs
+++ b/src/mailer/mail-templates/apticStructureDuplication.ejs
@@ -1,4 +1,4 @@
 Bonjour,<br />
 <br />
 La fiche structure: <strong><%= name %></strong> a été créée après récupération des données aptic. Elle correspond
-potientiellement a la structure existante : <strong><%= duplicatedStructureName %></strong>.
+potientiellement à la structure existante : <strong><%= duplicatedStructureName %></strong>.
diff --git a/src/mailer/mail-templates/resetPassword.ejs b/src/mailer/mail-templates/resetPassword.ejs
index cf29cee55cd7ee9881479fef67ac49eaf27d1a7d..233966c0e062c056cb73c5afcbdd2461448c941b 100644
--- a/src/mailer/mail-templates/resetPassword.ejs
+++ b/src/mailer/mail-templates/resetPassword.ejs
@@ -1,4 +1,4 @@
-Bonjour<br />
+Bonjour,<br />
 <br />
 Vous avez demandé une réinitialisation de votre mot de passe pour le
 <em>Réseau des Acteurs de la Médiation Numérique de la Métropole de Lyon</em>. Pour changer de mot de passe, merci de
@@ -7,4 +7,4 @@ cliquer sur le lien suivant :
   href="<%= config.protocol %>://<%= config.host %><%= config.port ? ':' + config.port : '' %>/reset-password?token=<%= token %>"
   >ce lien</a
 ><br />
-Si vous n'avez pas demander de réinitiallisation de votre mot de passe, merci d'ignorer cet email.
+Si vous n'avez pas demandé de réinitiallisation de votre mot de passe, merci d'ignorer cet email.
diff --git a/src/mailer/mail-templates/structureClaimValidation.ejs b/src/mailer/mail-templates/structureClaimValidation.ejs
index 9e04b8973bf0a6fea16782f07e4537bf65369314..63622c87def5631e1568e59dd550d4cb969b8c88 100644
--- a/src/mailer/mail-templates/structureClaimValidation.ejs
+++ b/src/mailer/mail-templates/structureClaimValidation.ejs
@@ -1,11 +1,11 @@
-Bonjour<br />
+Bonjour,<br />
 <br />
-La demande de rattachement de votre compte a la structure <strong><%= name %></strong> a été
+La demande de rattachement de votre compte à la structure <strong><%= name %></strong> a été
 <strong><%= status %></strong>. <%if (status === 'refusée') { %>
 <p>
-  Vous considérer qu’une erreur a été commise, vous pouvez les contacter les administrateurs à l’adresse
-  <a href="mailto:inclusionnumerique@grandlyon.com">inclusionnumerique@grandlyon.com</a>
+  Vous considérez qu’une erreur a été commise, vous pouvez contacter les administrateurs à l’adresse
+  <a href="mailto:inclusionnumerique@grandlyon.com">inclusionnumerique@grandlyon.com</a>.
 </p>
 <% } else{ %>
-<p>Vous pouvez dorénavant mettre à jour la fiche de votre structure</p>
+<p>Vous pouvez dorénavant mettre à jour la fiche de votre structure.</p>
 <% } %>
diff --git a/src/mailer/mail-templates/structureDeletionNotification.ejs b/src/mailer/mail-templates/structureDeletionNotification.ejs
new file mode 100644
index 0000000000000000000000000000000000000000..0ea05b23462a8b189f4e73d923945c27f165fa94
--- /dev/null
+++ b/src/mailer/mail-templates/structureDeletionNotification.ejs
@@ -0,0 +1,3 @@
+Bonjour,<br />
+<br />
+Un utilisateur a supprimé la fiche de sa structure (<%= structureName %>).
diff --git a/src/mailer/mail-templates/structureDeletionNotification.json b/src/mailer/mail-templates/structureDeletionNotification.json
new file mode 100644
index 0000000000000000000000000000000000000000..3fabb0edbd05f73e363f5f035dafd55614d4a33f
--- /dev/null
+++ b/src/mailer/mail-templates/structureDeletionNotification.json
@@ -0,0 +1,3 @@
+{
+  "subject": "Une structure à été supprimé de Res'in, Réseau des Acteurs de la Médiation Numérique de la Métropole de Lyon"
+}
diff --git a/src/mailer/mail-templates/structureErrorReport.ejs b/src/mailer/mail-templates/structureErrorReport.ejs
index 829029e95f157b6034c60889e7ee0798f2518d48..18b32cd0ab99a7fcf5246656f1b19bd2a4121727 100644
--- a/src/mailer/mail-templates/structureErrorReport.ejs
+++ b/src/mailer/mail-templates/structureErrorReport.ejs
@@ -1,4 +1,4 @@
-Bonjour<br />
+Bonjour,<br />
 <br />
 Un utilisateur de Res'in a relevé une erreur sur la fiche de votre structure (<%= structureName %>).
 <br />
diff --git a/src/mailer/mail-templates/structureJoinRequest.ejs b/src/mailer/mail-templates/structureJoinRequest.ejs
index e668707556f5e096aa2a84028bbf179612091f52..cdfbb3c341198a71bc97947a5d59aaef20e0cdf9 100644
--- a/src/mailer/mail-templates/structureJoinRequest.ejs
+++ b/src/mailer/mail-templates/structureJoinRequest.ejs
@@ -1,6 +1,6 @@
-Bonjour<br />
+Bonjour,<br />
 <br />
-Vous recevez ce message car <strong><%= surname %></strong> <strong><%= name %></strong> demande a rejoindre votre
+Vous recevez ce message car <strong><%= surname %></strong> <strong><%= name %></strong> demande à rejoindre votre
 stucture <strong><%= structureName %></strong> sur RES'in, le réseau des acteurs de l'inclusion numérique de la
 Métropole de Lyon. Vous pouvez dès maintenant valider la demande en
 <a
diff --git a/src/mailer/mail-templates/structureModificationNotification.ejs b/src/mailer/mail-templates/structureModificationNotification.ejs
new file mode 100644
index 0000000000000000000000000000000000000000..6a055cd4595dc21c7546a30d0a0f791bb5b41f1a
--- /dev/null
+++ b/src/mailer/mail-templates/structureModificationNotification.ejs
@@ -0,0 +1,7 @@
+Bonjour,<br />
+<br />
+Un utilisateur a modifié une ou plusieurs informations sur la fiche de sa structure (<%= structureName %>).
+<br />
+<a href="<%= config.protocol %>://<%= config.host %><%= config.port ? ':' + config.port : '' %>/acteurs?id=<%= id %>"
+  >Acceder à cette structure</a
+>.
diff --git a/src/mailer/mail-templates/structureModificationNotification.json b/src/mailer/mail-templates/structureModificationNotification.json
new file mode 100644
index 0000000000000000000000000000000000000000..516a30844c6f178ee77134da581d1b44786b6548
--- /dev/null
+++ b/src/mailer/mail-templates/structureModificationNotification.json
@@ -0,0 +1,3 @@
+{
+  "subject": "Une fiche de structure à été mise à jour, Réseau des Acteurs de la Médiation Numérique de la Métropole de Lyon"
+}
diff --git a/src/mailer/mail-templates/structureOutdatedInfo.ejs b/src/mailer/mail-templates/structureOutdatedInfo.ejs
index 5427f8b22825c64ab25c3da4d903b3dc27742cbd..a5caf60e0c7cff65131144da363bfb58bcfecc38 100644
--- a/src/mailer/mail-templates/structureOutdatedInfo.ejs
+++ b/src/mailer/mail-templates/structureOutdatedInfo.ejs
@@ -1,6 +1,6 @@
-Bonjour<br />
+Bonjour,<br />
 <br />
-Vous recevez ce message, parce que votre structure <strong><%= name %></strong> est référencée sur RES'in, le réseau des
+Vous recevez ce message car votre structure <strong><%= name %></strong> est référencée sur RES'in, le réseau des
 acteurs de l'inclusion numérique de la Métropole de Lyon. Pouvez-vous nous aider en vérifiant que vos données sont bien
 à jour en
 <a href="<%= config.protocol %>://<%= config.host %><%= config.port ? ':' + config.port : '' %>/acteurs?id=<%= id %>"
diff --git a/src/mailer/mail-templates/tempUserRegistration.ejs b/src/mailer/mail-templates/tempUserRegistration.ejs
index fb336b0625aa83309199cd5f791f6f4037db87d4..59e46a0b6678dae30977d9ca44dd514052a00526 100644
--- a/src/mailer/mail-templates/tempUserRegistration.ejs
+++ b/src/mailer/mail-templates/tempUserRegistration.ejs
@@ -1,6 +1,6 @@
-Bonjour<br />
+Bonjour,<br />
 <br />
-Vous recevez ce message car vous avez été relié a la stucture <strong><%= name %></strong> sur RES'in, le réseau des
+Vous recevez ce message car vous avez été relié à la stucture <strong><%= name %></strong> sur RES'in, le réseau des
 acteurs de l'inclusion numérique de la Métropole de Lyon. Vous pouvez dès maitenant vous créer un compte sur la
 plateforme pour accéder a votre structure en
 <a href="<%= config.protocol %>://<%= config.host %><%= config.port ? ':' + config.port : '' %>/register?id=<%= id %>"
diff --git a/src/mailer/mail-templates/verify.ejs b/src/mailer/mail-templates/verify.ejs
index 4f2780e183b6d598a6c94d5dc8ad463abe9bf06f..c2c57e73b624c9915da4af8680e1a3bcb4afba82 100644
--- a/src/mailer/mail-templates/verify.ejs
+++ b/src/mailer/mail-templates/verify.ejs
@@ -1,8 +1,8 @@
-Bonjour<br />
+Bonjour,<br />
 <br />
 Afin de pouvoir vous connecter sur la plateforme, merci de cliquer sur
 <a
   href="<%= config.protocol %>://<%= config.host %><%= config.port ? ':' + config.port : '' %>/users/verify/<%= userId %>?token=<%= token %>"
   >ce lien</a
 >
-afin de valider votre inscription<br />
+pour valider votre inscription.<br />
diff --git a/src/migrations/scripts/1617962328658-add-newsletter-data.ts b/src/migrations/scripts/1617962328658-add-newsletter-data.ts
deleted file mode 100644
index 17821b927c47a2d58fb3544f34b98917d7f465e4..0000000000000000000000000000000000000000
--- a/src/migrations/scripts/1617962328658-add-newsletter-data.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { Db } from 'mongodb';
-import { getDb } from '../migrations-utils/db';
-import * as fs from 'fs';
-
-export const up = async () => {
-  const db: Db = await getDb();
-  const data = fs.readFileSync('/app/src/migrations/data/newsletter-data.json', 'utf8');
-  const parsedData = JSON.parse(data);
-  db.collection('newslettersubscriptions').insertMany(parsedData);
-};
-
-export const down = async () => {
-  const db: Db = await getDb();
-  /*
-      Code you downgrade script here!
-   */
-};
diff --git a/src/migrations/scripts/1618322296327-clean-data.ts b/src/migrations/scripts/1618322296327-clean-data.ts
new file mode 100644
index 0000000000000000000000000000000000000000..03afdd82c811aefcbae834a4f84a3ed7e083a590
--- /dev/null
+++ b/src/migrations/scripts/1618322296327-clean-data.ts
@@ -0,0 +1,90 @@
+import { Db } from 'mongodb';
+import { getDb } from '../migrations-utils/db';
+
+export const up = async () => {
+  const db: Db = await getDb();
+
+  const cursor = db.collection('structures').find({});
+  let document;
+  while ((document = await cursor.next())) {
+    const newDoc = updateStructure(document);
+    await db
+      .collection('structures')
+      .updateOne({ _id: document._id }, [
+        { $set: newDoc },
+        { $unset: ['equipmentsDetails', 'nomDeLusager', 'statutJuridique', 'documentsMeeting'] },
+      ]);
+  }
+  console.log(`Update done`);
+};
+
+export const down = async () => {
+  const db: Db = await getDb();
+
+  const cursor = db.collection('structures').find({});
+  let document;
+  while ((document = await cursor.next())) {
+    const newDoc = downgradeStructure(document);
+    await db.collection('structures').updateOne({ _id: document._id }, [{ $set: newDoc }]);
+  }
+  console.log(`Update done`);
+};
+
+function updateStructure(doc) {
+  return updateHours(doc);
+}
+
+function downgradeStructure(doc) {
+  doc = restoreHours(doc);
+  return doc;
+}
+
+function updateHours(doc) {
+  if (doc.hours) {
+    Object.keys(doc.hours).forEach((key) => {
+      if (doc.hours[key].time.length > 0) {
+        doc.hours[key].time.forEach((timeRange) => {
+          timeRange.openning = formatHours(timeRange.openning);
+          timeRange.closing = formatHours(timeRange.closing);
+        });
+      }
+    });
+    return doc;
+  } else {
+    console.warn(`No hours on doc ${doc._id}`);
+    return doc;
+  }
+}
+
+function restoreHours(doc) {
+  if (doc.hours) {
+    Object.keys(doc.hours).forEach((key) => {
+      if (doc.hours[key].time.length > 0) {
+        doc.hours[key].time.forEach((timeRange) => {
+          timeRange.openning = formatBackHours(timeRange.openning);
+          timeRange.closing = formatBackHours(timeRange.closing);
+        });
+      }
+    });
+    return doc;
+  } else {
+    console.warn(`No hours on doc ${doc._id}`);
+    return doc;
+  }
+}
+
+function formatHours(hour): string {
+  const stringifiedHour = hour.toString();
+  if (stringifiedHour.length === 3) {
+    // 930
+    return stringifiedHour.slice(0, 1) + ':' + stringifiedHour.slice(1, 3);
+  } else if (stringifiedHour.length === 4) {
+    // 1200
+    return stringifiedHour.slice(0, 2) + ':' + stringifiedHour.slice(2, 4);
+  }
+}
+
+function formatBackHours(hour): number {
+  const splitedHour = hour.split(':');
+  return parseInt(''.concat(...splitedHour), 10);
+}
diff --git a/src/migrations/scripts/1620229047628-opening-hours.ts b/src/migrations/scripts/1620229047628-opening-hours.ts
new file mode 100644
index 0000000000000000000000000000000000000000..69c65461eaf66c60ef1444c3eeb40b154c57fb3a
--- /dev/null
+++ b/src/migrations/scripts/1620229047628-opening-hours.ts
@@ -0,0 +1,66 @@
+import { Db } from 'mongodb';
+import { getDb } from '../migrations-utils/db';
+
+export const up = async () => {
+  const db: Db = await getDb();
+
+  const cursor = db.collection('structures').find({});
+  let document;
+  while ((document = await cursor.next())) {
+    const newDoc = updateStructure(document);
+    await db.collection('structures').updateOne({ _id: document._id }, [{ $set: newDoc }]);
+  }
+  console.log(`Update done`);
+};
+
+export const down = async () => {
+  const db: Db = await getDb();
+
+  const cursor = db.collection('structures').find({});
+  let document;
+  while ((document = await cursor.next())) {
+    const newDoc = downgradeStructure(document);
+    await db.collection('structures').updateOne({ _id: document._id }, [{ $set: newDoc }]);
+  }
+  console.log(`Update done`);
+};
+
+function updateStructure(doc) {
+  return updateHours(doc);
+}
+
+function downgradeStructure(doc) {
+  return restoreHours(doc);
+}
+
+function updateHours(doc) {
+  if (doc.hours) {
+    Object.keys(doc.hours).forEach((key) => {
+      doc.hours[key].time.forEach((timeRange) => {
+        timeRange.opening = timeRange.openning;
+        delete timeRange.openning;
+      });
+    });
+    return doc;
+  } else {
+    console.warn(`No hours on doc ${doc._id}`);
+    return doc;
+  }
+}
+
+function restoreHours(doc) {
+  if (doc.hours) {
+    Object.keys(doc.hours).forEach((key) => {
+      if (doc.hours[key].time.length > 0) {
+        doc.hours[key].time.forEach((timeRange) => {
+          timeRange.openning = timeRange.opening;
+          delete timeRange.opening;
+        });
+      }
+    });
+    return doc;
+  } else {
+    console.warn(`No hours on doc ${doc._id}`);
+    return doc;
+  }
+}
diff --git a/src/migrations/scripts/1620289895495-timestamp-format.ts b/src/migrations/scripts/1620289895495-timestamp-format.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1abbf94695e8f3f0280bb98d2f31754383ef668f
--- /dev/null
+++ b/src/migrations/scripts/1620289895495-timestamp-format.ts
@@ -0,0 +1,46 @@
+import { Db } from 'mongodb';
+import { getDb } from '../migrations-utils/db';
+
+export const up = async () => {
+  const db: Db = await getDb();
+
+  const cursor = db.collection('structures').find({});
+  let document;
+  while ((document = await cursor.next())) {
+    const newDoc = updateStructure(document);
+    await db.collection('structures').updateOne({ _id: document._id }, [{ $set: newDoc }]);
+  }
+  console.log(`Update done`);
+};
+
+export const down = async () => {
+  const db: Db = await getDb();
+
+  const cursor = db.collection('structures').find({});
+  let document;
+  while ((document = await cursor.next())) {
+    const newDoc = downgradeStructure(document);
+    await db.collection('structures').updateOne({ _id: document._id }, [{ $set: newDoc }]);
+  }
+  console.log(`Update done`);
+};
+
+function updateStructure(doc) {
+  return updateTimestamp(doc);
+}
+
+function downgradeStructure(doc) {
+  return restoreTimestamp(doc);
+}
+
+function updateTimestamp(doc) {
+  doc.createdAt = new Date(doc.createdAt).toISOString();
+  doc.updatedAt = new Date(doc.updatedAt).toISOString();
+  return doc;
+}
+
+function restoreTimestamp(doc) {
+  doc.createdAt = new Date(doc.createdAt).toString();
+  doc.updatedAt = new Date(doc.updatedAt).toISOString();
+  return doc;
+}
diff --git a/src/newsletter/newsletter.service.ts b/src/newsletter/newsletter.service.ts
index c1ca5efc0e07368586b7a3ac99c7248c43d8a85f..57dab32d153c9d0843eca5e005a49da16123853f 100644
--- a/src/newsletter/newsletter.service.ts
+++ b/src/newsletter/newsletter.service.ts
@@ -2,7 +2,7 @@ import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
 import { InjectModel } from '@nestjs/mongoose';
 import { Model, Types } from 'mongoose';
 import { INewsletterSubscription } from './interface/newsletter-subscription.interface';
-import { NewsletterSubscription } from './newsletter-subscription.schema';
+import { NewsletterSubscription, NewsletterSubscriptionDocument } from './newsletter-subscription.schema';
 
 @Injectable()
 export class NewsletterService {
@@ -32,10 +32,14 @@ export class NewsletterService {
     return this.newsletterSubscriptionModel.findOne({ email: mail }).exec();
   }
 
-  public async searchNewsletterSubscription(searchString: string) {
+  public async searchNewsletterSubscription(searchString: string): Promise<NewsletterSubscriptionDocument[]> {
     return this.newsletterSubscriptionModel.find({ email: new RegExp(searchString, 'i') }).exec();
   }
 
+  public async countNewsletterSubscriptions(): Promise<number> {
+    return this.newsletterSubscriptionModel.countDocuments({}).exec();
+  }
+
   public async deleteOneEmail(mail: string): Promise<NewsletterSubscription | undefined> {
     const subscription = await this.newsletterSubscriptionModel.findOne({ email: mail }).exec();
     if (!subscription) {
diff --git a/src/search/search.module.ts b/src/search/search.module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8e9b5e85b2226d75c157886fe06eabf64c265d7b
--- /dev/null
+++ b/src/search/search.module.ts
@@ -0,0 +1,22 @@
+import { Module } from '@nestjs/common';
+import { ConfigModule, ConfigService } from '@nestjs/config';
+import { ElasticsearchModule } from '@nestjs/elasticsearch';
+
+@Module({
+  imports: [
+    ConfigModule,
+    ElasticsearchModule.registerAsync({
+      imports: [ConfigModule],
+      useFactory: async (configService: ConfigService) => ({
+        node: configService.get('ELASTICSEARCH_NODE'),
+        auth: {
+          username: configService.get('ELASTICSEARCH_USERNAME'),
+          password: configService.get('ELASTICSEARCH_PASSWORD'),
+        },
+      }),
+      inject: [ConfigService],
+    }),
+  ],
+  exports: [ElasticsearchModule],
+})
+export class SearchModule {}
diff --git a/src/structures/interfaces/structure-search-body.interface.ts b/src/structures/interfaces/structure-search-body.interface.ts
new file mode 100644
index 0000000000000000000000000000000000000000..24d7591930d82643cd181ced7132665d8d2007d9
--- /dev/null
+++ b/src/structures/interfaces/structure-search-body.interface.ts
@@ -0,0 +1,8 @@
+import { Address } from '../schemas/address.schema';
+
+export interface StructureSearchBody {
+  structureId: string;
+  structureName: string;
+  structureType: string;
+  address: Address;
+}
diff --git a/src/structures/interfaces/structure-search-response.interface.ts b/src/structures/interfaces/structure-search-response.interface.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7497343827756c4a16df4e15a861709604a00ce0
--- /dev/null
+++ b/src/structures/interfaces/structure-search-response.interface.ts
@@ -0,0 +1,10 @@
+import { StructureSearchBody } from './structure-search-body.interface';
+
+export interface StructureSearchResult {
+  hits: {
+    total: number;
+    hits: Array<{
+      _source: StructureSearchBody;
+    }>;
+  };
+}
diff --git a/src/structures/schemas/time.schema.ts b/src/structures/schemas/time.schema.ts
index 986b7773a38ace7f052d28519321bbb2e37efeab..8a2261331041add1791775b9da1c2e1ee323a708 100644
--- a/src/structures/schemas/time.schema.ts
+++ b/src/structures/schemas/time.schema.ts
@@ -4,8 +4,8 @@ import { Document } from 'mongoose';
 export type TimeDocument = Time & Document;
 
 export class Time {
-  openning: number;
-  closing: number;
+  opening: string;
+  closing: string;
 }
 
 export const TimeSchema = SchemaFactory.createForClass(Time);
diff --git a/src/structures/services/structures-search.service.ts b/src/structures/services/structures-search.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e809c58f9f53f9e0d1291df3ee28c7f163cb212c
--- /dev/null
+++ b/src/structures/services/structures-search.service.ts
@@ -0,0 +1,91 @@
+import { Injectable } from '@nestjs/common';
+import { ElasticsearchService } from '@nestjs/elasticsearch';
+import { structureDto } from '../dto/structure.dto';
+import { StructureDocument } from '../schemas/structure.schema';
+import { StructureSearchBody } from '../interfaces/structure-search-body.interface';
+import { StructureSearchResult } from '../interfaces/structure-search-response.interface';
+
+@Injectable()
+export class StructuresSearchService {
+  private index = 'structures';
+
+  constructor(private readonly elasticsearchService: ElasticsearchService) {}
+
+  public async indexStructure(structure: StructureDocument): Promise<StructureDocument> {
+    this.elasticsearchService.index<StructureSearchResult, StructureSearchBody>({
+      index: this.index,
+      id: structure._id,
+      body: {
+        structureName: structure.structureName,
+        structureType: structure.structureType,
+        structureId: structure._id,
+        address: structure.address,
+      },
+    });
+    return structure;
+  }
+
+  public async createStructureIndex(): Promise<any> {
+    return await this.elasticsearchService.indices.create({
+      index: this.index,
+    });
+  }
+
+  public async dropIndex(): Promise<any> {
+    if (
+      (
+        await this.elasticsearchService.indices.exists({
+          index: this.index,
+        })
+      ).body
+    ) {
+      return this.elasticsearchService.indices.delete({
+        index: this.index,
+      });
+    }
+  }
+
+  public async deleteIndexStructure(structure: StructureDocument): Promise<StructureDocument> {
+    this.elasticsearchService.delete<StructureSearchResult, StructureSearchBody>({
+      index: this.index,
+      id: structure._id,
+    });
+    return structure;
+  }
+
+  public async search(searchString: string): Promise<StructureSearchBody[]> {
+    searchString = searchString ? searchString + '*' : '*';
+    const { body } = await this.elasticsearchService.search<StructureSearchResult>({
+      index: this.index,
+      body: {
+        from: 0,
+        size: 200,
+        query: {
+          query_string: {
+            analyze_wildcard: 'true',
+            query: searchString,
+            fields: ['structureName^5', 'structureType^5', 'address.street', 'address.commune^5'],
+            fuzziness: 'AUTO',
+          },
+        },
+      },
+    });
+    const hits = body.hits.hits;
+    return hits.map((item) => item._source);
+  }
+
+  public async update(structure: structureDto, id: string): Promise<any> {
+    return this.elasticsearchService.update({
+      index: this.index,
+      id: id,
+      body: {
+        doc: {
+          structureName: structure.structureName,
+          structureType: structure.structureType,
+          structureId: id,
+          address: structure.address,
+        },
+      },
+    });
+  }
+}
diff --git a/src/structures/services/structures.service.ts b/src/structures/services/structures.service.ts
index 71b6bb189b6aef32dcf401e1bfcdcebe08febdb9..aec2207c635d21b40560bf7df44019fae8f76c5c 100644
--- a/src/structures/services/structures.service.ts
+++ b/src/structures/services/structures.service.ts
@@ -14,6 +14,12 @@ import { DateTime } from 'luxon';
 import { IUser } from '../../users/interfaces/user.interface';
 import * as _ from 'lodash';
 import { OwnerDto } from '../../users/dto/owner.dto';
+import { StructuresSearchService } from './structures-search.service';
+import { CategoriesFormationsModule } from '../../categories/schemas/categoriesFormationsModule.schema';
+import { CategoriesModule } from '../../categories/categories.module';
+import { CategoriesAccompagnement } from '../../categories/schemas/categoriesAccompagnement.schema';
+import { CategoriesFormations } from '../../categories/schemas/categoriesFormations.schema';
+import { CategoriesOthers } from '../../categories/schemas/categoriesOthers.schema';
 
 @Injectable()
 export class StructuresService {
@@ -21,9 +27,44 @@ export class StructuresService {
     private readonly httpService: HttpService,
     private readonly userService: UsersService,
     private readonly mailerService: MailerService,
+    private structuresSearchService: StructuresSearchService,
     @InjectModel(Structure.name) private structureModel: Model<StructureDocument>
   ) {}
 
+  async initiateStructureIndex(): Promise<StructureDocument[]> {
+    await this.structuresSearchService.dropIndex();
+    await this.structuresSearchService.createStructureIndex();
+    return this.populateES();
+  }
+
+  async searchForStructures(text: string, filters?: Array<any>): Promise<StructureDocument[]> {
+    const results = await this.structuresSearchService.search(text);
+    const ids = results.map((result) => result.structureId);
+    if (!ids.length) {
+      return [];
+    }
+    //we match ids from Elasticsearch with ids from mongoDB (and filters) and sort the result according to ElasticSearch order.
+    if (filters.length > 0) {
+      return (
+        await this.structureModel
+          .find({
+            _id: { $in: ids },
+            $and: [...this.parseFilter(filters), { deletedAt: { $exists: false }, accountVerified: true }],
+          })
+          .exec()
+      ).sort((a, b) => ids.indexOf(a.id) - ids.indexOf(b.id));
+    } else {
+      return (
+        await this.structureModel
+          .find({
+            _id: { $in: ids },
+            $and: [{ deletedAt: { $exists: false }, accountVerified: true }],
+          })
+          .exec()
+      ).sort((a, b) => ids.indexOf(a.id) - ids.indexOf(b.id));
+    }
+  }
+
   public async create(idUser: string, structure: structureDto): Promise<Structure> {
     const user = await this.userService.findOne(idUser);
     if (!user) {
@@ -32,16 +73,25 @@ export class StructuresService {
     const createdStructure = new this.structureModel(structure);
     createdStructure._id = Types.ObjectId();
     await createdStructure.save();
-    await this.getStructurePosition(createdStructure).then((postition: StructureDocument) => {
-      return this.structureModel
-        .findByIdAndUpdate(Types.ObjectId(createdStructure._id), { address: postition.address, coord: postition.coord })
-        .exec();
+    await this.getStructurePosition(createdStructure).then(async (postition: StructureDocument) => {
+      return this.structuresSearchService.indexStructure(
+        await this.structureModel
+          .findByIdAndUpdate(Types.ObjectId(createdStructure._id), {
+            address: postition.address,
+            coord: postition.coord,
+          })
+          .exec()
+      );
     });
     user.structuresLink.push(createdStructure._id);
     user.save();
 
     // Senc admin notification mail
-    this.userService.sendAdminNewStructureMail(createdStructure.structureName, createdStructure._id);
+    this.sendAdminStructureNotification(
+      createdStructure,
+      this.mailerService.config.templates.adminStructureCreate.ejs,
+      this.mailerService.config.templates.adminStructureCreate.json
+    );
 
     return createdStructure;
   }
@@ -102,6 +152,111 @@ export class StructuresService {
     return this.structureModel.find({ deletedAt: { $exists: false }, accountVerified: true }).exec();
   }
 
+  public async populateES(): Promise<StructureDocument[]> {
+    const structures = await this.structureModel.find({ deletedAt: { $exists: false } }).exec();
+    await Promise.all(
+      structures.map((structure: StructureDocument) => {
+        this.structuresSearchService.indexStructure(structure);
+      })
+    );
+    return structures;
+  }
+
+  public async findAllFormated(
+    formationCategories: CategoriesFormations[],
+    accompagnementCategories: CategoriesAccompagnement[],
+    otherCategories: CategoriesOthers[]
+  ): Promise<StructureDocument[]> {
+    const structures = await this.structureModel.find({ deletedAt: { $exists: false } }).exec();
+
+    // Update structures coord and address before sending them
+    await Promise.all(
+      structures.map((structure: StructureDocument) => {
+        // If structre has no address, add it
+        if (!structure.address || structure.coord.length <= 0) {
+          return this.getStructurePosition(structure).then((postition: StructureDocument) => {
+            this.structureModel
+              .findByIdAndUpdate(Types.ObjectId(structure._id), {
+                address: postition.address,
+                coord: postition.coord,
+              })
+              .exec();
+          });
+        }
+      })
+    );
+    return (
+      await this.structureModel
+        .find({ deletedAt: { $exists: false }, accountVerified: true })
+        .select('-_id -accountVerified -otherDescription')
+        .exec()
+    ).map((structure) => {
+      structure.proceduresAccompaniment = this.mapModules(
+        structure.proceduresAccompaniment,
+        accompagnementCategories.find((category) => category.name === 'Accompagnement des démarches').modules
+      );
+      structure.labelsQualifications = this.mapModules(
+        structure.labelsQualifications,
+        otherCategories.find((category) => category.name === 'Labels et qualifications').modules
+      );
+      structure.publics = this.mapModules(
+        structure.publics,
+        otherCategories.find((category) => category.name === 'Publics acceptés').modules
+      );
+      structure.accessModality = this.mapModules(
+        structure.accessModality,
+        otherCategories.find((category) => category.name === "Modalités d'accès").modules
+      );
+      structure.publicsAccompaniment = this.mapModules(
+        structure.publicsAccompaniment,
+        otherCategories.find((category) => category.name === 'Accompagnement des publics spécifique').modules
+      );
+      structure.equipmentsAndServices = this.mapModules(
+        structure.equipmentsAndServices,
+        otherCategories.find((category) => category.name === 'Équipements et services proposés').modules
+      );
+      structure.baseSkills = this.mapFormationModules(
+        structure.baseSkills,
+        formationCategories.find((category) => category.name === 'Les compétences de base').modules
+      );
+      structure.accessRight = this.mapFormationModules(
+        structure.accessRight,
+        formationCategories.find((category) => category.name === 'Accès aux droits').modules
+      );
+      structure.socialAndProfessional = this.mapFormationModules(
+        structure.socialAndProfessional,
+        formationCategories.find((category) => category.name === 'Insertion sociale et professionnelle').modules
+      );
+      structure.parentingHelp = this.mapFormationModules(
+        structure.parentingHelp,
+        formationCategories.find((category) => category.name === 'Aide à la parentalité').modules
+      );
+      structure.digitalCultureSecurity = this.mapFormationModules(
+        structure.digitalCultureSecurity,
+        formationCategories.find((category) => category.name === 'Culture et sécurité numérique').modules
+      );
+      return structure;
+    });
+  }
+  public mapFormationModules(structureModule: string[], baseModule: CategoriesFormationsModule[]): string[] {
+    if (structureModule == []) {
+      return [];
+    }
+    return structureModule.map((id) => {
+      const formatedText = baseModule.find((module) => module.display_id === id)?.text;
+      return formatedText ? formatedText : id;
+    });
+  }
+  public mapModules(structureModule: string[], baseModule: CategoriesModule[]): string[] {
+    if (structureModule == []) {
+      return [];
+    }
+    return structureModule.map((id) => {
+      const formatedText = baseModule.find((module) => module.id === id)?.text;
+      return formatedText ? formatedText : id;
+    });
+  }
+
   public async update(idStructure: string, structure: structureDto): Promise<Structure> {
     const oldStructure = await this.findOne(idStructure);
     if (!_.isEqual(oldStructure.address, structure.address)) {
@@ -111,6 +266,12 @@ export class StructuresService {
     if (!result) {
       throw new HttpException('Invalid structure id', HttpStatus.BAD_REQUEST);
     } else {
+      await this.structuresSearchService.update(structure, idStructure);
+      this.sendAdminStructureNotification(
+        result,
+        this.mailerService.config.templates.structureModificationNotification.ejs,
+        this.mailerService.config.templates.structureModificationNotification.json
+      );
       this.userService.removeOutdatedStructureFromArray(idStructure);
     }
     return this.findOne(idStructure);
@@ -195,12 +356,14 @@ export class StructuresService {
         keyList.push({
           [key]: { $elemMatch: { $eq: value } },
           deletedAt: { $exists: false },
+          accountVerified: true,
         });
         if (selected && selected.length > 0) {
           for (const val of selected) {
             keyList.push({
               [val.text]: { $elemMatch: { $eq: val.id } },
               deletedAt: { $exists: false },
+              accountVerified: true,
             });
           }
         }
@@ -228,14 +391,43 @@ export class StructuresService {
     if (!structure) {
       throw new HttpException('Invalid structure id', HttpStatus.BAD_REQUEST);
     }
+    this.structuresSearchService.deleteIndexStructure(structure);
     structure.structureType = null;
     structure.deletedAt = DateTime.local().setZone('Europe/Paris').toString();
     this.anonymizeStructure(structure).save();
     // Remove structure from userModel
     this.userService.removeStructureIdFromUsers(structure._id);
+    this.sendAdminStructureNotification(
+      structure,
+      this.mailerService.config.templates.structureDeletionNotification.ejs,
+      this.mailerService.config.templates.structureDeletionNotification.json
+    );
     return structure;
   }
 
+  public async sendAdminStructureNotification(
+    structure: StructureDocument,
+    templateLocation: any,
+    jsonConfigLocation: any
+  ) {
+    const uniqueAdminEmails = [...new Set((await this.userService.getAdmins()).map((admin) => admin.email))].map(
+      (item) => {
+        return { email: item };
+      }
+    );
+
+    const config = this.mailerService.config;
+    const ejsPath = this.mailerService.getTemplateLocation(templateLocation);
+    const jsonConfig = this.mailerService.loadJsonConfig(jsonConfigLocation);
+
+    const html = await ejs.renderFile(ejsPath, {
+      config,
+      id: structure ? structure._id : 0,
+      structureName: structure ? structure.structureName : '',
+    });
+    this.mailerService.send(uniqueAdminEmails, jsonConfig.subject, html);
+  }
+
   private anonymizeStructure(structure: StructureDocument): StructureDocument {
     structure.contactPhone = '';
     structure.contactMail = '';
diff --git a/src/structures/structures.controller.ts b/src/structures/structures.controller.ts
index 67e12c9a15469d46919601363dbfbe8882344fce..65dcfd00b0b4d5495ce84306e940f99a82982981 100644
--- a/src/structures/structures.controller.ts
+++ b/src/structures/structures.controller.ts
@@ -15,6 +15,9 @@ import {
 import { ApiParam } from '@nestjs/swagger';
 import { Types } from 'mongoose';
 import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
+import { CategoriesAccompagnementService } from '../categories/services/categories-accompagnement.service';
+import { CategoriesFormationsService } from '../categories/services/categories-formations.service';
+import { CategoriesOthersService } from '../categories/services/categories-others.service';
 import { CreateTempUserDto } from '../temp-user/dto/create-temp-user.dto';
 import { TempUserService } from '../temp-user/temp-user.service';
 import { Roles } from '../users/decorators/roles.decorator';
@@ -24,8 +27,9 @@ import { UsersService } from '../users/users.service';
 import { CreateStructureDto } from './dto/create-structure.dto';
 import { QueryStructure } from './dto/query-structure.dto';
 import { structureDto } from './dto/structure.dto';
-import { Structure } from './schemas/structure.schema';
+import { Structure, StructureDocument } from './schemas/structure.schema';
 import { StructuresService } from './services/structures.service';
+import { RolesGuard } from '../users/guards/roles.guard';
 
 @Controller('structures')
 export class StructuresController {
@@ -33,7 +37,10 @@ export class StructuresController {
     private readonly httpService: HttpService,
     private readonly structureService: StructuresService,
     private readonly userService: UsersService,
-    private readonly tempUserService: TempUserService
+    private readonly tempUserService: TempUserService,
+    private readonly categoriesFormationsService: CategoriesFormationsService,
+    private readonly categoriesOthersService: CategoriesOthersService,
+    private readonly categoriesAccompagnementService: CategoriesAccompagnementService
   ) {}
 
   /**
@@ -59,7 +66,14 @@ export class StructuresController {
 
   @Post('search')
   public async search(@Query() query: QueryStructure, @Body() body): Promise<Structure[]> {
-    return this.structureService.search(query.query, body ? body.filters : null);
+    return await this.structureService.searchForStructures(query.query, body ? body.filters : null);
+  }
+
+  @Post('resetSearchIndex')
+  @UseGuards(JwtAuthGuard, RolesGuard)
+  @Roles('admin')
+  public async resetES(): Promise<StructureDocument[]> {
+    return this.structureService.initiateStructureIndex();
   }
 
   @Put('updateAfterOwnerVerify/:id')
@@ -79,6 +93,14 @@ export class StructuresController {
     return this.structureService.findAll();
   }
 
+  @Get('formated')
+  public async findAllFormated(): Promise<Structure[]> {
+    const formationCategories = await this.categoriesFormationsService.findAll();
+    const accompagnementCategories = await this.categoriesAccompagnementService.findAll();
+    const otherCategories = await this.categoriesOthersService.findAll();
+    return this.structureService.findAllFormated(formationCategories, accompagnementCategories, otherCategories);
+  }
+
   @Post(':id/isClaimed')
   public async isClaimed(@Param('id') id: string, @Body() user?: User): Promise<boolean> {
     return this.structureService.isClaimed(id, user);
diff --git a/src/structures/structures.module.ts b/src/structures/structures.module.ts
index 1445999d289ff826e1504e3754d814f10ed06322..650e3adfd9b7ef57e13d8e06090f1b9100f26e33 100644
--- a/src/structures/structures.module.ts
+++ b/src/structures/structures.module.ts
@@ -11,6 +11,8 @@ import { StructureTypeController } from './structure-type/structure-type.control
 import { StructureTypeService } from './structure-type/structure-type.service';
 import { StructureType, StructureTypeSchema } from './structure-type/structure-type.schema';
 import { CategoriesModule } from '../categories/categories.module';
+import { StructuresSearchService } from './services/structures-search.service';
+import { SearchModule } from '../search/search.module';
 
 @Module({
   imports: [
@@ -23,9 +25,10 @@ import { CategoriesModule } from '../categories/categories.module';
     forwardRef(() => UsersModule),
     CategoriesModule,
     TempUserModule,
+    SearchModule,
   ],
   controllers: [StructuresController, StructureTypeController],
   exports: [StructuresService, StructureTypeService],
-  providers: [StructuresService, StructureTypeService, ApticStructuresService],
+  providers: [StructuresSearchService, StructuresService, StructureTypeService, ApticStructuresService],
 })
 export class StructuresModule {}
diff --git a/src/users/users.controller.spec.ts b/src/users/users.controller.spec.ts
index 584333cf2ae2eb111d14b392e8f5bb1db26664e3..68da5450f95300fde9828f6a2ad2d1905b738753 100644
--- a/src/users/users.controller.spec.ts
+++ b/src/users/users.controller.spec.ts
@@ -1,10 +1,13 @@
 import { HttpModule } from '@nestjs/common';
 import { getModelToken } from '@nestjs/mongoose';
 import { Test, TestingModule } from '@nestjs/testing';
+import { CategoriesModule } from '../categories/categories.module';
 import { ConfigurationModule } from '../configuration/configuration.module';
 import { MailerService } from '../mailer/mailer.service';
+import { SearchModule } from '../search/search.module';
 import { Structure } from '../structures/schemas/structure.schema';
 import { StructuresService } from '../structures/services/structures.service';
+import { StructuresSearchService } from '../structures/services/structures-search.service';
 import { TempUser } from '../temp-user/temp-user.schema';
 import { TempUserService } from '../temp-user/temp-user.service';
 import { User } from './schemas/user.schema';
@@ -16,10 +19,11 @@ describe('UsersController', () => {
 
   beforeEach(async () => {
     const module: TestingModule = await Test.createTestingModule({
-      imports: [ConfigurationModule, HttpModule],
+      imports: [ConfigurationModule, HttpModule, SearchModule],
       providers: [
         UsersService,
         StructuresService,
+        StructuresSearchService,
         MailerService,
         TempUserService,
         {
diff --git a/src/users/users.controller.ts b/src/users/users.controller.ts
index 46433a721d056558c711c268c0521fe622901523..6f513374851bfd2b405d920bf55e78b56cc5bd5e 100644
--- a/src/users/users.controller.ts
+++ b/src/users/users.controller.ts
@@ -9,12 +9,14 @@ import { PasswordResetDto } from './dto/reset-password.dto';
 import { UsersService } from './users.service';
 import { StructuresService } from '../structures/services/structures.service';
 import { TempUserService } from '../temp-user/temp-user.service';
+import { ConfigurationService } from '../configuration/configuration.service';
 @Controller('users')
 export class UsersController {
   constructor(
     private usersService: UsersService,
     private structureService: StructuresService,
-    private tempUserService: TempUserService
+    private tempUserService: TempUserService,
+    private configurationService: ConfigurationService
   ) {}
 
   @UseGuards(JwtAuthGuard)
@@ -39,6 +41,11 @@ export class UsersController {
     const user = await this.usersService.create(createUserDto);
     if (structureId) {
       this.usersService.updateStructureLinkedClaim(createUserDto.email, structureId);
+      this.structureService.sendAdminStructureNotification(
+        null,
+        this.configurationService.config.templates.adminStructureClaim.ejs,
+        this.configurationService.config.templates.adminStructureClaim.json
+      );
     }
     // Remove temp user if exist
     const tempUser = await this.tempUserService.findOne(createUserDto.email);
diff --git a/src/users/users.service.ts b/src/users/users.service.ts
index 00cb1129c062731347632cc2c3b64359a63e9839..b329eb71fe594731e7b8c0deb6a8825ecdec08de 100644
--- a/src/users/users.service.ts
+++ b/src/users/users.service.ts
@@ -138,43 +138,6 @@ export class UsersService {
     return user;
   }
 
-  /**
-   * Send to all admins validation email for structures
-   * new account.
-   */
-  private async sendAdminStructureValidationMail(): Promise<any> {
-    const config = this.mailerService.config;
-    const ejsPath = this.mailerService.getTemplateLocation(config.templates.adminStructureClaim.ejs);
-    const jsonConfig = this.mailerService.loadJsonConfig(config.templates.adminStructureClaim.json);
-
-    const html = await ejs.renderFile(ejsPath, {
-      config,
-    });
-    const admins = await this.getAdmins();
-    admins.forEach((admin) => {
-      this.mailerService.send(admin.email, jsonConfig.subject, html);
-    });
-  }
-
-  /**
-   * Send to all admins notification email for new structures
-   */
-  public async sendAdminNewStructureMail(structureName: string, structureId: string): Promise<any> {
-    const config = this.mailerService.config;
-    const ejsPath = this.mailerService.getTemplateLocation(config.templates.adminStructureCreate.ejs);
-    const jsonConfig = this.mailerService.loadJsonConfig(config.templates.adminStructureCreate.json);
-
-    const html = await ejs.renderFile(ejsPath, {
-      config,
-      name: structureName,
-      id: structureId,
-    });
-    const admins = await this.getAdmins();
-    admins.forEach((admin) => {
-      this.mailerService.send(admin.email, jsonConfig.subject, html);
-    });
-  }
-
   /**
    * Send to all admins mail for aptic duplicated data
    */
@@ -352,7 +315,6 @@ export class UsersService {
 
   public async updateStructureLinkedClaim(userEmail: string, idStructure: string): Promise<Types.ObjectId[]> {
     const stucturesLinked = this.updatePendingStructureLinked(userEmail, idStructure);
-    this.sendAdminStructureValidationMail();
     return stucturesLinked;
   }
 
diff --git a/template.env b/template.env
index 41cb576d15639e668ff90bbdadc2e508f70a9e03..027d8b6a62352ab2d9b95ae9c6d337d9e19d13c6 100644
--- a/template.env
+++ b/template.env
@@ -20,3 +20,10 @@ GHOST_CONTENT_API_KEY=<Ghost global api key, can be found in integration part of
 GHOST_ADMIN_API_KEY=<Ghost admin api key, can be found in integration part of ghost UI>
 GHOST_HOST_AND_PORT=<Ghost host and port, ex:http://localhost:2368>
 USER_PWD=<test user password, this password will be user by every test users>
+ELASTICSEARCH_NODE=<elastic search container node>
+ELASTICSEARCH_PATH=<elastic search container path>
+ELASTICSEARCH_PORT=<elastic search port>
+ELASTICSEARCH_USERNAME=<elastic search username>
+ELASTICSEARCH_PASSWORD=<elastic search password>
+ELASTIC_SECURITY=<elastic search security boolean (true = secure)>
+KIBANA_PORT=<kibana port>
\ No newline at end of file