diff --git a/cloudbuild.yaml b/cloudbuild.yaml index ebc627e..4314931 100644 --- a/cloudbuild.yaml +++ b/cloudbuild.yaml @@ -26,7 +26,7 @@ steps: - set - image - deployment/groomeong-logstash - - logstash-sha256-1=asia.gcr.io/project-groomeong/logstash:1.1 + - logstash-sha256-1=asia.gcr.io/project-groomeong/logstash:1.2 env: - CLOUDSDK_COMPUTE_ZONE=asia-northeast3 - CLOUDSDK_CONTAINER_CLUSTER=autopilot-cluster-5 diff --git a/docker-compose.prod.yaml b/docker-compose.prod.yaml index 8c6af5f..0b9c4ad 100644 --- a/docker-compose.prod.yaml +++ b/docker-compose.prod.yaml @@ -9,7 +9,7 @@ services: dockerfile: Dockerfile.prod logstash: - image: asia.gcr.io/project-groomeong/logstash:1.1 + image: asia.gcr.io/project-groomeong/logstash:1.2 platform: linux/x86_64 build: context: . diff --git a/elk/logstash/logstash.prod.conf b/elk/logstash/logstash.prod.conf index a3aaf82..84adb20 100644 --- a/elk/logstash/logstash.prod.conf +++ b/elk/logstash/logstash.prod.conf @@ -2,14 +2,14 @@ input { jdbc { jdbc_driver_library => "/usr/share/logstash/mysql-connector-java-8.0.28.jar" jdbc_driver_class => "com.mysql.cj.jdbc.Driver" - jdbc_connection_string => "jdbc:mysql://10.42.208.3:3306/groomeongprod" # jdbc:mysql://SQL인스턴스비공개IP주소:포트번호/db이름 + jdbc_connection_string => "jdbc:mysql://10.42.208.3:3306/prod" # jdbc:mysql://SQL인스턴스비공개IP주소:포트번호/db이름 jdbc_user => "root" jdbc_password => "root" schedule => "*/30 * * * *" use_column_value => true tracking_column => "updatedat" tracking_column_type => "numeric" - last_run_metadata_path => "./updatedat_auto.txt" + last_run_metadata_path => "./updatedat_auto2.txt" statement => "select *, unix_timestamp(updatedat) as updatedat from shop inner join shop_image on shop.id = shop_image.shopid where unix_timestamp(updatedat) > :sql_last_value or shop_image.isthumbnail = 1 order by updatedat asc" } } @@ -27,7 +27,7 @@ output { hosts => "https://search-groomeong-elasticsearch-7mvk7xnf5m2a6tcx6p5ro5qste.ap-southeast-2.es.amazonaws.com:443" user => "groomeong11" password => "QKQHwngus1!" - index => "auto_shop_1" + index => "auto_shop_2" document_id => "%{shopid}" manage_template => true template => "/usr/share/logstash/auto_template3.json" diff --git a/src/apis/auth/strategies/jwt-social-kakao.strategy.ts b/src/apis/auth/strategies/jwt-social-kakao.strategy.ts index 73e0ba2..77029eb 100644 --- a/src/apis/auth/strategies/jwt-social-kakao.strategy.ts +++ b/src/apis/auth/strategies/jwt-social-kakao.strategy.ts @@ -7,6 +7,7 @@ export class JwtKakaoStrategy extends PassportStrategy(Strategy, 'kakao') { clientID: process.env.KAKAO_CLIENT_ID, clientSecret: process.env.KAKAO_CLIENT_SECRET, callbackURL: 'https://groomeong.shop/login/kakao', + // callbackURL: 'https://localhost:3000/login/kakao', scope: ['account_email', 'profile_nickname'], }); } diff --git a/src/apis/dogs/dogs.resolver.ts b/src/apis/dogs/dogs.resolver.ts index 1bc6427..105c7db 100644 --- a/src/apis/dogs/dogs.resolver.ts +++ b/src/apis/dogs/dogs.resolver.ts @@ -2,7 +2,6 @@ import { Args, Context, Mutation, Query, Resolver } from '@nestjs/graphql'; import { CreateDogInput } from './dto/create-dog.input'; import { DogsService } from './dogs.service'; import { Dog } from './entities/dog.entity'; -import { UpdateDogInput } from './dto/update-dog.input'; import { UseGuards } from '@nestjs/common'; import { GqlAuthGuard } from '../auth/guards/gql-auth.guard'; import { IContext } from 'src/commons/interface/context'; @@ -47,17 +46,6 @@ export class DogsResolver { return this.dogsService.create({ createDogInput, userId }); } - @Mutation( - () => Dog, - { description: ' Return: 업데이트한 강아지 데이터 ' }, // - ) - updateDog( - @Args('id') id: string, // - @Args('updateDogInput') updateDogInput: UpdateDogInput, // - ): Promise { - return this.dogsService.updateOneById({ id, updateDogInput }); - } - @Mutation( () => Boolean, { description: ' Return: id로 강아지 데이터 삭제 후 삭제 여부 반환 ' }, // diff --git a/src/apis/dogs/dogs.service.ts b/src/apis/dogs/dogs.service.ts index 1a86d9d..4581253 100644 --- a/src/apis/dogs/dogs.service.ts +++ b/src/apis/dogs/dogs.service.ts @@ -6,7 +6,6 @@ import { IDogsServiceDeleteById, IDogsServiceFindByUserId, IDogsServiceFindOneById, - IDogsServiceUpdateOneById, } from './interfaces/dogs-service.interface'; import { Repository } from 'typeorm'; @@ -49,18 +48,6 @@ export class DogsService { return dog; } - async updateOneById({ - id, - updateDogInput, - }: IDogsServiceUpdateOneById): Promise { - const founded = await this.findOneById({ id }); - const updated = await this.dogsRepository.save({ - ...founded, - ...updateDogInput, - }); - return updated; - } - async deleteOneById({ id, userId, diff --git a/src/apis/dogs/dto/update-dog.input.ts b/src/apis/dogs/dto/update-dog.input.ts deleted file mode 100644 index f375c1e..0000000 --- a/src/apis/dogs/dto/update-dog.input.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { CreateDogInput } from './create-dog.input'; -import { InputType, PartialType } from '@nestjs/graphql'; - -@InputType() -export class UpdateDogInput extends PartialType(CreateDogInput) {} diff --git a/src/apis/dogs/interfaces/dogs-service.interface.ts b/src/apis/dogs/interfaces/dogs-service.interface.ts index 1bf0794..4b8fb32 100644 --- a/src/apis/dogs/interfaces/dogs-service.interface.ts +++ b/src/apis/dogs/interfaces/dogs-service.interface.ts @@ -1,5 +1,4 @@ import { CreateDogInput } from '../dto/create-dog.input'; -import { UpdateDogInput } from '../dto/update-dog.input'; export interface IDogsServiceFindOneById { id: string; @@ -14,11 +13,6 @@ export interface IDogsServiceCreate { userId: string; } -export interface IDogsServiceUpdateOneById { - id: string; - updateDogInput: UpdateDogInput; -} - export interface IDogsServiceDeleteById { id: string; userId: string; diff --git a/src/apis/files/files.service.ts b/src/apis/files/files.service.ts index ac8f149..3293227 100644 --- a/src/apis/files/files.service.ts +++ b/src/apis/files/files.service.ts @@ -22,11 +22,11 @@ export class FilesService { let filename = ''; if (dogId) { - filename = `origin/dog/${uuid()}/${image.filename}`; // 강아지 이미지 주소 설정 + filename = `origin/dog/${uuid()}/${image.filename}`; } else if (shopId) { - filename = `origin/shop/${uuid()}/${image.filename}`; // 미용샵 이미지 주소 설정 + filename = `origin/shop/${uuid()}/${image.filename}`; } else { - filename = `origin/profile/${uuid()}/${image.filename}`; // 프로필 이미지 주소 설정 + filename = `origin/profile/${uuid()}/${image.filename}`; } image diff --git a/src/apis/reservations/__test__/reservation.resolver.spec.ts b/src/apis/reservations/__test__/reservation.resolver.spec.ts index c1a9c3d..ee87458 100644 --- a/src/apis/reservations/__test__/reservation.resolver.spec.ts +++ b/src/apis/reservations/__test__/reservation.resolver.spec.ts @@ -11,8 +11,8 @@ import { ShopsService } from 'src/apis/shops/shops.service'; import { UsersService } from 'src/apis/users/user.service'; import { CreateReservationInput } from '../dto/create-reservation.input'; import { Reservation } from '../entities/reservation.entity'; -import { ReservationsResolver } from '../reservation.resolver'; -import { ReservationsService } from '../reservation.service'; +import { ReservationsResolver } from '../reservations.resolver'; +import { ReservationsService } from '../reservations.service'; import { MOCK_RESERVATION, MOCK_REVIEW, diff --git a/src/apis/reservations/reservation.module.ts b/src/apis/reservations/reservations.module.ts similarity index 87% rename from src/apis/reservations/reservation.module.ts rename to src/apis/reservations/reservations.module.ts index 4426a90..e8566c3 100644 --- a/src/apis/reservations/reservation.module.ts +++ b/src/apis/reservations/reservations.module.ts @@ -9,8 +9,8 @@ import { ShopsService } from '../shops/shops.service'; import { User } from '../users/entities/user.entity'; import { UsersService } from '../users/user.service'; import { Reservation } from './entities/reservation.entity'; -import { ReservationsResolver } from './reservation.resolver'; -import { ReservationsService } from './reservation.service'; +import { ReservationsResolver } from './reservations.resolver'; +import { ReservationsService } from './reservations.service'; @Module({ imports: [ diff --git a/src/apis/reservations/reservation.resolver.ts b/src/apis/reservations/reservations.resolver.ts similarity index 64% rename from src/apis/reservations/reservation.resolver.ts rename to src/apis/reservations/reservations.resolver.ts index d668fe2..73faffb 100644 --- a/src/apis/reservations/reservation.resolver.ts +++ b/src/apis/reservations/reservations.resolver.ts @@ -5,7 +5,7 @@ import { GqlAuthGuard } from '../auth/guards/gql-auth.guard'; import { CreateReservationInput } from './dto/create-reservation.input'; import { returnUserWithReviewOutput } from './dto/return-reservation.output'; import { Reservation } from './entities/reservation.entity'; -import { ReservationsService } from './reservation.service'; +import { ReservationsService } from './reservations.service'; @Resolver() export class ReservationsResolver { @@ -13,63 +13,68 @@ export class ReservationsResolver { private readonly reservationsService: ReservationsService, // ) {} - //예약 생성하기 - @Mutation(() => Reservation, { description: 'Return: 생성된 신규 예약 정보' }) - async createReservation( - @Args('createReservationInput') - createReservationInput: CreateReservationInput, // - ): Promise { - return await this.reservationsService.create({ - createReservationInput, - }); - } - - // 예약ID로 예약정보 가져오기 - @Query(() => Reservation, { - description: 'Return : 예약 정보', - }) + @Query( + () => Reservation, // + { description: 'Return : 예약 정보' }, + ) fetchReservation( @Args('reservationId') reservationId: string, // ): Promise { return this.reservationsService.findOne({ reservationId }); } - // 회원의 모든 예약 가져오기 @UseGuards(GqlAuthGuard('access')) - @Query(() => [Reservation], { - description: 'Return : 한 회원의 예약 정보', - }) + @Query( + () => [Reservation], // + { description: 'Return : 한 회원의 모든 예약 정보' }, + ) fetchReservationsByUser( @Context() context: IContext, // ): Promise { const userId = context.req.user.id; - console.log(userId, '@@@@'); return this.reservationsService.findAllByUserId({ userId }); } - // 가게의 모든 예약 가져오기 - @Query(() => [Reservation], { - description: 'Return : 한 가게의 예약 정보', - }) + @Query( + () => [Reservation], // + { description: 'Return : 한 가게의 예약 정보' }, + ) fetchReservationsByShop( @Args('shopId') shopId: string, // ): Promise { return this.reservationsService.findAllByShopId({ shopId }); } - // 가게의 모든 예약과 예약자 가져오기 - @Query(() => [returnUserWithReviewOutput], { - description: - 'Return : { profile: 회원정보 , review: 그 회원이 작성한 리뷰 } 형식의 객체들이 모인 배열', - }) + @Query( + () => [returnUserWithReviewOutput], // + { + description: + 'Return : { profile: 회원정보 , review: 그 회원이 작성한 리뷰 } 형식의 배열', + }, + ) fetchForShopDetailPage( @Args('shopId') shopId: string, // ): Promise { return this.reservationsService.findForShopDetailPage({ shopId }); } - //예약 삭제하기 - @Mutation(() => Boolean, { description: ' Return: 예약 삭제하기' }) + @Mutation( + () => Reservation, // + { description: 'Return: 생성된 신규 예약 정보' }, + ) + async createReservation( + @Args('createReservationInput') + createReservationInput: CreateReservationInput, // + ): Promise { + return await this.reservationsService.create({ + createReservationInput, + }); + } + + @Mutation( + () => Boolean, // + { description: ' Return: 예약 삭제하기' }, + ) deleteReservation( @Args('reservationId') reservationId: string, // ): Promise { diff --git a/src/apis/reservations/reservation.service.ts b/src/apis/reservations/reservations.service.ts similarity index 79% rename from src/apis/reservations/reservation.service.ts rename to src/apis/reservations/reservations.service.ts index b0773c4..a01b22c 100644 --- a/src/apis/reservations/reservation.service.ts +++ b/src/apis/reservations/reservations.service.ts @@ -7,9 +7,7 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { DogsService } from '../dogs/dogs.service'; import { Review } from '../reviews/entities/review.entity'; -import { ReviewsService } from '../reviews/reviews.service'; import { ShopsService } from '../shops/shops.service'; -import { User } from '../users/entities/user.entity'; import { UsersService } from '../users/user.service'; import { returnUserWithReviewOutput } from './dto/return-reservation.output'; import { Reservation } from './entities/reservation.entity'; @@ -20,7 +18,6 @@ import { IReservationsServiceFindAllByShopId, IReservationsServiceFindAllByUserId, IReservationsServiceFindById, - IReservationsServiceFindDeletedById, IReservationsServiceFindForShopDetailPage, } from './interfaces/reservations-service.interface'; @@ -28,20 +25,19 @@ import { export class ReservationsService { constructor( @InjectRepository(Reservation) - private readonly reservationsRepository: Repository, // + private readonly reservationsRepository: Repository, + @InjectRepository(Review) + private readonly reviewsRepository: Repository, + private readonly usersService: UsersService, private readonly shopsService: ShopsService, private readonly dogsService: DogsService, - @InjectRepository(Review) - private readonly reviewsRepository: Repository, ) {} - // 신규 예약 정보 생성 async create({ createReservationInput, }: IReservationsServiceCreate): Promise { const { date, time, shopId, userId, dogId } = createReservationInput; - const checkReservation = await this.checkDuplication({ date, time, @@ -82,7 +78,6 @@ export class ReservationsService { }); } - // 예약 가능 여부 확인하기 async checkDuplication({ date, time, @@ -98,13 +93,12 @@ export class ReservationsService { return checkReservation; } - // 예약ID로 해당 예약정보 찾기 async findOne({ reservationId, }: IReservationsServiceFindById): Promise { const result = await this.reservationsRepository.findOne({ where: { id: reservationId }, - relations: ['shop', 'user', 'dog'], + relations: ['shop', 'user', 'dog', 'review'], order: { date: 'ASC', time: 'ASC', @@ -118,7 +112,6 @@ export class ReservationsService { return result; } - // 회원의 모든 예약 가져오기 async findAllByUserId({ userId, }: IReservationsServiceFindAllByUserId): Promise { @@ -140,13 +133,12 @@ export class ReservationsService { return result; } - // 가게의 모든 예약 가져오기 async findAllByShopId({ shopId, }: IReservationsServiceFindAllByShopId): Promise { const result = await this.reservationsRepository.find({ where: { shop: { id: shopId } }, - relations: ['shop', 'user', 'dog'], + relations: ['shop', 'user', 'dog', 'review'], order: { date: 'ASC', time: 'ASC', @@ -214,7 +206,6 @@ export class ReservationsService { return fetchList; } - //예약 삭제하기 async delete({ reservationId, }: IReservationsServiceDelete): Promise { @@ -234,43 +225,4 @@ export class ReservationsService { return result.affected ? true : false; } - - // // <--- 기능 필요하다면 주석 해제 ---> - // // 삭제된 예약 정보 가져오기 - // async findDeletedById({ - // reservationId, - // }: IReservationsServiceFindDeletedById): Promise { - // const result = await this.reservationsRepository.findOne({ - // where: { id: reservationId }, - // withDeleted: true, - // // relations: ['shop', 'user', 'dog'], - // }); - - // if (!result) { - // throw new UnprocessableEntityException( - // `예약ID가 ${reservationId}인 예약을 찾을 수 없습니다`, - // ); - // } - - // return result; - // } - - // // 유저의 삭제된 예약 정보 가져오기 - // async findDeletedByUserId({ - // userId, - // }: IReservationsServiceFindAllByUserId): Promise { - // const result = await this.reservationsRepository.find({ - // where: { user: { id: userId } }, - // withDeleted: true, - // // relations: ['shop', 'user', 'dog'], - // }); - - // if (!result) { - // throw new NotFoundException( - // `회원ID가 ${userId}인 예약을 찾을 수 없습니다`, - // ); - // } - - // return result; - // } } diff --git a/src/apis/shops/entities/shop.entity.ts b/src/apis/shops/entities/shop.entity.ts index 06b6a95..ff412fb 100644 --- a/src/apis/shops/entities/shop.entity.ts +++ b/src/apis/shops/entities/shop.entity.ts @@ -22,7 +22,7 @@ export class Shop { @Field(() => String) name: string; - @Column({ length: 13 }) + @Column({ length: 30 }) @Field(() => String) phone: string; diff --git a/src/apis/shops/shops.resolver.ts b/src/apis/shops/shops.resolver.ts index 11f09a5..337e5db 100644 --- a/src/apis/shops/shops.resolver.ts +++ b/src/apis/shops/shops.resolver.ts @@ -29,7 +29,7 @@ export class ShopsResolver { searchKeyword: string, // ): Promise { const searchResult = await this.elasticsearchService.search({ - index: 'auto_shop_1', + index: 'auto_shop_2', body: { query: { multi_match: { diff --git a/src/apis/users/entities/user.entity.ts b/src/apis/users/entities/user.entity.ts index a5f0222..b0f6b88 100644 --- a/src/apis/users/entities/user.entity.ts +++ b/src/apis/users/entities/user.entity.ts @@ -30,7 +30,7 @@ export class User { // @Field(() => String) password: string; - @Column({ length: 16 }) + @Column({ length: 30 }) @Field(() => String) phone?: string; diff --git a/src/app.module.ts b/src/app.module.ts index 77a6e3a..04ff6e5 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -16,7 +16,7 @@ import { JwtGoogleStrategy } from './apis/auth/strategies/jwt-social-google.stra import { MailerModule } from '@nestjs-modules/mailer'; import { HandlebarsAdapter } from '@nestjs-modules/mailer/dist/adapters/handlebars.adapter'; import { JwtKakaoStrategy } from './apis/auth/strategies/jwt-social-kakao.strategy'; -import { ReservationsModule } from './apis/reservations/reservation.module'; +import { ReservationsModule } from './apis/reservations/reservations.module'; import { ReviewsModule } from './apis/reviews/reviews.module'; import { ShopImagesModule } from './apis/shopImages/shopImage.module'; import { AppController } from './app.controller';