diff --git a/.vscode/settings.json b/.vscode/settings.json index bc0c55dbdb85e179e697c67efd39d9dfd2c71887..9e93bd20a34710f3b859cde1b560b846400d1a8c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -69,6 +69,7 @@ "désembouant", "désembouer", "doctypes", + "Doesnt", "ecogesture", "Ecogesture", "ecogestures", @@ -141,8 +142,8 @@ "testid", "Tétris", "timestep", - "timesteps", "TIMESTEP", + "timesteps", "UNCOMING", "Unstarted", "UNSTARTED", diff --git a/src/components/Action/ActionCard/ActionCard.tsx b/src/components/Action/ActionCard/ActionCard.tsx index 909829154ee4ead6e682b18a35d2b1b87c39c35b..b14f909d5324041a112bc3a0538d48ef63028282 100644 --- a/src/components/Action/ActionCard/ActionCard.tsx +++ b/src/components/Action/ActionCard/ActionCard.tsx @@ -2,12 +2,8 @@ import { Button } from '@material-ui/core' import defaultIcon from 'assets/icons/visu/ecogesture/default.svg' import StyledIcon from 'components/CommonKit/Icon/StyledIcon' import EcogestureModal from 'components/Ecogesture/EcogestureModal/EcogestureModal' -import { useClient } from 'cozy-client' -import { UsageEventType } from 'enums' import { Ecogesture } from 'models' import React, { useCallback, useEffect, useState } from 'react' -import UsageEventService from 'services/usageEvent.service' -import { useAppSelector } from 'store/hooks' import { importIconById } from 'utils/utils' import './actionCard.scss' @@ -22,8 +18,6 @@ const ActionCard = ({ setSelectedAction, setShowList, }: ActionCardProps) => { - const client = useClient() - const { currentChallenge } = useAppSelector(state => state.ecolyo.challenge) const [actionIcon, setActionIcon] = useState<string>('') const [openEcogestureModal, setOpenEcogestureModal] = useState<boolean>(false) const toggleModal = useCallback(() => { @@ -33,20 +27,8 @@ const ActionCard = ({ const selectEcogesture = useCallback(() => { setSelectedAction(action) setShowList(false) - UsageEventService.addEvent(client, { - type: UsageEventType.ACTION_CHANGE_EVENT, - target: action.id, - context: currentChallenge ? currentChallenge.id : '', - }) toggleModal() - }, [ - setSelectedAction, - setShowList, - action, - toggleModal, - currentChallenge, - client, - ]) + }, [setSelectedAction, setShowList, action, toggleModal]) useEffect(() => { async function handleEcogestureIcon() { diff --git a/src/components/Action/ActionDone/ActionDone.spec.tsx b/src/components/Action/ActionDone/ActionDone.spec.tsx index d293d094852cb135f96e457666bc624988e9cc67..09c2d698ff27ff4764736c633b536282298775cc 100644 --- a/src/components/Action/ActionDone/ActionDone.spec.tsx +++ b/src/components/Action/ActionDone/ActionDone.spec.tsx @@ -2,16 +2,11 @@ import { render, screen } from '@testing-library/react' import { userEvent } from '@testing-library/user-event' import React from 'react' import { Provider } from 'react-redux' -import UsageEventService from 'services/usageEvent.service' import * as challengeActions from 'store/challenge/challenge.slice' import { createMockEcolyoStore } from 'tests/__mocks__/store' import { userChallengeData } from 'tests/__mocks__/userChallengeData.mock' import ActionDone from './ActionDone' -jest.mock('services/usageEvent.service') -const mockAddEvent = jest.fn() -UsageEventService.addEvent = mockAddEvent - const mockUpdateUserChallenge = jest.fn() jest.mock('services/challenge.service', () => { return jest.fn(() => ({ diff --git a/src/components/Action/ActionDone/ActionDone.tsx b/src/components/Action/ActionDone/ActionDone.tsx index 39b6ccce33c1c025191f17e5b819ac131b9eca72..40c5a4b4897192c73f977faa62537933d5707e79 100644 --- a/src/components/Action/ActionDone/ActionDone.tsx +++ b/src/components/Action/ActionDone/ActionDone.tsx @@ -3,12 +3,11 @@ import starFilled from 'assets/icons/visu/challenge/starFilled.svg' import StyledIcon from 'components/CommonKit/Icon/StyledIcon' import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' -import { UsageEventType, UserChallengeUpdateFlag } from 'enums' +import { UserChallengeUpdateFlag } from 'enums' import { UserChallenge } from 'models' import React, { useCallback } from 'react' import { useNavigate } from 'react-router-dom' import ChallengeService from 'services/challenge.service' -import UsageEventService from 'services/usageEvent.service' import { updateUserChallengeList } from 'store/challenge/challenge.slice' import { toggleChallengeActionNotification } from 'store/global/global.slice' import { useAppDispatch } from 'store/hooks' @@ -29,14 +28,6 @@ const ActionDone = ({ currentChallenge, UserChallengeUpdateFlag.ACTION_DONE ) - await UsageEventService.addEvent(client, { - type: UsageEventType.ACTION_END_EVENT, - target: currentChallenge.action.ecogesture - ? currentChallenge.action.ecogesture.id - : '', - context: currentChallenge.id, - startDate: currentChallenge.action.startDate, - }) dispatch(toggleChallengeActionNotification(false)) dispatch(updateUserChallengeList(updatedChallenge)) navigate(-1) diff --git a/src/components/Challenge/ChallengeCardUnlocked/ChallengeCardUnlocked.spec.tsx b/src/components/Challenge/ChallengeCardUnlocked/ChallengeCardUnlocked.spec.tsx index 7ac922efb3966c92c59af76cc516215f42c6f369..46c7d7a5ff3dbaa547b01c59af4ec345d753f0ea 100644 --- a/src/components/Challenge/ChallengeCardUnlocked/ChallengeCardUnlocked.spec.tsx +++ b/src/components/Challenge/ChallengeCardUnlocked/ChallengeCardUnlocked.spec.tsx @@ -3,7 +3,6 @@ import { userEvent } from '@testing-library/user-event' import { FluidType } from 'enums' import React from 'react' import { Provider } from 'react-redux' -import UsageEventService from 'services/usageEvent.service' import { createMockEcolyoStore, mockChallengeState, @@ -19,9 +18,6 @@ jest.mock('services/challenge.service', () => { })) }) -jest.mock('services/usageEvent.service') -UsageEventService.addEvent = jest.fn() - describe('ChallengeCardUnlocked component', () => { const store = createMockEcolyoStore() it('should be rendered correctly', () => { diff --git a/src/components/Challenge/ChallengeCardUnlocked/ChallengeCardUnlocked.tsx b/src/components/Challenge/ChallengeCardUnlocked/ChallengeCardUnlocked.tsx index be661f7eb8a4002db535d7d089470063483d0d97..83926cbe364a54b9e8a17c80d1e5f80bcf32429e 100644 --- a/src/components/Challenge/ChallengeCardUnlocked/ChallengeCardUnlocked.tsx +++ b/src/components/Challenge/ChallengeCardUnlocked/ChallengeCardUnlocked.tsx @@ -3,11 +3,10 @@ import defaultIcon from 'assets/icons/visu/challenge/challengeLocked.svg' import StyledIcon from 'components/CommonKit/Icon/StyledIcon' import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' -import { FluidState, UsageEventType } from 'enums' +import { FluidState } from 'enums' import { UserChallenge } from 'models' import React, { useCallback, useEffect, useState } from 'react' import ChallengeService from 'services/challenge.service' -import UsageEventService from 'services/usageEvent.service' import { updateUserChallengeList } from 'store/challenge/challenge.slice' import { useAppDispatch, useAppSelector } from 'store/hooks' import { getChallengeTitleWithLineReturn, importIconById } from 'utils/utils' @@ -48,10 +47,6 @@ const ChallengeCardUnlocked = ({ const challengeService = new ChallengeService(client) const updatedChallenge = await challengeService.startUserChallenge(userChallenge) - await UsageEventService.addEvent(client, { - type: UsageEventType.CHALLENGE_LAUNCH_EVENT, - target: userChallenge.id, - }) dispatch(updateUserChallengeList(updatedChallenge)) } else { return toggleNoFluidModal() diff --git a/src/components/Connection/GRDFConnect/GrdfInit.tsx b/src/components/Connection/GRDFConnect/GrdfInit.tsx index 8761ee395e1bac7ac8fbcc9a15b075cb798a7731..d851448b4ba66e7fc1f36d827593bcb1bc938b4e 100644 --- a/src/components/Connection/GRDFConnect/GrdfInit.tsx +++ b/src/components/Connection/GRDFConnect/GrdfInit.tsx @@ -1,11 +1,10 @@ import GrdfConnectModal from 'components/Connection/PartnerConnectModal/GrdfConnectModal' import { useClient } from 'cozy-client' -import { FluidType, UsageEventType } from 'enums' +import { FluidType } from 'enums' import { FluidConnection, Konnector, Trigger } from 'models' import React, { useCallback, useState } from 'react' import AccountService from 'services/account.service' import TriggerService from 'services/triggers.service' -import UsageEventService from 'services/usageEvent.service' import { updateFluidConnection } from 'store/global/global.slice' import { useAppDispatch, useAppSelector } from 'store/hooks' import { openConnectionModal } from 'store/modal/modal.slice' @@ -24,8 +23,6 @@ const GrdfInit = ({ onSuccess }: { onSuccess: () => Promise<void> }) => { const [showForm, setShowForm] = useState(false) const currentFluidStatus = fluidStatus[FluidType.GAS] - const konnectorSlug: string = - currentFluidStatus.connection.konnectorConfig.slug const siteLink: string = currentFluidStatus.connection.konnectorConfig.siteLink const konnector: Konnector | null = currentFluidStatus.connection.konnector @@ -47,11 +44,6 @@ const GrdfInit = ({ onSuccess }: { onSuccess: () => Promise<void> }) => { fluidConnection: updatedConnection, }) ) - await UsageEventService.addEvent(client, { - type: UsageEventType.KONNECTOR_CONNECT_EVENT, - target: konnectorSlug, - result: 'error', - }) } else { const triggersServices = new TriggerService(client) const trigger: Trigger = await triggersServices.createTrigger( @@ -80,7 +72,6 @@ const GrdfInit = ({ onSuccess }: { onSuccess: () => Promise<void> }) => { currentFluidStatus.fluidType, currentFluidStatus.connection, onSuccess, - konnectorSlug, ] ) diff --git a/src/components/Connection/PartnerConnectModal/Steps/GrdfFormOAuth.tsx b/src/components/Connection/PartnerConnectModal/Steps/GrdfFormOAuth.tsx index 30941eb12345ab546420212726d5f09d88f371fb..828689ad01331fb06012ddb16143ccbb79e80dbe 100644 --- a/src/components/Connection/PartnerConnectModal/Steps/GrdfFormOAuth.tsx +++ b/src/components/Connection/PartnerConnectModal/Steps/GrdfFormOAuth.tsx @@ -2,10 +2,9 @@ import Button from '@material-ui/core/Button' import { useClient } from 'cozy-client' import { OAuthWindow } from 'cozy-harvest-lib/dist/components/OAuthWindow' import { useI18n } from 'cozy-ui/transpiled/react/I18n' -import { FluidType, UsageEventType } from 'enums' +import { FluidType } from 'enums' import { Konnector } from 'models' import React, { useCallback, useEffect, useState } from 'react' -import UsageEventService from 'services/usageEvent.service' import { setShouldRefreshConsent } from 'store/global/global.slice' import { useAppDispatch, useAppSelector } from 'store/hooks' @@ -32,18 +31,6 @@ const GrdfFormOAuth = ({ dispatch(setShouldRefreshConsent(false)) }, [dispatch]) - const startOAuth = useCallback(async () => { - // If first connexion, send the usage event - if (konnector?.slug && currentFluidStatus.lastDataDate === null) { - await UsageEventService.addEvent(client, { - type: UsageEventType.KONNECTOR_ATTEMPT_EVENT, - target: konnector.slug, - result: 'error', - }) - } - setStatus(WAITING) - }, [client, currentFluidStatus.lastDataDate, konnector]) - const handleAccountId = useCallback( (accountId: string) => { endOAuth() @@ -56,10 +43,10 @@ const GrdfFormOAuth = ({ useEffect(() => { if (shouldRefreshConsent) { - // If user has selected accept button on Expired consent modal, his account has been deleted on KonnectorViewerCard, such as his consent (for GRDF), then automatically launch oauth connxion flow - startOAuth() + // If user has selected accept button on Expired consent modal, his account has been deleted on KonnectorViewerCard, such as his consent (for GRDF), then automatically launch oauth connection flow + setStatus(WAITING) } - }, [shouldRefreshConsent, startOAuth]) + }, [shouldRefreshConsent]) if (!konnector) { return null @@ -69,7 +56,7 @@ const GrdfFormOAuth = ({ <> <Button aria-label={t('auth.accessibility.button_connect')} - onClick={startOAuth} + onClick={() => setStatus(WAITING)} disabled={isWaiting} className="btnPrimary" > diff --git a/src/components/Consumption/FluidButtons/FluidButton.spec.tsx b/src/components/Consumption/FluidButtons/FluidButton.spec.tsx index dac6e52ceb74f3fad1ce7ee4c889971a420d16d1..1c8fa5ea6e1821077906d7488b060d1a10013548 100644 --- a/src/components/Consumption/FluidButtons/FluidButton.spec.tsx +++ b/src/components/Consumption/FluidButtons/FluidButton.spec.tsx @@ -1,17 +1,11 @@ import { render } from '@testing-library/react' -import { userEvent } from '@testing-library/user-event' import { FluidState, FluidType } from 'enums' import { GlobalState } from 'models' import React from 'react' import { Provider } from 'react-redux' -import UsageEventService from 'services/usageEvent.service' import { createMockEcolyoStore, mockGlobalState } from 'tests/__mocks__/store' import FluidButton from './FluidButton' -const mockAddEvent = jest.fn() -jest.mock('services/usageEvent.service') -UsageEventService.addEvent = mockAddEvent - describe('FluidButton component', () => { const store = createMockEcolyoStore() @@ -41,18 +35,6 @@ describe('FluidButton component', () => { ) expect(container.getElementsByClassName('active').length).toBeTruthy() }) - - it('should trigger nav event', async () => { - const { container } = render( - <Provider store={store}> - <FluidButton fluidType={FluidType.GAS} isActive={false} /> - </Provider> - ) - const navButton = container.getElementsByClassName('fluid-button')[0] - await userEvent.click(navButton) - expect(mockAddEvent).toHaveBeenCalled() - }) - it('should render errored button', () => { const updatedInitialState: GlobalState = { ...mockGlobalState, diff --git a/src/components/Consumption/FluidButtons/FluidButton.tsx b/src/components/Consumption/FluidButtons/FluidButton.tsx index 80e2a2da4ee4c94231c9159900a4c81493fa3207..f68eaa2d10542bfcbe93bfa8351ea37d049ce2a5 100644 --- a/src/components/Consumption/FluidButtons/FluidButton.tsx +++ b/src/components/Consumption/FluidButtons/FluidButton.tsx @@ -2,12 +2,10 @@ import { IconButton } from '@material-ui/core' import ErrorNotif from 'assets/icons/ico/notif_error.svg' import PartnerIssueNotif from 'assets/icons/ico/notif_maintenance.svg' import StyledIcon from 'components/CommonKit/Icon/StyledIcon' -import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' -import { FluidState, FluidType, UsageEventType } from 'enums' +import { FluidState, FluidType } from 'enums' import React, { useCallback, useEffect, useState } from 'react' import { useNavigate } from 'react-router-dom' -import UsageEventService from 'services/usageEvent.service' import { useAppSelector } from 'store/hooks' import { getNavPicto } from 'utils/picto' import { getFluidName, isKonnectorActive } from 'utils/utils' @@ -19,7 +17,6 @@ interface FluidButtonProps { const FluidButton = ({ fluidType, isActive }: FluidButtonProps) => { const { t } = useI18n() - const client = useClient() const navigate = useNavigate() const { fluidStatus } = useAppSelector(state => state.ecolyo.global) const [showError, setShowError] = useState<boolean>(false) @@ -45,16 +42,12 @@ const FluidButton = ({ fluidType, isActive }: FluidButtonProps) => { const iconType = getNavPicto(fluidType, isActive, isConnected()) const goToFluid = useCallback(async () => { - await UsageEventService.addEvent(client, { - type: UsageEventType.NAVIGATION_EVENT, - target: getFluidName(fluidType), - }) navigate( fluidType === FluidType.MULTIFLUID ? '/consumption' : `/consumption/${getFluidName(fluidType)}` ) - }, [navigate, fluidType, client]) + }, [navigate, fluidType]) const isFluidMaintenance = () => fluidStatus[fluidType]?.maintenance diff --git a/src/components/ConsumptionVisualizer/DataloadConsumptionVisualizer.spec.tsx b/src/components/ConsumptionVisualizer/DataloadConsumptionVisualizer.spec.tsx index f492d59e1824998ce1162220e7946128b106057d..b3c3b46eaefb8309acf47d6d73350e92f672bf24 100644 --- a/src/components/ConsumptionVisualizer/DataloadConsumptionVisualizer.spec.tsx +++ b/src/components/ConsumptionVisualizer/DataloadConsumptionVisualizer.spec.tsx @@ -1,12 +1,10 @@ import { render, screen } from '@testing-library/react' -import { userEvent } from '@testing-library/user-event' import { DataloadState, FluidType } from 'enums' import { DateTime } from 'luxon' import { Dataload } from 'models' import React from 'react' import { Provider } from 'react-redux' import { BrowserRouter } from 'react-router-dom' -import UsageEventService from 'services/usageEvent.service' import { baseDataLoad, baseMultiFluidDataLoad, @@ -179,14 +177,14 @@ describe('Dataload consumption visualizer component', () => { .item(0) expect(element).toBeInTheDocument() }) - it('should render multifluid with no compare and navigate to singleFluid page', async () => { + it('should render multifluid with euro conversions', async () => { jest.mock('services/converter.service', () => { return jest.fn(() => ({ LoadToEuro: jest.fn(), })) }) - render( + const { container } = render( <Provider store={store}> <BrowserRouter> <DataloadConsumptionVisualizer @@ -198,12 +196,10 @@ describe('Dataload consumption visualizer component', () => { </BrowserRouter> </Provider> ) - jest.mock('services/usageEvent.service') - const mockAddEvent = jest.fn() - UsageEventService.addEvent = mockAddEvent - const links = screen.getAllByRole('link') - await userEvent.click(links[0]) - expect(mockAddEvent).toHaveBeenCalled() + const element = container + .getElementsByClassName('dataloadvisualizer-euro') + .item(0) + expect(element).toBeInTheDocument() }) }) diff --git a/src/components/ConsumptionVisualizer/DataloadSectionDetail.tsx b/src/components/ConsumptionVisualizer/DataloadSectionDetail.tsx index 91ad2308e6373f01ab92e4b54bf6bec977856b1b..b16a11c999c779d482b909339e28b9ca433f5b92 100644 --- a/src/components/ConsumptionVisualizer/DataloadSectionDetail.tsx +++ b/src/components/ConsumptionVisualizer/DataloadSectionDetail.tsx @@ -1,18 +1,11 @@ import classNames from 'classnames' -import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import Icon from 'cozy-ui/transpiled/react/Icon' -import { - DataloadSectionType, - DataloadState, - FluidType, - UsageEventType, -} from 'enums' +import { DataloadSectionType, DataloadState, FluidType } from 'enums' import { Dataload } from 'models' -import React, { useCallback } from 'react' +import React from 'react' import { NavLink } from 'react-router-dom' import ConverterService from 'services/converter.service' -import UsageEventService from 'services/usageEvent.service' import { getNavPicto } from 'utils/picto' import { formatNumberValues, getFluidName } from 'utils/utils' @@ -27,23 +20,12 @@ const DataloadSectionDetail = ({ fluidType, dataloadSectionType, }: DataloadSectionDetailProps) => { - const client = useClient() const { t } = useI18n() const converterService = new ConverterService() const isMulti = fluidType === FluidType.MULTIFLUID const isCompare = dataloadSectionType === DataloadSectionType.NO_COMPARE - const emitNavEvent = useCallback( - async (targetPage: string) => { - await UsageEventService.addEvent(client, { - type: UsageEventType.NAVIGATION_EVENT, - target: targetPage, - }) - }, - [client] - ) - if (!isMulti) { return ( <div @@ -84,7 +66,6 @@ const DataloadSectionDetail = ({ key={FluidType[index]} to={`/consumption/${FluidType[index].toLowerCase()}`} className="dataloadvisualizer-euro-link" - onClick={() => emitNavEvent(FluidType[index].toLowerCase())} > <div className={classNames('dataloadvisualizer-euro-fluid', { diff --git a/src/components/Duel/DuelOngoing/DuelOngoing.tsx b/src/components/Duel/DuelOngoing/DuelOngoing.tsx index 574bf643e97845bca6bfa021d8b5e2932a33c816..d0ea2a2b03882d64ee2de72e8a864fcd7824626d 100644 --- a/src/components/Duel/DuelOngoing/DuelOngoing.tsx +++ b/src/components/Duel/DuelOngoing/DuelOngoing.tsx @@ -6,7 +6,6 @@ import { useChartResize } from 'components/Hooks/useChartResize' import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { - UsageEventType, UserChallengeSuccess, UserChallengeUpdateFlag, UserDuelState, @@ -15,7 +14,6 @@ import { Dataload, UserChallenge } from 'models' import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useNavigate } from 'react-router-dom' import ChallengeService from 'services/challenge.service' -import UsageEventService from 'services/usageEvent.service' import { unlockNextUserChallenge, updateUserChallengeList, @@ -67,17 +65,6 @@ const DuelOngoing = ({ userChallenge, isFinished }: DuelOngoingProps) => { ? UserChallengeUpdateFlag.DUEL_WIN : UserChallengeUpdateFlag.DUEL_LOSS ) - await UsageEventService.addEvent(client, { - type: UsageEventType.DUEL_END_EVENT, - target: userChallenge.duel.id, - result: winChallenge ? 'win' : 'loss', - startDate: userChallenge.startDate, - }) - await UsageEventService.addEvent(client, { - type: UsageEventType.CHALLENGE_END_EVENT, - target: userChallenge.id, - startDate: userChallenge.startDate, - }) dispatch(updateUserChallengeList(updatedChallenge)) dispatch(unlockNextUserChallenge(updatedChallenge)) dispatch(toggleChallengeDuelNotification(false)) diff --git a/src/components/Duel/DuelUnlocked/DuelUnlocked.spec.tsx b/src/components/Duel/DuelUnlocked/DuelUnlocked.spec.tsx index d1835e74fdd1ee74d2612e44db56a6e8bfa932e7..2020acbf2463e81a138d16451c5542e727c618d3 100644 --- a/src/components/Duel/DuelUnlocked/DuelUnlocked.spec.tsx +++ b/src/components/Duel/DuelUnlocked/DuelUnlocked.spec.tsx @@ -17,8 +17,6 @@ jest.mock('services/challenge.service', () => { })) }) -jest.mock('services/usageEvent.service') - describe('DuelUnlocked component', () => { const store = createMockEcolyoStore() diff --git a/src/components/Duel/DuelUnlocked/DuelUnlocked.tsx b/src/components/Duel/DuelUnlocked/DuelUnlocked.tsx index 27b865cea43441de5a0f32ebacdcb06433df7645..eb4ddcd86952d5ccb0eb188ceb51b8ec497ab27a 100644 --- a/src/components/Duel/DuelUnlocked/DuelUnlocked.tsx +++ b/src/components/Duel/DuelUnlocked/DuelUnlocked.tsx @@ -4,11 +4,10 @@ import defaultIcon from 'assets/icons/visu/duel/default.svg' import StyledIcon from 'components/CommonKit/Icon/StyledIcon' import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' -import { UsageEventType, UserChallengeUpdateFlag } from 'enums' +import { UserChallengeUpdateFlag } from 'enums' import { UserChallenge } from 'models' import React, { useCallback, useEffect, useState } from 'react' import ChallengeService from 'services/challenge.service' -import UsageEventService from 'services/usageEvent.service' import { setChallengeConsumption } from 'store/challenge/challenge.slice' import { useAppDispatch } from 'store/hooks' import { formatNumberValues, importIconById } from 'utils/utils' @@ -36,11 +35,6 @@ const DuelUnlocked = ({ userChallenge }: { userChallenge: UserChallenge }) => { ) const dataloads = await challengeService.getUserChallengeDataload(updatedChallenge) - await UsageEventService.addEvent(client, { - type: UsageEventType.DUEL_LAUNCH_EVENT, - target: userChallenge.duel.id, - context: userChallenge.id, - }) dispatch( setChallengeConsumption({ userChallenge: updatedChallenge, diff --git a/src/components/Exploration/ExplorationFinished.tsx b/src/components/Exploration/ExplorationFinished.tsx index eb883e7f945416fd0d4f2feeee85bc7c80933392..3bcce5d7650c1262d28dfa7a5f41277588c4c2e3 100644 --- a/src/components/Exploration/ExplorationFinished.tsx +++ b/src/components/Exploration/ExplorationFinished.tsx @@ -3,16 +3,11 @@ import starResult from 'assets/icons/visu/quiz/starResult.svg' import StyledIcon from 'components/CommonKit/Icon/StyledIcon' import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' -import { - UsageEventType, - UserChallengeUpdateFlag, - UserExplorationState, -} from 'enums' +import { UserChallengeUpdateFlag, UserExplorationState } from 'enums' import { UserChallenge } from 'models' import React, { useCallback } from 'react' import { useNavigate } from 'react-router-dom' import ChallengeService from 'services/challenge.service' -import UsageEventService from 'services/usageEvent.service' import { updateUserChallengeList } from 'store/challenge/challenge.slice' import { toggleChallengeExplorationNotification } from 'store/global/global.slice' import { useAppDispatch } from 'store/hooks' @@ -35,12 +30,6 @@ const ExplorationFinished = ({ userChallenge }: ExplorationFinishedProps) => { userChallenge, UserChallengeUpdateFlag.EXPLORATION_DONE ) - await UsageEventService.addEvent(client, { - type: UsageEventType.EXPLORATION_END_EVENT, - target: userChallenge.exploration.id, - context: userChallenge.id, - startDate: userChallenge.exploration.date, - }) dispatch(toggleChallengeExplorationNotification(false)) dispatch(updateUserChallengeList(updatedChallenge)) } diff --git a/src/components/Exploration/ExplorationOngoing.tsx b/src/components/Exploration/ExplorationOngoing.tsx index 380a389a114df1e89b947313fb8fc2db7b1207c5..850f4aabd717e9c86057be61e586670c49080ad6 100644 --- a/src/components/Exploration/ExplorationOngoing.tsx +++ b/src/components/Exploration/ExplorationOngoing.tsx @@ -5,7 +5,6 @@ import StarsContainer from 'components/CommonKit/StarsContainer/StarsContainer' import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' import { - UsageEventType, UserChallengeUpdateFlag, UserExplorationState, UserExplorationType, @@ -14,7 +13,6 @@ import { UserChallenge } from 'models' import React from 'react' import { useNavigate } from 'react-router-dom' import ChallengeService from 'services/challenge.service' -import UsageEventService from 'services/usageEvent.service' import { updateUserChallengeList } from 'store/challenge/challenge.slice' import { useAppDispatch } from 'store/hooks' import './explorationOngoing.scss' @@ -46,12 +44,6 @@ const ExplorationOngoing = ({ userChallenge }: ExplorationOngoingProps) => { userChallenge, UserChallengeUpdateFlag.EXPLORATION_DONE ) - await UsageEventService.addEvent(client, { - type: UsageEventType.EXPLORATION_END_EVENT, - target: userChallenge.exploration.id, - context: userChallenge.id, - startDate: userChallenge.exploration.date, - }) dispatch(updateUserChallengeList(updatedChallenge)) navigate('/challenges') } diff --git a/src/components/FluidChart/FluidChart.tsx b/src/components/FluidChart/FluidChart.tsx index 908daec4451c91d102c11f5c2f0e3ac6a9f0aa9f..d5e335507007941e2b40dd7dcb92b1dff872a3d6 100644 --- a/src/components/FluidChart/FluidChart.tsx +++ b/src/components/FluidChart/FluidChart.tsx @@ -5,12 +5,11 @@ import StyledSwitch from 'components/CommonKit/Switch/StyledSwitch' import useExploration from 'components/Hooks/useExploration' import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' -import { FluidType, TimeStep, UsageEventType, UserExplorationID } from 'enums' +import { FluidType, TimeStep, UserExplorationID } from 'enums' import React, { useCallback, useEffect, useState } from 'react' import { useNavigate } from 'react-router-dom' import ConsumptionService from 'services/consumption.service' import DateChartService from 'services/dateChart.service' -import UsageEventService from 'services/usageEvent.service' import { setCurrentIndex, setSelectedDate, @@ -50,13 +49,6 @@ const FluidChart = ({ fluidType, setActive }: FluidChartProps) => { const lowercaseFluidType = getFluidName(fluidType) const handleChangeSwitch = async () => { - if (!showCompare) { - await UsageEventService.addEvent(client, { - type: UsageEventType.CONSUMPTION_COMPARE_EVENT, - target: TimeStep[currentTimeStep].toLowerCase(), - context: lowercaseFluidType, - }) - } dispatch(setShowCompare(!showCompare)) } diff --git a/src/components/FluidChart/TimeStepSelector/TimeStepSelector.spec.tsx b/src/components/FluidChart/TimeStepSelector/TimeStepSelector.spec.tsx index 896eee1c8698f2898e3314f4b9ba822b9216035f..60ddf0fedc7ea42905fcea16dbdd6798484559ad 100644 --- a/src/components/FluidChart/TimeStepSelector/TimeStepSelector.spec.tsx +++ b/src/components/FluidChart/TimeStepSelector/TimeStepSelector.spec.tsx @@ -5,14 +5,9 @@ import { FluidType, TimeStep } from 'enums' import { DateTime } from 'luxon' import React from 'react' import { Provider } from 'react-redux' -import UsageEventService from 'services/usageEvent.service' import * as chartActions from 'store/chart/chart.slice' import { createMockEcolyoStore } from 'tests/__mocks__/store' -jest.mock('services/usageEvent.service') -const mockAddEvent = jest.fn() -UsageEventService.addEvent = mockAddEvent - const setCurrentTimeStepSpy = jest.spyOn(chartActions, 'setCurrentTimeStep') const setCurrentIndexSpy = jest.spyOn(chartActions, 'setCurrentIndex') const setSelectedDateSpy = jest.spyOn(chartActions, 'setSelectedDate') diff --git a/src/components/FluidChart/TimeStepSelector/TimeStepSelector.tsx b/src/components/FluidChart/TimeStepSelector/TimeStepSelector.tsx index d5d59d5340e20443334a3691e49a9c30efc6b04c..d05db4af3cd184efe03f575eb577e96ecbe7a532 100644 --- a/src/components/FluidChart/TimeStepSelector/TimeStepSelector.tsx +++ b/src/components/FluidChart/TimeStepSelector/TimeStepSelector.tsx @@ -1,18 +1,15 @@ import { Button } from '@material-ui/core' -import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' -import { FluidType, TimeStep, UsageEventType } from 'enums' +import { FluidType, TimeStep } from 'enums' import { DateTime } from 'luxon' import React from 'react' import DateChartService from 'services/dateChart.service' -import UsageEventService from 'services/usageEvent.service' import { setCurrentIndex, setCurrentTimeStep, setSelectedDate, } from 'store/chart/chart.slice' import { useAppDispatch, useAppSelector } from 'store/hooks' -import { getFluidName } from 'utils/utils' import './timeStepSelector.scss' const TimeStepSelector = ({ fluidType }: { fluidType: FluidType }) => { @@ -22,8 +19,6 @@ const TimeStepSelector = ({ fluidType }: { fluidType: FluidType }) => { state => state.ecolyo.chart ) const dateChartService = new DateChartService() - const client = useClient() - const timeStepMultiArray: TimeStep[] = [ TimeStep.WEEK, TimeStep.DAY, @@ -41,11 +36,6 @@ const TimeStepSelector = ({ fluidType }: { fluidType: FluidType }) => { keepLocalTime: true, }) .startOf('day') - UsageEventService.addEvent(client, { - type: UsageEventType.CONSUMPTION_CHANGE_TIMESTEP_EVENT, - target: TimeStep[TimeStep.WEEK].toLowerCase(), - context: getFluidName(fluidType), - }) dispatch(setCurrentIndex(0)) dispatch(setSelectedDate(today)) dispatch(setCurrentTimeStep(TimeStep.WEEK)) @@ -55,11 +45,6 @@ const TimeStepSelector = ({ fluidType }: { fluidType: FluidType }) => { targetTimestep, selectedDate ) - UsageEventService.addEvent(client, { - type: UsageEventType.CONSUMPTION_CHANGE_TIMESTEP_EVENT, - target: TimeStep[currentTimeStep].toLowerCase(), - context: getFluidName(fluidType), - }) dispatch(setCurrentTimeStep(targetTimestep)) dispatch(setCurrentIndex(index)) } diff --git a/src/components/Hooks/useKonnectorAuth.tsx b/src/components/Hooks/useKonnectorAuth.tsx index 1750eff2df85a7848c8bfad5ac0dca5bf0be7bd8..ce50e44044a4cc66403a78fd400233bdb32adcd4 100644 --- a/src/components/Hooks/useKonnectorAuth.tsx +++ b/src/components/Hooks/useKonnectorAuth.tsx @@ -1,17 +1,11 @@ import * as Sentry from '@sentry/react' import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' -import { FluidSlugType, FluidType, UsageEventType } from 'enums' -import { - AccountAuthData, - AccountSgeData, - FluidConnection, - UsageEvent, -} from 'models' +import { FluidSlugType, FluidType } from 'enums' +import { AccountAuthData, AccountSgeData, FluidConnection } from 'models' import { useState } from 'react' import AccountService from 'services/account.service' import ConnectionService from 'services/connection.service' -import UsageEventService from 'services/usageEvent.service' import { setLoading } from 'store/chart/chart.slice' import { updateFluidConnection } from 'store/global/global.slice' import { useAppDispatch, useAppSelector } from 'store/hooks' @@ -31,29 +25,15 @@ const useKonnectorAuth = ( const currentFluidStatus = fluidStatus[fluidType] const konnectorSlug: FluidSlugType = currentFluidStatus.connection.konnectorConfig.slug - const [connectError, setError] = useState<string>('') - - const sendUsageEventError = async (slug: string): Promise<UsageEvent> => { - return UsageEventService.addEvent(client, { - type: UsageEventType.KONNECTOR_CONNECT_EVENT, - target: slug, - result: 'error', - }) - } + const [connectError, setConnectError] = useState<string>('') const connect = async () => { const connectionService = new ConnectionService(client) try { - // If first connexion, send the usage event - await UsageEventService.addEvent(client, { - type: UsageEventType.KONNECTOR_ATTEMPT_EVENT, - target: konnectorSlug, - result: 'error', - }) const { account: _account, trigger: _trigger } = konnectorSlug === FluidSlugType.WATER ? await connectionService.connectNewUser(konnectorSlug, { - login: login ? login : '', + login: login ?? '', password: password, }) : await connectionService.connectNewUser( @@ -62,8 +42,7 @@ const useKonnectorAuth = ( sgeConnect ) if (!_trigger || !_account) { - setError(t('konnector_form.error_account_creation')) - sendUsageEventError(konnectorSlug) + setConnectError(t('konnector_form.error_account_creation')) return null } const updatedConnection: FluidConnection = { @@ -81,7 +60,6 @@ const useKonnectorAuth = ( ) } catch (error) { setLoading(false) - sendUsageEventError(konnectorSlug) logApp.error(error) Sentry.captureException(error) } diff --git a/src/components/Konnector/KonnectorViewerCard.tsx b/src/components/Konnector/KonnectorViewerCard.tsx index a4e3b2d97bd8bd8c344dcbcbd410577c649e1519..a0d5503fb8fc7dfb82078cd4a93924d375055da0 100644 --- a/src/components/Konnector/KonnectorViewerCard.tsx +++ b/src/components/Konnector/KonnectorViewerCard.tsx @@ -30,7 +30,6 @@ import { FluidState, FluidType, KonnectorError, - UsageEventType, UserChallengeState, UserDuelState, } from 'enums' @@ -43,7 +42,6 @@ import { Konnector, PartnersInfo, Trigger, - UsageEvent, } from 'models' import React, { useCallback, useEffect, useMemo, useState } from 'react' import { useNavigate } from 'react-router-dom' @@ -260,38 +258,6 @@ const KonnectorViewerCard = ({ ] ) - const sendUsageEventSuccess = useCallback( - async ( - konnectorSlug: string, - isConnexion: boolean - ): Promise<UsageEvent> => { - return UsageEventService.addEvent(client, { - type: isConnexion - ? UsageEventType.KONNECTOR_CONNECT_EVENT - : UsageEventType.KONNECTOR_REFRESH_EVENT, - target: konnectorSlug, - result: 'success', - }) - }, - [client] - ) - - const sendUsageEventError = useCallback( - async ( - konnectorSlug: string, - isConnexion: boolean - ): Promise<UsageEvent> => { - return UsageEventService.addEvent(client, { - type: isConnexion - ? UsageEventType.KONNECTOR_CONNECT_EVENT - : UsageEventType.KONNECTOR_REFRESH_EVENT, - target: konnectorSlug, - result: 'error', - }) - }, - [client] - ) - const toggleModalConnection = useCallback(() => { switch (fluidType) { case FluidType.ELECTRICITY: @@ -502,25 +468,13 @@ const KonnectorViewerCard = ({ const connectionFlow = new ConnectionFlow(client, trigger, konnector) await connectionFlow.launch() connectionFlow.jobWatcher.on(ERROR_EVENT, () => { - sendUsageEventError( - fluidSlug, - currentFluidStatus.lastDataDate === null - ) setKonnectorErrorDescription(connectionFlow.jobWatcher.on()._error) callbackResponse(ERROR_EVENT) }) connectionFlow.jobWatcher.on(LOGIN_SUCCESS_EVENT, () => { setIsLogging(false) - sendUsageEventSuccess( - fluidSlug, - currentFluidStatus.lastDataDate === null - ) }) connectionFlow.jobWatcher.on(SUCCESS_EVENT, () => { - sendUsageEventSuccess( - fluidSlug, - currentFluidStatus.lastDataDate === null - ) callbackResponse(SUCCESS_EVENT) }) } @@ -546,8 +500,6 @@ const KonnectorViewerCard = ({ fluidSlug, fluidType, konnector, - sendUsageEventError, - sendUsageEventSuccess, shouldRefreshConsent, trigger, ]) @@ -604,9 +556,7 @@ const KonnectorViewerCard = ({ </AccordionDetails> </Accordion> ) : ( - <> - <AccordionDetails>{getConnectionCard()}</AccordionDetails> - </> + <AccordionDetails>{getConnectionCard()}</AccordionDetails> )} <KonnectorModal open={openModal} diff --git a/src/components/Navbar/Navbar.tsx b/src/components/Navbar/Navbar.tsx index aadb0016f83be044278a7ef2fd14277b7c7445f1..7fbb1d66fdf1829e508d2cc578d2837c6cefbedc 100644 --- a/src/components/Navbar/Navbar.tsx +++ b/src/components/Navbar/Navbar.tsx @@ -11,12 +11,9 @@ import ParameterIconOff from 'assets/icons/tabbar/parametre/parametre-off.svg' import ParameterIconOn from 'assets/icons/tabbar/parametre/parametre-on.svg' import logos from 'assets/png/logos_partenaires.svg' import StyledIcon from 'components/CommonKit/Icon/StyledIcon' -import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' -import { UsageEventType } from 'enums' -import React, { useCallback } from 'react' +import React from 'react' import { NavLink, useLocation } from 'react-router-dom' -import UsageEventService from 'services/usageEvent.service' import { useAppSelector } from 'store/hooks' import './navBar.scss' @@ -30,17 +27,6 @@ const Navbar = () => { } = useAppSelector(state => state.ecolyo.global) const { pathname } = useLocation() - const client = useClient() - const emitNavEvent = useCallback( - async (targetPage: string) => { - await UsageEventService.addEvent(client, { - type: UsageEventType.NAVIGATION_EVENT, - target: targetPage, - }) - }, - [client] - ) - /** Return class "is-active" if pathname includes matcher */ const isActive = (matcher: string) => { return pathname.includes(matcher) ? 'is-active' : '' @@ -55,7 +41,6 @@ const Navbar = () => { component={NavLink} to="/consumption" className={`c-nav-link ${isActive('/consumption')}`} - onClick={() => emitNavEvent('consumption')} > <StyledIcon className="c-nav-icon off" icon={ConsoIconOff} /> <StyledIcon className="c-nav-icon on" icon={ConsoIconOn} /> @@ -67,7 +52,6 @@ const Navbar = () => { component={NavLink} to="/challenges" className={`c-nav-link ${isActive('/challenges')}`} - onClick={() => emitNavEvent('challenges')} > {(challengeExplorationNotification || challengeActionNotification || @@ -82,7 +66,6 @@ const Navbar = () => { component={NavLink} to="/ecogestures" className={`c-nav-link ${isActive('/ecogesture')}`} - onClick={() => emitNavEvent('ecogestures')} > <StyledIcon className="c-nav-icon off" icon={BulbIconOff} /> <StyledIcon className="c-nav-icon on" icon={BulbIconOn} /> @@ -94,7 +77,6 @@ const Navbar = () => { component={NavLink} to="/analysis" className={`c-nav-link ${isActive('/analysis')}`} - onClick={() => emitNavEvent('analysis')} > {analysisNotification && <div className="nb-notif">1</div>} <StyledIcon className="c-nav-icon off" icon={AnalysisIconOff} /> @@ -107,7 +89,6 @@ const Navbar = () => { component={NavLink} to="/options" className={`c-nav-link ${isActive('/options')}`} - onClick={() => emitNavEvent('options')} > <StyledIcon className="c-nav-icon off" icon={ParameterIconOff} /> <StyledIcon className="c-nav-icon on" icon={ParameterIconOn} /> diff --git a/src/components/Options/LegalNotice/LegalNoticeLink.tsx b/src/components/Options/LegalNotice/LegalNoticeLink.tsx index 5786982a77f766c14451781f04c19d17806bb0a6..e158282f8124c1fa85b8f6c266666369297426fc 100644 --- a/src/components/Options/LegalNotice/LegalNoticeLink.tsx +++ b/src/components/Options/LegalNotice/LegalNoticeLink.tsx @@ -1,23 +1,14 @@ import Link from '@material-ui/core/Link' import LegalNoticeIcon from 'assets/icons/ico/legal-notice.svg' import StyledIcon from 'components/CommonKit/Icon/StyledIcon' -import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' -import { UsageEventType } from 'enums' -import React, { useCallback } from 'react' +import React from 'react' import { Link as RouterLink } from 'react-router-dom' -import UsageEventService from 'services/usageEvent.service' import './legalNoticeLink.scss' const LegalNoticeLink = () => { const { t } = useI18n() - const client = useClient() - const emitNavEvent = useCallback(async () => { - await UsageEventService.addEvent(client, { - type: UsageEventType.NAVIGATION_EVENT, - target: 'legalNotice', - }) - }, [client]) + return ( <div className="legal-notice-root"> <div className="legal-notice-content"> @@ -28,7 +19,6 @@ const LegalNoticeLink = () => { className="legal-notice-card-link" component={RouterLink} to="/options/legalnotice" - onClick={emitNavEvent} > <div className="card"> <div className="legal-notice-card"> diff --git a/src/components/Quiz/QuizQuestion/QuizQuestionContentCustom.tsx b/src/components/Quiz/QuizQuestion/QuizQuestionContentCustom.tsx index 92e94e5df2676f65b5b376f3c09e84d1b9b5d00b..72cf01ba2719b26e4da2132d41193389d67eaf70 100644 --- a/src/components/Quiz/QuizQuestion/QuizQuestionContentCustom.tsx +++ b/src/components/Quiz/QuizQuestion/QuizQuestionContentCustom.tsx @@ -5,12 +5,11 @@ import Loader from 'components/Loader/Loader' import QuizExplanationModal from 'components/Quiz/QuizExplanationModal/QuizExplanationModal' import { useClient } from 'cozy-client' import { useI18n } from 'cozy-ui/transpiled/react/I18n' -import { UsageEventType, UserChallengeUpdateFlag } from 'enums' +import { UserChallengeUpdateFlag } from 'enums' import { Answer, QuestionEntity, UserChallenge, UserQuiz } from 'models' import React, { useState } from 'react' import ChallengeService from 'services/challenge.service' import QuizService from 'services/quiz.service' -import UsageEventService from 'services/usageEvent.service' import { updateUserChallengeList } from 'store/challenge/challenge.slice' import { useAppDispatch } from 'store/hooks' import './quizQuestion.scss' @@ -74,13 +73,6 @@ const QuizQuestionContentCustom = ({ userChallenge, UserChallengeUpdateFlag.QUIZ_DONE ) - await UsageEventService.addEvent(client, { - type: UsageEventType.QUIZ_END_EVENT, - startDate: userChallenge.quiz.startDate, - target: userChallenge.quiz.id, - result: userChallenge.quiz.result.toString(), - context: userChallenge.id, - }) dispatch(updateUserChallengeList(userChallengeUpdated)) } diff --git a/src/components/Splash/SplashRoot.tsx b/src/components/Splash/SplashRoot.tsx index 5084ce80f6fe7c35724b079f97dee58d16cefd8e..068f256c176eb0af7d04ddf2f29bcedbb352df2f 100644 --- a/src/components/Splash/SplashRoot.tsx +++ b/src/components/Splash/SplashRoot.tsx @@ -3,7 +3,6 @@ import classNames from 'classnames' import useExploration from 'components/Hooks/useExploration' import { useClient } from 'cozy-client' import { - UsageEventType, UserActionState, UserChallengeState, UserDuelState, @@ -30,7 +29,6 @@ import FluidService from 'services/fluid.service' import InitializationService from 'services/initialization.service' import PartnersInfoService from 'services/partnersInfo.service' import ProfileTypeEntityService from 'services/profileTypeEntity.service' -import UsageEventService from 'services/usageEvent.service' import { setAnalysisMonth } from 'store/analysis/analysis.slice' import { setChallengeConsumption, @@ -326,18 +324,6 @@ const SplashRoot = ({ fadeTimer = 1000, children }: SplashRootProps) => { } } } - if (profile) { - await UsageEventService.addEvent(client, { - type: UsageEventType.CONNECTION_EVENT, - result: profile.isFirstConnection ? 'firstConnection' : undefined, - context: - /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test( - navigator.userAgent - ) - ? 'mobile' - : 'desktop', - }) - } /** * Load custom popup and partners info synchronously so these treatments don't block the loading diff --git a/src/enums/dacc.enum.ts b/src/enums/dacc.enum.ts deleted file mode 100644 index 707054fda7dc96682b4dd4cf4f1dd07e02dfde20..0000000000000000000000000000000000000000 --- a/src/enums/dacc.enum.ts +++ /dev/null @@ -1,18 +0,0 @@ -export enum DaccEvent { - CONNECTION_COUNT_DAILY = 'connection-count-daily', - KONNECTOR_EVENT_DAILY = 'konnector-event-daily', - KONNECTOR_CONNECTED_PER_DAY = 'konnector-connected-daily', - NAVIGATION_COUNT_DAILY = 'navigation-count-daily', - CHALLENGE_LAUNCH_EVENT_DAILY = 'challenge-launch-daily', - CONSUMPTION_VARIATION_MONTHLY = 'consumption-variation-monthly', - SESSION_DURATION = 'session-duration', - NAVIGATION_ACTION_DAILY = 'navigation-action-daily', - EVENT_DURATION = 'event-duration', - QUIZ_STARS = 'quiz-stars', - SUMMARY_SUBSCRIPTION_MONTHLY = 'summary-subscription-monthly', - FLUID_DATA_GRANULARITY = 'fluid-data-granularity-monthly', - PARTNER_SUCCESS_MONTHLY = 'konnector-attempts-before-success', - UNINITIALIZED_KONNECTOR_ATTEMPTS_MONTHLY = 'uninitialized-konnector-attempts-monthly', - CONNECTION_COUNT_MONTHLY = 'connection-count-monthly', - PROFILE_COUNT_MONTHLY = 'profile-count', -} diff --git a/src/enums/index.ts b/src/enums/index.ts index 921ed6776e0b3113c1163fc3dd8437b8032bf144..17dc988521c2ada45d2f3bb958be03f4ddb74e80 100644 --- a/src/enums/index.ts +++ b/src/enums/index.ts @@ -1,4 +1,3 @@ -export * from './dacc.enum' export * from './dataload.enum' export * from './ecogesture.enum' export * from './ecogestureForm.enum' diff --git a/src/enums/usageEvent.enum.ts b/src/enums/usageEvent.enum.ts index 93cbd57f7a14a209f3735247d7c67a06d7096663..f8cd6f836f7ef46eccb0d1c089856f5a59df9226 100644 --- a/src/enums/usageEvent.enum.ts +++ b/src/enums/usageEvent.enum.ts @@ -1,19 +1,4 @@ export enum UsageEventType { - CONNECTION_EVENT = 'ConnectionEvent', - KONNECTOR_CONNECT_EVENT = 'KonnectorConnectEvent', - KONNECTOR_ATTEMPT_EVENT = 'KonnectorAttemptEvent', - KONNECTOR_REFRESH_EVENT = 'KonnectorRefreshEvent', - NAVIGATION_EVENT = 'NavigationEvent', - CONSUMPTION_COMPARE_EVENT = 'ConsumptionCompareEvent', - CONSUMPTION_CHANGE_TIMESTEP_EVENT = 'ConsumptionChangeTimeStepEvent', - CHALLENGE_LAUNCH_EVENT = 'ChallengeLaunchEvent', - CHALLENGE_END_EVENT = 'ChallengeEndEvent', - DUEL_LAUNCH_EVENT = 'DuelLaunchEvent', - DUEL_END_EVENT = 'DuelEndEvent', - QUIZ_END_EVENT = 'QuizEndEvent', - EXPLORATION_END_EVENT = 'ExplorationEndEvent', - ACTION_CHANGE_EVENT = 'ActionChangeEvent', - ACTION_END_EVENT = 'ActionEndEvent', PROFILE_SET_EVENT = 'ProfileSetEvent', REPORT_FROM_EMAIL = 'ReportFromEvent', } diff --git a/src/services/usageEvent.service.spec.ts b/src/services/usageEvent.service.spec.ts index 237f7c74dff74ee0799075260c8df7008e61ee81..6eb49c7b2c8699c807f927a0c05464f025c3fa27 100644 --- a/src/services/usageEvent.service.spec.ts +++ b/src/services/usageEvent.service.spec.ts @@ -6,10 +6,8 @@ import mockClient from 'tests/__mocks__/client.mock' import { getError } from 'tests/__mocks__/testUtils' import { allUsageEventsData, - connectionAttemptEGLError, - connectionAttemptEGLSuccess, - connectionEventEntitiesData, - connectionUsageEventsData, + profileSetEventEntitiesData, + profileSetUsageEventsData, usageEventData, usageEventEntityData, } from 'tests/__mocks__/usageEventsData.mock' @@ -74,24 +72,24 @@ describe('UsageEvent service', () => { }) }) describe('getEvents method', () => { - it('should return all Connection events', async () => { + it('should return all ProfileSet events', async () => { const mockQueryResult: QueryResult<UsageEventEntity[]> = { - data: connectionEventEntitiesData, + data: profileSetEventEntitiesData, bookmark: '', next: false, skip: 0, } mockClient.query.mockResolvedValueOnce(mockQueryResult) const result = await UsageEventService.getEvents(mockClient, { - type: UsageEventType.CONNECTION_EVENT, + type: UsageEventType.PROFILE_SET_EVENT, }) - expect(result).toEqual(connectionUsageEventsData) + expect(result).toEqual(profileSetUsageEventsData) }) }) describe('addEventIfDoesntExist method', () => { it('should not add event', async () => { const mockQueryResult: QueryResult<UsageEventEntity[]> = { - data: connectionEventEntitiesData, + data: profileSetEventEntitiesData, bookmark: '', next: false, skip: 0, @@ -99,7 +97,7 @@ describe('UsageEvent service', () => { mockClient.query.mockResolvedValueOnce(mockQueryResult) const result = await UsageEventService.addEventIfDoesntExist( mockClient, - { type: UsageEventType.CONNECTION_EVENT }, + { type: UsageEventType.PROFILE_SET_EVENT }, { id: { $gt: 0 } } ) expect(result).toEqual(null) @@ -121,61 +119,10 @@ describe('UsageEvent service', () => { mockClient.create.mockResolvedValueOnce(mockQueryResult2) const result = await UsageEventService.addEventIfDoesntExist( mockClient, - { type: UsageEventType.CONNECTION_EVENT }, + { type: UsageEventType.PROFILE_SET_EVENT }, { id: { $gt: 0 } } ) expect(result).toEqual(usageEventData) }) }) - describe('updateConnectionAttemptEvent method', () => { - it('should update the last attempt to true', async () => { - const mockQueryResult: QueryResult<UsageEventEntity[]> = { - data: [connectionAttemptEGLError], - bookmark: '', - next: false, - skip: 0, - } - const mockQueryResult2: QueryResult<UsageEventEntity> = { - data: connectionAttemptEGLSuccess, - bookmark: '', - next: false, - skip: 0, - } - mockClient.query.mockResolvedValueOnce(mockQueryResult) - mockClient.save.mockResolvedValueOnce(mockQueryResult2) - const result = await UsageEventService.updateConnectionAttemptEvent( - mockClient, - 'eglgrandlyon' - ) - expect(result).toEqual(connectionAttemptEGLSuccess) - }) - it('should fail to update the attempts', async () => { - const mockQueryResult: QueryResult<UsageEventEntity[] | undefined> = { - data: undefined, - bookmark: '', - next: false, - skip: 0, - } - mockClient.query.mockResolvedValueOnce(mockQueryResult) - const result = await UsageEventService.updateConnectionAttemptEvent( - mockClient, - 'eglgrandlyon' - ) - expect(result).toEqual(undefined) - }) - it('should find no attempt', async () => { - const mockQueryResult: QueryResult<UsageEventEntity[] | undefined> = { - data: [], - bookmark: '', - next: false, - skip: 0, - } - mockClient.query.mockResolvedValueOnce(mockQueryResult) - const result = await UsageEventService.updateConnectionAttemptEvent( - mockClient, - 'eglgrandlyon' - ) - expect(result).toEqual(undefined) - }) - }) }) diff --git a/src/services/usageEvent.service.ts b/src/services/usageEvent.service.ts index cc362ee26dbc8fdde3df3ed4e5abd36dffae94dc..5f971c83c9f93048118d01adc3ce1370fdd084a6 100644 --- a/src/services/usageEvent.service.ts +++ b/src/services/usageEvent.service.ts @@ -8,7 +8,6 @@ import { } from 'cozy-client' import logger from 'cozy-logger' import { USAGEEVENT_DOCTYPE } from 'doctypes' -import { UsageEventType } from 'enums' import { DateTime } from 'luxon' import { AddEventParams, @@ -60,44 +59,6 @@ export default class UsageEventService { return null } - static async updateConnectionAttemptEvent( - client: Client, - konnectorSlug: string - ): Promise<UsageEventEntity | undefined> { - try { - // Get last Connection attempt Event - const query: QueryDefinition = Q(USAGEEVENT_DOCTYPE) - .where({ - target: konnectorSlug, - }) - .partialIndex({ - type: UsageEventType.KONNECTOR_ATTEMPT_EVENT, - result: 'error', - }) - .indexFields(['eventDate', 'type']) - .sortBy([{ eventDate: 'desc' }]) - .limitBy(1) - const { - data: [usageEventEntity], - }: QueryResult<UsageEventEntity[]> = await client.query(query) - if (usageEventEntity) { - const updatedEvent: UsageEventEntity = { - ...usageEventEntity, - result: 'success', - } - const { data: savedEvent } = await client.save(updatedEvent) - return savedEvent - } - } catch (error) { - const errorMessage = `UsageEvent service error on updateConnectionAttemptEvent: ${JSON.stringify( - error - )}` - logStack('error', errorMessage) - logApp.error(errorMessage) - Sentry.captureException(error) - } - } - /** * @returns {Promise<boolean>} return true if all events are updated */ diff --git a/src/targets/services/aggregatorUsageEvents.ts b/src/targets/services/aggregatorUsageEvents.ts index 09ef985fc44fd8dd98d997f2656cc30783bbb1cb..f54542bdd4b6ab97fbc94bc198e6fcafc696c819 100644 --- a/src/targets/services/aggregatorUsageEvents.ts +++ b/src/targets/services/aggregatorUsageEvents.ts @@ -2,21 +2,16 @@ import * as Sentry from '@sentry/react' import { Client } from 'cozy-client' import logger from 'cozy-logger' import { - DaccEvent, - FluidSlugType, FluidState, FluidType, HotWaterFluid, TimeStep, - UsageEventProperties, UsageEventType, - UserChallengeState, WarmingType, } from 'enums' -import { toNumber, uniq } from 'lodash' +import { uniq } from 'lodash' import { DateTime } from 'luxon' import { FluidStatus, PerformanceIndicator, UsageEvent } from 'models' -import ChallengeService from 'services/challenge.service' import ConsumptionService from 'services/consumption.service' import EnvironmentService from 'services/environment.service' import FluidService from 'services/fluid.service' @@ -29,6 +24,14 @@ import { runService } from './service' const logStack = logger.namespace('aggregatorUsageEvents') +enum DaccIndicator { + CONSUMPTION_VARIATION_MONTHLY = 'consumption-variation-monthly', + FLUID_DATA_GRANULARITY = 'fluid-data-granularity-monthly', + KONNECTOR_CONNECTED_PER_DAY = 'konnector-connected-daily', + PROFILE_COUNT_MONTHLY = 'profile-count', + SUMMARY_SUBSCRIPTION_MONTHLY = 'summary-subscription-monthly', +} + interface AggregatorUsageEventsProps { client: Client } @@ -90,234 +93,6 @@ const sendIndicator = async ( } } -const reduceEvents = ( - events: UsageEvent[] -): { [key: string]: UsageEvent[] } => { - return events.reduce(function ( - acc: { - [key: string]: UsageEvent[] - }, - event: UsageEvent - ) { - const key = `${event.eventDate.startOf('day').toString()}|${event.target}|${ - event.result - }|${event.context}` - if (!acc[key]) { - acc[key] = [] - } - acc[key].push(event) - readUsageEvents.push(event) - return acc - }, {}) -} - -const sendAggregatedEventByDay = async ( - events: UsageEvent[], - eventType: DaccEvent, - client: Client, - groupsKeys: { group1: string; group2?: string; group3?: string }, - groupsIndexes: number[], - customValues?: (string | null)[] -) => { - const reducedEvents = reduceEvents(events) - for (const item of Object.keys(reducedEvents)) { - const splittedKey = item.split('|') - let group1 = {} - let group2 = {} - let group3 = {} - if (groupsKeys.group1 && (groupsIndexes[0] !== 0 || customValues?.[0])) { - group1 = { - [groupsKeys.group1]: customValues?.[0] - ? customValues[0] - : splittedKey[groupsIndexes[0]], - } - } - if (groupsKeys.group2 && (groupsIndexes[1] !== 0 || customValues?.[1])) { - group2 = { - [groupsKeys.group2]: customValues?.[1] - ? customValues[1] - : splittedKey[groupsIndexes[1]], - } - } - if (groupsKeys.group3 && (groupsIndexes[2] !== 0 || customValues?.[2])) { - group3 = { - [groupsKeys.group3]: customValues?.[2] - ? customValues[2] - : splittedKey[groupsIndexes[2]], - } - } - const indicator: Indicator = { - createdBy: 'ecolyo', - measureName: eventType, - startDate: DateTime.fromISO(splittedKey[0]).toISODate(), - value: reducedEvents[item].length, - group1: group1, - ...(Object.keys(group2).length > 0 && { group2: group2 }), - ...(Object.keys(group3).length > 0 && { group3: group3 }), - } - const result = await sendIndicator(indicator, client) - if (result) { - readUsageEvents.push(...reducedEvents[item]) - } - } -} - -const handleQuizStars = async (events: UsageEvent[], client: Client) => { - events.forEach(async event => { - const indicator: Indicator = { - createdBy: 'ecolyo', - measureName: DaccEvent.QUIZ_STARS, - startDate: event.startDate ? event.startDate.toISODate() : '', - value: parseInt(event.result ? event.result : '0'), - // eslint-disable-next-line camelcase - group1: { challenge_id: event.context ? event.context : '' }, - // eslint-disable-next-line camelcase - group2: { quiz_id: event.target ? event.target : '' }, - } - const result = await sendIndicator(indicator, client) - if (result) { - readUsageEvents.push(event) - } - }) -} - -const calculSessionTime = async (events: UsageEvent[], client: Client) => { - let startSessionDate: DateTime | null = null - let isFirstConnection = false - let navigationCount = 0 - for (const [index, event] of events.entries()) { - if (event.type === UsageEventType.CONNECTION_EVENT) { - if ( - startSessionDate && - index > 0 && - events[index - 1].type !== UsageEventType.CONNECTION_EVENT - ) { - const endDate = events[index - 1].eventDate - const duration = endDate - .diff(startSessionDate, ['seconds']) - .toObject().seconds - const sessionIndicator: Indicator = { - createdBy: 'ecolyo', - measureName: DaccEvent.SESSION_DURATION, - startDate: startSessionDate.toISODate(), - value: duration === undefined ? 0 : duration, - // eslint-disable-next-line camelcase - group1: { number_pages: navigationCount.toString() }, - // eslint-disable-next-line camelcase - group2: { session_type: isFirstConnection ? 'first' : 'any' }, - } - await sendIndicator(sessionIndicator, client) - navigationCount = 0 - } - startSessionDate = event.eventDate - isFirstConnection = - event.result && event.result === 'firstConnection' ? true : false - } else if (event.type === UsageEventType.NAVIGATION_EVENT) { - if (startSessionDate) { - navigationCount += 1 - } - } else if (index === events.length - 1) { - if (startSessionDate) { - const endDate = event.eventDate - const duration = endDate - .diff(startSessionDate, ['seconds']) - .toObject().seconds - const sessionIndicator: Indicator = { - createdBy: 'ecolyo', - measureName: DaccEvent.SESSION_DURATION, - startDate: startSessionDate.toISODate(), - value: duration === undefined ? 0 : duration, - // eslint-disable-next-line camelcase - group1: { number_pages: navigationCount.toString() }, - // eslint-disable-next-line camelcase - group2: { session_type: isFirstConnection ? 'first' : 'any' }, - } - await sendIndicator(sessionIndicator, client) - } - } - } -} - -const calculPeriodBetweenFirstConnectionAndFirstChallenge = async ( - events: UsageEvent[], - firstConnectionEvent: UsageEvent, - client: Client -) => { - const challengeLaunchEvents: UsageEvent[] = events.filter( - (event: UsageEvent) => event.type === UsageEventType.CHALLENGE_LAUNCH_EVENT - ) - if ( - challengeLaunchEvents.length > 0 && - challengeLaunchEvents[0].target === 'CHALLENGE0001' - ) { - const periodIndicator: Indicator = { - createdBy: 'ecolyo', - measureName: DaccEvent.EVENT_DURATION, - startDate: firstConnectionEvent.eventDate.toISODate(), - value: challengeLaunchEvents[0].eventDate.diff( - firstConnectionEvent.eventDate - ).seconds, - // eslint-disable-next-line camelcase - group1: { start_event: 'first_session' }, - // eslint-disable-next-line camelcase - group2: { end_event: 'first_challenge' }, - group3: { params: '' }, - } - const result = await sendIndicator(periodIndicator, client) - if (result) { - readUsageEvents.push(challengeLaunchEvents[0]) - } - } -} - -const calculPeriodBetweenChallenge = async ( - events: UsageEvent[], - client: Client -) => { - const challengeLaunchEvents: UsageEvent[] = events.filter( - (event: UsageEvent) => event.type === UsageEventType.CHALLENGE_LAUNCH_EVENT - ) - if (challengeLaunchEvents.length > 0) { - const allEndedChallengeEvents: UsageEvent[] = - await UsageEventService.getEvents(client, { - type: UsageEventType.CHALLENGE_END_EVENT, - }) - for (const event of challengeLaunchEvents) { - if (event.target && event.target !== 'CHALLENGE0001') { - const challengeId: number = toNumber( - event.target.substr(event.target.length - 4) - ) - const prevChallengeId = `CHALLENGE${(challengeId - 1) - .toString() - .padStart(4, '0')}` - const previousEndedChallengeIndex: number = - allEndedChallengeEvents.findIndex( - (endedEvent: UsageEvent) => endedEvent.target === prevChallengeId - ) - if (previousEndedChallengeIndex > -1) { - const periodChallengeIndicator: Indicator = { - createdBy: 'ecolyo', - measureName: DaccEvent.EVENT_DURATION, - startDate: - allEndedChallengeEvents[ - previousEndedChallengeIndex - ].eventDate.toISODate(), - value: event.eventDate.diff( - allEndedChallengeEvents[previousEndedChallengeIndex].eventDate - ).seconds, - // eslint-disable-next-line camelcase - group1: { start_event: 'first_session' }, - // eslint-disable-next-line camelcase - group2: { end_event: 'first_challenge' }, - group3: { params: event.target + ':' + prevChallengeId }, - } - await sendIndicator(periodChallengeIndicator, client) - } - } - } - } -} - /** * Format a string with all konnectors in success state * @param konnectorFluidTypes FluidType[] @@ -359,7 +134,7 @@ const calculateConnectedKonnectorPerDay = async (client: Client) => { } const KonnectorConnectedPerDayIndicator: Indicator = { createdBy: 'ecolyo', - measureName: DaccEvent.KONNECTOR_CONNECTED_PER_DAY, + measureName: DaccIndicator.KONNECTOR_CONNECTED_PER_DAY, startDate: DateTime.local() .setZone('utc', { keepLocalTime: true, @@ -496,135 +271,69 @@ const calculateConsumptionVariation = async (client: Client) => { FluidType.GAS, FluidType.WATER, ]) { - if (fluidType < FluidType.MULTIFLUID.toFixed()) { - // Seniority process - const [firstConnectionEvent] = await UsageEventService.getEvents(client, { - type: UsageEventType.CONNECTION_EVENT, - result: 'firstConnection', - }) - - if (firstConnectionEvent) { - const seniority = 0 - // Seniority is set to 0, otherwise the indicator is too specific - // DateTime.local() - // .setZone('utc', { - // keepLocalTime: true, - // }) - // .diff(firstConnectionEvent.eventDate, 'month') - // .get('month') + // Seniority is set to 0, otherwise the indicator is too specific + const seniority = 0 - const consumptionVariationIndicator: Indicator = { - createdBy: 'ecolyo', - measureName: DaccEvent.CONSUMPTION_VARIATION_MONTHLY, - startDate: DateTime.local() - .setZone('utc', { - keepLocalTime: true, - }) - .startOf('day') - .toISODate(), - value: consumptionData[fluidType]?.percentageVariation - ? consumptionData[fluidType].percentageVariation - : 0, // in percent - // eslint-disable-next-line camelcase - group1: { fluid_type: FluidType[fluidType].toLowerCase() }, - // eslint-disable-next-line camelcase - group2: { seniority: Math.round(seniority).toString() }, - group3: { - // eslint-disable-next-line camelcase - fluid_usage: await buildProfileWithFluidType( - client, - getFluidType(FluidType[fluidType]) - ), - }, - } - - // if user wasn't connected during current month, dont send indicator - const events: UsageEvent[] = await UsageEventService.getEvents(client, { - eventDate: { - $lt: DateTime.local() - .setZone('utc', { - keepLocalTime: true, - }) - .endOf('month') - .minus({ month: 1 }) - .toString(), - $gt: DateTime.local() - .setZone('utc', { - keepLocalTime: true, - }) - .startOf('month') - .minus({ month: 1 }) - .toString(), - }, - }) - - if (events.length > 0 && consumptionVariationIndicator.value !== 0) { - logStack( - 'info', - `Send variation indicator : ${JSON.stringify( - consumptionVariationIndicator - )}` - ) - await sendIndicator(consumptionVariationIndicator, client) - } - } - } - } -} - -const sendConnectionCount = async (client: Client) => { - logStack('info', `sendConnectionCount`) - // Get daily connexion - const events: UsageEvent[] = await UsageEventService.getEvents(client, { - type: UsageEventType.CONNECTION_EVENT, - eventDate: { - $lt: DateTime.local() - .setZone('utc', { - keepLocalTime: true, - }) - .endOf('month') - .minus({ month: 1 }) - .toString(), - $gt: DateTime.local() + const consumptionVariationIndicator: Indicator = { + createdBy: 'ecolyo', + measureName: DaccIndicator.CONSUMPTION_VARIATION_MONTHLY, + startDate: DateTime.local() .setZone('utc', { keepLocalTime: true, }) - .startOf('month') - .minus({ month: 1 }) - .toString(), - }, - }) + .startOf('day') + .toISODate(), + value: consumptionData[fluidType]?.percentageVariation + ? consumptionData[fluidType].percentageVariation + : 0, // in percent + // eslint-disable-next-line camelcase + group1: { fluid_type: FluidType[fluidType].toLowerCase() }, + group2: { seniority: Math.round(seniority).toString() }, + group3: { + // eslint-disable-next-line camelcase + fluid_usage: await buildProfileWithFluidType( + client, + getFluidType(FluidType[fluidType]) + ), + }, + } - let uniqueDates = 0 - // If there is at least one connection, filter each unique connection in order to send it - if (events.length > 0) { - uniqueDates = events - .map(s => s.eventDate.day) - .filter((s, i, a) => a.indexOf(s) == i).length - } + // if user wasn't connected during current month, dont send indicator + const events = await UsageEventService.getEvents(client, { + eventDate: { + $lt: DateTime.local() + .setZone('utc', { + keepLocalTime: true, + }) + .endOf('month') + .minus({ month: 1 }) + .toString(), + $gt: DateTime.local() + .setZone('utc', { + keepLocalTime: true, + }) + .startOf('month') + .minus({ month: 1 }) + .toString(), + }, + }) - const connectionMonthly: Indicator = { - createdBy: 'ecolyo', - measureName: DaccEvent.CONNECTION_COUNT_MONTHLY, - startDate: DateTime.local() - .setZone('utc', { - keepLocalTime: true, - }) - .startOf('day') - .toISODate(), - value: uniqueDates, + if (events.length > 0 && consumptionVariationIndicator.value !== 0) { + logStack( + 'info', + `Send variation indicator : ${JSON.stringify( + consumptionVariationIndicator + )}` + ) + await sendIndicator(consumptionVariationIndicator, client) + } } - logStack( - 'info', - `Send connectionMonthly indicator : ${JSON.stringify(connectionMonthly)}` - ) - await sendIndicator(connectionMonthly, client) } const sendProfileCount = async (client: Client) => { logStack('info', `sendProfileCount`) // Get profile setEvents - const events: UsageEvent[] = await UsageEventService.getEvents(client, { + const events = await UsageEventService.getEvents(client, { type: UsageEventType.PROFILE_SET_EVENT, }) @@ -632,7 +341,7 @@ const sendProfileCount = async (client: Client) => { if (events.length > 0) { const profileSet: Indicator = { createdBy: 'ecolyo', - measureName: DaccEvent.PROFILE_COUNT_MONTHLY, + measureName: DaccIndicator.PROFILE_COUNT_MONTHLY, startDate: DateTime.local() .setZone('utc', { keepLocalTime: true, @@ -645,27 +354,67 @@ const sendProfileCount = async (client: Client) => { } } -const sendEmailSubscription = async (client: Client) => { - logStack('info', `sendEmailSubscription`) - const profile = await new ProfileService(client).getProfile() - if (profile?.sendAnalysisNotification) { - const cameBackFromEmail: Indicator = { +/** Send if user has came back to Ecolyo using the button in the newsletter */ +const sendNewsletterComeBack = async (client: Client) => { + logStack('info', `sendNewsletterComeBack`) + const events = await UsageEventService.getEvents(client, { + type: UsageEventType.REPORT_FROM_EMAIL, + eventDate: { + $lt: DateTime.local() + .setZone('utc', { + keepLocalTime: true, + }) + .minus({ days: 1 }) + .endOf('day') + .toString(), + $gt: DateTime.local() + .setZone('utc', { + keepLocalTime: true, + }) + .minus({ days: 1 }) + .startOf('day') + .toString(), + }, + }) + if (events.length) { + const cameBackFromNewsletter: Indicator = { createdBy: 'ecolyo', - measureName: DaccEvent.SUMMARY_SUBSCRIPTION_MONTHLY, + measureName: DaccIndicator.SUMMARY_SUBSCRIPTION_MONTHLY, startDate: DateTime.local() .setZone('utc', { keepLocalTime: true, }) + .minus({ days: 1 }) .startOf('day') .toISODate(), - value: profile.sendAnalysisNotification ? 1 : 0, + value: 1, // eslint-disable-next-line camelcase - group1: { event_type: 'subscribed' }, + group1: { event_type: 'email' }, } - await sendIndicator(cameBackFromEmail, client) + await sendIndicator(cameBackFromNewsletter, client) } } +const sendNewsletterSubscription = async (client: Client) => { + logStack('info', `sendEmailSubscription`) + const profile = await new ProfileService(client).getProfile() + if (!profile) return + const isSubscribed: Indicator = { + createdBy: 'ecolyo', + measureName: DaccIndicator.SUMMARY_SUBSCRIPTION_MONTHLY, + startDate: DateTime.local() + .setZone('utc', { + keepLocalTime: true, + }) + .startOf('day') + .toISODate(), + value: profile.sendAnalysisNotification ? 1 : 0, + // eslint-disable-next-line camelcase + group1: { event_type: 'subscribed' }, + } + await sendIndicator(isSubscribed, client) +} + /** * Send indicator to dacc, if user has half-hour data. * @param client CozyClient @@ -681,10 +430,9 @@ const sendHalfHourConsumption = async (client: Client) => { const halfHourConsumption: Indicator = { createdBy: 'ecolyo', - measureName: DaccEvent.FLUID_DATA_GRANULARITY, + measureName: DaccIndicator.FLUID_DATA_GRANULARITY, // eslint-disable-next-line camelcase group1: { fluid_type: 'electricity' }, - // eslint-disable-next-line camelcase group2: { granularity: 'half_hour' }, startDate: DateTime.local() .setZone('utc', { @@ -697,457 +445,6 @@ const sendHalfHourConsumption = async (client: Client) => { await sendIndicator(halfHourConsumption, client) } -/** - * Send indicator to dacc, each month send if user has succeeded to configure a connector with the number of try. - * @param client CozyClient - */ -const sendKonnectorEvents = async (client: Client) => { - logStack('info', `sendKonnectorEvents`) - const slugs = Object.values(FluidSlugType) - const today = DateTime.local().setZone('utc', { - keepLocalTime: true, - }) - slugs.forEach(async slug => { - let successEvents: UsageEvent[] = await UsageEventService.getEvents( - client, - { - type: UsageEventType.KONNECTOR_CONNECT_EVENT, - target: slug, - result: 'success', - eventDate: { - $lte: today.endOf('month').minus({ month: 1 }).toString(), - $gte: today.startOf('month').minus({ month: 1 }).toString(), - }, - }, - true - ) - - // If there is no success in month, send nothing - if (successEvents && successEvents.length > 0) { - // Get all success events - successEvents = await UsageEventService.getEvents( - client, - { - type: UsageEventType.KONNECTOR_CONNECT_EVENT, - target: slug, - result: 'success', - }, - true - ) - // Remove success from other month, they should have been already processed - // successEvents.length = successEventsOfCurrentMonth - - for (let index = 0; index < successEvents.length; index++) { - const successEvent = successEvents[index] - let query = null - - // If there is a previous value take it as reference for the query - // Else get all previous because it's the first one - if (index + 1 < successEvents.length) { - query = { - type: UsageEventType.KONNECTOR_CONNECT_EVENT, - target: slug, - result: 'error', - eventDate: { - $lte: successEvent.eventDate, - $gte: successEvents[index + 1].eventDate, - }, - } - } else { - query = { - type: UsageEventType.KONNECTOR_CONNECT_EVENT, - target: slug, - result: 'error', - eventDate: { - $lte: successEvent.eventDate, - }, - } - } - - const allConnectionEvents: UsageEvent[] = - await UsageEventService.getEvents(client, query, true) - - const konnectorSuccess: Indicator = { - createdBy: 'ecolyo', - measureName: DaccEvent.PARTNER_SUCCESS_MONTHLY, - // eslint-disable-next-line camelcase - group1: { fluid_type: slug }, - startDate: DateTime.local() - .setZone('utc', { - keepLocalTime: true, - }) - .startOf('day') - .toISODate(), - value: allConnectionEvents.length + 1, // +1 in order to count the success - } - // Send indicator if it's in current month - if (successEvent.eventDate.month === today.minus({ month: 1 }).month) { - await sendIndicator(konnectorSuccess, client) - } - } - } - }) -} - -/** - * Send the total number of partner connection attempts and the number of success - * @param client CozyClient - */ -const sendKonnectorAttemptsMonthly = async (client: Client) => { - logStack('info', `sendkonnectorAttemptsMonthly`) - const slugs = Object.values(FluidSlugType) - const today = DateTime.local().setZone('utc', { - keepLocalTime: true, - }) - // Count the number of connection and refresh events - slugs.forEach(async slug => { - const konnectorEvents: UsageEvent[] = await UsageEventService.getEvents( - client, - { - type: UsageEventType.KONNECTOR_ATTEMPT_EVENT, - target: slug, - eventDate: { - $lte: today.endOf('month').minus({ month: 1 }).toString(), - $gte: today.startOf('month').minus({ month: 1 }).toString(), - }, - }, - true - ) - logStack('info', ` : ${JSON.stringify(konnectorEvents)}`) - - // Check if there is a success (will be false or true since the event is triggered only for the first connexion) - const success: boolean = - konnectorEvents.filter(event => event.result == 'success').length > 0 - - const konnectorAttempts: Indicator = { - createdBy: 'ecolyo', - measureName: DaccEvent.UNINITIALIZED_KONNECTOR_ATTEMPTS_MONTHLY, - // eslint-disable-next-line camelcase - group1: { slug: slug }, - group2: { success: success }, - startDate: DateTime.local() - .setZone('utc', { - keepLocalTime: true, - }) - .startOf('day') - .toISODate(), - value: konnectorEvents.length, - } - // Send indicator if there is connection events - if (konnectorEvents.length > 0) { - await sendIndicator(konnectorAttempts, client) - } - }) -} - -const aggregateEvents = async ( - events: UsageEvent[], - eventType: UsageEventType, - firstConnectionEvent: UsageEvent, - client: Client -) => { - let reducedEvents = null // Used to store reducedEvents during calculation - switch (eventType) { - case UsageEventType.CONNECTION_EVENT: - await sendAggregatedEventByDay( - events, - DaccEvent.CONNECTION_COUNT_DAILY, - client, - { group1: 'device' }, - [UsageEventProperties.CONTEXT] - ) - break - case UsageEventType.KONNECTOR_CONNECT_EVENT: - await sendAggregatedEventByDay( - events, - DaccEvent.KONNECTOR_EVENT_DAILY, - client, - { group1: 'slug', group2: 'event_type', group3: 'status' }, - [UsageEventProperties.TARGET, 0, UsageEventProperties.RESULT], - [null, 'connexion', null] - ) - break - case UsageEventType.KONNECTOR_REFRESH_EVENT: - await sendAggregatedEventByDay( - events, - DaccEvent.KONNECTOR_EVENT_DAILY, - client, - { group1: 'slug', group2: 'event_type', group3: 'status' }, - [UsageEventProperties.TARGET, 0, UsageEventProperties.RESULT], - [null, 'refresh', null] - ) - break - case UsageEventType.NAVIGATION_EVENT: - await sendAggregatedEventByDay( - events, - DaccEvent.NAVIGATION_COUNT_DAILY, - client, - { group1: 'page' }, - [UsageEventProperties.TARGET] - ) - break - case UsageEventType.PROFILE_SET_EVENT: - await sendAggregatedEventByDay( - events, - DaccEvent.NAVIGATION_ACTION_DAILY, - client, - { group1: 'page', group2: 'feature', group3: 'params' }, - [0, 0, 0], - ['profile', 'profile_completed', '{}'] - ) - break - case UsageEventType.CONSUMPTION_COMPARE_EVENT: - reducedEvents = reduceEvents(events) - for (const item of Object.keys(reducedEvents)) { - const splitedKey = item.split('|') - const indicator: Indicator = { - createdBy: 'ecolyo', - measureName: DaccEvent.NAVIGATION_ACTION_DAILY, - startDate: DateTime.fromISO(splitedKey[0]).toISODate(), - value: reducedEvents[item].length, - group1: { - page: 'consumption', - }, - group2: { - feature: 'compare', - }, - group3: { - params: - splitedKey[UsageEventProperties.CONTEXT] + - ':' + - splitedKey[UsageEventProperties.TARGET], - }, - } - const result = await sendIndicator(indicator, client) - if (result) { - readUsageEvents.push(...reducedEvents[item]) - } - } - break - case UsageEventType.CONSUMPTION_CHANGE_TIMESTEP_EVENT: - reducedEvents = reduceEvents(events) - for (const item of Object.keys(reducedEvents)) { - const splitedKey = item.split('|') - const indicator: Indicator = { - createdBy: 'ecolyo', - measureName: DaccEvent.NAVIGATION_ACTION_DAILY, - startDate: DateTime.fromISO(splitedKey[0]).toISODate(), - value: reducedEvents[item].length, - group1: { - page: 'consumption', - }, - group2: { - feature: 'changestep', - }, - group3: { - params: - splitedKey[UsageEventProperties.CONTEXT] + - ':' + - splitedKey[UsageEventProperties.TARGET], - }, - } - const result = await sendIndicator(indicator, client) - if (result) { - readUsageEvents.push(...reducedEvents[item]) - } - } - break - case UsageEventType.ACTION_CHANGE_EVENT: - reducedEvents = reduceEvents(events) - for (const item of Object.keys(reducedEvents)) { - const splitedKey = item.split('|') - const indicator: Indicator = { - createdBy: 'ecolyo', - measureName: DaccEvent.NAVIGATION_ACTION_DAILY, - startDate: DateTime.fromISO(splitedKey[0]).toISODate(), - value: reducedEvents[item].length, - group1: { - page: 'action', - }, - group2: { - feature: 'change_ecogesture', - }, - group3: { - params: - splitedKey[UsageEventProperties.TARGET] + - ':' + - splitedKey[UsageEventProperties.CONTEXT], - }, - } - const result = await sendIndicator(indicator, client) - if (result) { - readUsageEvents.push(...reducedEvents[item]) - } - } - break - case UsageEventType.CHALLENGE_END_EVENT: - for (const event of events) { - const duelLaunchIndicator: Indicator = { - createdBy: 'ecolyo', - measureName: DaccEvent.EVENT_DURATION, - startDate: event.eventDate.toISODate(), - value: event.startDate - ? event.eventDate.diff(event.startDate, ['seconds']).seconds - : 0, - // eslint-disable-next-line camelcase - group1: { start_event: 'start_challenge' }, - // eslint-disable-next-line camelcase - group2: { end_event: 'end_challenge' }, - group3: { params: event.target ? event.target : '' }, - } - const result = await sendIndicator(duelLaunchIndicator, client) - - if (result) { - readUsageEvents.push(event) - } - } - break - case UsageEventType.QUIZ_END_EVENT: - handleQuizStars(events, client) - break - case UsageEventType.EXPLORATION_END_EVENT: - for (const event of events) { - const duelLaunchIndicator: Indicator = { - createdBy: 'ecolyo', - measureName: DaccEvent.EVENT_DURATION, - startDate: event.eventDate.toISODate(), - value: event.startDate - ? event.eventDate.diff(event.startDate, ['seconds']).seconds - : 0, - // eslint-disable-next-line camelcase - group1: { start_event: 'start_exploration' }, - // eslint-disable-next-line camelcase - group2: { end_event: 'end_exploration' }, - group3: { params: event.context + ':' + event.target }, - } - const result = await sendIndicator(duelLaunchIndicator, client) - - if (result) { - readUsageEvents.push(event) - } - } - break - case UsageEventType.ACTION_END_EVENT: - for (const event of events) { - const duelLaunchIndicator: Indicator = { - createdBy: 'ecolyo', - measureName: DaccEvent.EVENT_DURATION, - startDate: event.eventDate.toISODate(), - value: event.startDate - ? event.eventDate.diff(event.startDate, ['seconds']).seconds - : 0, - // eslint-disable-next-line camelcase - group1: { start_event: 'start_action' }, - // eslint-disable-next-line camelcase - group2: { end_event: 'end_action' }, - group3: { params: event.target + ':' + event.context }, - } - const result = await sendIndicator(duelLaunchIndicator, client) - - if (result) { - readUsageEvents.push(event) - } - } - break - case UsageEventType.DUEL_END_EVENT: - for (const event of events) { - const duelLaunchIndicator: Indicator = { - createdBy: 'ecolyo', - measureName: DaccEvent.EVENT_DURATION, - startDate: event.eventDate.toISODate(), - value: event.startDate - ? event.eventDate.diff(event.startDate, ['seconds']).seconds - : 0, - // eslint-disable-next-line camelcase - group1: { start_event: 'start_duel' }, - // eslint-disable-next-line camelcase - group2: { end_event: 'end_duel' }, - group3: { - params: event.target + ':' + event.context + ':' + event.result, - }, - } - const result = await sendIndicator(duelLaunchIndicator, client) - - if (result) { - readUsageEvents.push(event) - } - } - break - case UsageEventType.DUEL_LAUNCH_EVENT: - // Get challenge ID - const challenges = await new ChallengeService( - client - ).getAllUserChallengeEntities() - const filteredCurrentChallenge = challenges.filter( - challenge => - challenge.state === UserChallengeState.ONGOING || - challenge.state === UserChallengeState.DUEL - ) - const currentChallenge = filteredCurrentChallenge[0] - ? filteredCurrentChallenge[0] - : null - - let starNumbers = 0 - if (currentChallenge?.progress) { - starNumbers = - currentChallenge.progress.actionProgress + - currentChallenge.progress.explorationProgress + - currentChallenge.progress.quizProgress - } - - for (const event of events) { - const duelLaunchIndicator: Indicator = { - createdBy: 'ecolyo', - measureName: DaccEvent.EVENT_DURATION, - startDate: event.eventDate.toISODate(), - value: event.startDate - ? event.eventDate.diff(event.startDate, ['seconds']).seconds - : 0, - // eslint-disable-next-line camelcase - group1: { start_event: 'start_duel' }, - // eslint-disable-next-line camelcase - group2: { end_event: 'start_duel' }, - group3: { - params: event.target + ':' + event.context + ':' + starNumbers, - }, - } - const result = await sendIndicator(duelLaunchIndicator, client) - - if (result) { - readUsageEvents.push(event) - } - } - break - case UsageEventType.CHALLENGE_LAUNCH_EVENT: - await calculPeriodBetweenFirstConnectionAndFirstChallenge( - events, - firstConnectionEvent, - client - ) - await calculPeriodBetweenChallenge(events, client) - break - case UsageEventType.REPORT_FROM_EMAIL: - for (const event of events) { - const cameBackFromEmail: Indicator = { - createdBy: 'ecolyo', - measureName: DaccEvent.SUMMARY_SUBSCRIPTION_MONTHLY, - startDate: event.eventDate.toISODate(), - value: 1, - // eslint-disable-next-line camelcase - group1: { event_type: 'email' }, - } - const result = await sendIndicator(cameBackFromEmail, client) - - if (result) { - readUsageEvents.push(event) - } - } - break - default: - break - } -} - const AggregatorUsageEvents = async ({ client, }: AggregatorUsageEventsProps) => { @@ -1159,40 +456,9 @@ const AggregatorUsageEvents = async ({ return } - const events: UsageEvent[] = await UsageEventService.getEvents(client, { - aggregated: false, - eventDate: { - $lt: DateTime.local() - .setZone('utc', { - keepLocalTime: true, - }) - .startOf('day'), - }, - }) - const [firstConnectionEvent] = await UsageEventService.getEvents(client, { - type: UsageEventType.CONNECTION_EVENT, - result: 'firstConnection', - }) - if (events.length > 0) { - logStack('info', `Fetching Sessions`) - calculSessionTime(events, client) - for (const eventType of Object.values(UsageEventType)) { - logStack('info', `Fetching ${eventType}`) - const filteredEvents: UsageEvent[] = events.filter( - event => event.type === eventType - ) - if (filteredEvents.length > 0) { - await aggregateEvents( - filteredEvents, - eventType, - firstConnectionEvent, - client - ) - } - } - } // Daily events - calculateConnectedKonnectorPerDay(client) + await calculateConnectedKonnectorPerDay(client) + await sendNewsletterComeBack(client) // Monthly events const profile = await new ProfileService(client).getProfile() if ( @@ -1203,12 +469,9 @@ const AggregatorUsageEvents = async ({ }) .startOf('day').day === profile.monthlyAnalysisDate.day ) { - await sendKonnectorAttemptsMonthly(client) await calculateConsumptionVariation(client) - await sendEmailSubscription(client) + await sendNewsletterSubscription(client) await sendHalfHourConsumption(client) - await sendKonnectorEvents(client) - await sendConnectionCount(client) await sendProfileCount(client) } diff --git a/tests/__mocks__/usageEventsData.mock.ts b/tests/__mocks__/usageEventsData.mock.ts index d96ad448d38f992e294302ea5f114caf3ab4d897..baef2eb627af43f6e319df2e54ae65427f3ad506 100644 --- a/tests/__mocks__/usageEventsData.mock.ts +++ b/tests/__mocks__/usageEventsData.mock.ts @@ -4,16 +4,14 @@ import { UsageEvent, UsageEventEntity } from 'models' export const usageEventEntityData: UsageEventEntity = { _id: '0001', - type: UsageEventType.CONNECTION_EVENT, - context: 'test', + type: UsageEventType.PROFILE_SET_EVENT, eventDate: '2020-10-10T08:08:08.008Z', aggregated: false, } export const usageEventData: UsageEvent = { _id: '0001', - type: UsageEventType.CONNECTION_EVENT, - context: 'test', + type: UsageEventType.PROFILE_SET_EVENT, eventDate: DateTime.fromISO('2020-10-10T08:08:08.008Z', { zone: 'utc', }), @@ -23,8 +21,7 @@ export const usageEventData: UsageEvent = { export const allUsageEventsData: UsageEvent[] = [ { _id: '0001', - type: UsageEventType.CONNECTION_EVENT, - context: 'desktop', + type: UsageEventType.PROFILE_SET_EVENT, eventDate: DateTime.fromISO('2020-10-10T08:08:08.008Z', { zone: 'utc', }), @@ -32,8 +29,8 @@ export const allUsageEventsData: UsageEvent[] = [ }, { _id: '0002', - type: UsageEventType.NAVIGATION_EVENT, - target: 'consumption', + type: UsageEventType.REPORT_FROM_EMAIL, + target: 'analysis', eventDate: DateTime.fromISO('2020-10-10T08:09:08.008Z', { zone: 'utc', }), @@ -41,8 +38,7 @@ export const allUsageEventsData: UsageEvent[] = [ }, { _id: '0003', - type: UsageEventType.CONNECTION_EVENT, - context: 'desktop', + type: UsageEventType.PROFILE_SET_EVENT, eventDate: DateTime.fromISO('2020-10-11T08:08:08.008Z', { zone: 'utc', }), @@ -50,8 +46,8 @@ export const allUsageEventsData: UsageEvent[] = [ }, { _id: '0004', - type: UsageEventType.NAVIGATION_EVENT, - context: 'challenge', + type: UsageEventType.REPORT_FROM_EMAIL, + context: 'analysis', eventDate: DateTime.fromISO('2020-10-11T08:09:08.008Z', { zone: 'utc', }), @@ -59,44 +55,25 @@ export const allUsageEventsData: UsageEvent[] = [ }, ] -export const connectionEventEntitiesData: UsageEventEntity[] = [ +export const profileSetEventEntitiesData: UsageEventEntity[] = [ { _id: '0001', - type: UsageEventType.CONNECTION_EVENT, - context: 'desktop', + type: UsageEventType.PROFILE_SET_EVENT, eventDate: '2020-10-10T08:08:08.008Z', aggregated: false, }, { _id: '0002', - type: UsageEventType.CONNECTION_EVENT, - context: 'desktop', + type: UsageEventType.PROFILE_SET_EVENT, eventDate: '2020-10-11T08:08:08.008Z', aggregated: false, }, ] -export const connectionAttemptEGLError: UsageEventEntity = { - _id: '00078', - type: UsageEventType.KONNECTOR_ATTEMPT_EVENT, - target: 'eglgrandlyon', - result: 'error', - eventDate: '2020-10-10T08:08:08.008Z', - aggregated: false, -} -export const connectionAttemptEGLSuccess: UsageEventEntity = { - _id: '00078', - type: UsageEventType.KONNECTOR_ATTEMPT_EVENT, - target: 'eglgrandlyon', - result: 'success', - eventDate: '2020-10-10T08:08:08.008Z', - aggregated: false, -} -export const connectionUsageEventsData: UsageEvent[] = [ +export const profileSetUsageEventsData: UsageEvent[] = [ { _id: '0001', - type: UsageEventType.CONNECTION_EVENT, - context: 'desktop', + type: UsageEventType.PROFILE_SET_EVENT, eventDate: DateTime.fromISO('2020-10-10T08:08:08.008Z', { zone: 'utc', }), @@ -104,8 +81,7 @@ export const connectionUsageEventsData: UsageEvent[] = [ }, { _id: '0002', - type: UsageEventType.CONNECTION_EVENT, - context: 'desktop', + type: UsageEventType.PROFILE_SET_EVENT, eventDate: DateTime.fromISO('2020-10-11T08:08:08.008Z', { zone: 'utc', }),