From f02c8a968b74b5540d06a0b0766f1d7325e7bf34 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20PAILHAREY?= <rpailharey@grandlyon.com>
Date: Thu, 20 Jan 2022 13:11:26 +0000
Subject: [PATCH] feat(fluidPrices): Dynamic prices for EGL fluid

---
 src/components/FAQ/FAQData.spec.tsx       |  4 +-
 src/db/fluidPrices.json                   | 60 +++++++++++++++++++++++
 src/migrations/migration.data.ts          | 21 ++++++++
 src/migrations/migration.ts               |  2 +
 src/services/fluidsPrices.service.spec.ts | 60 ++++++++++++++++++++++-
 src/services/fluidsPrices.service.ts      | 17 +++++++
 src/targets/services/fluidsPrices.ts      | 22 +++++----
 tests/__mocks__/fluidPrice.mock.ts        | 30 +++++++++---
 8 files changed, 196 insertions(+), 20 deletions(-)

diff --git a/src/components/FAQ/FAQData.spec.tsx b/src/components/FAQ/FAQData.spec.tsx
index ce8cdd348..dcdd2188d 100644
--- a/src/components/FAQ/FAQData.spec.tsx
+++ b/src/components/FAQ/FAQData.spec.tsx
@@ -1,6 +1,6 @@
 import mockClient from '../../../tests/__mocks__/client'
 import FaqData from 'components/FAQ/FAQData'
-import { allFluidPrices } from '../../../tests/__mocks__/fluidPrice.mock'
+import { allLastFluidPrices } from '../../../tests/__mocks__/fluidPrice.mock'
 import { FAQSection } from 'models'
 
 jest.mock('cozy-ui/transpiled/react/I18n', () => {
@@ -28,7 +28,7 @@ describe('FAQData', () => {
   })
 
   it('should return', async () => {
-    mockGetAllLastPrices.mockResolvedValue(allFluidPrices)
+    mockGetAllLastPrices.mockResolvedValue(allLastFluidPrices)
     const result: FAQSection[] = await FaqData(mockClient)
     expect(result.length).toBe(3)
   })
diff --git a/src/db/fluidPrices.json b/src/db/fluidPrices.json
index 2f1689af3..218978887 100644
--- a/src/db/fluidPrices.json
+++ b/src/db/fluidPrices.json
@@ -83,6 +83,66 @@
     "startDate": "2021-08-01T00:00:00.000Z",
     "endDate": null
   },
+  {
+    "fluidType": 1,
+    "price": 0.0030735,
+    "startDate": "2012-01-01T00:00:00.000Z",
+    "endDate": "2012-12-31T23:59:59.000Z"
+  },
+  {
+    "fluidType": 1,
+    "price": 0.0031483,
+    "startDate": "2013-01-01T00:00:00.000Z",
+    "endDate": "2013-12-31T23:59:59.000Z"
+  },
+  {
+    "fluidType": 1,
+    "price": 0.0031381,
+    "startDate": "2014-01-01T00:00:00.000Z",
+    "endDate": "2014-12-31T23:59:59.000Z"
+  },
+  {
+    "fluidType": 1,
+    "price": 0.00307,
+    "startDate": "2015-01-01T00:00:00.000Z",
+    "endDate": "2015-12-31T23:59:59.000Z"
+  },
+  {
+    "fluidType": 1,
+    "price": 0.0031,
+    "startDate": "2016-01-01T00:00:00.000Z",
+    "endDate": "2016-12-31T23:59:59.000Z"
+  },
+  {
+    "fluidType": 1,
+    "price": 0.00311,
+    "startDate": "2017-01-01T00:00:00.000Z",
+    "endDate": "2017-12-31T23:59:59.000Z"
+  },
+  {
+    "fluidType": 1,
+    "price": 0.00313,
+    "startDate": "2018-01-01T00:00:00.000Z",
+    "endDate": "2018-12-31T23:59:59.000Z"
+  },
+  {
+    "fluidType": 1,
+    "price": 0.00313,
+    "startDate": "2019-01-01T00:00:00.000Z",
+    "endDate": "2019-12-31T23:59:59.000Z"
+  },
+  {
+    "fluidType": 1,
+    "price": 0.00315,
+    "startDate": "2020-01-01T00:00:00.000Z",
+    "endDate": "2020-12-31T23:59:59.000Z"
+  },
+  {
+    "fluidType": 1,
+    "price": 0.00319,
+    "startDate": "2021-01-01T00:00:00.000Z",
+    "endDate": null
+  },
   {
     "fluidType": 2,
     "price": 0.0919,
diff --git a/src/migrations/migration.data.ts b/src/migrations/migration.data.ts
index 094b30109..b2ce44182 100644
--- a/src/migrations/migration.data.ts
+++ b/src/migrations/migration.data.ts
@@ -19,6 +19,7 @@ import { Client } from 'cozy-client'
 import { DateTime } from 'luxon'
 import { UserQuizState } from 'enum/userQuiz.enum'
 import fluidsPricesData from 'db/fluidPrices.json'
+import { FluidType } from 'enum/fluid.enum'
 
 export const SCHEMA_INITIAL_VERSION = 0
 
@@ -485,4 +486,24 @@ export const migrations: Migration[] = [
       })
     },
   },
+  {
+    baseSchemaVersion: 17,
+    targetSchemaVersion: 18,
+    appVersion: '1.7.0',
+    description: 'Init new fluidPrices for water',
+    releaseNotes: null,
+    docTypes: FLUIDPRICES_DOCTYPE,
+
+    run: async (_client: Client, docs: any[]): Promise<any> => {
+      const waterPricesData = fluidsPricesData.filter(fluidPriceData => {
+        return fluidPriceData.fluidType === FluidType.WATER
+      })
+      const createWaterPricesData = waterPricesData.map(waterPriceData => {
+        waterPriceData.createAction = true
+        waterPriceData.doctype = FLUIDPRICES_DOCTYPE
+        return waterPriceData
+      })
+      return createWaterPricesData
+    },
+  },
 ]
diff --git a/src/migrations/migration.ts b/src/migrations/migration.ts
index fa9c222a1..11acfabad 100644
--- a/src/migrations/migration.ts
+++ b/src/migrations/migration.ts
@@ -87,6 +87,8 @@ async function save(_client: Client, docs: any[]): Promise<MigrationResult> {
     docs.forEach(async doc => {
       if (doc.deleteAction) {
         await _client.destroy(doc)
+      } else if (doc.createAction) {
+        await _client.create(doc.doctype, doc)
       } else {
         await _client.save(doc)
       }
diff --git a/src/services/fluidsPrices.service.spec.ts b/src/services/fluidsPrices.service.spec.ts
index a146ffba2..c3a9fe500 100644
--- a/src/services/fluidsPrices.service.spec.ts
+++ b/src/services/fluidsPrices.service.spec.ts
@@ -2,7 +2,10 @@ import FluidPricesService from './fluidsPrices.service'
 import mockClient from '../../tests/__mocks__/client'
 import { QueryResult } from 'cozy-client'
 import { FluidPrice } from 'models'
-import { fluidPrices } from '../../tests/__mocks__/fluidPrice.mock'
+import {
+  fluidPrices,
+  allLastFluidPrices,
+} from '../../tests/__mocks__/fluidPrice.mock'
 import { FluidType } from 'enum/fluid.enum'
 import { DateTime } from 'luxon'
 
@@ -60,4 +63,59 @@ describe('FluidPrices service', () => {
       expect(mockClient.query).toBeCalled()
     })
   })
+
+  describe('Fluid Prices - getAllLastPrices', () => {
+    it('should getAllLastPrice', async () => {
+      const mockQueryResult: QueryResult<FluidPrice[]> = {
+        data: fluidPrices,
+        bookmark: '',
+        next: false,
+        skip: 0,
+      }
+      mockClient.query.mockResolvedValueOnce(mockQueryResult)
+      const prices = await fluidPricesService.getAllLastPrices()
+      console.log('Prix reçus :', prices)
+      console.log('Prix attendus :', allLastFluidPrices)
+      expect(prices).toStrictEqual(allLastFluidPrices)
+      expect(mockClient.query).toBeCalled()
+    })
+  })
+
+  describe('Fluid Prices - deleteAllFluidsPrices', () => {
+    it('should return true when fluidsPrices stored', async () => {
+      const mockQueryResult: QueryResult<FluidPrice[]> = {
+        data: fluidPrices,
+        bookmark: '',
+        next: false,
+        skip: 0,
+      }
+      mockClient.query.mockResolvedValueOnce(mockQueryResult)
+      const result = await fluidPricesService.deleteAllFluidsPrices()
+      expect(mockClient.destroy).toBeCalledTimes(6)
+      expect(result).toBe(true)
+    })
+    it('should return true when no fluidsPrices stored', async () => {
+      const mockQueryResult: QueryResult<FluidPrice[]> = {
+        data: [],
+        bookmark: '',
+        next: false,
+        skip: 0,
+      }
+      mockClient.query.mockResolvedValueOnce(mockQueryResult)
+      const result = await fluidPricesService.deleteAllFluidsPrices()
+      expect(result).toBe(true)
+    })
+    it('should return false when error happened on deletion', async () => {
+      const mockQueryResult: QueryResult<FluidPrice[]> = {
+        data: fluidPrices,
+        bookmark: '',
+        next: false,
+        skip: 0,
+      }
+      mockClient.destroy.mockRejectedValue(new Error())
+      mockClient.query.mockResolvedValueOnce(mockQueryResult)
+      const result = await fluidPricesService.deleteAllFluidsPrices()
+      expect(result).toBe(false)
+    })
+  })
 })
diff --git a/src/services/fluidsPrices.service.ts b/src/services/fluidsPrices.service.ts
index 8e131cdfa..2304a2f51 100644
--- a/src/services/fluidsPrices.service.ts
+++ b/src/services/fluidsPrices.service.ts
@@ -85,4 +85,21 @@ export default class FluidPricesService {
 
     return fluidsPrices
   }
+
+  /**
+   * Delete all fluidPrices entities from the db
+   * @returns {boolean} - true when deleted with success
+   * @throws {Error}
+   */
+  public async deleteAllFluidsPrices(): Promise<boolean> {
+    const fluidsPrices = await this.getAllPrices()
+    try {
+      for (let index = 0; index < fluidsPrices.length; index++) {
+        await this._client.destroy(fluidsPrices[index])
+      }
+      return true
+    } catch (error) {
+      return false
+    }
+  }
 }
diff --git a/src/targets/services/fluidsPrices.ts b/src/targets/services/fluidsPrices.ts
index d658871d4..32a9e11d1 100644
--- a/src/targets/services/fluidsPrices.ts
+++ b/src/targets/services/fluidsPrices.ts
@@ -6,11 +6,7 @@ import FluidPricesService from 'services/fluidsPrices.service'
 import { DataloadEntity, TimePeriod } from 'models'
 import ConsumptionDataManager from 'services/consumption.service'
 import { TimeStep } from 'enum/timeStep.enum'
-import {
-  ENEDIS_DAY_DOCTYPE,
-  ENEDIS_MINUTE_DOCTYPE,
-  GRDF_DAY_DOCTYPE,
-} from 'doctypes'
+import { ENEDIS_DAY_DOCTYPE, GRDF_DAY_DOCTYPE, EGL_DAY_DOCTYPE } from 'doctypes'
 import { FluidType } from 'enum/fluid.enum'
 import QueryRunner from 'services/queryRunner.service'
 const log = logger.namespace('fluidPrices')
@@ -64,7 +60,7 @@ const aggregatePrices = async (
 ) => {
   const tsa = [TimeStep.MONTH, TimeStep.YEAR]
   log('debug', `Aggregation...`)
-  const aggregartePromises = tsa.map(async ts => {
+  const aggregatePromises = tsa.map(async ts => {
     return new Promise<void>(async resolve => {
       let date: DateTime = DateTime.local()
       Object.assign(date, firstDate)
@@ -97,7 +93,7 @@ const aggregatePrices = async (
     })
   })
 
-  await Promise.all(aggregartePromises)
+  await Promise.all(aggregatePromises)
   log('debug', `Aggregation done`)
 }
 
@@ -108,6 +104,9 @@ const getDoctypeTypeByFluid = (fluidType: FluidType): string => {
   if (fluidType === FluidType.GAS) {
     return GRDF_DAY_DOCTYPE
   }
+  if (fluidType === FluidType.WATER) {
+    return EGL_DAY_DOCTYPE
+  }
   log('error', 'Unkown FluidType')
   throw new Error()
 }
@@ -116,9 +115,10 @@ const getTimeSetByFluid = (fluidType: FluidType): TimeStep[] => {
   if (fluidType === FluidType.ELECTRICITY) {
     return [TimeStep.DAY, TimeStep.HALF_AN_HOUR]
   }
-  if (fluidType === FluidType.GAS) {
+  if (fluidType === FluidType.GAS || fluidType === FluidType.WATER) {
     return [TimeStep.DAY]
   }
+
   log('error', 'Unkown FluidType')
   throw new Error()
 }
@@ -204,8 +204,12 @@ const processPrices = async ({ client }: PricesProps) => {
   log('info', `Electricity data done`)
   log('info', `Processing gas data...`)
   const gas = applyPrices(client, FluidType.GAS)
-  await Promise.all([elec, gas])
   log('info', `Gas data done`)
+  log('info', `Processing water data...`)
+  const water = applyPrices(client, FluidType.WATER)
+  log('info', `Water data done`)
+  await Promise.all([elec, gas, water])
+  log('info', `processPrices done`)
 }
 
 runService(processPrices)
diff --git a/tests/__mocks__/fluidPrice.mock.ts b/tests/__mocks__/fluidPrice.mock.ts
index ad5ebb806..63f6b6f56 100644
--- a/tests/__mocks__/fluidPrice.mock.ts
+++ b/tests/__mocks__/fluidPrice.mock.ts
@@ -17,11 +17,18 @@ export const fluidPrices: FluidPrice[] = [
   },
   {
     _id: '03045ea1afecc7a86e5443a52e00b07d',
-    endDate: '2021-10-31T23:59:59.000Z',
+    endDate: '',
     fluidType: 0,
     price: 0.1329,
     startDate: '2021-10-10T00:00:00.000Z',
   },
+  {
+    _id: '03045ea1afecc7a86e5443a52e00b07d',
+    endDate: '',
+    fluidType: 1,
+    price: 0.0039,
+    startDate: '2013-08-01T00:00:00.000Z',
+  },
   {
     _id: '03045ea1afecc7a86e5443a52e00b07d',
     endDate: '2014-10-31T23:59:59.000Z',
@@ -29,28 +36,35 @@ export const fluidPrices: FluidPrice[] = [
     price: 1.029,
     startDate: '2013-08-01T00:00:00.000Z',
   },
+  {
+    _id: '03045ea1afecc7a86e5443a52e00b07d',
+    endDate: '',
+    fluidType: 2,
+    price: 1.029,
+    startDate: '2014-11-01T00:00:00.000Z',
+  },
 ]
 
-export const allFluidPrices: FluidPrice[] = [
+export const allLastFluidPrices: FluidPrice[] = [
   {
     _id: '03045ea1afecc7a86e5443a52e00b07d',
     endDate: '',
     fluidType: 0,
-    price: 0.1429,
-    startDate: '2020-08-01T00:00:00.000Z',
+    price: 0.1329,
+    startDate: '2021-10-10T00:00:00.000Z',
   },
   {
     _id: '03045ea1afecc7a86e5443a52e00b07d',
     endDate: '',
     fluidType: 1,
-    price: 0.1529,
-    startDate: '2021-01-01T00:00:00.000Z',
+    price: 0.0039,
+    startDate: '2013-08-01T00:00:00.000Z',
   },
   {
     _id: '03045ea1afecc7a86e5443a52e00b07d',
     endDate: '',
     fluidType: 2,
-    price: 0.1329,
-    startDate: '2021-10-10T00:00:00.000Z',
+    price: 1.029,
+    startDate: '2014-11-01T00:00:00.000Z',
   },
 ]
-- 
GitLab