From c7e1a7f4675d46ce525f5172c03d7e29161ae312 Mon Sep 17 00:00:00 2001
From: Yoan VALLET <ext.sopra.yvallet@grandlyon.com>
Date: Mon, 26 Apr 2021 12:06:49 +0200
Subject: [PATCH] feat: update profile data

---
 src/db/profileData.json              |  68 +++++++------
 src/models/profile.model.ts          |  70 +++++++------
 src/services/profile.service.ts      | 144 ++++++++++++++-------------
 src/store/profile/profile.reducer.ts | 136 +++++++++++++------------
 tests/__mocks__/profile.mock.ts      |   4 +
 tests/__mocks__/store.ts             |   4 +
 6 files changed, 230 insertions(+), 196 deletions(-)

diff --git a/src/db/profileData.json b/src/db/profileData.json
index 285bc7709..f83000e5e 100644
--- a/src/db/profileData.json
+++ b/src/db/profileData.json
@@ -1,32 +1,36 @@
-[
-  {
-    "ecogestureHash": "",
-    "challengeHash": "",
-    "duelHash": "",
-    "quizHash": "",
-    "isFirstConnection": true,
-    "lastConnectionDate": "0000-01-01T00:00:00.000Z",
-    "haveSeenOldFluidModal": false,
-    "haveSeenLastAnalysis": true,
-    "sendAnalysisNotification": false,
-    "monthlyAnalysisDate": "0000-01-01T00:00:00.000Z",
-    "isProfileTypeCompleted": false,
-    "profileType": {
-      "housingType": "individual_house",
-      "constructionYear": "between_1975_and_1989",
-      "area": 100,
-      "occupantsNumber": 4,
-      "outsideFacingWalls": 2,
-      "floor": "not_applicable",
-      "heating": "individual",
-      "coldWater": "individual",
-      "hotWater": "individual",
-      "individualInsulationWork": ["window_replacement_and_wall_insulation"],
-      "facilitiesInstallation": "none",
-      "hotWaterEquipment": "solar",
-      "warmingFluid": 0,
-      "hotWaterFluid": 0,
-      "cookingFluid": 0
-    }
-  }
-]
+[
+  {
+    "ecogestureHash": "",
+    "challengeHash": "",
+    "duelHash": "",
+    "quizHash": "",
+    "isFirstConnection": true,
+    "GCUApprovalDate": null,
+    "lastConnectionDate": "0000-01-01T00:00:00.000Z",
+    "haveSeenOldFluidModal": false,
+    "haveSeenLastAnalysis": true,
+    "sendAnalysisNotification": false,
+    "monthlyAnalysisDate": "0000-01-01T00:00:00.000Z",
+    "isProfileTypeCompleted": false,
+    "profileType": {
+      "housingType": "individual_house",
+      "constructionYear": "between_1975_and_1989",
+      "area": 100,
+      "occupantsNumber": 4,
+      "outsideFacingWalls": 2,
+      "floor": "not_applicable",
+      "heating": "individual",
+      "coldWater": "individual",
+      "hotWater": "individual",
+      "individualInsulationWork": ["window_replacement_and_wall_insulation"],
+      "facilitiesInstallation": "none",
+      "hotWaterEquipment": "solar",
+      "warmingFluid": 0,
+      "hotWaterFluid": 0,
+      "cookingFluid": 0
+    },
+    "tutorial": {
+      "isWelcomeSeen": false
+    }
+  }
+]
diff --git a/src/models/profile.model.ts b/src/models/profile.model.ts
index 2e672bde8..f4dc003ed 100644
--- a/src/models/profile.model.ts
+++ b/src/models/profile.model.ts
@@ -1,29 +1,41 @@
-import { DateTime } from 'luxon'
-import { ProfileType } from './profileType.model'
-export interface ProfileEntity {
-  id: string
-  ecogestureHash: string
-  challengeHash: string
-  duelHash: string
-  quizHash: string
-  explorationHash: string
-  isFirstConnection: boolean
-  lastConnectionDate: string
-  haveSeenLastAnalysis: boolean
-  haveSeenOldFluidModal: string | boolean
-  sendAnalysisNotification: boolean
-  monthlyAnalysisDate: string
-  profileType: ProfileType
-  isProfileTypeCompleted: boolean
-  _id?: string
-  _rev?: string
-}
-export interface Profile
-  extends Omit<
-    ProfileEntity,
-    'haveSeenOldFluidModal' | 'lastConnectionDate' | 'monthlyAnalysisDate'
-  > {
-  lastConnectionDate: DateTime
-  haveSeenOldFluidModal: DateTime | boolean
-  monthlyAnalysisDate: DateTime
-}
+import { DateTime } from 'luxon'
+import { ProfileType } from './profileType.model'
+
+interface Tutorial {
+  isWelcomeSeen: boolean
+}
+
+export interface ProfileEntity {
+  id: string
+  ecogestureHash: string
+  challengeHash: string
+  duelHash: string
+  quizHash: string
+  explorationHash: string
+  isFirstConnection: boolean
+  GCUApprovalDate: string | null
+  lastConnectionDate: string
+  haveSeenLastAnalysis: boolean
+  haveSeenOldFluidModal: string | boolean
+  sendAnalysisNotification: boolean
+  monthlyAnalysisDate: string
+  profileType: ProfileType
+  isProfileTypeCompleted: boolean
+  tutorial: Tutorial
+  _id?: string
+  _rev?: string
+}
+
+export interface Profile
+  extends Omit<
+    ProfileEntity,
+    | 'GCUApprovalDate'
+    | 'haveSeenOldFluidModal'
+    | 'lastConnectionDate'
+    | 'monthlyAnalysisDate'
+  > {
+  GCUApprovalDate: DateTime | null
+  lastConnectionDate: DateTime
+  haveSeenOldFluidModal: DateTime | boolean
+  monthlyAnalysisDate: DateTime
+}
diff --git a/src/services/profile.service.ts b/src/services/profile.service.ts
index 46a43c5c2..2927967a8 100644
--- a/src/services/profile.service.ts
+++ b/src/services/profile.service.ts
@@ -1,69 +1,75 @@
-import { Client, Q, QueryDefinition, QueryResult } from 'cozy-client'
-import { Profile, ProfileEntity } from 'models'
-import { PROFILE_DOCTYPE } from 'doctypes'
-import { DateTime } from 'luxon'
-
-export default class ProfileService {
-  private readonly _client: Client
-
-  constructor(_client: Client) {
-    this._client = _client
-  }
-  /**
-   * Retrieve Profile from the ProfileEntity
-   * @param {ProfileEntity} profileEntity
-   * @returns {Profile}
-   */
-  private parseProfileEntityToProfile(profileEntity: ProfileEntity): Profile {
-    const profile: Profile = {
-      ...profileEntity,
-      haveSeenOldFluidModal:
-        typeof profileEntity.haveSeenOldFluidModal === 'string'
-          ? DateTime.fromISO(profileEntity.haveSeenOldFluidModal, {
-              zone: 'utc',
-            })
-          : profileEntity.haveSeenOldFluidModal,
-      monthlyAnalysisDate:
-        typeof profileEntity.monthlyAnalysisDate === 'string'
-          ? DateTime.fromISO(profileEntity.monthlyAnalysisDate, {
-              zone: 'utc',
-            })
-          : profileEntity.monthlyAnalysisDate,
-      lastConnectionDate: DateTime.fromISO(profileEntity.lastConnectionDate, {
-        zone: 'utc',
-      }),
-    }
-    return profile
-  }
-
-  public async getProfile(): Promise<Profile | null> {
-    const query: QueryDefinition = Q(PROFILE_DOCTYPE)
-    const {
-      data: [profile],
-    }: QueryResult<ProfileEntity[]> = await this._client.query(query.limitBy(1))
-    const profileEntity: ProfileEntity | null = profile ? profile : null
-    if (profileEntity) {
-      return this.parseProfileEntityToProfile(profileEntity)
-    }
-    return null
-  }
-
-  public async updateProfile(
-    attributes: Partial<Profile>
-  ): Promise<Profile | null> {
-    const query: QueryDefinition = Q(PROFILE_DOCTYPE)
-    const {
-      data: [doc],
-    }: QueryResult<ProfileEntity[]> = await this._client.query(query.limitBy(1))
-    const {
-      data: profileEntity,
-    }: QueryResult<ProfileEntity | null> = await this._client.save({
-      ...doc,
-      ...attributes,
-    })
-    if (profileEntity) {
-      return this.parseProfileEntityToProfile(profileEntity)
-    }
-    return null
-  }
-}
+import { Client, Q, QueryDefinition, QueryResult } from 'cozy-client'
+import { Profile, ProfileEntity } from 'models'
+import { PROFILE_DOCTYPE } from 'doctypes'
+import { DateTime } from 'luxon'
+
+export default class ProfileService {
+  private readonly _client: Client
+
+  constructor(_client: Client) {
+    this._client = _client
+  }
+  /**
+   * Retrieve Profile from the ProfileEntity
+   * @param {ProfileEntity} profileEntity
+   * @returns {Profile}
+   */
+  private parseProfileEntityToProfile(profileEntity: ProfileEntity): Profile {
+    const profile: Profile = {
+      ...profileEntity,
+      GCUApprovalDate:
+        typeof profileEntity.GCUApprovalDate === 'string'
+          ? DateTime.fromISO(profileEntity.GCUApprovalDate, {
+              zone: 'utc',
+            })
+          : profileEntity.GCUApprovalDate,
+      haveSeenOldFluidModal:
+        typeof profileEntity.haveSeenOldFluidModal === 'string'
+          ? DateTime.fromISO(profileEntity.haveSeenOldFluidModal, {
+              zone: 'utc',
+            })
+          : profileEntity.haveSeenOldFluidModal,
+      monthlyAnalysisDate:
+        typeof profileEntity.monthlyAnalysisDate === 'string'
+          ? DateTime.fromISO(profileEntity.monthlyAnalysisDate, {
+              zone: 'utc',
+            })
+          : profileEntity.monthlyAnalysisDate,
+      lastConnectionDate: DateTime.fromISO(profileEntity.lastConnectionDate, {
+        zone: 'utc',
+      }),
+    }
+    return profile
+  }
+
+  public async getProfile(): Promise<Profile | null> {
+    const query: QueryDefinition = Q(PROFILE_DOCTYPE)
+    const {
+      data: [profile],
+    }: QueryResult<ProfileEntity[]> = await this._client.query(query.limitBy(1))
+    const profileEntity: ProfileEntity | null = profile ? profile : null
+    if (profileEntity) {
+      return this.parseProfileEntityToProfile(profileEntity)
+    }
+    return null
+  }
+
+  public async updateProfile(
+    attributes: Partial<Profile>
+  ): Promise<Profile | null> {
+    const query: QueryDefinition = Q(PROFILE_DOCTYPE)
+    const {
+      data: [doc],
+    }: QueryResult<ProfileEntity[]> = await this._client.query(query.limitBy(1))
+    const {
+      data: profileEntity,
+    }: QueryResult<ProfileEntity | null> = await this._client.save({
+      ...doc,
+      ...attributes,
+    })
+    if (profileEntity) {
+      return this.parseProfileEntityToProfile(profileEntity)
+    }
+    return null
+  }
+}
diff --git a/src/store/profile/profile.reducer.ts b/src/store/profile/profile.reducer.ts
index 3f4c39056..4d8391817 100644
--- a/src/store/profile/profile.reducer.ts
+++ b/src/store/profile/profile.reducer.ts
@@ -1,66 +1,70 @@
-import { Reducer } from 'redux'
-import {
-  UPDATE_PROFILE,
-  ProfileActionTypes,
-} from 'store/profile/profile.actions'
-import { Profile } from 'models'
-import { DateTime } from 'luxon'
-import {
-  ConstructionYear,
-  Floor,
-  HotWaterEquipment,
-  HousingType,
-  IndividualOrCollective,
-  OutsideFacingWalls,
-  ThreeChoicesAnswer,
-} from 'enum/profileType.enum'
-import { FluidType } from 'enum/fluid.enum'
-
-const initialState: Profile = {
-  id: '',
-  ecogestureHash: '',
-  challengeHash: '',
-  duelHash: '',
-  quizHash: '',
-  explorationHash: '',
-  isFirstConnection: false,
-  lastConnectionDate: DateTime.fromISO('0000-01-01T00:00:00.000Z'),
-  haveSeenOldFluidModal: true,
-  haveSeenLastAnalysis: true,
-  sendAnalysisNotification: false,
-  monthlyAnalysisDate: DateTime.fromISO('0000-01-01T00:00:00.000Z'),
-  isProfileTypeCompleted: false,
-  profileType: {
-    housingType: HousingType.APPARTMENT,
-    constructionYear: ConstructionYear.AFTER_1999,
-    area: 35,
-    occupantsNumber: 1,
-    outsideFacingWalls: OutsideFacingWalls.ONE,
-    floor: Floor.INTERMEDIATE_FLOOR,
-    heating: IndividualOrCollective.COLLECTIVE,
-    coldWater: IndividualOrCollective.INDIVIDUAL,
-    hotWater: IndividualOrCollective.INDIVIDUAL,
-    individualInsulationWork: [],
-    hasInstalledVentilation: ThreeChoicesAnswer.NO,
-    hasReplacedHeater: ThreeChoicesAnswer.NO,
-    hotWaterEquipment: HotWaterEquipment.OTHER,
-    warmingFluid: FluidType.ELECTRICITY,
-    hotWaterFluid: FluidType.ELECTRICITY,
-    cookingFluid: FluidType.GAS,
-  },
-}
-
-export const profileReducer: Reducer<Profile> = (
-  state = initialState,
-  action: ProfileActionTypes
-): Profile => {
-  switch (action.type) {
-    case UPDATE_PROFILE:
-      return {
-        ...state,
-        ...action.payload,
-      }
-    default:
-      return state
-  }
-}
+import { Reducer } from 'redux'
+import {
+  UPDATE_PROFILE,
+  ProfileActionTypes,
+} from 'store/profile/profile.actions'
+import { Profile } from 'models'
+import { DateTime } from 'luxon'
+import {
+  ConstructionYear,
+  Floor,
+  HotWaterEquipment,
+  HousingType,
+  IndividualOrCollective,
+  OutsideFacingWalls,
+  ThreeChoicesAnswer,
+} from 'enum/profileType.enum'
+import { FluidType } from 'enum/fluid.enum'
+
+const initialState: Profile = {
+  id: '',
+  ecogestureHash: '',
+  challengeHash: '',
+  duelHash: '',
+  quizHash: '',
+  explorationHash: '',
+  isFirstConnection: false,
+  GCUApprovalDate: null,
+  lastConnectionDate: DateTime.fromISO('0000-01-01T00:00:00.000Z'),
+  haveSeenOldFluidModal: true,
+  haveSeenLastAnalysis: true,
+  sendAnalysisNotification: false,
+  monthlyAnalysisDate: DateTime.fromISO('0000-01-01T00:00:00.000Z'),
+  isProfileTypeCompleted: false,
+  profileType: {
+    housingType: HousingType.APPARTMENT,
+    constructionYear: ConstructionYear.AFTER_1999,
+    area: 35,
+    occupantsNumber: 1,
+    outsideFacingWalls: OutsideFacingWalls.ONE,
+    floor: Floor.INTERMEDIATE_FLOOR,
+    heating: IndividualOrCollective.COLLECTIVE,
+    coldWater: IndividualOrCollective.INDIVIDUAL,
+    hotWater: IndividualOrCollective.INDIVIDUAL,
+    individualInsulationWork: [],
+    hasInstalledVentilation: ThreeChoicesAnswer.NO,
+    hasReplacedHeater: ThreeChoicesAnswer.NO,
+    hotWaterEquipment: HotWaterEquipment.OTHER,
+    warmingFluid: FluidType.ELECTRICITY,
+    hotWaterFluid: FluidType.ELECTRICITY,
+    cookingFluid: FluidType.GAS,
+  },
+  tutorial: {
+    isWelcomeSeen: false,
+  },
+}
+
+export const profileReducer: Reducer<Profile> = (
+  state = initialState,
+  action: ProfileActionTypes
+): Profile => {
+  switch (action.type) {
+    case UPDATE_PROFILE:
+      return {
+        ...state,
+        ...action.payload,
+      }
+    default:
+      return state
+  }
+}
diff --git a/tests/__mocks__/profile.mock.ts b/tests/__mocks__/profile.mock.ts
index 543663b7f..701a3f02e 100644
--- a/tests/__mocks__/profile.mock.ts
+++ b/tests/__mocks__/profile.mock.ts
@@ -21,6 +21,7 @@ export const profileData: Profile = {
   quizHash: '1136feb6185c7643e071d14180c0e95782aa4ba3',
   explorationHash: '1136feb6185c7643e071d14180c0e95782aa4ba3',
   isFirstConnection: true,
+  GCUApprovalDate: null,
   lastConnectionDate: DateTime.fromISO('2020-11-03T00:00:00.000Z', {
     zone: 'utc',
   }),
@@ -49,4 +50,7 @@ export const profileData: Profile = {
     cookingFluid: FluidType.GAS,
   },
   isProfileTypeCompleted: false,
+  tutorial: {
+    isWelcomeSeen: false,
+  },
 }
diff --git a/tests/__mocks__/store.ts b/tests/__mocks__/store.ts
index e43fab87d..d13843c47 100644
--- a/tests/__mocks__/store.ts
+++ b/tests/__mocks__/store.ts
@@ -102,6 +102,7 @@ export const mockInitialProfileState: Profile = {
   quizHash: '',
   explorationHash: '',
   isFirstConnection: false,
+  GCUApprovalDate: null,
   lastConnectionDate: DateTime.fromISO('0000-01-01T00:00:00.000Z'),
   haveSeenOldFluidModal: true,
   haveSeenLastAnalysis: true,
@@ -126,6 +127,9 @@ export const mockInitialProfileState: Profile = {
     hotWaterFluid: FluidType.ELECTRICITY,
     cookingFluid: FluidType.GAS,
   },
+  tutorial: {
+    isWelcomeSeen: false,
+  },
 }
 
 export const mockInitialChartState: ChartState = {
-- 
GitLab