Skip to content

Commit

Permalink
Merge pull request #170 from innovationacademy-kr/feat-#143-1
Browse files Browse the repository at this point in the history
#143 trim 로직 개선
  • Loading branch information
niamu01 authored Mar 25, 2023
2 parents e109308 + 7991e46 commit 35ecba8
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 59 deletions.
8 changes: 8 additions & 0 deletions src/tag-log-v2/dto/device-info.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Cluster from 'src/enums/cluster.enum';
import InOut from 'src/enums/inout.enum';

export class DeviceInfoDto {
device_id: number;
campus: Cluster;
io_type: InOut;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { DeviceInfoDto } from 'src/tag-log-v2/dto/device-info.dto';

export interface IDeviceInfoRepository {
/**
* 모든 등록된 카드태깅 디바이스 정보를 가져옵니다.
*/
findAll(): Promise<DeviceInfoDto[]>;
}
16 changes: 16 additions & 0 deletions src/tag-log-v2/repository/mysql/device-info.repository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { DeviceInfoDto } from 'src/tag-log-v2/dto/device-info.dto';
import { IDeviceInfoRepository } from '../interface/device-info-repository.interface';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { DeviceInfo } from 'src/entities/device-info.entity';

export class DeviceInfoRepository implements IDeviceInfoRepository {
constructor(
@InjectRepository(DeviceInfo)
private deviceInfoRepository: Repository<DeviceInfo>,
) {}

async findAll(): Promise<DeviceInfoDto[]> {
return await this.deviceInfoRepository.find();
}
}
11 changes: 9 additions & 2 deletions src/tag-log-v2/tag-log-v2.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { TagLogRepository } from './repository/mysql/tag-log.repository';
import { TagLogController } from './tag-log-v2.controller';
import { TagLogService } from './tag-log-v2.service';
import { StatisticsModule } from 'src/statistics/statictics.module';
import { DeviceInfo } from 'src/entities/device-info.entity';
import { DeviceInfoRepository } from './repository/mysql/device-info.repository';

const tagLogRepo = {
provide: 'ITagLogRepository',
Expand All @@ -21,16 +23,21 @@ const pairInfoRepo = {
useClass: PairInfoRepository,
};

const deviceInfoRepo = {
provide: 'IDeviceInfoRepository',
useClass: DeviceInfoRepository,
};

@Module({
imports: [
AuthModule,
TypeOrmModule.forFeature([TagLog, PairInfo]),
TypeOrmModule.forFeature([TagLog, PairInfo, DeviceInfo]),
UtilsModule,
UserModule,
StatisticsModule,
],
exports: [TypeOrmModule],
controllers: [TagLogController],
providers: [tagLogRepo, pairInfoRepo, TagLogService],
providers: [tagLogRepo, pairInfoRepo, deviceInfoRepo, TagLogService],
})
export class TagLogModule2 {}
4 changes: 4 additions & 0 deletions src/tag-log-v2/tag-log-v2.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ const mocks = [
provide: 'IPairInfoRepository',
useClass: jest.fn(),
},
{
provide: 'IDeviceInfoRepository',
useClass: jest.fn(),
},
];

describe('Tag Log (v2) unit 테스트', () => {
Expand Down
133 changes: 76 additions & 57 deletions src/tag-log-v2/tag-log-v2.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { InOutLogType } from './dto/subType/InOutLog.type';
import { ITagLogRepository } from './repository/interface/tag-log-repository.interface';
import { IPairInfoRepository } from './repository/interface/pair-info-repository.interface';
import { CardDto } from 'src/user/dto/card.dto';
import { IDeviceInfoRepository } from './repository/interface/device-info-repository.interface';
import { DeviceInfoDto } from './dto/device-info.dto';

@Injectable()
export class TagLogService {
Expand All @@ -20,6 +22,8 @@ export class TagLogService {
private tagLogRepository: ITagLogRepository,
@Inject('IPairInfoRepository')
private pairInfoRepository: IPairInfoRepository,
@Inject('IDeviceInfoRepository')
private deviceInfoRepository: IDeviceInfoRepository,
private dateCalculator: DateCalculator,
) {}

Expand All @@ -42,44 +46,44 @@ export class TagLogService {
}

/**
* 카드 태그 로그에 대해 로그 맨 앞, 맨 뒤 원소가 잘려 있다면 앞, 뒤에 가상의 입출입 로그를 삽입합니다.
* 삽입하는 로그는 짝 여부에 관계없이 전후 원소를 삽입합니다.
* 짝 일치 여부 판단은 다른 로직에서 진행합니다.
* version 2: 카드의 짝을 맞추도록 수정하였습니다.
* version 3: 카드의 짝을 엄밀하게 맞추도록 수정하였습니다.
* version 4: 이전/이후 로그를 가져올 때, 카드의 유효 기간도 고려하도록 변경하였습니다.
* 인자로 들어온 태그 로그의 첫 기록이 OUT이라면, 더 과거 로그를 가져와 정각 기준으로 가상 로그를 삽입합니다.
*
* @param taglogs TagLogDto[]
* @return TagLogDto[]
* @version 4
* @param taglogs TagLogDto[] 태그 로그
* @param cards CardDto[] 태깅한 유저의 카드 정보와 유효 기간
* @param deviceInfos DeviceInfoDto[] 디바이스 정보
* @return TagLogDto[] 태그 로그
* @version 1
*/
async trimTagLogs(
async checkAndInsertStartVirtualTagLog(
taglogs: TagLogDto[],
cards: CardDto[],
start: Date,
end: Date,
pairs: PairInfoDto[],
deviceInfos: DeviceInfoDto[],
): Promise<TagLogDto[]> {
this.logger.debug(`@trimTagLogs)`);

// 1. 맨 앞의 로그를 가져옴.
// 1. 맨 앞의 로그를 가져온다.
const firstLog = taglogs.at(0);
if (firstLog) {
// 2. 맨 앞의 로그 이전의 로그를 가져옴.

// 2. 만약 맨 앞의 로그가 OUT이라면 맨 앞의 로그 이전의 로그를 가져온다.
if (
firstLog &&
!!deviceInfos.find(
(v) => v.device_id === firstLog.device_id && v.io_type === InOut.OUT,
)
) {
const beforeFirstLog = await this.tagLogRepository.findPrevTagLog(
cards.find((v) => v.card_id === firstLog.card_id),
firstLog.tag_at,
);
// NOTE: tag log에 기록된 첫번째 로그가 퇴실인 경우 현재는 짝을 맞추지 않음.
// 3. 만약 맨 앞의 로그 이전의 로그가 IN이 아니라면, 가상 로그를 삽입하지 않는다.
if (
beforeFirstLog !== null &&
this.validateDevicePair(
pairs,
beforeFirstLog.device_id,
firstLog.device_id,
!!deviceInfos.find(
(v) =>
v.device_id === beforeFirstLog.device_id && v.io_type === InOut.IN,
)
) {
const virtualEnterTime = this.dateCalculator.getStartOfDate(start);
const virtualEnterTime = this.dateCalculator.getStartOfDate(
firstLog.tag_at,
);
taglogs.unshift({
tag_at: virtualEnterTime,
device_id: beforeFirstLog.device_id,
Expand All @@ -88,24 +92,48 @@ export class TagLogService {
});
}
}
// 3. 맨 뒤의 로그를 가져옴.
return taglogs;
}

/**
* 인자로 들어온 태그 로그의 마지막 기록이 IN이라면, 더 최신 로그를 가져와 정각 기준으로 가상 로그를 삽입합니다.
*
* @param taglogs TagLogDto[] 태그 로그
* @param cards CardDto[] 태깅한 유저의 카드 정보와 유효 기간
* @param deviceInfos DeviceInfoDto[] 디바이스 정보
* @return TagLogDto[] 태그 로그
* @version 1
*/
async checkAndInsertEndVirtualTagLog(
taglogs: TagLogDto[],
cards: CardDto[],
deviceInfos: DeviceInfoDto[],
): Promise<TagLogDto[]> {
// 1. 맨 뒤의 로그를 가져온다.
const lastLog = taglogs.at(-1);
if (lastLog) {
// 6. 맨 뒤의 로그 이후의 로그를 가져옴.

// 2. 만약 맨 뒤의 로그가 IN이라면 맨 뒤의 로그 이후의 로그를 가져온다.
if (
lastLog &&
!!deviceInfos.find(
(v) => v.device_id === lastLog.device_id && v.io_type === InOut.IN,
)
) {
const afterLastLog = await this.tagLogRepository.findNextTagLog(
cards.find((v) => v.card_id === lastLog.card_id),
lastLog.tag_at,
);
// NOTE: 현재는 카뎃의 현재 입실여부에 관계없이 짝을 맞춤.
// 3. 만약 맨 뒤의 로그 이후의 로그가 OUT이 아니라면, 가상 로그를 삽입하지 않는다.
if (
afterLastLog !== null &&
this.validateDevicePair(
pairs,
lastLog.device_id,
afterLastLog.device_id,
!!deviceInfos.find(
(v) =>
v.device_id === afterLastLog.device_id && v.io_type === InOut.OUT,
)
) {
const virtualLeaveTime = this.dateCalculator.getEndOfDate(end);
const virtualLeaveTime = this.dateCalculator.getEndOfDate(
lastLog.tag_at,
);
taglogs.push({
tag_at: virtualLeaveTime,
device_id: afterLastLog.device_id,
Expand Down Expand Up @@ -318,25 +346,24 @@ export class TagLogService {
a.tag_at > b.tag_at ? 1 : -1,
);

const devicePairs = await this.pairInfoRepository.findAll();
const deviceInfos = await this.deviceInfoRepository.findAll();

const filteredTagLogs = sortedTagLogs.filter(
(taglog) =>
!!devicePairs.find(
(temp) =>
temp.in_device === taglog.device_id ||
temp.out_device === taglog.device_id,
),
!!deviceInfos.find((temp) => temp.device_id === taglog.device_id),
);

const trimmedTagLogs = await this.trimTagLogs(
filteredTagLogs,
const deduplicatedTagLogs = this.removeDuplicates(filteredTagLogs);
const trimmedStartTagLogs = await this.checkAndInsertStartVirtualTagLog(
deduplicatedTagLogs,
cards,
tagStart,
tagEnd,
devicePairs,
deviceInfos,
);
const trimmedTagLogs = await this.checkAndInsertEndVirtualTagLog(
trimmedStartTagLogs,
cards,
deviceInfos,
);

return trimmedTagLogs;
}

Expand All @@ -357,10 +384,8 @@ export class TagLogService {

const taglogs = await this.getAllTagLogsByPeriod(userId, tagStart, tagEnd);

const newtaglogs = this.removeDuplicates(taglogs);

//짝이 안맞는 로그도 null과 pair를 만들어 반환한다.
const resultPairs = this.getAllPairsByTagLogs(newtaglogs, pairs);
const resultPairs = this.getAllPairsByTagLogs(taglogs, pairs);

return resultPairs;
}
Expand Down Expand Up @@ -392,9 +417,7 @@ export class TagLogService {
today,
);

const newtaglogs = this.removeDuplicates(taglogs);

const resultPairs = this.getAllPairsByTagLogs(newtaglogs, pairs);
const resultPairs = this.getAllPairsByTagLogs(taglogs, pairs);

const ret: number[] = [];

Expand Down Expand Up @@ -438,9 +461,7 @@ export class TagLogService {
// this.logger.debug(`taglogs: ${element.device_id}, ${element.tag_at}`);
//});

const newtaglogs = this.removeDuplicates(taglogs);

const resultPairs = this.getAllPairsByTagLogs(newtaglogs, pairs);
const resultPairs = this.getAllPairsByTagLogs(taglogs, pairs);

//resultPairs.forEach((element) => {
// this.logger.debug(
Expand Down Expand Up @@ -474,9 +495,7 @@ export class TagLogService {
today,
);

const newtaglogs = this.removeDuplicates(taglogs);

const resultPairs = this.getAllPairsByTagLogs(newtaglogs, pairs);
const resultPairs = this.getAllPairsByTagLogs(taglogs, pairs);

const ret: number[] = [];

Expand Down

0 comments on commit 35ecba8

Please sign in to comment.