From cb51ec048504e47a6102c32d827ee0208e8a241e Mon Sep 17 00:00:00 2001
From: Yoan Vallet <yoan.vallet@gmail.com>
Date: Sun, 15 Nov 2020 18:29:25 +0100
Subject: [PATCH] feat: tests for query runner

---
 src/models/dataload.model.ts                 |  13 +
 src/services/__mocks__/enedisDayData.json    |  50 ++++
 src/services/__mocks__/enedisMinuteData.json |  74 ++++++
 src/services/queryRunner.service.spec.ts     | 257 +++++++++++++++----
 src/services/queryRunner.service.ts          | 248 +++++++++---------
 5 files changed, 464 insertions(+), 178 deletions(-)
 create mode 100644 src/services/__mocks__/enedisDayData.json
 create mode 100644 src/services/__mocks__/enedisMinuteData.json

diff --git a/src/models/dataload.model.ts b/src/models/dataload.model.ts
index bb4be319d..06fd28408 100644
--- a/src/models/dataload.model.ts
+++ b/src/models/dataload.model.ts
@@ -5,3 +5,16 @@ export interface Dataload {
   value: number
   valueDetail?: number[] | null
 }
+
+export interface DataloadEntity {
+  id: string
+  _id?: string
+  _type?: string
+  _rev?: string
+  day: number
+  hour: number
+  load: number
+  minute: number
+  month: number
+  year: number
+}
diff --git a/src/services/__mocks__/enedisDayData.json b/src/services/__mocks__/enedisDayData.json
new file mode 100644
index 000000000..fa0395bbc
--- /dev/null
+++ b/src/services/__mocks__/enedisDayData.json
@@ -0,0 +1,50 @@
+[
+  {
+    "id": "bf1ce3a5774e140056714c4c200c093e",
+    "_id": "bf1ce3a5774e140056714c4c200c093e",
+    "_type": "com.grandlyon.enedis.day",
+    "_rev": "1-4fe971dff073a3c3c6cc12a0246e642e",
+    "day": 1,
+    "hour": 0,
+    "load": 25.25,
+    "minute": 0,
+    "month": 11,
+    "year": 2020
+  },
+  {
+    "id": "cf7dc6f44a19b354f99b01ba1a0b4840",
+    "_id": "cf7dc6f44a19b354f99b01ba1a0b4840",
+    "_type": "com.grandlyon.enedis.day",
+    "_rev": "1-4fe971dff073a3c3c6cc12a0246e642e",
+    "day": 2,
+    "hour": 0,
+    "load": 20.5,
+    "minute": 0,
+    "month": 11,
+    "year": 2020
+  },
+  {
+    "id": "cf7dc6f44a19b354f99b01ba1a0b4840",
+    "_id": "cf7dc6f44a19b354f99b01ba1a0b4840",
+    "_type": "com.grandlyon.enedis.day",
+    "_rev": "1-4fe971dff073a3c3c6cc12a0246e642e",
+    "day": 3,
+    "hour": 0,
+    "load": 30.33,
+    "minute": 0,
+    "month": 11,
+    "year": 2020
+  },
+  {
+    "id": "cf7dc6f44a19b354f99b01ba1a0b4840",
+    "_id": "cf7dc6f44a19b354f99b01ba1a0b4840",
+    "_type": "com.grandlyon.enedis.day",
+    "_rev": "1-4fe971dff073a3c3c6cc12a0246e642e",
+    "day": 4,
+    "hour": 0,
+    "load": 1.22,
+    "minute": 0,
+    "month": 11,
+    "year": 2020
+  }
+]
diff --git a/src/services/__mocks__/enedisMinuteData.json b/src/services/__mocks__/enedisMinuteData.json
new file mode 100644
index 000000000..65e093d9c
--- /dev/null
+++ b/src/services/__mocks__/enedisMinuteData.json
@@ -0,0 +1,74 @@
+[
+  {
+    "id": "bf1ce3a5774e140056714c4c200c093e",
+    "_id": "bf1ce3a5774e140056714c4c200c093e",
+    "_type": "com.grandlyon.enedis.minute",
+    "_rev": "1-4fe971dff073a3c3c6cc12a0246e642e",
+    "day": 1,
+    "hour": 23,
+    "load": 2.25,
+    "minute": 30,
+    "month": 11,
+    "year": 2020
+  },
+  {
+    "id": "cf7dc6f44a19b354f99b01ba1a0b4840",
+    "_id": "cf7dc6f44a19b354f99b01ba1a0b4840",
+    "_type": "com.grandlyon.enedis.minute",
+    "_rev": "1-4fe971dff073a3c3c6cc12a0246e642e",
+    "day": 2,
+    "hour": 0,
+    "load": 4.5,
+    "minute": 0,
+    "month": 11,
+    "year": 2020
+  },
+  {
+    "id": "cf7dc6f44a19b354f99b01ba1a0b4840",
+    "_id": "cf7dc6f44a19b354f99b01ba1a0b4840",
+    "_type": "com.grandlyon.enedis.minute",
+    "_rev": "1-4fe971dff073a3c3c6cc12a0246e642e",
+    "day": 2,
+    "hour": 0,
+    "load": 1.33,
+    "minute": 30,
+    "month": 11,
+    "year": 2020
+  },
+  {
+    "id": "cf7dc6f44a19b354f99b01ba1a0b4840",
+    "_id": "cf7dc6f44a19b354f99b01ba1a0b4840",
+    "_type": "com.grandlyon.enedis.minute",
+    "_rev": "1-4fe971dff073a3c3c6cc12a0246e642e",
+    "day": 2,
+    "hour": 1,
+    "load": 3.22,
+    "minute": 0,
+    "month": 11,
+    "year": 2020
+  },
+  {
+    "id": "cf7dc6f44a19b354f99b01ba1a0b4840",
+    "_id": "cf7dc6f44a19b354f99b01ba1a0b4840",
+    "_type": "com.grandlyon.enedis.minute",
+    "_rev": "1-4fe971dff073a3c3c6cc12a0246e642e",
+    "day": 2,
+    "hour": 1,
+    "load": 7.82,
+    "minute": 30,
+    "month": 11,
+    "year": 2020
+  },
+  {
+    "id": "cf7dc6f44a19b354f99b01ba1a0b4840",
+    "_id": "cf7dc6f44a19b354f99b01ba1a0b4840",
+    "_type": "com.grandlyon.enedis.minute",
+    "_rev": "1-4fe971dff073a3c3c6cc12a0246e642e",
+    "day": 2,
+    "hour": 2,
+    "load": 1.23,
+    "minute": 0,
+    "month": 11,
+    "year": 2020
+  }
+]
diff --git a/src/services/queryRunner.service.spec.ts b/src/services/queryRunner.service.spec.ts
index 0f7792930..28cf73a4f 100644
--- a/src/services/queryRunner.service.spec.ts
+++ b/src/services/queryRunner.service.spec.ts
@@ -1,88 +1,239 @@
+import { QueryResult } from 'cozy-client'
+import { FluidType } from 'enum/fluid.enum'
 import { TimeStep } from 'enum/timeStep.enum'
 import { DateTime } from 'luxon'
+import { DataloadEntity } from 'models'
 import QueryRunner from './queryRunner.service'
 import mockClient from './__mocks__/client'
-
-const mockTimePeriod = {
-  startDate: DateTime.fromISO('2020-11-01T00:00:00.000+01:00'),
-  endDate: DateTime.fromISO('2020-11-30T23:59:59.999+01:00'),
-}
-
-const queryResult = {
-  data: [
-    {
-      id: 'bf1ce3a5774e140056714c4c200c093e',
-      _id: 'bf1ce3a5774e140056714c4c200c093e',
-      _type: 'com.grandlyon.egl.day',
-      _rev: '1-4fe971dff073a3c3c6cc12a0246e642e',
-      day: 1,
-      hour: 0,
-      load: 257.25,
-      minute: 0,
-      month: 11,
-      year: 2020,
-    },
-    {
-      id: 'cf7dc6f44a19b354f99b01ba1a0b4840',
-      _id: 'cf7dc6f44a19b354f99b01ba1a0b4840',
-      _type: 'com.grandlyon.egl.day',
-      _rev: '1-4fe971dff073a3c3c6cc12a0246e642e',
-      day: 1,
-      hour: 0,
-      load: 257.25,
-      minute: 0,
-      month: 11,
-      year: 2020,
-    },
-  ],
-  next: false,
-  skip: 0,
-  bookmark:
-    'g2wAAAACaAJkAA5zdGFydGtleV9kb2NpZG0AAAAgY2Y3ZGM2ZjQ0YTE5YjM1NGY5OWIwMWJhMWEwYjI3ZjhoAmQACHN0YXJ0a2V5bAAAAANiAAAH5GELYQRqag',
-}
+import enedisDayData from './__mocks__/enedisDayData.json'
+import enedisMinuteData from './__mocks__/enedisMinuteData.json'
 
 describe('queryRunner service', () => {
   const queryRunner = new QueryRunner(mockClient)
-  const fluidType = 0
-  describe('fetchFluidData', () => {
+
+  describe('fetchFluidData method', () => {
+    const mockTimePeriod = {
+      startDate: DateTime.fromISO('2020-11-01T00:00:00.000+01:00'),
+      endDate: DateTime.fromISO('2020-11-30T23:59:59.999+01:00'),
+    }
     const expectedResult = [
       {
         date: DateTime.fromISO('2020-11-01T00:00:00.000+01:00'),
-        value: 257.25,
+        value: 25.25,
       },
       {
-        date: DateTime.fromISO('2020-11-01T00:00:00.000+01:00'),
-        value: 257.25,
+        date: DateTime.fromISO('2020-11-02T00:00:00.000+01:00'),
+        value: 20.5,
+      },
+      {
+        date: DateTime.fromISO('2020-11-03T00:00:00.000+01:00'),
+        value: 30.33,
+      },
+      {
+        date: DateTime.fromISO('2020-11-04T00:00:00.000+01:00'),
+        value: 1.22,
       },
     ]
-    it('should return the data of the selected Fluid', async () => {
-      mockClient.query.mockImplementation(() => Promise.resolve(queryResult))
 
+    it('should return the data of the selected Fluid', async () => {
+      const mockQueryResult: QueryResult<DataloadEntity[]> = {
+        data: enedisDayData,
+        bookmark: '',
+        next: false,
+        skip: 0,
+      }
+      mockClient.query.mockResolvedValue(mockQueryResult)
       const result = await queryRunner.fetchFluidData(
         mockTimePeriod,
         TimeStep.DAY,
-        fluidType
+        FluidType.ELECTRICITY
       )
       expect(result).toEqual(expectedResult)
     })
-    it('should return null', async () => {
-      mockClient.query.mockImplementationOnce(() => Promise.resolve(null))
+
+    it('should return null when fetch data failed', async () => {
+      mockClient.query.mockRejectedValue(new Error())
       const result = await queryRunner.fetchFluidData(
         mockTimePeriod,
         TimeStep.DAY,
-        fluidType
+        FluidType.ELECTRICITY
       )
       expect(result).toBeNull()
     })
-  })
-  describe('fetchFluidMaxData', () => {
-    it('should return the max data of the selected Fluid', async () => {
+
+    it('should return null when unknown fluid type', async () => {
+      const result = await queryRunner.fetchFluidData(
+        mockTimePeriod,
+        TimeStep.DAY,
+        99
+      )
+      expect(result).toBeNull()
+    })
+
+    it('should return null when unknown time step', async () => {
       const result = await queryRunner.fetchFluidData(
+        mockTimePeriod,
+        99,
+        FluidType.ELECTRICITY
+      )
+      expect(result).toBeNull()
+    })
+  })
+
+  describe('fetchFluidMaxData method', () => {
+    it('should return the max load for elec fluid with day timestep', async () => {
+      const mockTimePeriod = {
+        startDate: DateTime.fromISO('2020-11-01T00:00:00.000+01:00'),
+        endDate: DateTime.fromISO('2020-11-30T23:59:59.999+01:00'),
+      }
+      const mockQueryResult: QueryResult<DataloadEntity[]> = {
+        data: enedisDayData.sort((a, b) => b.load - a.load),
+        bookmark: '',
+        next: false,
+        skip: 0,
+      }
+      mockClient.query.mockResolvedValue(mockQueryResult)
+      const result = await queryRunner.fetchFluidMaxData(
+        mockTimePeriod,
+        TimeStep.DAY,
+        FluidType.ELECTRICITY
+      )
+      expect(result).toBe(30.33)
+    })
+
+    it('should return the max load for elec fluid with half an hour timestep', async () => {
+      const mockTimePeriod = {
+        startDate: DateTime.fromISO('2020-11-02T00:00:00.000+01:00'),
+        endDate: DateTime.fromISO('2020-11-2T23:59:59.999+01:00'),
+      }
+      const mockQueryResult: QueryResult<DataloadEntity[]> = {
+        data: [enedisMinuteData[4]],
+        bookmark: '',
+        next: false,
+        skip: 0,
+      }
+      const mockQueryResult2: QueryResult<DataloadEntity[]> = {
+        data: [enedisMinuteData[0]],
+        bookmark: '',
+        next: false,
+        skip: 0,
+      }
+      mockClient.query
+        .mockResolvedValueOnce(mockQueryResult)
+        .mockResolvedValueOnce(mockQueryResult2)
+      const result = await queryRunner.fetchFluidMaxData(
+        mockTimePeriod,
+        TimeStep.HALF_AN_HOUR,
+        FluidType.ELECTRICITY
+      )
+      expect(result).toBe(7.82)
+    })
+
+    it('should return null when fetch data failed', async () => {
+      const mockTimePeriod = {
+        startDate: DateTime.fromISO('2020-11-01T00:00:00.000+01:00'),
+        endDate: DateTime.fromISO('2020-11-30T23:59:59.999+01:00'),
+      }
+      mockClient.query.mockRejectedValue(new Error())
+      const result = await queryRunner.fetchFluidMaxData(
         mockTimePeriod,
         TimeStep.DAY,
-        fluidType
+        FluidType.ELECTRICITY
       )
       expect(result).toBeNull()
     })
+
+    it('should return null when unknown fluid type', async () => {
+      const mockTimePeriod = {
+        startDate: DateTime.fromISO('2020-11-01T00:00:00.000+01:00'),
+        endDate: DateTime.fromISO('2020-11-30T23:59:59.999+01:00'),
+      }
+      const result = await queryRunner.fetchFluidMaxData(
+        mockTimePeriod,
+        TimeStep.DAY,
+        99
+      )
+      expect(result).toBeNull()
+    })
+
+    it('should return null when unknown time step', async () => {
+      const mockTimePeriod = {
+        startDate: DateTime.fromISO('2020-11-01T00:00:00.000+01:00'),
+        endDate: DateTime.fromISO('2020-11-30T23:59:59.999+01:00'),
+      }
+      const result = await queryRunner.fetchFluidMaxData(
+        mockTimePeriod,
+        99,
+        FluidType.ELECTRICITY
+      )
+      expect(result).toBeNull()
+    })
+  })
+
+  describe('getLastDateData method', () => {
+    it('should return the last load for elec fluid', async () => {
+      const lastMockData = [...enedisDayData]
+      lastMockData.sort(
+        (a, b) =>
+          (b.year - a.year) * 100 + (b.month - a.month) * 10 + (b.day - a.day)
+      )
+      const mockQueryResult: QueryResult<DataloadEntity[]> = {
+        data: [lastMockData[0]],
+        bookmark: '',
+        next: false,
+        skip: 0,
+      }
+      mockClient.query.mockResolvedValue(mockQueryResult)
+      const result = await queryRunner.getLastDateData(FluidType.ELECTRICITY)
+      expect(result).toEqual(
+        DateTime.local(
+          enedisDayData[3].year,
+          enedisDayData[3].month,
+          enedisDayData[3].day
+        )
+      )
+    })
+
+    it('should return null when fetch data failed', async () => {
+      mockClient.query.mockRejectedValue(new Error())
+      const result = await queryRunner.getLastDateData(FluidType.ELECTRICITY)
+      expect(result).toBeNull()
+    })
+  })
+
+  describe('getEntries method', () => {
+    it('should return query result for elec fluid with day timestep', async () => {
+      const mockQueryResult: QueryResult<DataloadEntity[]> = {
+        data: enedisDayData,
+        bookmark: '',
+        next: false,
+        skip: 0,
+      }
+      mockClient.query.mockResolvedValue(mockQueryResult)
+      const result = await queryRunner.getEntries(
+        FluidType.ELECTRICITY,
+        TimeStep.DAY
+      )
+      expect(result).toEqual(mockQueryResult)
+    })
+
+    it('should return null when fetch data failed', async () => {
+      mockClient.query.mockRejectedValue(new Error())
+      const result = await queryRunner.getEntries(
+        FluidType.ELECTRICITY,
+        TimeStep.DAY
+      )
+      expect(result).toBeNull()
+    })
+
+    it('should return null when unknown fluid type', async () => {
+      const result = await queryRunner.getEntries(99, TimeStep.DAY)
+      expect(result).toBeNull()
+    })
+
+    it('should return null when unknown time step', async () => {
+      const result = await queryRunner.getEntries(FluidType.ELECTRICITY, 99)
+      expect(result).toBeNull()
+    })
   })
 })
diff --git a/src/services/queryRunner.service.ts b/src/services/queryRunner.service.ts
index 051d2fec1..f4a4e9b30 100644
--- a/src/services/queryRunner.service.ts
+++ b/src/services/queryRunner.service.ts
@@ -62,103 +62,54 @@ export default class QueryRunner {
     this._client = _client
   }
 
-  public async fetchFluidData(
-    timePeriod: TimePeriod,
+  private buildListQuery(
     timeStep: TimeStep,
-    fluidType: FluidType
-  ): Promise<Dataload[] | null> {
-    const result = await this.fetchData(
-      this.buildListQuery(timeStep, timePeriod, fluidType, this._max_limit)
-    )
-    if (result && result.data) {
-      const filteredResult = this.filterDataList(result, timePeriod)
-      const mappedResult = this.mapDataList(filteredResult)
-
-      return mappedResult
-    }
+    timePeriod: TimePeriod,
+    fluidType: FluidType,
+    limit: number
+  ) {
+    const doctype = this.getRelevantDoctype(fluidType, timeStep)
 
-    return null
+    return Q(doctype)
+      .where(this.getPredicate(timePeriod, timeStep))
+      .limitBy(limit)
   }
 
-  public async fetchFluidMaxData(
-    maxTimePeriod: TimePeriod,
+  private buildMaxQuery(
     timeStep: TimeStep,
-    fluidType: FluidType
-  ): Promise<number | null> {
-    const result = await this.fetchData(
-      this.buildMaxQuery(timeStep, maxTimePeriod, fluidType, this._max_limit)
-    )
+    maxTimePeriod: TimePeriod,
+    fluidType: FluidType,
+    limit: number
+  ) {
+    const doctype = this.getRelevantDoctype(fluidType, timeStep)
     if (timeStep === TimeStep.HALF_AN_HOUR) {
-      const lastDayOfPreviousMonth = {
-        startDate: maxTimePeriod.startDate.plus({ day: -1 }),
-        endDate: maxTimePeriod.startDate.plus({ day: -1 }).endOf('days'),
-      }
-      const lastDayOfPreviousMonthResult = await this.fetchData(
-        this.buildMaxQuery(
-          timeStep,
-          lastDayOfPreviousMonth,
-          fluidType,
-          this._max_limit
-        )
-      )
-      return Math.max(
-        lastDayOfPreviousMonthResult.data[0]
-          ? lastDayOfPreviousMonthResult.data[0].load
-          : 0,
-        result.data[0] ? result.data[0].load : 0
-      )
-    }
-
-    if (result && result.data) {
-      const filteredResult = this.filterDataList(result, maxTimePeriod)
-      const mappedResult = this.mapDataList(filteredResult)
-      return mappedResult && mappedResult[0] && mappedResult[0].value
+      return Q(doctype)
+        .where(this.getPredicate(maxTimePeriod, TimeStep.HALF_AN_HOUR))
+        .limitBy(1)
+        .sortBy([{ load: 'desc' }])
     }
-    return null
+    return Q(doctype)
+      .where(this.getPredicate(maxTimePeriod, timeStep))
+      .limitBy(limit)
+      .sortBy([{ load: 'desc' }])
   }
 
-  public async getLastDateData(fluidType: FluidType): Promise<DateTime | null> {
-    const result = await this.fetchData(this.buildLastDateQuery(fluidType, 1))
-
-    if (
-      result &&
-      result.data &&
-      result.data[0] &&
-      result.data[0].year &&
-      result.data[0].month &&
-      result.data[0].day
-    ) {
-      return DateTime.local(
-        result.data[0].year,
-        result.data[0].month,
-        result.data[0].day
-      )
-    }
-
-    return null
+  private buildLastDateQuery(fluidType: FluidType, limit: number) {
+    const doctype = this.getRelevantDoctype(fluidType, TimeStep.DAY)
+    return Q(doctype)
+      .where({})
+      .indexFields(['year', 'month', 'day'])
+      .sortBy([{ year: 'desc' }, { month: 'desc' }, { day: 'desc' }])
+      .limitBy(limit)
   }
 
   private async fetchData(query: QueryDefinition) {
     let result = null
     try {
       result = await this._client.query(query)
-      console.log(result)
     } catch (error) {
       // log stuff
-      //throw new Error("Cozy Cient Error");
-
-      return null
-    }
-    return result
-  }
-
-  public async getEntries(fluidType: FluidType, timeStep: TimeStep) {
-    let result = null
-    const doctype = this.getRelevantDoctype(fluidType, timeStep)
-    try {
-      result = await this._client.query(this._client.find(doctype).where({}))
-    } catch (error) {
-      return null
+      // throw new Error('Fetch data failed in query runner')
     }
     return result
   }
@@ -193,40 +144,6 @@ export default class QueryRunner {
     return mappedResult
   }
 
-  private buildListQuery(
-    timeStep: TimeStep,
-    timePeriod: TimePeriod,
-    fluidType: FluidType,
-    limit: number
-  ) {
-    const doctype = this.getRelevantDoctype(fluidType, timeStep)
-
-    return Q(doctype)
-      .where(this.getPredicate(timePeriod, timeStep))
-      .limitBy(limit)
-  }
-
-  private buildMaxQuery(
-    timeStep: TimeStep,
-    maxTimePeriod: TimePeriod,
-    fluidType: FluidType,
-    limit: number
-  ) {
-    const doctype = this.getRelevantDoctype(fluidType, timeStep)
-    if (timeStep === TimeStep.HALF_AN_HOUR) {
-      return this._client
-        .find(doctype)
-        .where(this.getPredicate(maxTimePeriod, 20))
-        .limitBy(1)
-        .sortBy([{ load: 'desc' }])
-    }
-    return this._client
-      .find(doctype)
-      .where(this.getPredicate(maxTimePeriod, timeStep))
-      .limitBy(limit)
-      .sortBy([{ load: 'desc' }])
-  }
-
   private withinDateBoundaries(dateTime: DateTime, timePeriod: TimePeriod) {
     return dateTime <= timePeriod.endDate && dateTime >= timePeriod.startDate
   }
@@ -273,17 +190,6 @@ export default class QueryRunner {
     return dayList
   }
 
-  private buildLastDateQuery(fluidType: FluidType, limit: number) {
-    const doctype = this.getRelevantDoctype(fluidType, TimeStep.DAY)
-
-    return this._client
-      .find(doctype)
-      .where({})
-      .indexFields(['year', 'month', 'day'])
-      .sortBy([{ year: 'desc' }, { month: 'desc' }, { day: 'desc' }])
-      .limitBy(limit)
-  }
-
   private getPredicate(timePeriod: TimePeriod, timeStep: TimeStep) {
     let predicate = {}
 
@@ -409,4 +315,96 @@ export default class QueryRunner {
 
     return doctype
   }
+
+  public async fetchFluidData(
+    timePeriod: TimePeriod,
+    timeStep: TimeStep,
+    fluidType: FluidType
+  ): Promise<Dataload[] | null> {
+    const query: QueryDefinition = this.buildListQuery(
+      timeStep,
+      timePeriod,
+      fluidType,
+      this._max_limit
+    )
+    const result = await this.fetchData(query)
+    if (result && result.data) {
+      const filteredResult = this.filterDataList(result, timePeriod)
+      const mappedResult = this.mapDataList(filteredResult)
+      return mappedResult
+    }
+    return null
+  }
+
+  public async fetchFluidMaxData(
+    maxTimePeriod: TimePeriod,
+    timeStep: TimeStep,
+    fluidType: FluidType
+  ): Promise<number | null> {
+    const query: QueryDefinition = this.buildMaxQuery(
+      timeStep,
+      maxTimePeriod,
+      fluidType,
+      this._max_limit
+    )
+    const result = await this.fetchData(query)
+    if (timeStep === TimeStep.HALF_AN_HOUR) {
+      const lastDayOfPreviousMonth = {
+        startDate: maxTimePeriod.startDate.plus({ day: -1 }),
+        endDate: maxTimePeriod.startDate.plus({ day: -1 }).endOf('days'),
+      }
+      const lastDayOfPreviousMonthQuery: QueryDefinition = this.buildMaxQuery(
+        timeStep,
+        lastDayOfPreviousMonth,
+        fluidType,
+        this._max_limit
+      )
+      const lastDayOfPreviousMonthResult = await this.fetchData(
+        lastDayOfPreviousMonthQuery
+      )
+      return Math.max(
+        lastDayOfPreviousMonthResult && lastDayOfPreviousMonthResult.data[0]
+          ? lastDayOfPreviousMonthResult.data[0].load
+          : 0,
+        result && result.data[0] ? result.data[0].load : 0
+      )
+    }
+    if (result && result.data) {
+      const filteredResult = this.filterDataList(result, maxTimePeriod)
+      const mappedResult = this.mapDataList(filteredResult)
+      return mappedResult && mappedResult[0] && mappedResult[0].value
+    }
+    return null
+  }
+
+  public async getLastDateData(fluidType: FluidType): Promise<DateTime | null> {
+    const query: QueryDefinition = this.buildLastDateQuery(fluidType, 1)
+    const result = await this.fetchData(query)
+    if (
+      result &&
+      result.data &&
+      result.data[0] &&
+      result.data[0].year &&
+      result.data[0].month &&
+      result.data[0].day
+    ) {
+      return DateTime.local(
+        result.data[0].year,
+        result.data[0].month,
+        result.data[0].day
+      )
+    }
+    return null
+  }
+
+  public async getEntries(fluidType: FluidType, timeStep: TimeStep) {
+    const doctype = this.getRelevantDoctype(fluidType, timeStep)
+    try {
+      const query = Q(doctype).where({})
+      const result = await this._client.query(query)
+      return result
+    } catch (error) {
+      return null
+    }
+  }
 }
-- 
GitLab