All files / search search.service.ts

100% Statements 49/49
100% Branches 9/9
100% Functions 8/8
100% Lines 46/46

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 1162x 2x 2x       2x 2x     2x 2x 2x   2x   2x       2x   13x 13x             4x       4x   4x 3x 3x   1x     4x 4x 2x     2x       2x   2x       1x 1x       2x 2x 1x     1x               2x 2x 1x     1x   1x         2x 2x 1x     1x   1x       2x 2x 1x     1x               1x      
import { Injectable, NotFoundException } from '@nestjs/common';
import { plainToInstance } from 'class-transformer';
import { ERROR } from 'src/commons/constants/error';
import { LastItemIdResponseDto } from 'src/commons/dtos/last-item-id-response.dto';
import { ListResponseDto } from 'src/commons/dtos/list-response.dto';
import { UuidResponseDto } from 'src/commons/dtos/uuid-response.dto';
import { isEmpty } from 'src/commons/util/is/is-empty';
import { generateUUID } from 'src/commons/util/uuid';
import { PlaceEntity } from 'src/entities/place.entity';
import { SearchLogEntity } from 'src/entities/search_log.entity';
import { PlaceQueryRepository } from 'src/place/place.query.repository';
import { ApiSearchGetDetailResponseDto } from 'src/search/dto/api-search-get-detail-response.dto';
import { ApiSearchGetRecentResponseDto } from 'src/search/dto/api-search-get-recent-response.dto';
import { ApiSearchGetRequestQueryDto } from 'src/search/dto/api-search-get-request-query.dto';
import { ApiSearchGetResponseDto } from 'src/search/dto/api-search-get-response.dto';
import { SearchDetailDto } from 'src/search/dto/search-detail.dto';
import { SearchQueryRepository } from 'src/search/search.query.repository';
import { UserDto } from 'src/user/dto/user.dto';
 
@Injectable()
export class SearchService {
  constructor(
    private readonly searchQueryRepository: SearchQueryRepository,
    private readonly placeQueryRepository: PlaceQueryRepository,
  ) {}
 
  async getSearchPlace(
    dto: ApiSearchGetRequestQueryDto,
    user: UserDto,
  ): Promise<LastItemIdResponseDto<ApiSearchGetResponseDto>> {
    const userSearchLog: SearchLogEntity[] = await this.searchQueryRepository.findUserSearchLog(
      dto.search,
      user,
    );
    const existingLog = userSearchLog.find((log) => log.search === dto.search);
 
    if (isEmpty(existingLog)) {
      const uuid = generateUUID();
      await this.searchQueryRepository.addLog(dto.search, uuid, user);
    } else {
      await this.searchQueryRepository.updateSearchDate(existingLog.id);
    }
 
    const searchList = await this.placeQueryRepository.getSearchPlace(dto);
    if (isEmpty(searchList)) {
      return { items: [], last_item_id: 0 };
    }
 
    const apiSearchGetResponseDto = plainToInstance(ApiSearchGetResponseDto, searchList, {
      excludeExtraneousValues: true,
    });
 
    const lastItemId = searchList.length === dto.size ? searchList[searchList.length - 1].id : 0;
 
    return { items: apiSearchGetResponseDto, last_item_id: lastItemId };
  }
 
  async getPopularSearches(): Promise<ListResponseDto<string>> {
    const result = ['마라탕', '더현대', '스시', '아쿠아리움', '감자탕'];
    return { items: result };
  }
 
  async getRecentSearches(user: UserDto): Promise<ListResponseDto<ApiSearchGetRecentResponseDto>> {
    const searchLog: SearchLogEntity[] = await this.searchQueryRepository.findRecentUserLog(user);
    if (isEmpty(searchLog)) {
      return { items: [] };
    }
 
    return {
      items: plainToInstance(ApiSearchGetRecentResponseDto, searchLog, {
        excludeExtraneousValues: true,
      }),
    };
  }
 
  async deleteSearchLog(uuid: string, user: UserDto): Promise<UuidResponseDto> {
    const userSearchLog = await this.searchQueryRepository.findUserLogToUuid(uuid, user);
    if (isEmpty(userSearchLog)) {
      throw new NotFoundException(ERROR.NOT_EXIST_DATA);
    }
 
    await this.searchQueryRepository.deleteSearchLog(userSearchLog);
 
    return { uuid };
  }
 
  async deleteAllSearchLog(user: UserDto): Promise<UuidResponseDto> {
    const userTotalSearchLog: SearchLogEntity[] =
      await this.searchQueryRepository.findUserTotalSearchLog(user);
    if (isEmpty(userTotalSearchLog)) {
      throw new NotFoundException(ERROR.NOT_EXIST_DATA);
    }
 
    await this.searchQueryRepository.updateDateDelete(userTotalSearchLog);
 
    return { uuid: user.uuid };
  }
 
  async getSearchDetail(uuid: string): Promise<ApiSearchGetDetailResponseDto> {
    const searchDetail: PlaceEntity = await this.placeQueryRepository.findOne(uuid);
    if (isEmpty(searchDetail)) {
      throw new NotFoundException(ERROR.NOT_EXIST_DATA);
    }
 
    const apiSearchDetailGetResponseDto: SearchDetailDto = plainToInstance(
      ApiSearchGetDetailResponseDto,
      searchDetail,
      {
        excludeExtraneousValues: true,
      },
    );
 
    return apiSearchDetailGetResponseDto;
  }
}