Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/logs/entities/history-type.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export enum HISTORY_TYPE {
ALL = 'all',
LOCATION_DATA = 'location',
BATTERY_DATA = 'battery',
}
44 changes: 42 additions & 2 deletions src/logs/logs.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ 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';
import { HISTORY_TYPE } from './entities/history-type.entity';

describe('LogsController', () => {
let accountService: AccountService;
Expand Down Expand Up @@ -161,7 +162,8 @@ describe('LogsController', () => {
it('should be able to sync data with a timestamp', async () => {
const dto = new SyncDto();

dto.socDisplay = 80;
dto.latitude = 32.123;
dto.longitude = 34.111;
dto.timestamp = '2022-11-06T22:15:58.238Z';

const response = await controller.syncData(testAccount.akey, dto);
Expand All @@ -176,13 +178,51 @@ describe('LogsController', () => {
);

expect(response).toHaveLength(2);
expect(response.at(1)).toHaveProperty('socDisplay', 80);
expect(response.at(1)).toHaveProperty('latitude', 32.123);
expect(response.at(1)).toHaveProperty('longitude', 34.111);
expect(response.at(1)).toHaveProperty(
'timestamp',
'2022-11-06T22:15:58.238Z',
);
});

it('should be able to retrieve location log history', async () => {
const response = await controller.findOneWithHistory(
testAccount.akey,
logId,
HISTORY_TYPE.LOCATION_DATA
);

expect(response).toHaveLength(1);
expect(response.at(0)).toHaveProperty('latitude', 32.123);
expect(response.at(0)).toHaveProperty('longitude', 34.111);
expect(response.at(0)).toHaveProperty(
'timestamp',
'2022-11-06T22:15:58.238Z',
);
});

it('should be able to retrieve battery log history', async () => {
const response = await controller.findOneWithHistory(
testAccount.akey,
logId,
HISTORY_TYPE.BATTERY_DATA
);

expect(response).toHaveLength(1);
expect(response.at(0)).toHaveProperty('socDisplay', 80);
});

it('should be able to retrieve all log history', async () => {
const response = await controller.findOneWithHistory(
testAccount.akey,
logId,
HISTORY_TYPE.ALL
);

expect(response).toHaveLength(2);
});

it('should be able to update log', async () => {
const dto = new UpdateLogDto();

Expand Down
4 changes: 3 additions & 1 deletion src/logs/logs.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { LogNotExistsException } from './exceptions/log-not-exists.exception';
import { LogMissingSyncDataException } from './exceptions/log-missing-sync-data.exception';
import { TYPE } from './entities/type.entity';
import { LogNotRunningException } from './exceptions/log-not-running.exception';
import { HISTORY_TYPE } from './entities/history-type.entity';

@Controller('logs')
@UseGuards(AuthGuard)
Expand Down Expand Up @@ -75,9 +76,10 @@ export class LogsController {
async findOneWithHistory(
@Param('akey') akey: string,
@Param('id') id: string,
@Query('type') type?: HISTORY_TYPE,
) {
try {
return await this.logsService.findOneWithHistory(akey, id);
return await this.logsService.findOneWithHistory(akey, id, type);
} catch (error) {
if (error instanceof LogNotExistsException) {
throw new NotFoundException(error.message);
Expand Down
82 changes: 73 additions & 9 deletions src/logs/logs.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Injectable } from '@nestjs/common';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { Model, Types } from 'mongoose';
import { LastSyncDto } from './dto/last-sync.dto';
import { LogDto } from './dto/log.dto';
import { SyncDto } from './dto/sync.dto';
Expand All @@ -19,6 +19,7 @@ import { Log } from './schemas/log.schema';
import { Sync } from './schemas/sync.schema';
import { TYPE } from './entities/type.entity';
import { LogNotRunningException } from './exceptions/log-not-running.exception';
import { HISTORY_TYPE } from './entities/history-type.entity';

@Injectable()
export class LogsService {
Expand Down Expand Up @@ -114,16 +115,79 @@ export class LogsService {
return Promise.resolve(new LogDto(log));
}

async findOneWithHistory(akey: string, id: string) {
const log = await this.logModel
.findOne({ akey, _id: id })
.select('history');

if (!log) {
throw new LogNotExistsException();
async findOneWithHistory(akey: string, id: string, type: HISTORY_TYPE = HISTORY_TYPE.ALL): Promise<Sync[]> {
let history = [];

switch (type) {
case HISTORY_TYPE.ALL:
const logWithAllHistory = await this.logModel
.findOne({ akey, _id: id })
.select('history');

if (!logWithAllHistory) {
throw new LogNotExistsException();
}

history = logWithAllHistory.history;
break;
case HISTORY_TYPE.LOCATION_DATA:
const logWithLocationHistory = await this.logModel.aggregate([
{
$match: { akey, _id: new Types.ObjectId(id) }
},
{
$project: {
_id: 0,
history: {
$filter: {
input: '$history',
as: 'entry',
cond: {
$and: [
{ $in: [{ $type: '$$entry.latitude' }, ['double', 'int', 'long']] },
{ $in: [{ $type: '$$entry.longitude' }, ['double', 'int', 'long']] },
],
},
},
},
}
}
]);

history = logWithLocationHistory.map((entry) => entry.history)[0];
break;
case HISTORY_TYPE.BATTERY_DATA:
const logWithBatteryHistory = await this.logModel.aggregate([
{
$match: { akey, _id: new Types.ObjectId(id) }
},
{
$project: {
_id: 0,
history: {
$filter: {
input: '$history',
as: 'entry',
cond: {
$or: [
{ $in: [{ $type: '$$entry.socDisplay' }, ['double', 'int', 'long']] },
{ $in: [{ $type: '$$entry.socBMS' }, ['double', 'int', 'long']] },
{ $in: [{ $type: '$$entry.dcBatteryPower' }, ['double', 'int', 'long']] },
],
},
},
},
}
}
]);

history = logWithBatteryHistory.map((entry) => entry.history)[0];
break;
default:
break;
}

return log.history;
return history;
}

async update(
Expand Down