diff --git a/src/index.js b/src/index.js
index 1053b32e59e01e1228fd53bb0008b7ff258a0614..bbc9e0d3923462a6f4f4203724d13965b1a4d71c 100644
--- a/src/index.js
+++ b/src/index.js
@@ -3,8 +3,8 @@ const {
   log,
   errors,
   addData,
+  updateOrCreate,
   hydrateAndFilter,
-  cozyClient,
 } = require('cozy-konnector-libs')
 
 const axios = require('axios').default
@@ -20,8 +20,7 @@ const Tracing = require('@sentry/tracing') // Needed for tracking performance in
 const { version } = require('../package.json')
 const { isDev } = require('./helpers/env')
 
-const manualExecution =
-  process.env.COZY_JOB_MANUAL_EXECUTION === 'true' ? true : false
+const manualExecution = process.env.COZY_JOB_MANUAL_EXECUTION === 'true'
 
 const startDate = manualExecution
   ? moment()
@@ -96,13 +95,32 @@ async function start(fields, cozyParameters) {
     const eglData = await getData(response, baseUrl, apiAuthKey)
     if (eglData) {
       log('debug', 'Process egl daily data')
-      const processedLoadData = await processData(
+      const filteredDocuments = await hydrateAndFilter(
         eglData,
         rangeDate.day.doctype,
-        rangeDate.day.keys
+        {
+          keys: rangeDate.day.keys,
+        }
+      )
+      await addData(filteredDocuments, rangeDate.day.doctype)
+
+      log('debug', 'Aggregate egl monthly load data')
+      const monthlyLoads = aggregateMonthlyLoad(eglData)
+      log('debug', 'Store aggregated egl monthly load data')
+      await updateOrCreate(
+        monthlyLoads,
+        rangeDate.month.doctype,
+        rangeDate.month.keys
+      )
+
+      log('debug', 'Aggregate egl yearly load data')
+      const yearlyLoads = aggregateYearlyLoad(monthlyLoads)
+      log('debug', 'Store aggregated egl yearly load data')
+      await updateOrCreate(
+        yearlyLoads,
+        rangeDate.year.doctype,
+        rangeDate.year.keys
       )
-      log('debug', 'Aggregate egl load data for month and year')
-      await aggregateMonthAndYearData(processedLoadData)
     } else {
       log('debug', 'No data found')
     }
@@ -124,83 +142,78 @@ async function start(fields, cozyParameters) {
   }
 }
 
-/**
- * Parse data
- * Remove existing data from DB using hydrateAndFilter
- * Store filtered data
- * Return the list of filtered data
- */
-async function processData(data, doctype, filterKeys) {
-  log('debug', 'processData - data formatted')
-  // Remove data for existing days into the DB
-  const filteredData = await hydrateAndFilter(data, doctype, {
-    keys: filterKeys,
-  })
-  log('debug', 'processData - data filtered')
-  // Store new day data
-  await storeData(filteredData, doctype, filterKeys)
-  return filteredData
-}
+function aggregateMonthlyLoad(data) {
+  const monthlyLoad = {}
 
-/**
- * Aggregate data from daily data to monthly and yearly data
- */
-async function aggregateMonthAndYearData(data) {
-  // Sum year and month values into object with year or year-month as keys
-  if (data && data.length !== 0) {
-    let monthData = {}
-    let yearData = {}
-
-    data.forEach(element => {
-      const monthDataKey = element.year + '-' + element.month
-      if (monthDataKey in monthData) {
-        monthData[monthDataKey] += element.load
-      } else {
-        monthData[monthDataKey] = element.load
+  for (const entry of data) {
+    const { year, month, load } = entry
+    const monthKey = `${year}-${month}`
+
+    if (!monthlyLoad[monthKey]) {
+      monthlyLoad[monthKey] = {
+        load: load,
+        year: year,
+        month: month,
+        day: 0,
+        hour: 0,
+        minute: 0,
+        type: 'R',
       }
+    } else {
+      monthlyLoad[monthKey].load += load
+    }
+  }
+
+  return Object.values(monthlyLoad)
+}
 
-      const yearDataKey = element.year
-      if (yearDataKey in yearData) {
-        yearData[yearDataKey] += element.load
-      } else {
-        yearData[yearDataKey] = element.load
+function aggregateYearlyLoad(data) {
+  const yearlyLoad = {}
+
+  for (const entry of data) {
+    const { year, load } = entry
+    if (!yearlyLoad[year]) {
+      yearlyLoad[year] = {
+        load: load,
+        year: year,
+        month: 0,
+        day: 0,
+        hour: 0,
+        minute: 0,
+        type: 'R',
       }
-    })
-    // Aggregation for Month data
-    const aggregatedMonthData = await buildAggregatedData(
-      monthData,
-      'com.grandlyon.egl.month'
-    )
-    await storeData(aggregatedMonthData, 'com.grandlyon.egl.month', [
-      'year',
-      'month',
-    ])
-    // Aggregation for Year data
-    const aggregatedYearData = await buildAggregatedData(
-      yearData,
-      'com.grandlyon.egl.year'
-    )
-    await storeData(aggregatedYearData, 'com.grandlyon.egl.year', ['year'])
+    } else {
+      yearlyLoad[year].load += load
+    }
   }
+
+  return Object.values(yearlyLoad)
 }
 
 /**
- * Retrieve and remove old data for a specific doctype
- * Return an Array of aggregated data
+ * @typedef {Object} AuthResponse
+ * @property {number} codeRetour
+ * @property {string} libelleRetour
+ * @property {AuthResult} resultatRetour
+ */
+
+/**
+ * @typedef {Object} AuthResult
+ * @property {number} num_abt
+ * @property {string} token
  */
-async function buildAggregatedData(data, doctype) {
-  log('info', 'entering buildAggregatedData')
-  let aggregatedData = []
-  for (let [key, value] of Object.entries(data)) {
-    const data = await buildDataFromKey(doctype, key, value)
-    const oldValue = await resetInProgressAggregatedData(data, doctype)
-    log('info', 'Data load + old value is ' + data.load + ' + ' + oldValue)
-    data.load += oldValue
-    aggregatedData.push(data)
-  }
-  return aggregatedData
-}
 
+/**
+ * Authenticates a user with the provided credentials and returns an authentication response.
+ *
+ * @param {number} login - The user's login.
+ * @param {string} password - The user's password.
+ * @param {string} baseUrl - The base URL for the authentication request.
+ * @param {string} apiAuthKey - The API authentication key.
+ *
+ * @throws {Error} - Throws a Cozy error (VENDOR_DOWN or LOGIN_FAILED) in case of authentication failure.
+ * @returns {Promise<AuthResponse>} - The authentication response containing a token.
+ */
 async function authenticate(login, password, baseUrl, apiAuthKey) {
   log('info', 'Authenticating ...')
   const authRequest = {
@@ -217,11 +230,13 @@ async function authenticate(login, password, baseUrl, apiAuthKey) {
   }
 
   try {
-    const resp = await axios(authRequest)
-    if (resp.data.codeRetour === 100) {
-      return resp.data
+    /** @type {AuthResponse} */
+    const respData = (await axios(authRequest)).data
+
+    if (respData.codeRetour === 100) {
+      return respData
     }
-    const errorMessage = `Authentication failed. Response data: ${resp?.data?.libelleRetour}`
+    const errorMessage = `Authentication failed. Response data: ${respData.libelleRetour}`
     log('error', errorMessage)
     throw new Error(errors.VENDOR_DOWN)
   } catch (error) {
@@ -241,6 +256,30 @@ async function authenticate(login, password, baseUrl, apiAuthKey) {
   }
 }
 
+/**
+ * @typedef {Object} GetDataResponse
+ * @property {number} codeRetour
+ * @property {string} libelleRetour
+ * @property {Array<Releve>} resultatRetour
+ */
+
+/**
+ * @typedef {Object} Releve
+ * @property {string} DateReleve
+ * @property {string} TypeAgregat
+ * @property {number} ValeurIndex
+ */
+
+/**
+ * Retrieves data from a specified API using the provided response data and API configuration.
+ *
+ * @param {ApiResponse} response - The authentication response containing a valid token.
+ * @param {string} baseUrl - The base URL for the data request.
+ * @param {string} apiAuthKey - The API authentication key.
+ *
+ * @throws {Error} - Throws an error with an error code in case of data retrieval failure.
+ * @returns {Promise<FormattedData>} - A promise that resolves to the retrieved and formatted data.
+ */
 async function getData(response, baseUrl, apiAuthKey) {
   const dataRequest = {
     method: 'post',
@@ -256,32 +295,34 @@ async function getData(response, baseUrl, apiAuthKey) {
       date_fin: endDate,
     },
   }
+
   try {
+    /** @type {GetDataResponse} */
+    const respData = (await axios(dataRequest)).data
+
     // Sort data by date
-    const resp = await axios(dataRequest)
-    resp.data.resultatRetour.sort(function(a, b) {
+    respData.resultatRetour.sort(function(a, b) {
       return new Date(a.DateReleve) - new Date(b.DateReleve)
     })
-
-    switch (resp.data.codeRetour) {
+    switch (respData.codeRetour) {
       case 100:
-        return format(resp.data)
+        return format(respData)
       case -2:
         log(
           'error',
-          `Get data failed. codeRetour -2. ${resp.data.libelleRetour}`
+          `Get data failed. codeRetour -2. ${respData.libelleRetour}`
         )
         throw errors.LOGIN_FAILED
       case -1:
         log(
           'error',
-          `Get data failed. codeRetour -1. ${resp.data.libelleRetour}`
+          `Get data failed. codeRetour -1. ${respData.libelleRetour}`
         )
         throw errors.VENDOR_DOWN
       default:
         log(
           'error',
-          `Get data failed. ${resp.data.codeRetour}. ${resp.data.libelleRetour}`
+          `Get data failed. ${respData.codeRetour}. ${respData.libelleRetour}`
         )
         throw errors.UNKNOWN_ERROR
     }
@@ -303,6 +344,27 @@ async function getData(response, baseUrl, apiAuthKey) {
   }
 }
 
+/**
+ * Represents a formatted data object after processing the getData response.
+ *
+ * @typedef {Object} FormattedData
+ * @property {number} load - The processed load value.
+ * @property {number} year - The year of the data point.
+ * @property {number} month - The month of the data point.
+ * @property {number} day - The day of the data point.
+ * @property {number} hour - The hour of the data point (in this case, always 0).
+ * @property {number} minute - The minute of the data point (in this case, always 0).
+ * @property {string} type - The type of the data point.
+ */
+
+/**
+ * Formats and processes data retrieved from the getData response.
+ *
+ * @param {GetDataResponse} response - The data response to be formatted.
+ *
+ * @throws {Error} - Throws an error with an error code in case of data processing failure.
+ * @returns {Array<FormattedData>} - An array of formatted data objects.
+ */
 function format(response) {
   log('info', 'origin response size is: ' + response.resultatRetour.length)
   // Store first value as reference for index processing
@@ -353,98 +415,3 @@ function format(response) {
     throw error
   }
 }
-
-/**
- * Save data in the right doctype db and prevent duplicated keys
- */
-async function storeData(data, doctype, filterKeys) {
-  log('debug', 'Store into ' + doctype)
-  log('debug', 'Store into keys : ' + filterKeys)
-  const filteredDocuments = await hydrateAndFilter(data, doctype, {
-    keys: filterKeys,
-  })
-  return await addData(filteredDocuments, doctype)
-}
-
-/**
- * Format an entry for DB storage
- * using key and value
- * For year doctype: key = 'YYYY'
- * For month doctype: key = 'YYYY-MM'
- */
-async function buildDataFromKey(doctype, key, value) {
-  let year, month, day, hour
-  if (doctype === 'com.grandlyon.egl.year') {
-    year = key
-    month = 1
-    day = 0
-    hour = 0
-  } else if (doctype === 'com.grandlyon.egl.month') {
-    const split = key.split('-')
-    year = split[0]
-    month = split[1]
-    day = 0
-    hour = 0
-  } else {
-    const split = key.split('-')
-    year = split[0]
-    month = split[1]
-    day = split[2]
-    hour = split[3]
-  }
-  return {
-    load: Math.round(value * 10000) / 10000,
-    year: parseInt(year),
-    month: parseInt(month),
-    day: parseInt(day),
-    hour: parseInt(hour),
-    minute: 0,
-  }
-}
-
-/**
- * Function handling special case.
- * The temporary aggregated data need to be remove in order for the most recent one te be saved.
- * ex for com.grandlyon.egl.month :
- * { load: 76.712, month: 2020, ... } need to be replace by
- * { load: 82.212, month: 2020, ... } after egl data reprocess
- */
-async function resetInProgressAggregatedData(data, doctype) {
-  // /!\ Warning: cannot use mongo queries because not supported for dev by cozy-konnectors-libs
-  log('debug', 'Remove aggregated data for ' + doctype)
-  const result = await cozyClient.data.findAll(doctype)
-  if (result && result.length > 0) {
-    // Filter data to remove
-    let filtered = []
-    if (doctype === 'com.grandlyon.egl.year') {
-      // Yearly case
-      filtered = result.filter(function(el) {
-        return el.year == data.year
-      })
-    } else if (doctype === 'com.grandlyon.egl.month') {
-      // Monthly case
-      filtered = result.filter(function(el) {
-        return el.year == data.year && el.month == data.month
-      })
-    } else {
-      // Hourly case
-      filtered = result.filter(function(el) {
-        return (
-          el.year == data.year &&
-          el.month == data.month &&
-          el.day == data.day &&
-          el.hour == data.hour
-        )
-      })
-    }
-    // Remove data
-    let sum = 0.0
-    for (const doc of filtered) {
-      sum += doc.load
-      log('debug', 'Removing this entry for ' + doc.load)
-      await cozyClient.data.delete(doctype, doc)
-    }
-    return sum
-  }
-  return 0.0
-}