From 8ae15522e8d6eb7403a43eee995c04fa8802db5c Mon Sep 17 00:00:00 2001 From: GPlay97 Date: Wed, 14 Aug 2024 22:32:52 +0200 Subject: [PATCH 1/3] =?UTF-8?q?=E2=9C=A8=20introduce=20log=20type,=20adapt?= =?UTF-8?q?=20code=20and=20log=20creation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/logs/dto/log.dto.ts | 10 ++++++---- src/logs/dto/update-log.dto.ts | 7 ++++--- src/logs/entities/status.entity.ts | 6 +++--- src/logs/entities/type.entity.ts | 5 +++++ src/logs/handler/metadata.ts | 2 +- src/logs/logs.controller.spec.ts | 5 +++-- src/logs/logs.controller.ts | 5 +++-- src/logs/logs.service.ts | 12 ++++++++---- src/logs/schemas/log.schema.ts | 9 +++++++-- 9 files changed, 40 insertions(+), 21 deletions(-) create mode 100644 src/logs/entities/type.entity.ts diff --git a/src/logs/dto/log.dto.ts b/src/logs/dto/log.dto.ts index c6ab1f0..8e3035a 100644 --- a/src/logs/dto/log.dto.ts +++ b/src/logs/dto/log.dto.ts @@ -11,6 +11,7 @@ import { } from 'class-validator'; import { STATUS } from '../entities/status.entity'; import { Log } from '../schemas/log.schema'; +import { TYPE } from '../entities/type.entity'; export class LogDto { constructor(log?: Log) { @@ -18,9 +19,9 @@ export class LogDto { this.updatedAt = log?.updatedAt; this.title = log?.title; this.status = log?.status; + this.type = log?.type; this.startDate = log?.startDate; this.endDate = log?.endDate; - this.isCharge = log?.isCharge; this.startSOC = log?.startSOC; this.endSOC = log?.endSOC; this.startODO = log?.startODO; @@ -50,6 +51,10 @@ export class LogDto { @IsNotEmpty() status: STATUS = STATUS.RUNNING; + @IsEnum(TYPE) + @IsNotEmpty() + type: TYPE = TYPE.UNKNOWN; + @IsDate() @IsNotEmpty() startDate: Date; @@ -58,9 +63,6 @@ export class LogDto { @IsOptional() endDate: Date; - @IsBoolean() - isCharge = false; - @IsNumber() @Min(0) @Max(100) diff --git a/src/logs/dto/update-log.dto.ts b/src/logs/dto/update-log.dto.ts index 849205f..3936a2d 100644 --- a/src/logs/dto/update-log.dto.ts +++ b/src/logs/dto/update-log.dto.ts @@ -1,11 +1,12 @@ -import { IsString, IsOptional, IsBoolean } from 'class-validator'; +import { IsString, IsOptional, IsBoolean, IsEnum } from 'class-validator'; +import { TYPE } from '../entities/type.entity'; export class UpdateLogDto { @IsString() @IsOptional() title: string; - @IsBoolean() + @IsEnum(TYPE) @IsOptional() - isCharge = false; + type: TYPE = TYPE.UNKNOWN; } diff --git a/src/logs/entities/status.entity.ts b/src/logs/entities/status.entity.ts index 6fcbc95..5db5a14 100644 --- a/src/logs/entities/status.entity.ts +++ b/src/logs/entities/status.entity.ts @@ -1,5 +1,5 @@ export enum STATUS { - RUNNING = 'RUNNING', - FINISHED = 'FINISHED', - ABORTED = 'ABORTED', + RUNNING = 'running', + FINISHED = 'finished', + ABORTED = 'aborted', } diff --git a/src/logs/entities/type.entity.ts b/src/logs/entities/type.entity.ts new file mode 100644 index 0000000..5617199 --- /dev/null +++ b/src/logs/entities/type.entity.ts @@ -0,0 +1,5 @@ +export enum TYPE { + CHARGE = 'charge', + DRIVE = 'drive', + UNKNOWN = 'unknown', +} diff --git a/src/logs/handler/metadata.ts b/src/logs/handler/metadata.ts index 3e5d925..8897bb0 100644 --- a/src/logs/handler/metadata.ts +++ b/src/logs/handler/metadata.ts @@ -37,7 +37,7 @@ export class MetadataHandler { } const mapping = { - isCharge: 'charging', + type: 'charging', startODO: 'odo', startCEC: 'cec', startCED: 'ced', diff --git a/src/logs/logs.controller.spec.ts b/src/logs/logs.controller.spec.ts index 712dd0f..1c4a328 100644 --- a/src/logs/logs.controller.spec.ts +++ b/src/logs/logs.controller.spec.ts @@ -14,6 +14,7 @@ import { EventEmitterModule } from '@nestjs/event-emitter'; import { UpdateLogDto } from './dto/update-log.dto'; import { STATUS } from './entities/status.entity'; import { LastSyncDto } from './dto/last-sync.dto'; +import { TYPE } from './entities/type.entity'; describe('LogsController', () => { let accountService: AccountService; @@ -123,7 +124,7 @@ describe('LogsController', () => { }); it('should be able to filter out log in list', async () => { - const response = await controller.findAll(testAccount.akey, false); + const response = await controller.findAll(testAccount.akey, TYPE.DRIVE); expect(response).toHaveLength(0); }); @@ -283,7 +284,7 @@ describe('LogsController', () => { const response = await controller.findOne(testAccount.akey, chargeLogId); expect(response).toBeInstanceOf(LogDto); - expect(response).toHaveProperty('isCharge', true); + expect(response).toHaveProperty('type', TYPE.CHARGE); expect(response).toHaveProperty('startSOC', 75); expect(response).toHaveProperty('averageKW', 10); }); diff --git a/src/logs/logs.controller.ts b/src/logs/logs.controller.ts index 402c7aa..ca1bf1a 100644 --- a/src/logs/logs.controller.ts +++ b/src/logs/logs.controller.ts @@ -22,6 +22,7 @@ import { SyncDto } from './dto/sync.dto'; import { ApiTags, ApiBearerAuth } from '@nestjs/swagger'; import { LogNotExistsException } from './exceptions/log-not-exists.exception'; import { LogMissingSyncDataException } from './exceptions/log-missing-sync-data.exception'; +import { TYPE } from './entities/type.entity'; @Controller('logs') @UseGuards(AuthGuard) @@ -32,8 +33,8 @@ export class LogsController { constructor(private readonly logsService: LogsService) {} @Get(':akey') - async findAll(@Param('akey') akey: string, @Query('isCharge') isCharge?: boolean) { - return this.logsService.findAll(akey, isCharge); + async findAll(@Param('akey') akey: string, @Query('type') type?: TYPE) { + return this.logsService.findAll(akey, type); } @Get(':akey/last-sync') diff --git a/src/logs/logs.service.ts b/src/logs/logs.service.ts index 4d142ca..a89c023 100644 --- a/src/logs/logs.service.ts +++ b/src/logs/logs.service.ts @@ -17,6 +17,7 @@ import { LogNotExistsException } from './exceptions/log-not-exists.exception'; import { LastSync } from './schemas/last-sync.schema'; import { Log } from './schemas/log.schema'; import { Sync } from './schemas/sync.schema'; +import { TYPE } from './entities/type.entity'; @Injectable() export class LogsService { @@ -54,7 +55,10 @@ export class LogsService { if (!log) { return await this.logModel.create({ akey }); } else { - if (syncDto.charging != null && syncDto.charging !== log.isCharge) { + if (syncDto.charging != null && log.type == TYPE.UNKNOWN) { + log.type = syncDto.charging ? TYPE.CHARGE : TYPE.DRIVE; + await log.save(); + } else if (syncDto.charging && log.type != TYPE.CHARGE || syncDto.charging == false && log.type != TYPE.DRIVE) { log.status = STATUS.FINISHED; await log.save(); this.eventEmitter.emit(LOG_FINISHED_EVENT, log); @@ -72,14 +76,14 @@ export class LogsService { return new LastSyncDto(lastSync); } - async findAll(akey: string, isCharge?: boolean): Promise { + async findAll(akey: string, type?: TYPE): Promise { const logs = this.logModel .find({ akey }) .select('-history') .sort('startDate'); - if (isCharge != null) { - logs.where({ isCharge }); + if (type != null) { + logs.where({ type }); } return Promise.resolve((await logs).map((log) => new LogDto(log))); diff --git a/src/logs/schemas/log.schema.ts b/src/logs/schemas/log.schema.ts index 5ec63f6..360be67 100644 --- a/src/logs/schemas/log.schema.ts +++ b/src/logs/schemas/log.schema.ts @@ -3,6 +3,7 @@ import { Document, Types } from 'mongoose'; import { AKEY_LENGTH } from '../../account/dto/account.dto'; import { STATUS } from '../entities/status.entity'; import { Sync } from './sync.schema'; +import { TYPE } from '../entities/type.entity'; export type LogDocument = Log & Document; @@ -34,8 +35,12 @@ export class Log { }) status: STATUS; - @Prop() - isCharge: boolean; + @Prop({ + required: true, + default: TYPE.UNKNOWN, + enum: TYPE, + }) + type: TYPE; @Prop() startDate: Date; From 552e6ab40399f7ef400e04b9b685365d02a24198 Mon Sep 17 00:00:00 2001 From: GPlay97 Date: Sun, 18 Aug 2024 13:27:43 +0200 Subject: [PATCH 2/3] =?UTF-8?q?=E2=9C=85=20extend=20test=20to=20cover=20ty?= =?UTF-8?q?pes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/logs/logs.controller.spec.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/logs/logs.controller.spec.ts b/src/logs/logs.controller.spec.ts index 1c4a328..868a0de 100644 --- a/src/logs/logs.controller.spec.ts +++ b/src/logs/logs.controller.spec.ts @@ -222,6 +222,7 @@ describe('LogsController', () => { const response = await controller.findAll(testAccount.akey); expect(response).toHaveLength(1); + expect(response.at(0)).toHaveProperty('type', TYPE.UNKNOWN); logId = response[0].id; }); @@ -257,6 +258,20 @@ describe('LogsController', () => { ); }); + it('should update log type instead of creating new log if unknown', async () => { + const dto = new SyncDto(); + + dto.charging = false; + + await controller.syncData(testAccount.akey, dto); + + const response = await controller.findAll(testAccount.akey); + + expect(response).toHaveLength(1); + expect(response.at(0)).toHaveProperty('id', logId); + expect(response.at(0)).toHaveProperty('type', TYPE.DRIVE); + }); + it('should create a new log once charging started', async () => { const dto = new SyncDto(); @@ -269,6 +284,7 @@ describe('LogsController', () => { const response = await controller.findAll(testAccount.akey); expect(response).toHaveLength(2); + expect(response.at(1)).toHaveProperty('type', TYPE.CHARGE); chargeLogId = response[1].id; }); From c76105c7ef613bc8f15a63467990d0e33deaa22b Mon Sep 17 00:00:00 2001 From: GPlay97 Date: Sun, 18 Aug 2024 13:28:03 +0200 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=90=9B=20log=20type=20not=20assigned?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/logs/handler/metadata.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/logs/handler/metadata.ts b/src/logs/handler/metadata.ts index 8897bb0..7b1ad8a 100644 --- a/src/logs/handler/metadata.ts +++ b/src/logs/handler/metadata.ts @@ -10,6 +10,7 @@ import { import { STATUS } from '../entities/status.entity'; import { Log } from '../schemas/log.schema'; import { Sync } from '../schemas/sync.schema'; +import { TYPE } from '../entities/type.entity'; @Injectable() export class MetadataHandler { @@ -46,9 +47,16 @@ export class MetadataHandler { for (const logField in mapping) { if (Object.prototype.hasOwnProperty.call(mapping, logField)) { const syncField = mapping[logField]; + const syncValue = sync[syncField]; - if (log[logField] == null && sync[syncField] != null) { - log[logField] = sync[syncField]; + if (syncField === 'charging' && log[logField] === TYPE.UNKNOWN && syncValue != null) { + log[logField] = syncValue ? TYPE.CHARGE : TYPE.DRIVE; + } else if (log[logField] == null && syncValue != null) { + log[logField] = syncValue; + } + + if ((syncField === 'charging' ? log[logField] == TYPE.UNKNOWN : log[logField] == null) && syncValue != null) { + log[logField] = syncValue; } } }