diff --git a/.env.template b/.env.template
index 1771b0ddd7123700a539a873be9ca5d6e5eb230c..6eff757694efae4006cac09ac11dbea8d7642627 100644
--- a/.env.template
+++ b/.env.template
@@ -5,7 +5,7 @@ ADMIN_ROLE=ADMINS
 DEBUG_MODE
 MOCK_OAUTH2
 HTTPS_PORT
-IMAGE_FOLDER
+IMAGE_FOLDER=mnt/image-lib
 
 # Needed to user OAuth2 authentication :
 REDIRECT_URL
diff --git a/.gitignore b/.gitignore
index 8d832a6f90912a8b03b6949ed96ad8a6630c91a4..d2cb364414f9cf2390d2ef842be9fe3dfc97adcb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,9 @@
 .env
 backoffice.db
-db_data/
\ No newline at end of file
+db_data/
+mnt/
+__debug_bin*
+
+# Swagger documentation
+docs/swagger.json
+docs/swagger.yaml
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000000000000000000000000000000000000..3ab34ffd7cbd31da6326bc575535ca07d690eaff
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,17 @@
+{
+  // Use IntelliSense to learn about possible attributes.
+  // Hover to view descriptions of existing attributes.
+  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+  "version": "0.2.0",
+  "configurations": [
+    {
+      "name": "Launch Backoffice Server",
+      "type": "go",
+      "request": "launch",
+      "mode": "debug",
+      "program": "${workspaceFolder}/main.go",
+      "envFile": "${workspaceFolder}/.env",
+      "showLog": true
+    }
+  ]
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 11a1978e8b65f62fa6d8ce4f9b7fba81a8f0623b..729c384ee9f3e02854db8881d8b48b0d28c353f7 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -25,18 +25,26 @@
         "backoffice",
         "ecogesture",
         "ecolyo",
+        "Enedis",
         "firstname",
         "fluidtype",
         "godoc",
         "gorm",
         "grandlyon",
+        "GRDF",
+        "imagebase",
         "insee",
         "lastname",
         "llle",
         "mysqldump",
         "numerique",
+        "redir",
         "rootmux",
         "selfdata",
-        "uroot"
+        "Sharedfor",
+        "Successfull",
+        "uroot",
+        "userinfo",
+        "xsrf"
     ]
 }
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index 7a0ec0fec112bd1e7456912e17c7a0be00c81377..f4efa81e01e91845d2e5aa036ec955ad556f9561 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -4,7 +4,7 @@
 # STEP 1 build executable binary #
 ##################################
 
-FROM golang as builder
+FROM golang AS builder
 
 # Install git + SSL ca certificates.
 # Git is required for fetching the dependencies.
@@ -28,11 +28,6 @@ WORKDIR /app
 
 ADD . .
 
-# Build Swagger documentation
-RUN go install github.com/swaggo/swag/cmd/swag@latest
-RUN go get github.com/swaggo/swag
-RUN swag init -g ./internal/rootmux/rootmux.go
-
 # Get dependencies and run tests
 RUN go version
 RUN go get -d -v
@@ -43,6 +38,8 @@ RUN CGO_ENABLED=0 go build \
     -ldflags='-w -s -extldflags "-static"' -a \
     -o /app/backoffice-server .
 
+RUN mkdir -p /app/mnt /app/mnt/configs
+
 RUN chown -Rf "${UID}" ./*
 
 # Allow running on ports < 1000
@@ -67,9 +64,6 @@ COPY --from=builder /app/backoffice-server /app/backoffice-server
 COPY --from=builder /app/dev_certificates /app/dev_certificates
 COPY --from=builder /app/mnt/configs /app/mnt/configs
 
-# Copy swagger documentation folder
-COPY --from=builder /app/docs /app/docs
-
 # Use an unprivileged user.
 USER appuser:appuser
 
diff --git a/docker-compose.yml b/docker-compose.yml
index e4a8d5a610e4fa1c361ea082835329b6ca9defba..374ce59b43dd396bdb72ce1b4dbd08fa215d5f17 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,36 +1,36 @@
-version: '3.1'
+version: "3.1"
 
-services: 
-    database:
-        image: mysql:8
-        healthcheck:
-            test: mysqladmin ping -h 127.0.0.1 -u root --password=$$MYSQL_ROOT_PASSWORD
-            interval: 5s
-            timeout: 10s
-            retries: 60
-        volumes:
-            - ./db_data:/var/lib/mysql
-        networks:
-            - ecolyo-agent-network
-        ports:
-            - 3306:3306
-        environment:
-            MYSQL_ROOT_PASSWORD: ${DATABASE_PASSWORD}
-            MYSQL_DATABASE: ${DATABASE_NAME}
+services:
+  database:
+    image: mysql:8
+    healthcheck:
+      test: mysqladmin ping -h 127.0.0.1 -u root --password=$$MYSQL_ROOT_PASSWORD
+      interval: 5s
+      timeout: 10s
+      retries: 60
+    volumes:
+      - ./db_data:/var/lib/mysql
+    networks:
+      - ecolyo-agent-network
+    ports:
+      - 3306:3306
+    environment:
+      MYSQL_ROOT_PASSWORD: ${DATABASE_PASSWORD}
+      MYSQL_DATABASE: ${DATABASE_NAME}
 
-    phpmyadmin:
-        image: phpmyadmin/phpmyadmin:latest
-        depends_on:
-            - database
-        networks:
-            - ecolyo-agent-network
-        ports:
-            - 8008:80
-        environment:
-            PMA_HOST: database
+  phpmyadmin:
+    image: phpmyadmin/phpmyadmin:latest
+    depends_on:
+      - database
+    networks:
+      - ecolyo-agent-network
+    ports:
+      - 8008:80
+    environment:
+      PMA_HOST: database
 
 volumes:
-    db_data:
+  db_data:
 
 networks:
-    ecolyo-agent-network:
\ No newline at end of file
+  ecolyo-agent-network:
diff --git a/internal/auth/auth.go b/internal/auth/auth.go
index 2670382e45bcb5ab9aad6b68a1e57b798888e20b..ed83d4e2e732c62a91b125e10ab66c2a2e875e91 100644
--- a/internal/auth/auth.go
+++ b/internal/auth/auth.go
@@ -10,6 +10,7 @@ import (
 	"strings"
 
 	"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/common"
+	"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants"
 	"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/tokens"
 )
 
@@ -76,7 +77,7 @@ func ValidateAuthMiddleware(next http.Handler, allowedRoles []string, checkXSRF
 			if perr == nil {
 				redirectTo += ":" + port
 			}
-			w.Header().Set("Content-Type", "text/html")
+			w.Header().Set(constants.ContentType, "text/html")
 			w.WriteHeader(http.StatusUnauthorized)
 			responseContent := fmt.Sprintf("error extracting token: %v<meta http-equiv=\"Refresh\" content=\"0; url=https://%v#login\"/>", err.Error(), redirectTo)
 			fmt.Fprint(w, responseContent)
diff --git a/internal/common/common.go b/internal/common/common.go
index 3514b4531a5c3e5cb649868e6540efecd34cd913..c2bd4ed727a0cc09aa9b3ee07dbbf230f34665f8 100644
--- a/internal/common/common.go
+++ b/internal/common/common.go
@@ -18,6 +18,8 @@ import (
 	"github.com/go-chi/chi/v5"
 )
 
+const missingQueryElement = "missing query element"
+
 var (
 	disableLogFatal = false
 	lock            sync.Mutex // Mutex used to lock file writing
@@ -156,7 +158,7 @@ func YearMonthFromRequest(r *http.Request) (year int, month int, err error) {
 	monthStr := chi.URLParam(r, "month")
 
 	if yearStr == "" || monthStr == "" {
-		return 0, 0, errors.New("missing query element")
+		return 0, 0, errors.New(missingQueryElement)
 	}
 
 	year, err = strconv.Atoi(yearStr)
@@ -191,7 +193,7 @@ func PageLimitFromRequest(r *http.Request) (page int, limit int, err error) {
 	limitStr := r.URL.Query().Get("limit")
 
 	if pageStr == "" || limitStr == "" {
-		return 0, 0, errors.New("missing query element")
+		return 0, 0, errors.New(missingQueryElement)
 	}
 
 	page, err = strconv.Atoi(pageStr)
@@ -215,12 +217,12 @@ func PageLimitFromRequest(r *http.Request) (page int, limit int, err error) {
 	return page, limit, nil
 }
 
-//Get fluidType from Request
+// Get fluidType from Request
 func FluidTypeFromRequest(r *http.Request) (fluidtype int, err error) {
 	fluidTypeStr := chi.URLParam(r, "fluidtype")
 
 	if fluidTypeStr == "" {
-		return 100, errors.New("missing query element")
+		return 100, errors.New(missingQueryElement)
 	}
 
 	fluidtype, err = strconv.Atoi(fluidTypeStr)
diff --git a/internal/constants/constants.go b/internal/constants/constants.go
new file mode 100644
index 0000000000000000000000000000000000000000..f56f127f6ec8e5325d9bb7990bcddc6660b67c38
--- /dev/null
+++ b/internal/constants/constants.go
@@ -0,0 +1,7 @@
+package constants
+
+const (
+	ContentType    = "Content-Type"
+	Json           = "application/json"
+	FormUrlEncoded = "application/x-www-form-urlencoded"
+)
diff --git a/internal/file/file.go b/internal/file/file.go
index 53e515b3cc87b4d5722ff2119e4b085862fb962a..050cc01192ded776e9304a53a9847d7107fec9c3 100644
--- a/internal/file/file.go
+++ b/internal/file/file.go
@@ -8,6 +8,7 @@ import (
 	"net/http"
 
 	"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/common"
+	"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants"
 )
 
 var (
@@ -22,7 +23,7 @@ func GetEcogestureImages(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set(constants.ContentType, constants.Json)
 	w.Write(jsondata)
 	log.Printf("| get image names | %v", r.RemoteAddr)
 }
diff --git a/internal/file/file_test.go b/internal/file/file_test.go
index d8dcc99b3b5b767933c9633adea7139ece1fab46..28a3feb530eb63fc6e14afd8a578347f7f943c9b 100644
--- a/internal/file/file_test.go
+++ b/internal/file/file_test.go
@@ -25,13 +25,13 @@ func TestFilenamesFromFolder(t *testing.T) {
 		t.Errorf(`error: %s`, err)
 		return
 	}
-	jsondata, err := json.Marshal(filenames)
+	jsonData, err := json.Marshal(filenames)
 	if err != nil {
 		t.Errorf(`error: %s`, err)
 		return
 	}
-	if string(jsondata) != expected {
-		t.Errorf(`unexpected answer: got %s want %s`, string(jsondata), expected)
+	if string(jsonData) != expected {
+		t.Errorf(`unexpected answer: got %s want %s`, string(jsonData), expected)
 		return
 	}
 	os.RemoveAll("test")
diff --git a/internal/mocks/mocks.go b/internal/mocks/mocks.go
index 724552d295444b5bbc6b24e095144deb69d79088..41c0663619f46451c9d6e3c43feee50c37dc6c34 100644
--- a/internal/mocks/mocks.go
+++ b/internal/mocks/mocks.go
@@ -4,6 +4,8 @@ package mocks
 import (
 	"fmt"
 	"net/http"
+
+	"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants"
 )
 
 var (
@@ -33,7 +35,7 @@ func CreateMockOAuth2() *http.ServeMux {
 
 	// Returns access token back to the user
 	mux.HandleFunc("/token", func(w http.ResponseWriter, r *http.Request) {
-		w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
+		w.Header().Set(constants.ContentType, constants.FormUrlEncoded)
 		w.Write([]byte("access_token=mocktoken&scope=user&token_type=bearer"))
 	})
 	// Returns userinfo back to the user (with an animator user)
@@ -51,7 +53,7 @@ func CreateMockOAuth2() *http.ServeMux {
 	})
 	// Returns userinfo back to the user (with an admin user)
 	mux.HandleFunc("/admininfo", func(w http.ResponseWriter, r *http.Request) {
-		w.Header().Set("Content-Type", "application/json")
+		w.Header().Set(constants.ContentType, constants.Json)
 		w.Write([]byte(`{
 			"displayName": "Ad MIN",
 			"memberOf": [
diff --git a/internal/models/consent.go b/internal/models/consent.go
index 6a79ba09751d117a8421d4b14ab9155e21a3ea4b..88e6a1771e08b6c474226b425181b4608e74f86e 100644
--- a/internal/models/consent.go
+++ b/internal/models/consent.go
@@ -8,6 +8,7 @@ import (
 	"time"
 
 	"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/common"
+	"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants"
 	"gorm.io/gorm"
 )
 
@@ -48,6 +49,7 @@ type UpdateConsentBody struct {
 }
 
 // GetConsentById godoc
+//
 //	@Summary		Get details of a specific consent
 //	@Description	Get details of a specific consent
 //	@Tags			consent
@@ -74,13 +76,14 @@ func (dh *DataHandler) GetConsentById(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set(constants.ContentType, constants.Json)
 	json.NewEncoder(w).Encode(consent)
 
 	log.Printf("| get consent | name : %v | %v", consent.Lastname, r.RemoteAddr)
 }
 
 // PostConsent godoc
+//
 //	@Summary		Create a new consent
 //	@Description	Create a new consent
 //	@Tags			consent
@@ -114,7 +117,7 @@ func (dh *DataHandler) PostConsent(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set(constants.ContentType, constants.Json)
 	w.WriteHeader(http.StatusCreated)
 	json.NewEncoder(w).Encode(consent)
 
@@ -122,6 +125,7 @@ func (dh *DataHandler) PostConsent(w http.ResponseWriter, r *http.Request) {
 }
 
 // UpdateConsent godoc
+//
 //	@Summary		Update a consent, giving it a serviceID
 //	@Description	Update a consent, giving it a serviceID
 //	@Tags			consent
@@ -173,13 +177,14 @@ func (dh *DataHandler) UpdateConsent(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set(constants.ContentType, constants.Json)
 	json.NewEncoder(w).Encode(consent)
 
 	log.Printf("| updated consent | name : %v | serviceID : %v | %v", consent.Lastname, consent.ServiceID, r.RemoteAddr)
 }
 
 // DeleteConsentById godoc
+//
 //	@Summary		Delete a specific consent
 //	@Description	Delete a specific consent
 //	@Tags			consent
@@ -219,6 +224,7 @@ func (dh *DataHandler) DeleteConsentById(w http.ResponseWriter, r *http.Request)
 }
 
 // SearchConsent godoc
+//
 //	@Summary		Search for consents
 //	@Description	Search for consents based on the pointID
 //	@Tags			consent
@@ -250,7 +256,7 @@ func (dh *DataHandler) SearchConsent(w http.ResponseWriter, r *http.Request) {
 	pagination.TotalRows = totalRows
 	pagination.Rows = consents
 
-	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set(constants.ContentType, constants.Json)
 	json.NewEncoder(w).Encode(pagination)
 
 	log.Printf("| get all consents | limit : %d | page : %d | %v", limit, page, r.RemoteAddr)
diff --git a/internal/models/customPopup.go b/internal/models/customPopup.go
index 6e3dd2732ead6106a651fa1d2061967ac7d69b37..79b8f6cd6e5dd4ae3c70c1244384a49bb3d2b095 100644
--- a/internal/models/customPopup.go
+++ b/internal/models/customPopup.go
@@ -7,6 +7,7 @@ import (
 	"net/http"
 	"time"
 
+	"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants"
 	"gorm.io/gorm"
 )
 
@@ -19,6 +20,7 @@ type CustomPopup struct {
 }
 
 // GetCustomPopup godoc
+//
 //	@Summary		Give status of custom popup
 //	@Description	Give status of custom poup
 //	@Tags			customPopup
@@ -35,12 +37,13 @@ func (dh *DataHandler) GetCustomPopup(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set(constants.ContentType, constants.Json)
 	json.NewEncoder(w).Encode(popupInfo)
 	log.Printf("| get customPopup | %v", r.RemoteAddr)
 }
 
 // SaveCustomPopup godoc
+//
 //	@Summary		Update custom popup content
 //	@Description	Update custom popup content
 //	@Tags			customPopup
@@ -80,7 +83,7 @@ func (dh *DataHandler) SaveCustomPopup(w http.ResponseWriter, r *http.Request) {
 
 	dh.sqlClient.Save(&updatedCustomPopup)
 
-	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set(constants.ContentType, constants.Json)
 	json.NewEncoder(w).Encode(customPopup)
 	log.Printf("| updated customPopup | %v", r.RemoteAddr)
 }
diff --git a/internal/models/mailSubject.go b/internal/models/mailSubject.go
index c3005a2f841a27b0c0166caddbd13e3f9eb4277d..b0c5f6cf7370a7190e861fb7051bff622495fee5 100644
--- a/internal/models/mailSubject.go
+++ b/internal/models/mailSubject.go
@@ -6,6 +6,7 @@ import (
 	"net/http"
 
 	"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/common"
+	"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants"
 )
 
 type MailSubject struct {
@@ -15,6 +16,7 @@ type MailSubject struct {
 }
 
 // GetSingleMailSubject godoc
+//
 //	@Summary		Get details of a specific mailSubject
 //	@Description	Get details of a specific mailSubject
 //	@Tags			mailSubject
@@ -31,7 +33,7 @@ func (dh *DataHandler) GetSingleMailSubject(w http.ResponseWriter, r *http.Reque
 		return
 	}
 
-	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set(constants.ContentType, constants.Json)
 
 	var mailSubject MailSubject
 	err = dh.sqlClient.Where("year = ? AND month = ?", year, month).First(&mailSubject).Error
@@ -44,6 +46,7 @@ func (dh *DataHandler) GetSingleMailSubject(w http.ResponseWriter, r *http.Reque
 }
 
 // SaveMailSubject godoc
+//
 //	@Summary		Create/update a specific mailSubject' content
 //	@Description	Create/update a specific mailSubject' content
 //	@Tags			mailSubject
@@ -103,6 +106,7 @@ func (dh *DataHandler) SaveMailSubject(w http.ResponseWriter, r *http.Request) {
 }
 
 // DeleteMailSubject godoc
+//
 //	@Summary		Delete a specific mailSubject
 //	@Description	Delete a specific mailSubject
 //	@Tags			mailSubject
diff --git a/internal/models/monthlyInfo.go b/internal/models/monthlyInfo.go
index 971c9c5f1817b2390b20f350f4b93a2d912607b5..3d98125e950a7a6729f1ea819dfe3ec64152ccc7 100644
--- a/internal/models/monthlyInfo.go
+++ b/internal/models/monthlyInfo.go
@@ -6,6 +6,7 @@ import (
 	"net/http"
 
 	"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/common"
+	"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants"
 )
 
 type MonthlyInfo struct {
@@ -16,6 +17,7 @@ type MonthlyInfo struct {
 }
 
 // GetAllMonthlyInfo godoc
+//
 //	@Summary		List all monthlyInfo
 //	@Description	Get details of all monthlyInfo
 //	@Tags			monthlyInfo
@@ -26,12 +28,13 @@ func (dh *DataHandler) GetAllMonthlyInfo(w http.ResponseWriter, r *http.Request)
 	var monthlyInfo []MonthlyInfo
 	dh.sqlClient.Find(&monthlyInfo)
 
-	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set(constants.ContentType, constants.Json)
 	json.NewEncoder(w).Encode(monthlyInfo)
 	log.Printf("| get all monthlyInfo | %v", r.RemoteAddr)
 }
 
 // GetSingleMonthlyInfo godoc
+//
 //	@Summary		Get details of a specific monthlyInfo
 //	@Description	Get details of a specific monthlyInfo
 //	@Tags			monthlyInfo
@@ -48,7 +51,7 @@ func (dh *DataHandler) GetSingleMonthlyInfo(w http.ResponseWriter, r *http.Reque
 		return
 	}
 
-	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set(constants.ContentType, constants.Json)
 
 	var monthlyInfo MonthlyInfo
 	err = dh.sqlClient.Where("year = ? AND month = ?", year, month).First(&monthlyInfo).Error
@@ -61,6 +64,7 @@ func (dh *DataHandler) GetSingleMonthlyInfo(w http.ResponseWriter, r *http.Reque
 }
 
 // SaveMonthlyInfo godoc
+//
 //	@Summary		Create/update a specific monthlyInfo' content
 //	@Description	Create/update a specific monthlyInfo' content
 //	@Tags			monthlyInfo
@@ -128,6 +132,7 @@ func (dh *DataHandler) SaveMonthlyInfo(w http.ResponseWriter, r *http.Request) {
 }
 
 // DeleteMonthlyInfo godoc
+//
 //	@Summary		Delete a specific monthlyInfo
 //	@Description	Delete a specific monthlyInfo
 //	@Tags			monthlyInfo
diff --git a/internal/models/monthlyNews.go b/internal/models/monthlyNews.go
index 9bdfdb8dccc79d8d987a558dca771e9463af2be6..9b687f144e860877ef966191ae554b32f198d4a2 100644
--- a/internal/models/monthlyNews.go
+++ b/internal/models/monthlyNews.go
@@ -6,6 +6,7 @@ import (
 	"net/http"
 
 	"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/common"
+	"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants"
 )
 
 type MonthlyNews struct {
@@ -16,6 +17,7 @@ type MonthlyNews struct {
 }
 
 // GetAllMonthlyNews godoc
+//
 //	@Summary		List all monthlyNews
 //	@Description	Get details of all monthlyNews
 //	@Tags			monthlyNews
@@ -26,12 +28,13 @@ func (dh *DataHandler) GetAllMonthlyNews(w http.ResponseWriter, r *http.Request)
 	var monthlyNews []MonthlyNews
 	dh.sqlClient.Find(&monthlyNews)
 
-	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set(constants.ContentType, constants.Json)
 	json.NewEncoder(w).Encode(monthlyNews)
 	log.Printf("| get all monthlyNews | %v", r.RemoteAddr)
 }
 
 // GetSingleMonthlyNews godoc
+//
 //	@Summary		Get details of a specific monthlyNews
 //	@Description	Get details of a specific monthlyNews
 //	@Tags			monthlyNews
@@ -48,7 +51,7 @@ func (dh *DataHandler) GetSingleMonthlyNews(w http.ResponseWriter, r *http.Reque
 		return
 	}
 
-	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set(constants.ContentType, constants.Json)
 
 	var monthlyNews MonthlyNews
 	err = dh.sqlClient.Where("year = ? AND month = ?", year, month).First(&monthlyNews).Error
@@ -61,6 +64,7 @@ func (dh *DataHandler) GetSingleMonthlyNews(w http.ResponseWriter, r *http.Reque
 }
 
 // SaveMonthlyNews godoc
+//
 //	@Summary		Create/update a specific monthlyNews' content
 //	@Description	Create/update a specific monthlyNews' content
 //	@Tags			monthlyNews
@@ -128,6 +132,7 @@ func (dh *DataHandler) SaveMonthlyNews(w http.ResponseWriter, r *http.Request) {
 }
 
 // DeleteMonthlyNews godoc
+//
 //	@Summary		Delete a specific monthlyNews
 //	@Description	Delete a specific monthlyNews
 //	@Tags			monthlyNews
diff --git a/internal/models/monthlyReport.go b/internal/models/monthlyReport.go
index c5df9c1a349ddee50174f3e04391a3e5db0e5860..136a9b463d25908a708f82a0686e63512bea6716 100644
--- a/internal/models/monthlyReport.go
+++ b/internal/models/monthlyReport.go
@@ -5,6 +5,8 @@ import (
 	"fmt"
 	"net/http"
 	"strconv"
+
+	"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants"
 )
 
 type MonthlyReport struct {
@@ -20,6 +22,7 @@ type MonthlyReport struct {
 }
 
 // GetMonthlyReport godoc
+//
 //	@Summary		Get details of a specific monthlyReport
 //	@Description	Get details of a specific monthlyReport
 //	@Tags			monthlyReport
@@ -48,7 +51,7 @@ func (dh *DataHandler) GetMonthlyReport(w http.ResponseWriter, r *http.Request)
 		return
 	}
 
-	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set(constants.ContentType, constants.Json)
 	json.NewEncoder(w).Encode(monthlyReport)
 }
 
diff --git a/internal/models/partnersInfo.go b/internal/models/partnersInfo.go
index cdea10aec1770bbba1051ccb1bfd934d8560a007..7d0b58c4515e85ab588f354170fc2d396fcc4739 100644
--- a/internal/models/partnersInfo.go
+++ b/internal/models/partnersInfo.go
@@ -6,6 +6,7 @@ import (
 	"log"
 	"net/http"
 
+	"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants"
 	"gorm.io/gorm"
 )
 
@@ -18,6 +19,7 @@ type PartnersInfo struct {
 }
 
 // GetPartnersInfo godoc
+//
 //	@Summary		Give status of partners' services
 //	@Description	Give status of partners' services
 //	@Tags			partnersInfo
@@ -34,12 +36,13 @@ func (dh *DataHandler) GetPartnersInfo(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set(constants.ContentType, constants.Json)
 	json.NewEncoder(w).Encode(partnersInfo)
 	log.Printf("| get partnersInfo | %v", r.RemoteAddr)
 }
 
 // SavePartnersInfo godoc
+//
 //	@Summary		Update partnersInfo' content
 //	@Description	Update partnersInfo' content
 //	@Tags			partnersInfo
@@ -79,7 +82,7 @@ func (dh *DataHandler) SavePartnersInfo(w http.ResponseWriter, r *http.Request)
 
 	dh.sqlClient.Save(&updatedPartnersInfo)
 
-	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set(constants.ContentType, constants.Json)
 	json.NewEncoder(w).Encode(partnersInfo)
 	log.Printf("| updated partnersInfo | %v", r.RemoteAddr)
 
diff --git a/internal/models/poll.go b/internal/models/poll.go
index 76683a20660ebd17f3b2ae1259062c5aefd636b4..e046ee5839e031633ad46c941ec801e51b4c952b 100644
--- a/internal/models/poll.go
+++ b/internal/models/poll.go
@@ -6,6 +6,7 @@ import (
 	"net/http"
 
 	"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/common"
+	"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants"
 )
 
 type Poll struct {
@@ -16,6 +17,7 @@ type Poll struct {
 }
 
 // GetAllPolls godoc
+//
 //	@Summary		List all polls
 //	@Description	Get details of all polls
 //	@Tags			poll
@@ -30,12 +32,13 @@ func (dh *DataHandler) GetAllPolls(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set(constants.ContentType, constants.Json)
 	json.NewEncoder(w).Encode(polls)
 	log.Printf("| get all polls | %v", r.RemoteAddr)
 }
 
 // GetSinglePoll godoc
+//
 //	@Summary		Get details of a specific poll
 //	@Description	Get details of a specific poll
 //	@Tags			poll
@@ -52,7 +55,7 @@ func (dh *DataHandler) GetSinglePoll(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set(constants.ContentType, constants.Json)
 
 	var poll Poll
 	err = dh.sqlClient.Where("year = ? AND month = ?", year, month).First(&poll).Error
@@ -65,6 +68,7 @@ func (dh *DataHandler) GetSinglePoll(w http.ResponseWriter, r *http.Request) {
 }
 
 // SavePoll godoc
+//
 //	@Summary		Update a specific poll' content
 //	@Description	Update a specific poll' content
 //	@Tags			poll
@@ -125,6 +129,7 @@ func (dh *DataHandler) SavePoll(w http.ResponseWriter, r *http.Request) {
 }
 
 // DeletePoll godoc
+//
 //	@Summary		Delete a specific poll
 //	@Description	Delete a specific poll
 //	@Tags			poll
diff --git a/internal/models/price.go b/internal/models/price.go
index 5503bf185fe55ec3d83bfad7709ba529fb7b9a3c..c0c59d127d9263587d2eb20bf7170f027c99f143 100644
--- a/internal/models/price.go
+++ b/internal/models/price.go
@@ -7,6 +7,7 @@ import (
 	"time"
 
 	"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/common"
+	"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/constants"
 	"gorm.io/gorm"
 )
 
@@ -19,6 +20,7 @@ type Price struct {
 }
 
 // GetPrices godoc
+//
 //	@Summary		Get all prices
 //	@Description	Get all prices
 //	@Tags			prices
@@ -30,12 +32,13 @@ func (dh *DataHandler) GetAllPrices(w http.ResponseWriter, r *http.Request) {
 	var prices []Price
 	dh.sqlClient.Find(&prices)
 
-	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set(constants.ContentType, constants.Json)
 	json.NewEncoder(w).Encode(prices)
 	log.Printf("| Get all prices | %v", r.RemoteAddr)
 }
 
 // GetPricesByFluid godoc
+//
 //	@Summary		Get all prices for a given fluid
 //	@Description	Get all prices for a given fluid
 //	@Tags			prices
@@ -51,7 +54,7 @@ func (dh *DataHandler) GetPricesByFluid(w http.ResponseWriter, r *http.Request)
 		return
 	}
 	var price []Price
-	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set(constants.ContentType, constants.Json)
 	err = dh.sqlClient.Where("fluid_type = ? ", fluidtype).Order("start_date desc").Find(&price).Error
 
 	if err != nil {
@@ -63,6 +66,7 @@ func (dh *DataHandler) GetPricesByFluid(w http.ResponseWriter, r *http.Request)
 }
 
 // SavePrice godoc
+//
 //	@Summary		Add a new price entry
 //	@Description	Add a new price entry
 //	@Tags			prices
@@ -143,9 +147,9 @@ func (dh *DataHandler) SavePrice(w http.ResponseWriter, r *http.Request) {
 			}
 		}
 
-		if isEditable == false {
+		if !isEditable {
 			w.WriteHeader(http.StatusForbidden)
-			log.Printf("Unallowed to edit price because is not included in the the last 3 editable prices")
+			log.Printf("Unauthorized to edit price because is not included in the the last 3 editable prices")
 			return
 		}
 		// Update existing price
@@ -155,7 +159,7 @@ func (dh *DataHandler) SavePrice(w http.ResponseWriter, r *http.Request) {
 			return
 		}
 
-		w.Header().Set("Content-Type", "application/json")
+		w.Header().Set(constants.ContentType, constants.Json)
 		json.NewEncoder(w).Encode(priceToUpdate)
 		log.Printf("| Updated price | fluidType : %d price : %v | startDate : %v | %v", priceToUpdate.FluidType, priceToUpdate.Price, priceToUpdate.StartDate, r.RemoteAddr)
 	}
diff --git a/internal/rootmux/rootmux.go b/internal/rootmux/rootmux.go
index 04e185c7d855b939f47234e24a144650da8a3d59..1d572e9fcab8fbaf61a1b4959c7632aee3848436 100644
--- a/internal/rootmux/rootmux.go
+++ b/internal/rootmux/rootmux.go
@@ -91,7 +91,7 @@ func CreateRootMux() RootMux {
 		r.Delete("/consent/{id}", dh.DeleteConsentById)
 	})
 
-	r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {})
+	r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { /** handles Oauth2 redirection */ })
 
 	swaggerFs := http.FileServer(http.Dir("./docs/"))
 	r.Handle("/doc/*", http.StripPrefix("/doc/", swaggerFs))
diff --git a/internal/rootmux/rootmux_test.go b/internal/rootmux/rootmux_test.go
index 9d86529c154af8225060079782a35c89b82b3433..5370dbaf074e88240ccfc543911ea28e0962a083 100644
--- a/internal/rootmux/rootmux_test.go
+++ b/internal/rootmux/rootmux_test.go
@@ -16,6 +16,14 @@ import (
 	"forge.grandlyon.com/web-et-numerique/factory/llle_project/backoffice-server/internal/tokens"
 )
 
+const (
+	SuccessfullDelete    = "successful delete"
+	ErrorExtractingToken = "error extracting token"
+	ErrorInvalidToken    = "invalid token"
+	ErrorEmptyBody       = "request body is empty"
+	ErrorXSRF            = "XSRF protection triggered"
+)
+
 var (
 	oAuth2Server    *httptest.Server
 	mailSubject     = models.MailSubject{Year: 2021, Month: 1, Subject: "[Ecolyo] Newsletter"}
@@ -90,7 +98,7 @@ func TestAll(t *testing.T) {
 	os.Setenv("AUTH_URL", oAuth2Server.URL+"/auth-wrong-state") // Set the server to access failing OAuth2 endpoints
 	oauth2Tests(t)
 	os.Setenv("AUTH_URL", oAuth2Server.URL+"/auth") // Set the server to access the correct OAuth2Endpoint
-	unloggedTests(t)
+	noAuthTests(t)
 	os.Setenv("USERINFO_URL", oAuth2Server.URL+"/animatorinfo")
 	animatorTests(t)
 	os.Setenv("USERINFO_URL", oAuth2Server.URL+"/admininfo")
@@ -112,16 +120,16 @@ func oauth2Tests(t *testing.T) {
 
 /*
 *
-UNLOGGED USER TESTS (this tests are to check that the security protections works)
+NO AUTH USER TESTS (this tests are to check that the security protections works)
 *
 */
-func unloggedTests(t *testing.T) {
+func noAuthTests(t *testing.T) {
 	// Create the tester
 	ts, do, _ := createTester(t)
 	defer ts.Close() // Close the tester
 
 	// Try to create a monthlyNews (must fail)
-	do("PUT", "/api/animator/monthlyNews", noH, monthlyNewsStr, http.StatusUnauthorized, "error extracting token")
+	do("PUT", "/api/animator/monthlyNews", noH, monthlyNewsStr, http.StatusUnauthorized, ErrorExtractingToken)
 	// Try to get a monthlyReport (must fail because no parameters are given)
 	do("GET", "/api/common/monthlyReport", noH, "", http.StatusBadRequest, "")
 	// Try to get a monthlyReport (must pass empty)
@@ -146,9 +154,9 @@ func animatorTests(t *testing.T) {
 		json.Unmarshal([]byte(response), &token)
 		xsrfHeader := map[string]string{"XSRF-TOKEN": token.XSRFToken}
 		// Try to create a monthlyNews without the XSRF-TOKEN (must fail)
-		do("PUT", "/api/animator/monthlyNews", noH, monthlyNewsStr, http.StatusUnauthorized, "XSRF protection triggered")
+		do("PUT", "/api/animator/monthlyNews", noH, monthlyNewsStr, http.StatusUnauthorized, ErrorXSRF)
 		// Try to create a monthlyNews without body (must fail)
-		do("PUT", "/api/animator/monthlyNews", xsrfHeader, "", http.StatusBadRequest, "request body is empty")
+		do("PUT", "/api/animator/monthlyNews", xsrfHeader, "", http.StatusBadRequest, ErrorEmptyBody)
 		// Try to get a monthlyNews before it is created (must fail because not found)
 		do("GET", "/api/animator/monthlyNews/2021/1", xsrfHeader, "", http.StatusNotFound, "")
 		// Try to create a monthlyNews (must pass)
@@ -161,9 +169,9 @@ func animatorTests(t *testing.T) {
 		do("GET", "/api/common/monthlyReport?year=2021&month=1", noH, "", http.StatusOK, `{"year":2021,"month":1,"subject":"[Ecolyo] Votre bilan de décembre 2020","info":"","image":"","newsTitle":"Les nouveautés du service","newsContent":"Nouvelles fonctionnalités","question":"","link":""}`)
 
 		// Try to create a poll without the XSRF-TOKEN (must fail)
-		do("PUT", "/api/animator/poll", noH, newPollStr, http.StatusUnauthorized, "XSRF protection triggered")
+		do("PUT", "/api/animator/poll", noH, newPollStr, http.StatusUnauthorized, ErrorXSRF)
 		// Try to create a poll without body (must fail)
-		do("PUT", "/api/animator/poll", xsrfHeader, "", http.StatusBadRequest, "request body is empty")
+		do("PUT", "/api/animator/poll", xsrfHeader, "", http.StatusBadRequest, ErrorEmptyBody)
 		// Try to get a poll before it is created (must fail because not found')
 		do("GET", "/api/animator/poll/2021/1", xsrfHeader, "", http.StatusNotFound, "")
 		// Try to create a poll (must pass)
@@ -176,9 +184,9 @@ func animatorTests(t *testing.T) {
 		do("GET", "/api/common/monthlyReport?year=2021&month=1", noH, "", http.StatusOK, `{"year":2021,"month":1,"subject":"[Ecolyo] Votre bilan de décembre 2020","info":"","image":"","newsTitle":"Les nouveautés du service","newsContent":"Nouvelles fonctionnalités","question":"pollQuestion","link":"pollLink"}`)
 
 		// Try to create a monthlyInfo without the XSRF-TOKEN (must fail)
-		do("PUT", "/api/animator/monthlyInfo", noH, monthlyInfoStr, http.StatusUnauthorized, "XSRF protection triggered")
+		do("PUT", "/api/animator/monthlyInfo", noH, monthlyInfoStr, http.StatusUnauthorized, ErrorXSRF)
 		// Try to create a monthlyInfo without body (must fail)
-		do("PUT", "/api/animator/monthlyInfo", xsrfHeader, "", http.StatusBadRequest, "request body is empty")
+		do("PUT", "/api/animator/monthlyInfo", xsrfHeader, "", http.StatusBadRequest, ErrorEmptyBody)
 		// Try to get a monthlyInfo before it is created (must fail because not found)
 		do("GET", "/api/animator/monthlyInfo/2021/1", xsrfHeader, "", http.StatusNotFound, "")
 		// Try to create a monthlyInfo (must pass)
@@ -201,7 +209,7 @@ func animatorTests(t *testing.T) {
 		do("GET", "/api/common/customPopup", xsrfHeader, "", http.StatusOK, customPopupStr)
 
 		// Try to delete the monthlyNews created (must pass)
-		do("DELETE", "/api/animator/monthlyNews/2021/1", xsrfHeader, "", http.StatusOK, "successful delete")
+		do("DELETE", "/api/animator/monthlyNews/2021/1", xsrfHeader, "", http.StatusOK, SuccessfullDelete)
 		// Try to get a monthlyNews after it is deleted (must fail because not found)
 		do("GET", "/api/animator/monthlyNews/2021/1", xsrfHeader, "", http.StatusNotFound, "")
 
@@ -210,14 +218,14 @@ func animatorTests(t *testing.T) {
 		// Try to get the monthlyReport (must pass)
 		do("GET", "/api/common/monthlyReport?year=2021&month=1", noH, "", http.StatusOK, `{"year":2021,"month":1,"subject":"[Ecolyo] Newsletter","info":"Informations du mois","image":"imagebase64","newsTitle":"","newsContent":"","question":"pollQuestion","link":"pollLink"`)
 		// Try to delete the poll created (must pass)
-		do("DELETE", "/api/animator/poll/2021/1", xsrfHeader, "", http.StatusOK, "successful delete")
+		do("DELETE", "/api/animator/poll/2021/1", xsrfHeader, "", http.StatusOK, SuccessfullDelete)
 		// Try to get a poll after it is deleted (must fail because not found)
 		do("GET", "/api/animator/poll/2021/1", xsrfHeader, "", http.StatusNotFound, "")
 		// Try to get the monthlyReport (must pass)
 		do("GET", "/api/common/monthlyReport?year=2021&month=1", noH, "", http.StatusOK, `{"year":2021,"month":1,"subject":"[Ecolyo] Newsletter","info":"Informations du mois","image":"imagebase64","newsTitle":"","newsContent":"","question":"","link":""`)
 
 		// Try to delete the mail subject created (must pass)
-		do("DELETE", "/api/animator/mailSubject/2021/1", xsrfHeader, "", http.StatusOK, "successful delete")
+		do("DELETE", "/api/animator/mailSubject/2021/1", xsrfHeader, "", http.StatusOK, SuccessfullDelete)
 		// Try to get a mail subject after it is deleted (must fail because not found)
 		do("GET", "/api/animator/mailSubject/2021/1", xsrfHeader, "", http.StatusNotFound, "")
 		// Try to get the monthlyReport (must pass)
@@ -233,9 +241,9 @@ func animatorTests(t *testing.T) {
 	// Try to logout (must pass)
 	do("GET", "/Logout", noH, "", http.StatusOK, "")
 	// Try to get a monthlyNews again (must fail)
-	do("GET", "/api/animator/monthlyNews", noH, "", http.StatusUnauthorized, "error extracting token")
+	do("GET", "/api/animator/monthlyNews", noH, "", http.StatusUnauthorized, ErrorExtractingToken)
 	// Try to get a poll again (must fail)
-	do("GET", "/api/animator/poll", noH, "", http.StatusUnauthorized, "error extracting token")
+	do("GET", "/api/animator/poll", noH, "", http.StatusUnauthorized, ErrorExtractingToken)
 
 }
 
@@ -257,7 +265,7 @@ func adminTests(t *testing.T) {
 	// Try to logout (must pass)
 	do("GET", "/Logout", noH, "", http.StatusOK, "")
 	// Try to get SGE consents again (must fail)
-	do("GET", "/api/admin/consent?limit=50&page=0", xsrfHeader, "", http.StatusUnauthorized, "error extracting token")
+	do("GET", "/api/admin/consent?limit=50&page=0", xsrfHeader, "", http.StatusUnauthorized, ErrorExtractingToken)
 }
 
 func sgeTests(t *testing.T) {
@@ -265,13 +273,13 @@ func sgeTests(t *testing.T) {
 	ts, do, _ := createTester(t)
 	defer ts.Close() // Close the tester
 	// Try to create a consent  (must fail)
-	do("POST", "/api/sge/consent", noH, consentStr, http.StatusUnauthorized, "invalid token")
+	do("POST", "/api/sge/consent", noH, consentStr, http.StatusUnauthorized, ErrorInvalidToken)
 	// Try to get a consent  (must fail)
-	do("GET", "/api/sge/consent/1", noH, "", http.StatusUnauthorized, "invalid token")
+	do("GET", "/api/sge/consent/1", noH, "", http.StatusUnauthorized, ErrorInvalidToken)
 	// Try to update a consent  (must fail)
-	do("PUT", "/api/sge/consent/1", noH, "", http.StatusUnauthorized, "invalid token")
+	do("PUT", "/api/sge/consent/1", noH, "", http.StatusUnauthorized, ErrorInvalidToken)
 	// Try to delete a consent  (must fail)
-	do("DELETE", "/api/sge/consent/1", noH, "", http.StatusUnauthorized, "invalid token")
+	do("DELETE", "/api/sge/consent/1", noH, "", http.StatusUnauthorized, ErrorInvalidToken)
 
 	// Create correct authorization header
 	sgeApiHeader := map[string]string{"Authorization": "Bearer " + auth.SGEApiToken}
diff --git a/internal/tester/tester.go b/internal/tester/tester.go
index d7c6a6739062d632843205b3a7de13ef13795618..51a9e80cc59c76c733728d6df4c14a648142a266 100644
--- a/internal/tester/tester.go
+++ b/internal/tester/tester.go
@@ -6,7 +6,6 @@ import (
 	"net"
 	"net/http"
 	"net/http/cookiejar"
-	"net/http/httptest"
 	"net/url"
 	"strings"
 	"testing"
@@ -15,26 +14,6 @@ import (
 
 type DoFn func(method string, url string, headers map[string]string, payload string, expectedStatus int, expectedBody string) string
 
-// DoRequestOnHandler does a request on a router (or handler) and check the response
-func DoRequestOnHandler(t *testing.T, router http.Handler, method string, route string, headers map[string]string, payload string, expectedStatus int, expectedBody string) string {
-	req, err := http.NewRequest(method, route, strings.NewReader(payload))
-	if err != nil {
-		t.Fatal(err)
-	}
-	for i, v := range headers {
-		req.Header.Set(i, v)
-	}
-	rr := httptest.NewRecorder()
-	router.ServeHTTP(rr, req)
-	if status := rr.Code; status != expectedStatus {
-		t.Errorf("Tested %v %v %v ; handler returned wrong status code: got %v want %v", method, route, payload, status, expectedStatus)
-	}
-	if !strings.HasPrefix(rr.Body.String(), expectedBody) {
-		t.Errorf("Tested %v %v %v ; handler returned unexpected body: got %v want %v", method, route, payload, rr.Body.String(), expectedBody)
-	}
-	return string(rr.Body.String())
-}
-
 // DoRequestOnServer does a request on listening server
 func DoRequestOnServer(t *testing.T, hostname string, port string, jar *cookiejar.Jar, method string, testURL string, headers map[string]string, payload string, expectedStatus int, expectedBody string) string {
 	dialer := &net.Dialer{
diff --git a/mnt/configs/tokenskey.json b/mnt/configs/tokenskey.json
deleted file mode 100644
index 3920d9ac878d69bc836ee66729cb1d027ed5b498..0000000000000000000000000000000000000000
--- a/mnt/configs/tokenskey.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-	"Key": "2ioa6+gmlILIQcsG/HmBqDSsszPCe4GWKjCfyrtgLek="
-}
\ No newline at end of file
diff --git a/scripts/import-convert-assets.sh b/scripts/import-convert-assets.sh
new file mode 100755
index 0000000000000000000000000000000000000000..6ebfa51ea3dde5594bff81715fd89bd8abfdb4af
--- /dev/null
+++ b/scripts/import-convert-assets.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+# See https://stackoverflow.com/questions/24112727/relative-paths-based-on-file-location-instead-of-current-working-directory
+WD=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )
+cd "$WD"
+
+# Get env variables
+source ../.env
+
+REGISTRY_ID=409
+EMAIL_ASSETS_PATH="src/assets/icons/email"
+ECOGESTURE_ASSETS_PATH="src/assets/icons/visu/ecogesture"
+
+# Clear folder
+rm -rf ../$IMAGE_FOLDER
+
+# Create folder
+mkdir -p ../$IMAGE_FOLDER ../$IMAGE_FOLDER/ecogesture
+
+# Fetch and convert email assets
+curl "https://forge.grandlyon.com/api/v4/projects/${REGISTRY_ID}/repository/archive?path=${EMAIL_ASSETS_PATH}" --output email.tar.gz
+tar -xf email.tar.gz
+find *-email/$EMAIL_ASSETS_PATH -type f -name "*.svg" | while read -r svg_file; do
+    filename="$(basename "$svg_file" .svg)"
+    inkscape -h 200 -o ../$IMAGE_FOLDER/$filename.png *-email/$EMAIL_ASSETS_PATH/$filename.svg
+done
+rm *-email/$EMAIL_ASSETS_PATH/*.svg
+
+# Fetch and convert ecogesture assets
+curl "https://forge.grandlyon.com/api/v4/projects/${REGISTRY_ID}/repository/archive?path=${ECOGESTURE_ASSETS_PATH}" --output ecogesture.tar.gz
+tar -xf ecogesture.tar.gz
+find *-ecogesture/$ECOGESTURE_ASSETS_PATH -type f -name "*.svg" | while read -r svg_file; do
+    filename="$(basename "$svg_file" .svg)"
+    inkscape -h 200 -o ../$IMAGE_FOLDER/ecogesture/$filename.png *-ecogesture/$ECOGESTURE_ASSETS_PATH/$filename.svg
+done
+rm *-ecogesture/$ECOGESTURE_ASSETS_PATH/*.svg
+
+# Cleanup
+rm -rf email.tar.gz ecogesture.tar.gz *-email *-ecogesture
diff --git a/scripts/init-fluidprices.sh b/scripts/init-fluidprices.sh
new file mode 100755
index 0000000000000000000000000000000000000000..89e01f52f8026f64ae3117b8b2963c72477b8595
--- /dev/null
+++ b/scripts/init-fluidprices.sh
@@ -0,0 +1,112 @@
+#!/bin/bash
+
+# See https://stackoverflow.com/questions/24112727/relative-paths-based-on-file-location-instead-of-current-working-directory
+WD=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )
+cd "$WD/.."
+
+source .env
+
+# REMOVE PRICES TABLE
+docker compose exec database mysql -u${DATABASE_USER} -p${DATABASE_PASSWORD} -e "use $DATABASE_NAME; DROP TABLE prices;"
+echo "Prices database dropped"
+
+# CREATE PRICES TABLE
+docker compose exec database mysql -u${DATABASE_USER} -p${DATABASE_PASSWORD} -e "use $DATABASE_NAME; CREATE TABLE prices (
+  id int(11) NOT NULL,
+  fluid_type bigint(20) DEFAULT NULL,
+  price float DEFAULT NULL,
+  start_date longtext,
+  end_date longtext,
+  created_at datetime(3) DEFAULT NULL,
+  updated_at datetime(3) DEFAULT NULL,
+  deleted_at datetime(3) DEFAULT NULL
+);"
+echo "Prices database created"
+
+# POPULATE PRICES TABLE
+docker compose exec database mysql -u${DATABASE_USER} -p${DATABASE_PASSWORD} -e "use $DATABASE_NAME; INSERT INTO prices (id, fluid_type, price, start_date, end_date) VALUES 
+  (1,0,0.1256,'2012-07-23 00:00:00','2013-07-31 23:59:59'),
+  (2,0,0.1329,'2013-08-01 00:00:00','2014-10-31 23:59:59'),
+  (3,0,0.1401,'2014-01-11 00:00:00','2015-07-31 23:59:59'),
+  (4,0,0.1437,'2015-08-01 00:00:00','2016-07-31 23:59:59'),
+  (5,0,0.1503,'2016-08-01 00:00:00','2017-07-31 23:59:59'),
+  (6,0,0.1546,'2017-08-01 00:00:00','2018-01-31 23:59:59'),
+  (7,0,0.1555,'2018-02-01 00:00:00','2018-07-31 23:59:59'),
+  (8,0,0.145,'2018-08-01 00:00:00','2019-05-31 23:59:59'),
+  (9,0,0.1531,'2019-02-01 00:00:00','2019-07-31 23:59:59'),
+  (10,0,0.1524,'2019-08-01 00:00:00','2020-01-31 23:59:59'),
+  (11,0,0.1546,'2020-02-01 00:00:00','2020-07-31 23:59:59'),
+  (12,0,0.1557,'2020-08-01 00:00:00','2021-01-31 23:59:59'),
+  (13,0,0.1582,'2021-02-01 00:00:00','2021-07-31 23:59:59'),
+  (14,0,0.1558,'2021-08-01 00:00:00','2022-01-31 23:59:59'),
+  (15,0,0.174,'2022-02-01 00:00:00',NULL),
+  (16,1,0.0030735,'2012-01-01 00:00:00','2012-12-31 23:59:59'),
+  (17,1,0.0031483,'2013-01-01 00:00:00','2013-12-31 23:59:59'),
+  (18,1,0.0031381,'2014-01-01 00:00:00','2014-12-31 23:59:59'),
+  (19,1,0.00307,'2015-01-01 00:00:00','2015-12-31 23:59:59'),
+  (20,1,0.0031,'2016-01-01 00:00:00','2016-12-31 23:59:59'),
+  (21,1,0.00311,'2017-01-01 00:00:00','2017-12-31 23:59:59'),
+  (22,1,0.00313,'2018-01-01 00:00:00','2018-12-31 23:59:59'),
+  (23,1,0.00313,'2019-01-01 00:00:00','2019-12-31 23:59:59'),
+  (24,1,0.00315,'2020-01-01 00:00:00','2020-12-31 23:59:59'),
+  (25,1,0.00319,'2021-01-01 00:00:00',NULL),
+  (26,2,0.0919,'2017-01-01 00:00:00','2017-01-31 23:59:59'),
+  (27,2,0.0915,'2017-02-01 00:00:00','2017-02-28 23:59:59'),
+  (28,2,0.0932,'2017-03-01 00:00:00','2017-03-31 23:59:59'),
+  (29,2,0.0927,'2017-04-01 00:00:00','2017-04-30 23:59:59'),
+  (30,2,0.0906,'2017-05-01 00:00:00','2017-05-31 23:59:59'),
+  (31,2,0.0906,'2017-06-01 00:00:00','2017-06-30 23:59:59'),
+  (32,2,0.0788,'2017-07-01 00:00:00','2017-07-31 23:59:59'),
+  (33,2,0.0783,'2017-08-01 00:00:00','2017-08-31 23:59:59'),
+  (34,2,0.0783,'2017-09-01 00:00:00','2017-09-30 23:59:59'),
+  (35,2,0.0791,'2017-10-01 00:00:00','2017-10-31 23:59:59'),
+  (36,2,0.0806,'2017-11-01 00:00:00','2017-11-30 23:59:59'),
+  (37,2,0.0812,'2017-12-01 00:00:00','2017-12-31 23:59:59'),
+  (38,2,0.0857,'2018-01-01 00:00:00','2018-01-31 23:59:59'),
+  (39,2,0.0866,'2018-02-01 00:00:00','2018-02-28 23:59:59'),
+  (40,2,0.0847,'2018-03-01 00:00:00','2018-03-31 23:59:59'),
+  (41,2,0.0839,'2018-04-01 00:00:00','2018-04-30 23:59:59'),
+  (42,2,0.0842,'2018-05-01 00:00:00','2018-05-31 23:59:59'),
+  (43,2,0.0855,'2018-06-01 00:00:00','2018-06-30 23:59:59'),
+  (44,2,0.0959,'2018-07-01 00:00:00','2018-07-31 23:59:59'),
+  (45,2,0.0961,'2018-08-01 00:00:00','2018-08-31 23:59:59'),
+  (46,2,0.0967,'2018-09-01 00:00:00','2018-09-30 23:59:59'),
+  (47,2,0.0989,'2018-10-01 00:00:00','2018-10-31 23:59:59'),
+  (48,2,0.1031,'2018-11-01 00:00:00','2018-11-30 23:59:59'),
+  (49,2,0.1013,'2018-12-01 00:00:00','2018-12-31 23:59:59'),
+  (50,2,0.0999,'2019-01-01 00:00:00','2019-01-31 23:59:59'),
+  (51,2,0.0993,'2019-02-01 00:00:00','2019-02-28 23:59:59'),
+  (52,2,0.0993,'2019-03-01 00:00:00','2019-03-31 23:59:59'),
+  (53,2,0.0977,'2019-04-01 00:00:00','2019-04-30 23:59:59'),
+  (54,2,0.0973,'2019-05-01 00:00:00','2019-05-31 23:59:59'),
+  (55,2,0.0969,'2019-06-01 00:00:00','2019-06-30 23:59:59'),
+  (56,2,0.0795,'2019-07-01 00:00:00','2019-07-31 23:59:59'),
+  (57,2,0.0791,'2019-08-01 00:00:00','2019-08-31 23:59:59'),
+  (58,2,0.0785,'2019-09-01 00:00:00','2019-09-30 23:59:59'),
+  (59,2,0.077,'2019-10-01 00:00:00','2019-10-31 23:59:59'),
+  (60,2,0.0789,'2019-11-01 00:00:00','2019-11-30 23:59:59'),
+  (61,2,0.0793,'2019-12-01 00:00:00','2019-12-31 23:59:59'),
+  (62,2,0.0787,'2020-01-01 00:00:00','2020-01-31 23:59:59'),
+  (63,2,0.0765,'2020-02-01 00:00:00','2020-02-29 23:59:59'),
+  (64,2,0.0736,'2020-03-01 00:00:00','2020-03-31 23:59:59'),
+  (65,2,0.071,'2020-04-01 00:00:00','2020-04-30 23:59:59'),
+  (66,2,0.0703,'2020-05-01 00:00:00','2020-05-31 23:59:59'),
+  (67,2,0.0687,'2020-06-01 00:00:00','2020-06-30 23:59:59'),
+  (68,2,0.0698,'2020-07-01 00:00:00','2020-07-31 23:59:59'),
+  (69,2,0.0705,'2020-08-01 00:00:00','2020-08-31 23:59:59'),
+  (70,2,0.0709,'2020-09-01 00:00:00','2020-09-30 23:59:59'),
+  (71,2,0.0735,'2020-10-01 00:00:00','2020-10-31 23:59:59'),
+  (72,2,0.0745,'2020-11-01 00:00:00','2020-11-30 23:59:59'),
+  (73,2,0.0759,'2020-12-01 00:00:00','2020-12-31 23:59:59'),
+  (74,2,0.076,'2021-01-01 00:00:00','2021-01-31 23:59:59'),
+  (75,2,0.0782,'2021-02-01 00:00:00','2021-02-28 23:59:59'),
+  (76,2,0.0818,'2021-03-01 00:00:00','2021-03-31 23:59:59'),
+  (77,2,0.079,'2021-04-01 00:00:00','2021-04-30 23:59:59'),
+  (78,2,0.0797,'2021-05-01 00:00:00','2021-05-31 23:59:59'),
+  (79,2,0.0826,'2021-06-01 00:00:00','2021-06-30 23:59:59'),
+  (80,2,0.0895,'2021-07-01 00:00:00','2021-07-31 23:59:59'),
+  (81,2,0.0934,'2021-08-01 00:00:00','2021-08-31 23:59:59'),
+  (82,2,0.1002,'2021-09-01 00:00:00','2021-09-30 23:59:59'),
+  (83,2,0.1121,'2021-10-01 00:00:00',NULL)
+;"
+echo "Prices database populated"
diff --git a/scripts/init-swagger-doc.sh b/scripts/init-swagger-doc.sh
new file mode 100755
index 0000000000000000000000000000000000000000..e8f11ada3741d307066dd4062202aa204a58dc16
--- /dev/null
+++ b/scripts/init-swagger-doc.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# See https://stackoverflow.com/questions/24112727/relative-paths-based-on-file-location-instead-of-current-working-directory
+WD=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )
+cd "$WD/.."
+
+source .env
+
+# Build documentation
+swag init -g ./internal/rootmux/rootmux.go
+
+# Keep only swagger.json and swagger.yaml
+rm ./docs/docs.go