Skip to content
Snippets Groups Projects
migration.data.ts 9.31 KiB
import { Migration } from './migration.type'
import {
  PROFILE_DOCTYPE,
  PROFILETYPE_DOCTYPE,
  USERCHALLENGE_DOCTYPE,
  EGL_DAY_DOCTYPE,
  EGL_MONTH_DOCTYPE,
  EGL_YEAR_DOCTYPE,
  FLUIDPRICES_DOCTYPE,
} from 'doctypes'
import { Profile, ProfileType, UserChallenge } from 'models'
import { Client } from 'cozy-client'
import { DateTime } from 'luxon'
import { UserQuizState } from 'enum/userQuiz.enum'
import fluidsPricesData from 'db/fluidPrices.json'

export const SCHEMA_INITIAL_VERSION = 0

export const MIGRATION_RESULT_NOOP = 'MigrationNoop'
export const MIGRATION_RESULT_COMPLETE = 'MigrationComplete'
export const MIGRATION_RESULT_FAILED = 'MigrationFailed'

export const migrations: Migration[] = [
  {
    baseSchemaVersion: SCHEMA_INITIAL_VERSION,
    targetSchemaVersion: 1,
    appVersion: '1.3.0',
    description:
      'Removes old profileType artifacts from users database : \n - Oldest profileType is deleted \n - Removes insulation work form fields that were prone to errors \n - Changes area and outsideFacingWalls form field to strings \n - Changes updateDate values of all existing profileType to match "created_at" entry (former updateDate values got corrupted and hold no meanings).',
    releaseNotes: null,
    docTypes: PROFILETYPE_DOCTYPE,
    run: async (_client: Client, docs: any[]): Promise<ProfileType[]> => {
      docs.sort(function(a, b) {
        const c = DateTime.fromISO(a.cozyMetadata.createdAt, {
          zone: 'utc',
        })
        const d = DateTime.fromISO(b.cozyMetadata.createdAt, {
          zone: 'utc',
        })
        return d.millisecond - c.millisecond
      })
      if (docs[0].area === 100) {
        docs[0].deleteAction = true
      }
      return docs.map(doc => {
        if (
          doc.individualInsulationWork.includes(
            'window_replacement_and_wall_insulation'
          )
        ) {
          doc.individualInsulationWork = [
            'window_replacement',
            'wall_insulation',
          ]
        }
        if (
          doc.individualInsulationWork.includes(
            'window_replacement_and_roof_insulation'
          )
        ) {
          doc.individualInsulationWork = [
            'window_replacement',
            'roof_insulation',
          ]
        }
        if (
          doc.individualInsulationWork.includes(
            'window_replacement_and_roof_and_wall_insulation'
          )
        ) {
          doc.individualInsulationWork = [
            'window_replacement',
            'roof_insulation',
            'wall_insulation',
          ]
        }

        doc.outsideFacingWalls = doc.outsideFacingWalls.toString()
        doc.area = doc.area.toString()
        doc.updateDate = doc.cozyMetadata.createdAt
        return doc
      })
    },
  },
  {
    baseSchemaVersion: 1,
    targetSchemaVersion: 2,
    appVersion: '1.3.0',
    description: 'Removes old profileType and GCUApprovalDate from profile.',
    docTypes: PROFILE_DOCTYPE,
    releaseNotes: null,
    run: async (_client: Client, docs: any[]): Promise<Profile[]> => {
      return docs.map(doc => {
        if (doc.GCUApprovalDate) {
          delete doc.GCUApprovalDate
        }
        if (doc.profileType) {
          delete doc.profileType
        }
        return doc
      })
    },
  },
  {
    baseSchemaVersion: 2,
    targetSchemaVersion: 3,
    appVersion: '1.3.0',
    description:
      'Updates userChallenges to make sure no quiz results are overflowing.',
    releaseNotes: null,
    docTypes: USERCHALLENGE_DOCTYPE,
    run: async (_client: Client, docs: any[]): Promise<UserChallenge[]> => {
      return docs.map(doc => {
        if (doc.quiz.result > 5) {
          doc.quiz.result = 5
          doc.progress = {
            actionProgress: 5,
            explorationProgress: 5,
            quizProgress: 5,
          }
          doc.quiz.state = UserQuizState.DONE
        }
        return doc
      })
    },
  },
  {
    baseSchemaVersion: 3,
    targetSchemaVersion: 4,
    appVersion: '1.4.3',
    description: 'Corrects daily EGL data.',
    releaseNotes: {
      title:
        "Des corrections sur la connexion aux données de consommation d'eau ont été apportées.",
      description:
        'Merci de mettre à jour votre connecteur après avoir fermé cette fenêtre. Pour mettre à jour votre connecteur, rendez-vous maintenant du côté de la page Conso, dans la page du fluide concerné.',
    },
    docTypes: EGL_DAY_DOCTYPE,
    queryOptions: {
      scope: 'conso',
      tag: 'day',
      limit: 120,
    },
    run: async (_client: Client, docs: any[]): Promise<any[]> => {
      return docs.map(doc => {
        doc.deleteAction = true
        return doc
      })
    },
  },
  {
    baseSchemaVersion: 4,
    targetSchemaVersion: 5,
    appVersion: '1.4.3',
    description: 'Corrects monthly EGL data.',
    releaseNotes: null,
    docTypes: EGL_MONTH_DOCTYPE,
    queryOptions: {
      scope: 'conso',
      tag: 'month',
      limit: 4,
    },
    run: async (_client: Client, docs: any[]): Promise<any[]> => {
      return docs.map(doc => {
        doc.deleteAction = true
        return doc
      })
    },
  },
  {
    baseSchemaVersion: 5,
    targetSchemaVersion: 6,
    appVersion: '1.4.3',
    description: 'Corrects yearly EGL data.',
    releaseNotes: null,
    docTypes: EGL_YEAR_DOCTYPE,
    queryOptions: {
      scope: 'conso',
      tag: 'year',
      limit: 1,
    },
    run: async (_client: Client, docs: any[]): Promise<any[]> => {
      return docs.map(doc => {
        doc.deleteAction = true
        return doc
      })
    },
  },
  {
    baseSchemaVersion: 6,
    targetSchemaVersion: 7,
    appVersion: '1.4.4',
    description: 'Corrects individual insulation work field on profileType.',
    releaseNotes: null,
    docTypes: PROFILETYPE_DOCTYPE,
    run: async (_client: Client, docs: any[]): Promise<ProfileType[]> => {
      return docs.map(doc => {
        if (!Array.isArray(doc.individualInsulationWork)) {
          doc.individualInsulationWork = [doc.individualInsulationWork]
        }
        if (
          doc.individualInsulationWork.includes(
            'window_replacement_and_wall_insulation'
          )
        ) {
          doc.individualInsulationWork = [
            'window_replacement',
            'wall_insulation',
          ]
        }
        if (
          doc.individualInsulationWork.includes(
            'window_replacement_and_roof_insulation'
          )
        ) {
          doc.individualInsulationWork = [
            'window_replacement',
            'roof_insulation',
          ]
        }
        if (
          doc.individualInsulationWork.includes(
            'window_replacement_and_roof_and_wall_insulation'
          )
        ) {
          doc.individualInsulationWork = [
            'window_replacement',
            'roof_insulation',
            'wall_insulation',
          ]
        }

        return doc
      })
    },
  },
  {
    baseSchemaVersion: 7,
    targetSchemaVersion: 8,
    appVersion: '1.5.0',
    description:
      'ProfileTypes start now at the begining of the month, no duplications can exist over the same month.',
    releaseNotes: null,
    docTypes: PROFILETYPE_DOCTYPE,
    run: async (_client: Client, docs: any[]): Promise<any[]> => {
      function checkDate(d1, d2) {
        const dtd1: DateTime = DateTime.fromISO(d1)
        const dtd2: DateTime = DateTime.fromISO(d2)
        return dtd1.year === dtd2.year && dtd1.month === dtd2.month
      }

      for (let i = 0; i < docs.length; i++) {
        const dtStartOfMonth: DateTime = DateTime.fromISO(docs[i].updateDate)
        docs[i].updateDate = dtStartOfMonth
          .setZone('utc', {
            keepLocalTime: true,
          })
          .startOf('month')
        if (
          docs[i + 1] &&
          checkDate(docs[i].updateDate, docs[i + 1].updateDate)
        ) {
          docs[i].deleteAction = true
        }
      }
      return docs
    },
  },
  {
    baseSchemaVersion: 8,
    targetSchemaVersion: 9,
    appVersion: '1.6.0',
    description: 'Init new doctype fluidPrices',
    releaseNotes: null,
    docTypes: FLUIDPRICES_DOCTYPE,
    isCreate: true,
    run: async (_client: Client, docs: any[]): Promise<any> => {
      for (const fluidPrice of fluidsPricesData) {
        await _client.create(FLUIDPRICES_DOCTYPE, fluidPrice)
      }
    },
  },
  {
    baseSchemaVersion: 9,
    targetSchemaVersion: 10,
    appVersion: '1.6.0',
    description:
      "Profil now contains partnersIssueDate in order to handle partners' issue display",
    releaseNotes: null,
    docTypes: PROFILE_DOCTYPE,
    run: async (_client: Client, docs: any[]): Promise<Profile[]> => {
      return docs.map((doc: Profile) => {
        doc.partnersIssueDate = DateTime.local()
          .minus({ day: 1 })
          .startOf('day')
        console.log(doc)
        return doc
      })
    },
  },
  {
    baseSchemaVersion: 10,
    targetSchemaVersion: 11,
    appVersion: '1.6.0',
    description:
      'Rename tutorial to onboaring in ecolyo profile, remove isLastTermAccepted',
    releaseNotes: null,
    docTypes: PROFILE_DOCTYPE,
    run: async (_client: Client, docs: any[]): Promise<ProfileType[]> => {
      return docs.map(doc => {
        if (doc.tutorial) {
          doc.onboarding = { ...doc.tutorial }
          delete doc.tutorial
        }
        if (typeof doc.isLastTermAccepted != 'undefined') {
          delete doc.isLastTermAccepted
        }
        return doc
      })
    },
  },
]