diff --git a/src/tag-log-v2/tag-log-v2.service.spec.ts b/src/tag-log-v2/tag-log-v2.service.spec.ts index d9eeb6b..b4399d1 100644 --- a/src/tag-log-v2/tag-log-v2.service.spec.ts +++ b/src/tag-log-v2/tag-log-v2.service.spec.ts @@ -81,6 +81,38 @@ describe('Tag Log (v2) unit 테스트', () => { expect(resultPairs).toHaveProperty('[0].durationSecond', 50 * 60); // 50 min }); + test('특정 일수 내 입-퇴실 짝이 맞긴 하지만, 중복으로 입실이 찍힌 케이스', async () => { + // given + const taglogs: TagLogDto[] = [ + { + idx: 1, + tag_at: new Date('2023-03-19T05:10Z'), // 오후 2:10:00 + card_id: '', + device_id: 1, + }, + { + idx: 2, + tag_at: new Date('2023-03-19T05:20Z'), // 오후 2:20:00 + card_id: '', + device_id: 1, + }, + { + idx: 3, + tag_at: new Date('2023-03-19T06:00Z'), // 오후 3:00:00 + card_id: '', + device_id: 2, + }, + ]; + + // when + const resultPairs = tagLogService.getAllPairsByTagLogs(taglogs, pairs); + + //then + expect(resultPairs).toHaveLength(2); + expect(resultPairs).toHaveProperty('[0].durationSecond', 40 * 60); // 40 min + expect(resultPairs).toHaveProperty('[1].outTimeStamp', null); // 짝이 맞지 않음. + }); + test('입-퇴실 짝이 월 경계 자정을 넘어가는 케이스', async () => { // given const taglogs: TagLogDto[] = [ @@ -158,4 +190,64 @@ describe('Tag Log (v2) unit 테스트', () => { expect(resultPairs).toHaveProperty('[0].durationSecond', 1); // 1 sec }); }); + describe('removeDuplicates', () => { + test('중복되지 않은 태그 로그', async () => { + // given + const taglogs: TagLogDto[] = [ + { + idx: 1, + tag_at: new Date('2023-03-19T05:10Z'), // 오후 2:10:00 + card_id: '', + device_id: 1, + }, + { + idx: 2, + tag_at: new Date('2023-03-19T06:00Z'), // 오후 3:00:00 + card_id: '', + device_id: 2, + }, + ]; + + // when + const resultPairs = tagLogService.removeDuplicates(taglogs); + + //then + expect(resultPairs).toHaveLength(2); + }); + test('중복되는 태그 로그', async () => { + // given + const taglogs: TagLogDto[] = [ + { + idx: 1, + tag_at: new Date('2023-03-19T05:10Z'), // 오후 2:10:00 + card_id: '', + device_id: 1, + }, + { + idx: 2, + tag_at: new Date('2023-03-19T06:00Z'), // 오후 3:00:00 + card_id: '', + device_id: 2, + }, + { + idx: 3, + tag_at: new Date('2023-03-19T06:00Z'), // 오후 3:00:00 + card_id: '', + device_id: 2, + }, + { + idx: 4, + tag_at: new Date('2023-03-19T06:00Z'), // 오후 3:00:00 + card_id: '', + device_id: 2, + }, + ]; + + // when + const resultPairs = tagLogService.removeDuplicates(taglogs); + + //then + expect(resultPairs).toHaveLength(2); + }); + }); }); diff --git a/src/tag-log-v2/tag-log-v2.service.ts b/src/tag-log-v2/tag-log-v2.service.ts index c937140..276b27d 100644 --- a/src/tag-log-v2/tag-log-v2.service.ts +++ b/src/tag-log-v2/tag-log-v2.service.ts @@ -22,6 +22,24 @@ export class TagLogService { private dateCalculator: DateCalculator, ) {} + /** + * DB에서 중복된 태그 기록이 올 경우, 중복된 태그 기록을 필터링합니다. + * 중복 기준은 태그 시간, 태그 ID, 태그 기기입니다. + * + * @param taglogs TagLogDto[] + * @return TagLogDto[] + */ + removeDuplicates(taglogs: TagLogDto[]): TagLogDto[] { + const comp = (a: TagLogDto, b: TagLogDto) => + a.tag_at.getTime() === b.tag_at.getTime() && + a.card_id === b.card_id && + a.device_id === b.device_id; + return taglogs.reduce( + (acc, tag) => (acc.find((val) => comp(val, tag)) ? acc : [...acc, tag]), + [], + ); + } + /** * 카드 태그 로그에 대해 로그 맨 앞, 맨 뒤 원소가 잘려 있다면 앞, 뒤에 가상의 입출입 로그를 삽입합니다. * 삽입하는 로그는 짝 여부에 관계없이 전후 원소를 삽입합니다. @@ -318,8 +336,10 @@ export class TagLogService { const taglogs = await this.getAllTagLogsByPeriod(userId, tagStart, tagEnd); + const newtaglogs = this.removeDuplicates(taglogs); + //짝이 안맞는 로그도 null과 pair를 만들어 반환한다. - const resultPairs = this.getAllPairsByTagLogs(taglogs, pairs); + const resultPairs = this.getAllPairsByTagLogs(newtaglogs, pairs); return resultPairs; } @@ -351,7 +371,9 @@ export class TagLogService { today, ); - const resultPairs = this.getAllPairsByTagLogs(taglogs, pairs); + const newtaglogs = this.removeDuplicates(taglogs); + + const resultPairs = this.getAllPairsByTagLogs(newtaglogs, pairs); const ret: number[] = []; @@ -395,7 +417,9 @@ export class TagLogService { // this.logger.debug(`taglogs: ${element.device_id}, ${element.tag_at}`); //}); - const resultPairs = this.getAllPairsByTagLogs(taglogs, pairs); + const newtaglogs = this.removeDuplicates(taglogs); + + const resultPairs = this.getAllPairsByTagLogs(newtaglogs, pairs); //resultPairs.forEach((element) => { // this.logger.debug( @@ -429,7 +453,9 @@ export class TagLogService { today, ); - const resultPairs = this.getAllPairsByTagLogs(taglogs, pairs); + const newtaglogs = this.removeDuplicates(taglogs); + + const resultPairs = this.getAllPairsByTagLogs(newtaglogs, pairs); const ret: number[] = [];