From 9448f9eb7a11ced2dad43b0afcc30647be8f2d08 Mon Sep 17 00:00:00 2001 From: mklee-mac Date: Sat, 15 Jul 2023 01:18:56 +0900 Subject: [PATCH 01/14] =?UTF-8?q?facade=20=EC=9E=91=EC=97=85=20=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/payments/entity/payments.entity.ts | 9 +++++ .../payments/payments-service.interface.ts | 15 +++++--- vet_nest/src/payments/payments.service.ts | 6 ++++ .../src/reservations/entity/payment.entity.ts | 35 ------------------- .../repository/reservation-repository.ts | 9 +++++ .../reservation-cancelation.interface.ts | 5 --- .../src/reservations/reservation-facade.ts | 18 ++++++++-- .../src/reservations/reservations.service.ts | 10 +++--- 8 files changed, 55 insertions(+), 52 deletions(-) delete mode 100644 vet_nest/src/reservations/entity/payment.entity.ts delete mode 100644 vet_nest/src/reservations/reservation-cancelation.interface.ts diff --git a/vet_nest/src/payments/entity/payments.entity.ts b/vet_nest/src/payments/entity/payments.entity.ts index 9fd2130..9008c4b 100644 --- a/vet_nest/src/payments/entity/payments.entity.ts +++ b/vet_nest/src/payments/entity/payments.entity.ts @@ -32,4 +32,13 @@ export class Payment { onDelete: 'CASCADE', }) reservation: Reservation; + + isCanceled(): boolean { + return this.status == PaymentStatus.COMPLETE + } +} + +export enum PaymentStatus { + COMPLETE = 'Complete', + CANCELD = 'Cancel' } diff --git a/vet_nest/src/payments/payments-service.interface.ts b/vet_nest/src/payments/payments-service.interface.ts index e6ee176..96eba02 100644 --- a/vet_nest/src/payments/payments-service.interface.ts +++ b/vet_nest/src/payments/payments-service.interface.ts @@ -1,7 +1,12 @@ -import { Payment } from "@/reservations/entity/payment.entity"; - +import { Payment } from "./entity/payments.entity"; export interface IPaymentService { - pay(): Promise; - cancelPayment(): Promise; - cancelPayments(): Promise; + getPaymentsByReservationId(reservationId: string): Promise; + pay(createPaymentDto: object): Promise; + cancelPayment(paymentId: number): Promise; + cancelPayments(paymentId: number[]): Promise; +} + +export interface IFakePgApi { + pay(createPgApiDto: object); + cancel(): any; } \ No newline at end of file diff --git a/vet_nest/src/payments/payments.service.ts b/vet_nest/src/payments/payments.service.ts index c3a05e1..f44690e 100644 --- a/vet_nest/src/payments/payments.service.ts +++ b/vet_nest/src/payments/payments.service.ts @@ -2,9 +2,11 @@ import { Injectable } from '@nestjs/common'; import { PaymentsRepository } from './repository/payments.repository'; import { HttpService } from '@nestjs/axios'; import { firstValueFrom } from 'rxjs'; +import { Payment } from './entity/payments.entity'; @Injectable() export class PaymentsService { + constructor( private readonly paymentsRepository: PaymentsRepository, private readonly httpService: HttpService, @@ -65,4 +67,8 @@ export class PaymentsService { return this.paymentsRepository.refund(refundPaymentDto.paymentId); } + + async cancelPayment(payment: Payment): Promise { + throw new Error("Method not implemented."); + } } diff --git a/vet_nest/src/reservations/entity/payment.entity.ts b/vet_nest/src/reservations/entity/payment.entity.ts deleted file mode 100644 index 22aa94d..0000000 --- a/vet_nest/src/reservations/entity/payment.entity.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; -import { Reservation } from './reservation.entity'; - -@Entity() -export class Payment { - @PrimaryGeneratedColumn() - id: number; - - @Column() - appId: string; - - @Column() - method: string; - - @Column() - amount: number; - - @Column() - status: string; - - @Column() - createdAt: Date; - - @Column() - canceledAt?: Date | null; - - @Column() - reservationId: number; - - @ManyToOne(() => Reservation, (reservation) => reservation.payments, { - nullable: false, - onDelete: 'CASCADE', - }) - reservation: Reservation; -} diff --git a/vet_nest/src/reservations/repository/reservation-repository.ts b/vet_nest/src/reservations/repository/reservation-repository.ts index abcf10b..236563c 100644 --- a/vet_nest/src/reservations/repository/reservation-repository.ts +++ b/vet_nest/src/reservations/repository/reservation-repository.ts @@ -1,6 +1,7 @@ import { DataSource, EntityRepository, Raw, Repository } from 'typeorm'; import { Reservation } from '../entity/reservation.entity'; import { Inject, Injectable } from '@nestjs/common'; +import { Payment } from '@/payments/entity/payments.entity'; @EntityRepository(Reservation) export class ReservationReposiotory extends Repository { @@ -49,4 +50,12 @@ export class ReservationReposiotory extends Repository { id: reservationId, }); } + + async getPaymentsByReservationId(reservationId: number): Promise { + const reservation = await this.findOne({ + where: {id: reservationId}, + relations: ['Payment'] + }); + return Promise.resolve(reservation.payments); + } } diff --git a/vet_nest/src/reservations/reservation-cancelation.interface.ts b/vet_nest/src/reservations/reservation-cancelation.interface.ts deleted file mode 100644 index e4bda4a..0000000 --- a/vet_nest/src/reservations/reservation-cancelation.interface.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Reservation } from "./entity/reservation.entity"; - -export interface IReservationsCancelation { - cancelReservation(reservationId: number): Promise; -} diff --git a/vet_nest/src/reservations/reservation-facade.ts b/vet_nest/src/reservations/reservation-facade.ts index 125c127..e3cba64 100644 --- a/vet_nest/src/reservations/reservation-facade.ts +++ b/vet_nest/src/reservations/reservation-facade.ts @@ -12,10 +12,22 @@ export class ReservationFacade { private readonly paymentService: PaymentsService ) {} - cancelReservation(reservationId: number): void { - const canceledReservation = this.reservationCancelationService.cancelReservation(reservationId); - //TODO: Payments를 가져온다. + async cancelReservation(reservationId: number): Promise { + const canceledReservation = await this.reservationCancelationService.cancelReservation(reservationId); + const payments = await this.reservationService.getPaymentsByReservationId(canceledReservation.id); + // 1:N - 예약금, 진료비 ( 예약 상태일 경우에는 무조건 1개 이지 않을까? ) + const cancelPaymentResults = await payments.map( async (payment) => + await this.paymentService.cancelPayment(payment) + ); + + // const allPaymentCanceled = await cancelPaymentResults.every((payment) => { + // return (await payment).isCanceled(); + // }); + + // if (!allPaymentCanceled) { + + // } } } \ No newline at end of file diff --git a/vet_nest/src/reservations/reservations.service.ts b/vet_nest/src/reservations/reservations.service.ts index 6340804..1dd8c44 100644 --- a/vet_nest/src/reservations/reservations.service.ts +++ b/vet_nest/src/reservations/reservations.service.ts @@ -5,15 +5,13 @@ import { ReservastionsDto } from './dto/reservations.dto'; import { ReservationSearchDto } from './dto/reservation-search.dto'; import moment from 'moment'; import { ReservationReposiotory } from './repository/reservation-repository'; +import { Payment } from '@/payments/entity/payments.entity'; @Injectable() export class ReservationService { - // private reservationRepository: Repository; constructor( private readonly reservationRepository: ReservationReposiotory - ) { - // this.reservationRepository = this.dataSource.getRepository(Reservation); - } + ) { } async create(data: ReservastionsDto): Promise { // new Logger().verbose('create Reservations in repo', JSON.stringify(data)); @@ -38,4 +36,8 @@ export class ReservationService { searchQuery.startDate, searchQuery.endDate); } + + async getPaymentsByReservationId(reservationId: number): Promise { + return await this.reservationRepository.getPaymentsByReservationId(reservationId); + } } From 30d2d0ac2a30a536d6d9eb77d8a915068b4fd0d1 Mon Sep 17 00:00:00 2001 From: mklee-mac Date: Sat, 15 Jul 2023 01:26:45 +0900 Subject: [PATCH 02/14] =?UTF-8?q?facade=20=EC=9E=91=EC=97=85=20=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reservation-cancelation.controller.ts | 24 +++---- .../reservation-cancelation.service.ts | 3 +- .../src/reservations/reservation-facade.ts | 62 ++++++++++++------- 3 files changed, 46 insertions(+), 43 deletions(-) diff --git a/vet_nest/src/reservations/reservation-cancelation.controller.ts b/vet_nest/src/reservations/reservation-cancelation.controller.ts index 832662b..89d31de 100644 --- a/vet_nest/src/reservations/reservation-cancelation.controller.ts +++ b/vet_nest/src/reservations/reservation-cancelation.controller.ts @@ -9,33 +9,23 @@ import { DataSource } from 'typeorm'; import { Reservation } from './entity/reservation.entity'; import { ReservationCancelationService } from './reservation-cancelation.service'; import { ApiTags } from '@nestjs/swagger'; +import { ReservationFacade } from './reservation-facade'; @Controller('reservation-cancelation') @ApiTags('Reservation-cancelation') export class ReservationCancelationController { constructor( - private reservationCancelationService: ReservationCancelationService, + // private reservationCancelationService: ReservationCancelationService, + private reservationFacadeService: ReservationFacade ) {} @Get(':id') async cancelReservation(@Param('id') id: number) { try { - const result = await this.reservationCancelationService.cancelReservation(id); - return { - result: result, - message: '예약이 취소되었습니다.', - }; - } catch (e) { - switch (e.name) { - case 'NotFoundException': - throw new HttpException(e.message, HttpStatus.NOT_FOUND); - case 'BadRequestException': - throw new HttpException(e.message, HttpStatus.BAD_REQUEST); - case 'ForbiddenException': - throw new HttpException(e.message, HttpStatus.FORBIDDEN); - default: - throw new HttpException(e.message, HttpStatus.INTERNAL_SERVER_ERROR); - } + return await this.reservationFacadeService.cancelReservation(id); + } + catch (e) { + throw e; } } } diff --git a/vet_nest/src/reservations/reservation-cancelation.service.ts b/vet_nest/src/reservations/reservation-cancelation.service.ts index 84399cf..c543996 100644 --- a/vet_nest/src/reservations/reservation-cancelation.service.ts +++ b/vet_nest/src/reservations/reservation-cancelation.service.ts @@ -4,12 +4,11 @@ import { import { Reservation } from '../reservations/entity/reservation.entity'; -import { IReservationsCancelation } from './reservation-cancelation.interface'; import ReservationCancelationValidator from './validator/reservation-cancelation.validator'; import { ReservationReposiotory } from './repository/reservation-repository'; @Injectable() -export class ReservationCancelationService implements IReservationsCancelation { +export class ReservationCancelationService { constructor( private readonly reservationRepository: ReservationReposiotory, ) {} diff --git a/vet_nest/src/reservations/reservation-facade.ts b/vet_nest/src/reservations/reservation-facade.ts index e3cba64..4c447b2 100644 --- a/vet_nest/src/reservations/reservation-facade.ts +++ b/vet_nest/src/reservations/reservation-facade.ts @@ -1,33 +1,47 @@ -import { Injectable } from "@nestjs/common"; -import { ReservationCancelationService } from "./reservation-cancelation.service"; -import { PaymentsService } from "@/payments/payments.service"; -import { ReservationService } from "./reservations.service"; +import { Injectable } from '@nestjs/common'; +import { ReservationCancelationService } from './reservation-cancelation.service'; +import { PaymentsService } from '@/payments/payments.service'; +import { ReservationService } from './reservations.service'; +import { Reservation } from './entity/reservation.entity'; @Injectable() export class ReservationFacade { + constructor( + private readonly reservationService: ReservationService, + private readonly reservationCancelationService: ReservationCancelationService, + private readonly paymentService: PaymentsService, + ) {} - constructor( - private readonly reservationService: ReservationService, - private readonly reservationCancelationService: ReservationCancelationService, - private readonly paymentService: PaymentsService - ) {} - - async cancelReservation(reservationId: number): Promise { - const canceledReservation = await this.reservationCancelationService.cancelReservation(reservationId); - const payments = await this.reservationService.getPaymentsByReservationId(canceledReservation.id); - - // 1:N - 예약금, 진료비 ( 예약 상태일 경우에는 무조건 1개 이지 않을까? ) - const cancelPaymentResults = await payments.map( async (payment) => - await this.paymentService.cancelPayment(payment) + async cancelReservation(reservationId: number): Promise { + try { + const canceledReservation = + await this.reservationCancelationService.cancelReservation( + reservationId, ); + + const payments = await this.reservationService.getPaymentsByReservationId( + canceledReservation.id, + ); + + // 1:N - 예약금, 진료비 ( 예약 상태일 경우에는 무조건 1개 이지 않을까? ) + const cancelPaymentResults = await payments.map( + async (payment) => await this.paymentService.cancelPayment(payment), + ); - // const allPaymentCanceled = await cancelPaymentResults.every((payment) => { - // return (await payment).isCanceled(); - // }); + //모든 값이 예약 취소면 ? 뭘 해야하나 + //1. transaction.commit + //2. 취소된 예약 정보 return; + // const allPaymentCanceled = await cancelPaymentResults.every((payment) => { + // return (await payment).isCanceled(); + // }); - // if (!allPaymentCanceled) { + // if (!allPaymentCanceled) { - // } - + // } + return Promise.resolve(canceledReservation); + } + catch (e) { + throw e; } -} \ No newline at end of file + } +} From d430cee020e8bca9b1c82c91a4d729f3c703f1b3 Mon Sep 17 00:00:00 2001 From: mklee-mac Date: Sun, 16 Jul 2023 18:14:11 +0900 Subject: [PATCH 03/14] cancelPayments --- vet_nest/src/app/app.module.ts | 17 +-- .../database/providers/database.provider.ts | 12 ++ .../src/payments/entity/payments.entity.ts | 25 +++- .../payments/payments-service.interface.ts | 8 +- vet_nest/src/payments/payments.controller.ts | 6 +- vet_nest/src/payments/payments.module.ts | 7 +- vet_nest/src/payments/payments.service.ts | 111 ++++++++++++------ vet_nest/src/payments/pg-api-caller.ts | 17 +++ .../repository/payments.repository.ts | 26 ++-- .../src/reservations/reservation-facade.ts | 25 ++-- .../src/reservations/reservations.module.ts | 10 +- 11 files changed, 164 insertions(+), 100 deletions(-) create mode 100644 vet_nest/src/payments/pg-api-caller.ts diff --git a/vet_nest/src/app/app.module.ts b/vet_nest/src/app/app.module.ts index ab8168f..a4fac54 100644 --- a/vet_nest/src/app/app.module.ts +++ b/vet_nest/src/app/app.module.ts @@ -20,13 +20,11 @@ import { PetsController } from '../pets/pets.controller'; import { VetsController } from '../vets/vets.controller'; import { PaymentsController } from '../payments/payments.controller'; import { UsersController } from '../users/users.controller'; -import { DisgnosisController } from '../diagnosis/diagnosis.controller'; import { PetsService } from '../pets/pets.service'; import { PetsRepository } from '../pets/repository/pets.repository'; import { VetsService } from '../vets/vets.service'; import { PaymentsService } from '../payments/payments.service'; import { UsersService } from '../users/users.service'; -import { DiagnosisService } from '../diagnosis/diagnosis.service'; import { UsersRepository } from '../users/repository/users.repository'; import { JwtService } from '@nestjs/jwt'; import { ExceptionsService } from '../exceptions/exceptions.service'; @@ -56,31 +54,18 @@ import { HttpModule } from '@nestjs/axios'; ], }), DatabaseModule, + PaymentsModule, ReservationsModule, DiagnosisModule, PetsModule, VetsModule, - PaymentsModule, UsersModule, ExceptionsModule, HttpModule, ], - controllers: [ - AppController, - PetsController, - VetsController, - PaymentsController, - UsersController, - ], providers: [ AppService, - PetsService, - PetsRepository, VetsService, - PaymentsService, - PaymentsRepository, - UsersService, - UsersRepository, JwtService, ExceptionsService, currentModeProviders, diff --git a/vet_nest/src/database/providers/database.provider.ts b/vet_nest/src/database/providers/database.provider.ts index d630c40..a1ccb68 100644 --- a/vet_nest/src/database/providers/database.provider.ts +++ b/vet_nest/src/database/providers/database.provider.ts @@ -16,6 +16,7 @@ import { } from '../../reservations/entity/reservation.entity'; import * as moment from 'moment'; import { ConfigService } from '@nestjs/config'; +import { Payment, PaymentMethod, PaymentStatus } from '@/payments/entity/payments.entity'; export const databaseProviders = [ { @@ -160,4 +161,15 @@ export async function dbInitializeCallback(db: DataSource) { amount: 20000, }, ]); + + const paymentRepo = db.getRepository(Payment); + paymentRepo.save([{ + paymentId: 1, + appId: 'APP-11111', + method: PaymentMethod.CARD, + amount: 5000, + status: PaymentStatus.COMPLETE, + reservationId: 1 + }, + ]); } diff --git a/vet_nest/src/payments/entity/payments.entity.ts b/vet_nest/src/payments/entity/payments.entity.ts index 9008c4b..2815cd1 100644 --- a/vet_nest/src/payments/entity/payments.entity.ts +++ b/vet_nest/src/payments/entity/payments.entity.ts @@ -9,14 +9,18 @@ export class Payment { @Column({ nullable: true }) appId: string; - @Column() - method: string; + @Column({ + type: 'varchar' + }) + method: PaymentMethod; @Column() amount: number; - @Column() - status: string; + @Column({ + type: 'varchar' + }) + status: PaymentStatus; @Column({ default: () => 'CURRENT_TIMESTAMP' }) createdAt: Date; @@ -34,7 +38,12 @@ export class Payment { reservation: Reservation; isCanceled(): boolean { - return this.status == PaymentStatus.COMPLETE + return this.status == PaymentStatus.CANCELD; + } + + cancel() { + this.status = PaymentStatus.CANCELD; + this.canceledAt = new Date(); } } @@ -42,3 +51,9 @@ export enum PaymentStatus { COMPLETE = 'Complete', CANCELD = 'Cancel' } + +export enum PaymentMethod { + CARD = 'CARD', + CASH = 'CASH', + ACCOUNT_TRANSFER = 'ACCOUNT_TRANSFER' +} diff --git a/vet_nest/src/payments/payments-service.interface.ts b/vet_nest/src/payments/payments-service.interface.ts index 96eba02..cd6ba6c 100644 --- a/vet_nest/src/payments/payments-service.interface.ts +++ b/vet_nest/src/payments/payments-service.interface.ts @@ -1,12 +1,12 @@ import { Payment } from "./entity/payments.entity"; export interface IPaymentService { - getPaymentsByReservationId(reservationId: string): Promise; + getPaymentsByReservationId(reservationId: number): Promise; pay(createPaymentDto: object): Promise; cancelPayment(paymentId: number): Promise; - cancelPayments(paymentId: number[]): Promise; + cancelPaymentsByReservationId(reservationId: number): Promise } export interface IFakePgApi { - pay(createPgApiDto: object); - cancel(): any; + pay(createPaymentDto: any): Promise, + cancelPayment(uuid: string): Promise } \ No newline at end of file diff --git a/vet_nest/src/payments/payments.controller.ts b/vet_nest/src/payments/payments.controller.ts index 1087e9d..93052f6 100644 --- a/vet_nest/src/payments/payments.controller.ts +++ b/vet_nest/src/payments/payments.controller.ts @@ -18,9 +18,9 @@ export class PaymentsController { @Post('refund') async refund(@Body() refundPaymentDto) { - await this.PaymentsService.refund(refundPaymentDto).catch((error) => { - throw new HttpException({ result: false, message: error.message }, 400); - }); + // await this.PaymentsService.refund(refundPaymentDto).catch((error) => { + // throw new HttpException({ result: false, message: error.message }, 400); + // }); return { result: true, code: 200, message: '/payments/refund' }; } diff --git a/vet_nest/src/payments/payments.module.ts b/vet_nest/src/payments/payments.module.ts index 8f2a51b..f455286 100644 --- a/vet_nest/src/payments/payments.module.ts +++ b/vet_nest/src/payments/payments.module.ts @@ -4,10 +4,15 @@ import { PaymentsController } from '@/payments/payments.controller'; import { PaymentsService } from '@/payments/payments.service'; import { PaymentsRepository } from '@/payments/repository/payments.repository'; import { HttpModule } from '@nestjs/axios'; +import { PgApiCaller } from './pg-api-caller'; @Module({ imports: [DatabaseModule, HttpModule], controllers: [PaymentsController], - providers: [PaymentsService, PaymentsRepository], + providers: [ + PaymentsService, + PaymentsRepository, + PgApiCaller + ], }) export class PaymentsModule {} diff --git a/vet_nest/src/payments/payments.service.ts b/vet_nest/src/payments/payments.service.ts index f44690e..9d6fbcb 100644 --- a/vet_nest/src/payments/payments.service.ts +++ b/vet_nest/src/payments/payments.service.ts @@ -2,15 +2,50 @@ import { Injectable } from '@nestjs/common'; import { PaymentsRepository } from './repository/payments.repository'; import { HttpService } from '@nestjs/axios'; import { firstValueFrom } from 'rxjs'; -import { Payment } from './entity/payments.entity'; +import { Payment, PaymentStatus } from './entity/payments.entity'; +import { IPaymentService } from './payments-service.interface'; +import { PgApiCaller } from './pg-api-caller'; +import { BusinessException } from 'util/exception.util'; @Injectable() -export class PaymentsService { +export class PaymentsService implements IPaymentService { constructor( private readonly paymentsRepository: PaymentsRepository, - private readonly httpService: HttpService, + // private readonly httpService: HttpService, + private readonly pgApiCaller: PgApiCaller ) {} + + pay(createPaymentDto: object): Promise { + throw new Error('Method not implemented.'); + } + cancelPayment(paymentId: number): Promise { + throw new Error('Method not implemented.'); + } + + async getPaymentsByReservationId(reservationId: number): Promise { + return this.paymentsRepository.findBy({ + reservationId: reservationId + }); + } + + async cancelPaymentsByReservationId(reservationId: number): Promise { + console.log(`paymentsService.cancelPaymentsByReservationId: ${reservationId}`); + const payments = await this.getPaymentsByReservationId(reservationId); + const canceledPayments = payments.map((payment: Payment) => { + payment.cancel(); + const result = this.pgApiCaller.cancelPayment(payment.appId); + return payment; + }); + + if (!canceledPayments.every((payment) => payment.isCanceled())) + throw new BusinessException(canceledPayments, 'PG 결제 오류', '500'); + + this.paymentsRepository.save(canceledPayments); + return canceledPayments; + } + + async create(createPaymentDto) { if (!(createPaymentDto.reservationId && createPaymentDto.amount)) { @@ -20,7 +55,7 @@ export class PaymentsService { const targetPayment = await this.paymentsRepository.findByReservationId( createPaymentDto.reservationId, ); - if (targetPayment && targetPayment.status === 'done') { + if (targetPayment && targetPayment.status === PaymentStatus.COMPLETE) { throw new Error('payment has already made'); } @@ -30,45 +65,45 @@ export class PaymentsService { amount: createPaymentDto.amount, }; - const pgResponse = ( - await firstValueFrom(this.httpService.post(pgCreateUrl, pgCreateBody)) - ).data; - if (pgResponse.code !== 201) { - throw new Error('pg error'); - } + // const pgResponse = ( + // await firstValueFrom(this.httpService.post(pgCreateUrl, pgCreateBody)) + // ).data; + // if (pgResponse.code !== 201) { + // throw new Error('pg error'); + // } - return this.paymentsRepository.createPayment( - createPaymentDto.reservationId, - createPaymentDto.amount, - pgResponse.result.appId, - ); + // return this.paymentsRepository.createPayment( + // createPaymentDto.reservationId, + // createPaymentDto.amount, + // pgResponse.result.appId, + // ); } - async refund(refundPaymentDto) { - if (!refundPaymentDto.paymentId) { - throw new Error('paymentId is required'); - } + // async refund(refundPaymentDto) { + // if (!refundPaymentDto.paymentId) { + // throw new Error('paymentId is required'); + // } - const targetPayment = await this.paymentsRepository.findByPaymentId( - refundPaymentDto.paymentId, - ); - if (!targetPayment || targetPayment.status === 'refund') { - throw new Error('payment is not refundable'); - } + // const targetPayment = await this.paymentsRepository.findByPaymentId( + // refundPaymentDto.paymentId, + // ); + // if (!targetPayment || targetPayment.status === 'refund') { + // throw new Error('payment is not refundable'); + // } - const pgRefundUrl = 'http://localhost:3001/pg/refund'; - const pgRefundBody = { appId: targetPayment.appId }; - const result = ( - await firstValueFrom(this.httpService.post(pgRefundUrl, pgRefundBody)) - ).data; - if (result.code !== 200) { - throw new Error('pg error'); - } + // const pgRefundUrl = 'http://localhost:3001/pg/refund'; + // const pgRefundBody = { appId: targetPayment.appId }; + // const result = ( + // await firstValueFrom(this.httpService.post(pgRefundUrl, pgRefundBody)) + // ).data; + // if (result.code !== 200) { + // throw new Error('pg error'); + // } - return this.paymentsRepository.refund(refundPaymentDto.paymentId); - } + // return this.paymentsRepository.refund(refundPaymentDto.paymentId); + // } - async cancelPayment(payment: Payment): Promise { - throw new Error("Method not implemented."); - } + // async cancelPayment(payment: Payment): Promise { + // throw new Error("Method not implemented."); + // } } diff --git a/vet_nest/src/payments/pg-api-caller.ts b/vet_nest/src/payments/pg-api-caller.ts new file mode 100644 index 0000000..0dbe891 --- /dev/null +++ b/vet_nest/src/payments/pg-api-caller.ts @@ -0,0 +1,17 @@ +import { Injectable } from "@nestjs/common"; +import { IFakePgApi } from "./payments-service.interface"; + +@Injectable() +export class PgApiCaller implements IFakePgApi +{ + constructor() { + + } + async pay(createPaymentDto: any): Promise { + return null; + } + + async cancelPayment(uuid: string): Promise { + return null; + } +} \ No newline at end of file diff --git a/vet_nest/src/payments/repository/payments.repository.ts b/vet_nest/src/payments/repository/payments.repository.ts index 742fe44..78bab98 100644 --- a/vet_nest/src/payments/repository/payments.repository.ts +++ b/vet_nest/src/payments/repository/payments.repository.ts @@ -1,5 +1,5 @@ import { Repository, DataSource, EntityRepository } from 'typeorm'; -import { Payment } from '../entity/payments.entity'; +import { Payment, PaymentMethod, PaymentStatus } from '../entity/payments.entity'; import { Inject, Logger } from '@nestjs/common'; @EntityRepository(Payment) @@ -26,19 +26,25 @@ export class PaymentsRepository extends Repository return await this.findOneById(paymentId); } - async createPayment(reservationId, amount, appId) { - const newPayment = this.create({ - reservationId, - amount, - appId, - status: 'done', - method: 'CARD', - }); + async createPayment(reservationId: number, amount, appId) { + const newPayment = new Payment(); + newPayment.reservationId = reservationId; + newPayment.amount = amount; + newPayment.appId = appId; + newPayment.status = PaymentStatus.COMPLETE; + newPayment.method = PaymentMethod.CARD; + // const newPayment = this.create({ + // reservationId: reservationId, + // amount: amount, + // appId: appId, + // status: 'done', + // method: 'CARD', + // }); await this.save(newPayment); return newPayment; } async refund(paymentId) { - return await this.update(paymentId, { status: 'refund' }); + // return await this.update(paymentId, { status: 'refund' }); } } \ No newline at end of file diff --git a/vet_nest/src/reservations/reservation-facade.ts b/vet_nest/src/reservations/reservation-facade.ts index 4c447b2..7649fce 100644 --- a/vet_nest/src/reservations/reservation-facade.ts +++ b/vet_nest/src/reservations/reservation-facade.ts @@ -19,25 +19,14 @@ export class ReservationFacade { reservationId, ); - const payments = await this.reservationService.getPaymentsByReservationId( - canceledReservation.id, - ); - - // 1:N - 예약금, 진료비 ( 예약 상태일 경우에는 무조건 1개 이지 않을까? ) - const cancelPaymentResults = await payments.map( - async (payment) => await this.paymentService.cancelPayment(payment), - ); - - //모든 값이 예약 취소면 ? 뭘 해야하나 - //1. transaction.commit - //2. 취소된 예약 정보 return; - // const allPaymentCanceled = await cancelPaymentResults.every((payment) => { - // return (await payment).isCanceled(); - // }); - - // if (!allPaymentCanceled) { + console.log(`reservation:${JSON.stringify(canceledReservation)}`); + console.log(`reservation.id:${JSON.stringify(canceledReservation.id)}`); + + const canceledPayments = await this.paymentService.cancelPaymentsByReservationId( + canceledReservation.id, + ); - // } + canceledReservation.payments = canceledPayments; return Promise.resolve(canceledReservation); } catch (e) { diff --git a/vet_nest/src/reservations/reservations.module.ts b/vet_nest/src/reservations/reservations.module.ts index ef27dd2..37398d7 100644 --- a/vet_nest/src/reservations/reservations.module.ts +++ b/vet_nest/src/reservations/reservations.module.ts @@ -6,12 +6,13 @@ import { ReservationReposiotory } from '@/reservations/repository/reservation-re import { ReservationService } from './reservations.service'; import { ReservationsController } from './reservations.controller'; import { ReservationFacade } from './reservation-facade'; +import { PaymentsModule } from '@/payments/payments.module'; import { PaymentsService } from '@/payments/payments.service'; -import { PaymentsRepository } from '../payments/repository/payments.repository'; -import { HttpModule } from '@nestjs/axios'; +import { PaymentsRepository } from '@/payments/repository/payments.repository'; +import { PgApiCaller } from '@/payments/pg-api-caller'; @Module({ - imports: [DatabaseModule, HttpModule], + imports: [DatabaseModule], controllers: [ReservationCancelationController, ReservationsController], providers: [ ReservationCancelationService, @@ -20,8 +21,7 @@ import { HttpModule } from '@nestjs/axios'; ReservationFacade, PaymentsService, PaymentsRepository, - - // ReservationMapperProfile + PgApiCaller ], }) export class ReservationsModule {} From cc81ae8b0cdffac1cfc32807814cb487a245c9d6 Mon Sep 17 00:00:00 2001 From: mklee-mac Date: Sun, 16 Jul 2023 23:07:18 +0900 Subject: [PATCH 04/14] =?UTF-8?q?payment=20service,=20fake-pg-module=20?= =?UTF-8?q?=EC=9E=91=EC=97=85=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vet_nest/package.json | 7 +- vet_nest/src/app/app.module.ts | 2 + .../__test__/pg.controller.spec.ts | 0 vet_nest/src/fake-pg/fake-pg.controller.ts | 50 ++++++++ vet_nest/src/fake-pg/fake-pg.module.ts | 8 ++ .../request/fake-pg-cancel-payment.request.ts | 13 +++ .../request/fake-pg-payment.request.ts | 41 +++++++ .../fake-pg-cancel-payment.response.ts | 4 + .../response/fake-pg-payment.response.ts | 10 ++ .../src/payments/dto/create-payment.dto.ts | 14 +++ .../payments/dto/pg-cancel-payment.request.ts | 3 + .../dto/pg-cancel-payment.response.ts | 10 ++ .../src/payments/dto/pg-payment.request.ts | 49 ++++++++ .../src/payments/dto/pg-payment.response.ts | 12 ++ .../src/payments/dto/search-payment.dto.ts | 4 + .../payments/payments-service.interface.ts | 15 ++- vet_nest/src/payments/payments.service.ts | 110 +++++++----------- vet_nest/src/payments/pg-api-caller.ts | 42 ++++++- vet_nest/src/pg/__test__/pg.service.spec.ts | 81 ------------- vet_nest/src/pg/pg.controller.ts | 29 ----- vet_nest/src/pg/pg.module.ts | 10 -- vet_nest/src/pg/pg.service.ts | 22 ---- .../src/reservations/reservations.module.ts | 3 +- vet_nest/yarn.lock | 2 +- 24 files changed, 313 insertions(+), 228 deletions(-) rename vet_nest/src/{pg => fake-pg}/__test__/pg.controller.spec.ts (100%) create mode 100644 vet_nest/src/fake-pg/fake-pg.controller.ts create mode 100644 vet_nest/src/fake-pg/fake-pg.module.ts create mode 100644 vet_nest/src/fake-pg/request/fake-pg-cancel-payment.request.ts create mode 100644 vet_nest/src/fake-pg/request/fake-pg-payment.request.ts create mode 100644 vet_nest/src/fake-pg/response/fake-pg-cancel-payment.response.ts create mode 100644 vet_nest/src/fake-pg/response/fake-pg-payment.response.ts create mode 100644 vet_nest/src/payments/dto/create-payment.dto.ts create mode 100644 vet_nest/src/payments/dto/pg-cancel-payment.request.ts create mode 100644 vet_nest/src/payments/dto/pg-cancel-payment.response.ts create mode 100644 vet_nest/src/payments/dto/pg-payment.request.ts create mode 100644 vet_nest/src/payments/dto/pg-payment.response.ts create mode 100644 vet_nest/src/payments/dto/search-payment.dto.ts delete mode 100644 vet_nest/src/pg/__test__/pg.service.spec.ts delete mode 100644 vet_nest/src/pg/pg.controller.ts delete mode 100644 vet_nest/src/pg/pg.module.ts delete mode 100644 vet_nest/src/pg/pg.service.ts diff --git a/vet_nest/package.json b/vet_nest/package.json index c7e4ed8..3b05a62 100644 --- a/vet_nest/package.json +++ b/vet_nest/package.json @@ -21,10 +21,10 @@ "test:e2e": "jest --config ./test/jest-e2e.json" }, "dependencies": { - "@nestjs/axios": "^3.0.0", - "@nestjs/common": "^10.0.5", "@automapper/core": "^8.7.7", "@automapper/nestjs": "^8.7.7", + "@nestjs/axios": "^3.0.0", + "@nestjs/common": "^10.0.5", "@nestjs/config": "^2.2.0", "@nestjs/core": "^9.2.1", "@nestjs/jwt": "^10.1.0", @@ -41,8 +41,8 @@ "@types/redis": "^4.0.11", "@types/winston": "^2.4.4", "@willsoto/nestjs-prometheus": "^5.2.0", - "axios": "^1.4.0", "applicationinsights": "^2.7.0", + "axios": "^1.4.0", "body-parser": "^1.20.1", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", @@ -61,6 +61,7 @@ "rxjs": "^7.6.0", "socket.io-redis": "^6.1.1", "typeorm": "^0.3.11", + "uuid": "^9.0.0", "winston": "^3.8.2", "winston-azure-application-insights": "^4.0.0", "winston-daily-rotate-file": "^4.7.1" diff --git a/vet_nest/src/app/app.module.ts b/vet_nest/src/app/app.module.ts index a4fac54..eb9bfd4 100644 --- a/vet_nest/src/app/app.module.ts +++ b/vet_nest/src/app/app.module.ts @@ -31,6 +31,7 @@ import { ExceptionsService } from '../exceptions/exceptions.service'; import { currentModeProviders } from './providers/currentMode.provider'; import { PaymentsRepository } from '../payments/repository/payments.repository'; import { HttpModule } from '@nestjs/axios'; +import { FakePgModule } from '@/fake-pg/fake-pg.module'; @Module({ imports: [ @@ -62,6 +63,7 @@ import { HttpModule } from '@nestjs/axios'; UsersModule, ExceptionsModule, HttpModule, + FakePgModule, ], providers: [ AppService, diff --git a/vet_nest/src/pg/__test__/pg.controller.spec.ts b/vet_nest/src/fake-pg/__test__/pg.controller.spec.ts similarity index 100% rename from vet_nest/src/pg/__test__/pg.controller.spec.ts rename to vet_nest/src/fake-pg/__test__/pg.controller.spec.ts diff --git a/vet_nest/src/fake-pg/fake-pg.controller.ts b/vet_nest/src/fake-pg/fake-pg.controller.ts new file mode 100644 index 0000000..6c91584 --- /dev/null +++ b/vet_nest/src/fake-pg/fake-pg.controller.ts @@ -0,0 +1,50 @@ +import { Controller, Post, Body, HttpException, Param, Patch } from '@nestjs/common'; +import { PgPaymentRequest } from '@/payments/dto/pg-payment.request'; +import { PgPaymentResponse } from '@/payments/dto/pg-payment.response'; +import { v4 as uuidv4 } from 'uuid'; +import { PgCancelPaymentRequest } from '@/payments/dto/pg-cancel-payment.request'; +import { PgCancelPaymentResponse } from '@/payments/dto/pg-cancel-payment.response'; +import { ApiTags } from '@nestjs/swagger'; +import { FakePgPaymentRequest } from './request/fake-pg-payment.request'; +import { FakePgPaymentResponse } from './response/fake-pg-payment.response'; +import { FakePgCancelPaymentRequest } from './request/fake-pg-cancel-payment.request'; +import { FakePgCancelPaymentResponse } from './response/fake-pg-cancel-payment.response'; + +@Controller('pg') +@ApiTags('FakePgController') +export class FakePgController { + constructor() {} + + @Post('create') + createPayment(@Body() param: FakePgPaymentRequest + ): FakePgPaymentResponse { + + let response = new PgPaymentResponse(); + response.resultCode = 'OK'; + response.uuid = uuidv4(); + response.cardNumber = param['cardNumber']; + response.amount = param['amount']; + return response; + } + + @Patch('cancel') + cancelPayment( + @Body() param: FakePgCancelPaymentRequest + ): FakePgCancelPaymentResponse { + return { + resultCode: 'OK', + uuid: param['uuid'] + }; + } + + @Post('refund') + refundPayment(@Body() refundPaymentDto) { + try { + // const result = this.PgService.refundPayment(refundPaymentDto); + return { result: {}, code: 200, message: 'OK' }; + } + catch (error) { + throw new HttpException({ result: false, message: error.message }, 400); + } + } +} diff --git a/vet_nest/src/fake-pg/fake-pg.module.ts b/vet_nest/src/fake-pg/fake-pg.module.ts new file mode 100644 index 0000000..8bb67cb --- /dev/null +++ b/vet_nest/src/fake-pg/fake-pg.module.ts @@ -0,0 +1,8 @@ +import { Module } from '@nestjs/common'; +import { FakePgController as FakePgController } from './fake-pg.controller'; + +@Module({ + imports: [], + controllers: [FakePgController] +}) +export class FakePgModule {} diff --git a/vet_nest/src/fake-pg/request/fake-pg-cancel-payment.request.ts b/vet_nest/src/fake-pg/request/fake-pg-cancel-payment.request.ts new file mode 100644 index 0000000..9bb27cb --- /dev/null +++ b/vet_nest/src/fake-pg/request/fake-pg-cancel-payment.request.ts @@ -0,0 +1,13 @@ +import { ApiProperty } from "@nestjs/swagger"; +import { IsOptional } from "class-validator"; + + +export class FakePgCancelPaymentRequest { + @IsOptional() + @ApiProperty({ + default: '1234-1234-1234-1234', + type: 'string', + description: '결제 uuid' + }) + uuid: string; +} \ No newline at end of file diff --git a/vet_nest/src/fake-pg/request/fake-pg-payment.request.ts b/vet_nest/src/fake-pg/request/fake-pg-payment.request.ts new file mode 100644 index 0000000..31d0313 --- /dev/null +++ b/vet_nest/src/fake-pg/request/fake-pg-payment.request.ts @@ -0,0 +1,41 @@ +import { PaymentMethod } from "@/payments/entity/payments.entity"; +import { ApiProperty } from "@nestjs/swagger"; +import { IsOptional } from "class-validator"; + +export class FakePgPaymentRequest { + @ApiProperty({ + default: 'CARD', + type: 'string', + description: '결제방법', + }) + @IsOptional() + method: PaymentMethod; + @ApiProperty({ + default: '1234-1234-1234-1234', + type: 'string', + description: '결제번호', + }) + @IsOptional() + cardNumber: string; + @ApiProperty({ + default: '10/23', + type: 'string', + description: '유효기간', + }) + @IsOptional() + validPeriod: string; + @ApiProperty({ + default: '10000', + type: 'number', + description: '결제금액' + }) + @IsOptional() + amount: number; + @ApiProperty({ + default: 'WON', + type: 'string', + description: '통화코드' + }) + @IsOptional() + currency: string; +} \ No newline at end of file diff --git a/vet_nest/src/fake-pg/response/fake-pg-cancel-payment.response.ts b/vet_nest/src/fake-pg/response/fake-pg-cancel-payment.response.ts new file mode 100644 index 0000000..0b07787 --- /dev/null +++ b/vet_nest/src/fake-pg/response/fake-pg-cancel-payment.response.ts @@ -0,0 +1,4 @@ +export class FakePgCancelPaymentResponse { + resultCode: string; + uuid: string; +} \ No newline at end of file diff --git a/vet_nest/src/fake-pg/response/fake-pg-payment.response.ts b/vet_nest/src/fake-pg/response/fake-pg-payment.response.ts new file mode 100644 index 0000000..d15d45b --- /dev/null +++ b/vet_nest/src/fake-pg/response/fake-pg-payment.response.ts @@ -0,0 +1,10 @@ +export class FakePgPaymentResponse { + uuid: string; + resultCode: string; + cardNumber: string; + amount: number; + + constructor() { + + } +} \ No newline at end of file diff --git a/vet_nest/src/payments/dto/create-payment.dto.ts b/vet_nest/src/payments/dto/create-payment.dto.ts new file mode 100644 index 0000000..52544b3 --- /dev/null +++ b/vet_nest/src/payments/dto/create-payment.dto.ts @@ -0,0 +1,14 @@ +import { PaymentMethod } from "../entity/payments.entity"; + +export class CreatePaymentDto { + reservationId: number; + method: PaymentMethod; + cardNumber: string; + validPeriod: string; + amount: number; + currency: string; + + constructor() { + + } +} \ No newline at end of file diff --git a/vet_nest/src/payments/dto/pg-cancel-payment.request.ts b/vet_nest/src/payments/dto/pg-cancel-payment.request.ts new file mode 100644 index 0000000..dde2a76 --- /dev/null +++ b/vet_nest/src/payments/dto/pg-cancel-payment.request.ts @@ -0,0 +1,3 @@ +export class PgCancelPaymentRequest { + uuid: string; +} \ No newline at end of file diff --git a/vet_nest/src/payments/dto/pg-cancel-payment.response.ts b/vet_nest/src/payments/dto/pg-cancel-payment.response.ts new file mode 100644 index 0000000..2b12e9d --- /dev/null +++ b/vet_nest/src/payments/dto/pg-cancel-payment.response.ts @@ -0,0 +1,10 @@ +export class PgCancelPaymentResponse { + resultCode: string; + uuid: string; + + constructor(p?: any) { + p = p ?? {}; + this.resultCode = p?.resultCode; + this.uuid = p?.uuid; + } +} \ No newline at end of file diff --git a/vet_nest/src/payments/dto/pg-payment.request.ts b/vet_nest/src/payments/dto/pg-payment.request.ts new file mode 100644 index 0000000..f209bda --- /dev/null +++ b/vet_nest/src/payments/dto/pg-payment.request.ts @@ -0,0 +1,49 @@ +import { ApiProperty } from "@nestjs/swagger"; +import { PaymentMethod } from "../entity/payments.entity" +import { CreatePaymentDto } from "./create-payment.dto" + +export class PgPaymentRequest { + + @ApiProperty({ + default: 'CARD', + required: true, + type: 'string', + description: '결제방법', + }) + method: PaymentMethod; + @ApiProperty({ + default: '1234-1234-1234-1234', + required: true, + type: 'string', + description: '결제번호', + }) + cardNumber: string; + @ApiProperty({ + default: '10/23', + required: true, + type: 'string', + description: '유효기간', + }) + validPeriod: string; + @ApiProperty({ + default: '10000', + required: true, + type: 'number', + description: '결제금액' + }) + amount: number; + @ApiProperty({ + default: 'WON', + required: true, + type: 'string', + description: '통화코드' + }) + currency: string; + + constructor() { + // this.method = dto?.method ?? PaymentMethod.CARD; + // this.cardNumber = '1234-1234-1234-1234'; + // this.validPeriod = '10/23'; + // this.amount = dto?.amount ?? 5000; + } +} \ No newline at end of file diff --git a/vet_nest/src/payments/dto/pg-payment.response.ts b/vet_nest/src/payments/dto/pg-payment.response.ts new file mode 100644 index 0000000..2cab5cc --- /dev/null +++ b/vet_nest/src/payments/dto/pg-payment.response.ts @@ -0,0 +1,12 @@ +export class PgPaymentResponse { + uuid: string; + resultCode: string; + cardNumber: string; + amount: number; + + constructor(p?: any) { + // p = p ?? {}; + // this.uuid = p?.uuid; + // this.resultCode = 'OK'; + } +} \ No newline at end of file diff --git a/vet_nest/src/payments/dto/search-payment.dto.ts b/vet_nest/src/payments/dto/search-payment.dto.ts new file mode 100644 index 0000000..4cec0ee --- /dev/null +++ b/vet_nest/src/payments/dto/search-payment.dto.ts @@ -0,0 +1,4 @@ + +export class SearchPaymentDto { + +} \ No newline at end of file diff --git a/vet_nest/src/payments/payments-service.interface.ts b/vet_nest/src/payments/payments-service.interface.ts index cd6ba6c..84010ab 100644 --- a/vet_nest/src/payments/payments-service.interface.ts +++ b/vet_nest/src/payments/payments-service.interface.ts @@ -1,12 +1,19 @@ +import { SearchOptions } from "redis"; import { Payment } from "./entity/payments.entity"; +import { SearchPaymentDto } from "./dto/search-payment.dto"; +import { PgCancelPaymentRequest } from "./dto/pg-cancel-payment.request"; +import { PgCancelPaymentResponse } from "./dto/pg-cancel-payment.response"; +import { PgPaymentResponse } from "./dto/pg-payment.response"; export interface IPaymentService { - getPaymentsByReservationId(reservationId: number): Promise; - pay(createPaymentDto: object): Promise; + // getPaymentsByUserId(userId: number, searchOption: SearchPaymentDto); + // getPaymentsByVetId(vetId: number, searchOption: SearchPaymentDto); + // getPaymentsByReservationId(reservationId: number): Promise; + createPayment(createPaymentDto: object): Promise; cancelPayment(paymentId: number): Promise; cancelPaymentsByReservationId(reservationId: number): Promise } export interface IFakePgApi { - pay(createPaymentDto: any): Promise, - cancelPayment(uuid: string): Promise + pay(createPaymentDto: any): Promise, + cancelPayment(uuid: string): Promise } \ No newline at end of file diff --git a/vet_nest/src/payments/payments.service.ts b/vet_nest/src/payments/payments.service.ts index 9d6fbcb..3bdb19d 100644 --- a/vet_nest/src/payments/payments.service.ts +++ b/vet_nest/src/payments/payments.service.ts @@ -1,109 +1,77 @@ import { Injectable } from '@nestjs/common'; import { PaymentsRepository } from './repository/payments.repository'; -import { HttpService } from '@nestjs/axios'; -import { firstValueFrom } from 'rxjs'; import { Payment, PaymentStatus } from './entity/payments.entity'; import { IPaymentService } from './payments-service.interface'; import { PgApiCaller } from './pg-api-caller'; import { BusinessException } from 'util/exception.util'; +import { CreatePaymentDto } from './dto/create-payment.dto'; @Injectable() export class PaymentsService implements IPaymentService { constructor( private readonly paymentsRepository: PaymentsRepository, - // private readonly httpService: HttpService, private readonly pgApiCaller: PgApiCaller ) {} - pay(createPaymentDto: object): Promise { - throw new Error('Method not implemented.'); - } - cancelPayment(paymentId: number): Promise { - throw new Error('Method not implemented.'); - } - async getPaymentsByReservationId(reservationId: number): Promise { + return this.paymentsRepository.findBy({ reservationId: reservationId }); } - async cancelPaymentsByReservationId(reservationId: number): Promise { - console.log(`paymentsService.cancelPaymentsByReservationId: ${reservationId}`); - const payments = await this.getPaymentsByReservationId(reservationId); - const canceledPayments = payments.map((payment: Payment) => { - payment.cancel(); - const result = this.pgApiCaller.cancelPayment(payment.appId); - return payment; - }); + createPayment(createPaymentDto: object): Promise { + throw new Error('Method not implemented.'); + } + + async cancelPayment(paymentId: number): Promise { + + const payment = await this.paymentsRepository.findOneBy({paymentId: paymentId}); + const result = await this.pgApiCaller.cancelPayment(payment.appId); + + if (result.resultCode != 'OK') { + throw new BusinessException(payment, 'PG 결제 오류', '500'); + } + payment.cancel(); + this.paymentsRepository.save(payment); + return Promise.resolve(payment); + } - if (!canceledPayments.every((payment) => payment.isCanceled())) + async cancelPayments(paymentIds: number[]): Promise { + + const canceledPayments = await Promise.all( + paymentIds.map(async (paymentId) => { + return await this.cancelPayment(paymentId); + })); + + if (!canceledPayments.every((payment) => payment.isCanceled())) { throw new BusinessException(canceledPayments, 'PG 결제 오류', '500'); + } - this.paymentsRepository.save(canceledPayments); return canceledPayments; } - + async cancelPaymentsByReservationId(reservationId: number): Promise { + + const paymentIds = (await this.getPaymentsByReservationId(reservationId)) + .map((payment) => payment.paymentId); + + const canceledPayments = await this.cancelPayments(paymentIds); + return canceledPayments; + } - async create(createPaymentDto) { - if (!(createPaymentDto.reservationId && createPaymentDto.amount)) { + async create(dto: CreatePaymentDto) { + + if (!(dto.reservationId && dto.amount)) { throw new Error('invalid data'); } const targetPayment = await this.paymentsRepository.findByReservationId( - createPaymentDto.reservationId, + dto.reservationId, ); if (targetPayment && targetPayment.status === PaymentStatus.COMPLETE) { throw new Error('payment has already made'); } - - const pgCreateUrl = 'http://localhost:3001/pg/create'; - const pgCreateBody = { - reservationId: createPaymentDto.reservationId, - amount: createPaymentDto.amount, - }; - - // const pgResponse = ( - // await firstValueFrom(this.httpService.post(pgCreateUrl, pgCreateBody)) - // ).data; - // if (pgResponse.code !== 201) { - // throw new Error('pg error'); - // } - - // return this.paymentsRepository.createPayment( - // createPaymentDto.reservationId, - // createPaymentDto.amount, - // pgResponse.result.appId, - // ); } - - // async refund(refundPaymentDto) { - // if (!refundPaymentDto.paymentId) { - // throw new Error('paymentId is required'); - // } - - // const targetPayment = await this.paymentsRepository.findByPaymentId( - // refundPaymentDto.paymentId, - // ); - // if (!targetPayment || targetPayment.status === 'refund') { - // throw new Error('payment is not refundable'); - // } - - // const pgRefundUrl = 'http://localhost:3001/pg/refund'; - // const pgRefundBody = { appId: targetPayment.appId }; - // const result = ( - // await firstValueFrom(this.httpService.post(pgRefundUrl, pgRefundBody)) - // ).data; - // if (result.code !== 200) { - // throw new Error('pg error'); - // } - - // return this.paymentsRepository.refund(refundPaymentDto.paymentId); - // } - - // async cancelPayment(payment: Payment): Promise { - // throw new Error("Method not implemented."); - // } } diff --git a/vet_nest/src/payments/pg-api-caller.ts b/vet_nest/src/payments/pg-api-caller.ts index 0dbe891..0e8247b 100644 --- a/vet_nest/src/payments/pg-api-caller.ts +++ b/vet_nest/src/payments/pg-api-caller.ts @@ -1,17 +1,47 @@ -import { Injectable } from "@nestjs/common"; +import { Injectable, InternalServerErrorException } from "@nestjs/common"; import { IFakePgApi } from "./payments-service.interface"; +import { HttpModule, HttpService } from "@nestjs/axios"; +import { BusinessException } from "util/exception.util"; +import { PgPaymentRequest } from "./dto/pg-payment.request"; +import { PgPaymentResponse } from "./dto/pg-payment.response"; +import { PgCancelPaymentResponse } from "./dto/pg-cancel-payment.response"; +import { PgCancelPaymentRequest } from "./dto/pg-cancel-payment.request"; +import { catchError, firstValueFrom } from "rxjs"; +import { AxiosError } from "axios"; @Injectable() export class PgApiCaller implements IFakePgApi { - constructor() { + private PG_API_ADDRESS: string = 'http://localhost:3001/pg'; + constructor(private httpClient: HttpService) { } - async pay(createPaymentDto: any): Promise { - return null; + async pay(param: PgPaymentRequest): Promise { + //TODO: parameter 만들어져서 넘어와야 하는가? or DTO 받아서 parameter 만들어야 하는가? + + this.httpClient.post(`${this.PG_API_ADDRESS}/create`, param) + .pipe() + .subscribe({ + next: (res: any) => { + const response = new PgPaymentResponse(res); + return Promise.resolve(response); + }, + error: (error: any) => { + throw new BusinessException(error, 'PG-ERROR', '500'); + } + }); } - async cancelPayment(uuid: string): Promise { - return null; + async cancelPayment(uuid: string): Promise { + const param = new PgCancelPaymentRequest(); + param.uuid = uuid; + const { data } = await firstValueFrom( + await this.httpClient.patch(`${this.PG_API_ADDRESS}/cancel`, param).pipe( + catchError((error: AxiosError) => { + throw new BusinessException(error, 'PG-ERROR', '500'); + }) + )); + console.log(`PG-API: ${JSON.stringify(data)}`); + return Promise.resolve(data); } } \ No newline at end of file diff --git a/vet_nest/src/pg/__test__/pg.service.spec.ts b/vet_nest/src/pg/__test__/pg.service.spec.ts deleted file mode 100644 index 3d989c7..0000000 --- a/vet_nest/src/pg/__test__/pg.service.spec.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { PgService } from '../pg.service'; - -describe('createPayment', () => { - let service: PgService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [PgService], - }).compile(); - - service = module.get(PgService); - }); - - test('createPayment passes with valid data', () => { - const createPaymentDto = { - amount: 100, - reservationId: 1, - }; - const createdPayment = { - appId: 'PG' + createPaymentDto.reservationId, - }; - - const result = service.createPayment(createPaymentDto); - - expect(result).toEqual(createdPayment); - }); - - test('createPayment fails when amount is empty', () => { - const createPaymentDto = { - amount: null, - reservationId: 1, - }; - - try { - service.createPayment(createPaymentDto); - } - catch(error) { - expect(error).toBeInstanceOf(Error); - } - - expect.assertions(1); - }); -}); - -describe('refundPayment', () => { - let service: PgService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [PgService], - }).compile(); - - service = module.get(PgService); - }); - - test('refundPayment passes with valid data', () => { - const refundPaymentDto = { - appId: 'PG1', - }; - - const result = service.refundPayment(refundPaymentDto); - - expect(result).toBeTruthy(); - }); - - test('refundPayment fails when appId is missing', () => { - const refundPaymentDto = { - appId: null, - }; - - try { - service.refundPayment(refundPaymentDto); - } - catch(error) { - expect(error).toBeInstanceOf(Error); - } - - expect.assertions(1); - }); -}); diff --git a/vet_nest/src/pg/pg.controller.ts b/vet_nest/src/pg/pg.controller.ts deleted file mode 100644 index b7422c9..0000000 --- a/vet_nest/src/pg/pg.controller.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Controller, Post, Body, HttpException } from '@nestjs/common'; -import { PgService } from './pg.service'; - -@Controller('pg') -export class PgController { - constructor(private PgService: PgService) {} - - @Post('create') - createPayment(@Body() createPaymentDto) { - try { - const result = this.PgService.createPayment(createPaymentDto); - return { result: result, code: 201, message: 'CREATED' }; - } - catch (error) { - throw new HttpException({ result: false, message: error.message }, 400); - } - } - - @Post('refund') - refundPayment(@Body() refundPaymentDto) { - try { - const result = this.PgService.refundPayment(refundPaymentDto); - return { result: result, code: 200, message: 'OK' }; - } - catch (error) { - throw new HttpException({ result: false, message: error.message }, 400); - } - } -} diff --git a/vet_nest/src/pg/pg.module.ts b/vet_nest/src/pg/pg.module.ts deleted file mode 100644 index 5efefd2..0000000 --- a/vet_nest/src/pg/pg.module.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Module } from '@nestjs/common'; -import { PgController } from './pg.controller'; -import { PgService } from './pg.service'; - -@Module({ - imports: [], - controllers: [PgController], - providers: [PgService], -}) -export class PgModule {} diff --git a/vet_nest/src/pg/pg.service.ts b/vet_nest/src/pg/pg.service.ts deleted file mode 100644 index 4057c99..0000000 --- a/vet_nest/src/pg/pg.service.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -@Injectable() -export class PgService { - createPayment(createPaymentDto) { - const { amount, reservationId } = createPaymentDto; - if (!amount || !reservationId) { - throw new Error('invalid data'); - } - - return { appId: 'PG' + reservationId }; - } - - refundPayment(refundPaymentDto) { - const { appId } = refundPaymentDto; - if (!appId) { - throw new Error('invalid appId'); - } - - return true; - } -} diff --git a/vet_nest/src/reservations/reservations.module.ts b/vet_nest/src/reservations/reservations.module.ts index 37398d7..668d234 100644 --- a/vet_nest/src/reservations/reservations.module.ts +++ b/vet_nest/src/reservations/reservations.module.ts @@ -10,9 +10,10 @@ import { PaymentsModule } from '@/payments/payments.module'; import { PaymentsService } from '@/payments/payments.service'; import { PaymentsRepository } from '@/payments/repository/payments.repository'; import { PgApiCaller } from '@/payments/pg-api-caller'; +import { HttpModule } from '@nestjs/axios'; @Module({ - imports: [DatabaseModule], + imports: [DatabaseModule, HttpModule], controllers: [ReservationCancelationController, ReservationsController], providers: [ ReservationCancelationService, diff --git a/vet_nest/yarn.lock b/vet_nest/yarn.lock index af22953..9eb69cc 100644 --- a/vet_nest/yarn.lock +++ b/vet_nest/yarn.lock @@ -6069,7 +6069,7 @@ uuid@8.3.2, uuid@^8.3.0, uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== -uuid@9.0.0: +uuid@9.0.0, uuid@^9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== From e5d9eb1c975628256f8bbb61498275186da6bb56 Mon Sep 17 00:00:00 2001 From: mklee-mac Date: Sun, 16 Jul 2023 23:08:37 +0900 Subject: [PATCH 05/14] =?UTF-8?q?paymentStatus=20=EA=B0=92=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vet_nest/src/payments/entity/payments.entity.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vet_nest/src/payments/entity/payments.entity.ts b/vet_nest/src/payments/entity/payments.entity.ts index 2815cd1..d1ed05b 100644 --- a/vet_nest/src/payments/entity/payments.entity.ts +++ b/vet_nest/src/payments/entity/payments.entity.ts @@ -48,8 +48,8 @@ export class Payment { } export enum PaymentStatus { - COMPLETE = 'Complete', - CANCELD = 'Cancel' + COMPLETE = 'COMPLETED', + CANCELD = 'CANCELED' } export enum PaymentMethod { From bf062f955e9496d94b74eeebd77b427e4497194b Mon Sep 17 00:00:00 2001 From: mklee-mac Date: Sun, 16 Jul 2023 23:14:49 +0900 Subject: [PATCH 06/14] =?UTF-8?q?pgApiCaller=20-=20pay=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vet_nest/src/payments/pg-api-caller.ts | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/vet_nest/src/payments/pg-api-caller.ts b/vet_nest/src/payments/pg-api-caller.ts index 0e8247b..89ed7df 100644 --- a/vet_nest/src/payments/pg-api-caller.ts +++ b/vet_nest/src/payments/pg-api-caller.ts @@ -16,20 +16,15 @@ export class PgApiCaller implements IFakePgApi constructor(private httpClient: HttpService) { } - async pay(param: PgPaymentRequest): Promise { + async pay(param: PgPaymentRequest): Promise { //TODO: parameter 만들어져서 넘어와야 하는가? or DTO 받아서 parameter 만들어야 하는가? + const { data } = await firstValueFrom( + await this.httpClient.post(`${this.PG_API_ADDRESS}/create`, param).pipe( + catchError((error: AxiosError) => { + throw new BusinessException(error, 'PG-ERROR', '500') + }))); - this.httpClient.post(`${this.PG_API_ADDRESS}/create`, param) - .pipe() - .subscribe({ - next: (res: any) => { - const response = new PgPaymentResponse(res); - return Promise.resolve(response); - }, - error: (error: any) => { - throw new BusinessException(error, 'PG-ERROR', '500'); - } - }); + return Promise.resolve(data); } async cancelPayment(uuid: string): Promise { From 612e2623025e731f0075f484f82af4c9d9c86ed8 Mon Sep 17 00:00:00 2001 From: mklee-mac Date: Sun, 16 Jul 2023 23:15:44 +0900 Subject: [PATCH 07/14] =?UTF-8?q?pgApiCaller=20-=20pay=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vet_nest/src/payments/pg-api-caller.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/vet_nest/src/payments/pg-api-caller.ts b/vet_nest/src/payments/pg-api-caller.ts index 89ed7df..f7fa1d2 100644 --- a/vet_nest/src/payments/pg-api-caller.ts +++ b/vet_nest/src/payments/pg-api-caller.ts @@ -19,7 +19,8 @@ export class PgApiCaller implements IFakePgApi async pay(param: PgPaymentRequest): Promise { //TODO: parameter 만들어져서 넘어와야 하는가? or DTO 받아서 parameter 만들어야 하는가? const { data } = await firstValueFrom( - await this.httpClient.post(`${this.PG_API_ADDRESS}/create`, param).pipe( + await this.httpClient.post(`${this.PG_API_ADDRESS}/create`, param) + .pipe( catchError((error: AxiosError) => { throw new BusinessException(error, 'PG-ERROR', '500') }))); @@ -31,12 +32,13 @@ export class PgApiCaller implements IFakePgApi const param = new PgCancelPaymentRequest(); param.uuid = uuid; const { data } = await firstValueFrom( - await this.httpClient.patch(`${this.PG_API_ADDRESS}/cancel`, param).pipe( + await this.httpClient.patch(`${this.PG_API_ADDRESS}/cancel`, param) + .pipe( catchError((error: AxiosError) => { throw new BusinessException(error, 'PG-ERROR', '500'); }) )); - console.log(`PG-API: ${JSON.stringify(data)}`); + return Promise.resolve(data); } } \ No newline at end of file From a0f9f0043b04419eca441935a87d8acec875f51f Mon Sep 17 00:00:00 2001 From: mklee-mac Date: Sun, 16 Jul 2023 23:33:16 +0900 Subject: [PATCH 08/14] =?UTF-8?q?payments.service=20-=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vet_nest/src/payments/payments.service.ts | 61 ++++++++++------------- 1 file changed, 27 insertions(+), 34 deletions(-) diff --git a/vet_nest/src/payments/payments.service.ts b/vet_nest/src/payments/payments.service.ts index 3bdb19d..be5b033 100644 --- a/vet_nest/src/payments/payments.service.ts +++ b/vet_nest/src/payments/payments.service.ts @@ -13,38 +13,44 @@ export class PaymentsService implements IPaymentService { private readonly paymentsRepository: PaymentsRepository, private readonly pgApiCaller: PgApiCaller ) {} - - async getPaymentsByReservationId(reservationId: number): Promise { + + async create(dto: CreatePaymentDto) { - return this.paymentsRepository.findBy({ - reservationId: reservationId - }); - } + if (!(dto.reservationId && dto.amount)) { + throw new Error('invalid data'); + } - createPayment(createPaymentDto: object): Promise { - throw new Error('Method not implemented.'); + const targetPayment = await this.paymentsRepository.findByReservationId( + dto.reservationId, + ); + if (targetPayment && targetPayment.status === PaymentStatus.COMPLETE) { + throw new Error('payment has already made'); + } } - async cancelPayment(paymentId: number): Promise { + getPaymentsByReservationId = async(reservationId: number): Promise => + this.paymentsRepository.findBy({ + reservationId: reservationId + }); + + cancelPayment = async(paymentId: number): Promise => { const payment = await this.paymentsRepository.findOneBy({paymentId: paymentId}); - const result = await this.pgApiCaller.cancelPayment(payment.appId); - - if (result.resultCode != 'OK') { - throw new BusinessException(payment, 'PG 결제 오류', '500'); + const pgResult = await this.pgApiCaller.cancelPayment(payment.appId); + if (pgResult.resultCode != 'OK') { + throw new BusinessException(pgResult, 'PG-ERROR', '500'); } payment.cancel(); this.paymentsRepository.save(payment); return Promise.resolve(payment); } - async cancelPayments(paymentIds: number[]): Promise { + cancelPayments = async(paymentIds: number[]): Promise => { const canceledPayments = await Promise.all( - paymentIds.map(async (paymentId) => { - return await this.cancelPayment(paymentId); - })); - + paymentIds.map(async (paymentId) => + await this.cancelPayment(paymentId))); + if (!canceledPayments.every((payment) => payment.isCanceled())) { throw new BusinessException(canceledPayments, 'PG 결제 오류', '500'); } @@ -52,26 +58,13 @@ export class PaymentsService implements IPaymentService { return canceledPayments; } - async cancelPaymentsByReservationId(reservationId: number): Promise { + cancelPaymentsByReservationId = async(reservationId: number): Promise => { - const paymentIds = (await this.getPaymentsByReservationId(reservationId)) + const paymentIds = (await + this.getPaymentsByReservationId(reservationId)) .map((payment) => payment.paymentId); const canceledPayments = await this.cancelPayments(paymentIds); return canceledPayments; } - - async create(dto: CreatePaymentDto) { - - if (!(dto.reservationId && dto.amount)) { - throw new Error('invalid data'); - } - - const targetPayment = await this.paymentsRepository.findByReservationId( - dto.reservationId, - ); - if (targetPayment && targetPayment.status === PaymentStatus.COMPLETE) { - throw new Error('payment has already made'); - } - } } From 8c066cc6c4543acc4b549e13e2e0841f6b39ed57 Mon Sep 17 00:00:00 2001 From: mklee-mac Date: Sun, 16 Jul 2023 23:42:01 +0900 Subject: [PATCH 09/14] =?UTF-8?q?reservation-facade=20-=20cancelReservatio?= =?UTF-8?q?n=20=EC=86=8C=EC=8A=A4=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../database/providers/database.provider.ts | 2 +- .../dto/reservation-profile.mapper.ts | 24 ------------------- .../src/reservations/reservation-facade.ts | 14 ++++------- 3 files changed, 5 insertions(+), 35 deletions(-) delete mode 100644 vet_nest/src/reservations/dto/reservation-profile.mapper.ts diff --git a/vet_nest/src/database/providers/database.provider.ts b/vet_nest/src/database/providers/database.provider.ts index a1ccb68..17b3158 100644 --- a/vet_nest/src/database/providers/database.provider.ts +++ b/vet_nest/src/database/providers/database.provider.ts @@ -165,7 +165,7 @@ export async function dbInitializeCallback(db: DataSource) { const paymentRepo = db.getRepository(Payment); paymentRepo.save([{ paymentId: 1, - appId: 'APP-11111', + appId: '1280ad9c-31d9-4342-a7b2-3126a5ff738f', method: PaymentMethod.CARD, amount: 5000, status: PaymentStatus.COMPLETE, diff --git a/vet_nest/src/reservations/dto/reservation-profile.mapper.ts b/vet_nest/src/reservations/dto/reservation-profile.mapper.ts deleted file mode 100644 index 1b51eee..0000000 --- a/vet_nest/src/reservations/dto/reservation-profile.mapper.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { AutomapperProfile, InjectMapper } from '@automapper/nestjs'; -import { createMap, MappingConfiguration, type Mapper, extend } from '@automapper/core'; -import { Injectable } from '@nestjs/common'; -import { Reservation } from '../entity/reservation.entity'; -import { ReservastionsDto } from './reservations.dto'; - -@Injectable() -export class ReservationMapperProfile extends AutomapperProfile { - - constructor(@InjectMapper() mapper: Mapper) { - super(mapper); - } - - override get profile() { - return (mapper) => { - createMap(mapper, Reservation, ReservastionsDto); - } - } - - protected get mappingConfigurations(): MappingConfiguration[] { - // the 3 createMap() above will get this `extend()` - return [extend(Reservation, ReservastionsDto)]; -} -} \ No newline at end of file diff --git a/vet_nest/src/reservations/reservation-facade.ts b/vet_nest/src/reservations/reservation-facade.ts index 7649fce..627fb5f 100644 --- a/vet_nest/src/reservations/reservation-facade.ts +++ b/vet_nest/src/reservations/reservation-facade.ts @@ -15,16 +15,10 @@ export class ReservationFacade { async cancelReservation(reservationId: number): Promise { try { const canceledReservation = - await this.reservationCancelationService.cancelReservation( - reservationId, - ); - - console.log(`reservation:${JSON.stringify(canceledReservation)}`); - console.log(`reservation.id:${JSON.stringify(canceledReservation.id)}`); - - const canceledPayments = await this.paymentService.cancelPaymentsByReservationId( - canceledReservation.id, - ); + await this.reservationCancelationService.cancelReservation(reservationId); + + const canceledPayments = await + this.paymentService.cancelPaymentsByReservationId(canceledReservation.id); canceledReservation.payments = canceledPayments; return Promise.resolve(canceledReservation); From 5f6d2f1041a34c1573b9ac0fd1852631be18053e Mon Sep 17 00:00:00 2001 From: mklee-mac Date: Sun, 16 Jul 2023 23:44:17 +0900 Subject: [PATCH 10/14] =?UTF-8?q?ipayment.service=20->=20createPayment=20?= =?UTF-8?q?=EC=A3=BC=EC=84=9D=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vet_nest/src/payments/payments-service.interface.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vet_nest/src/payments/payments-service.interface.ts b/vet_nest/src/payments/payments-service.interface.ts index 84010ab..f24e99b 100644 --- a/vet_nest/src/payments/payments-service.interface.ts +++ b/vet_nest/src/payments/payments-service.interface.ts @@ -8,7 +8,7 @@ export interface IPaymentService { // getPaymentsByUserId(userId: number, searchOption: SearchPaymentDto); // getPaymentsByVetId(vetId: number, searchOption: SearchPaymentDto); // getPaymentsByReservationId(reservationId: number): Promise; - createPayment(createPaymentDto: object): Promise; + // createPayment(createPaymentDto: object): Promise; cancelPayment(paymentId: number): Promise; cancelPaymentsByReservationId(reservationId: number): Promise } From fd171ef85c0547068eb6966b2c9d12a83cb10b69 Mon Sep 17 00:00:00 2001 From: mklee-mac Date: Mon, 17 Jul 2023 23:32:18 +0900 Subject: [PATCH 11/14] =?UTF-8?q?=EC=B4=88=EA=B8=B0=20=EB=8D=94=EB=AF=B8?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=BF=BC=EB=A6=AC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vet_nest/config/config.ts | 3 ++- .../src/database/providers/database.provider.ts | 10 +++++----- .../src/database/typeorm-maria-testing.module.ts | 4 ++-- .../reservation-cancelation.controller.spec.ts | 5 +++-- .../reservation-cancelation.service.spec.ts | 14 +++++++------- .../reservation-cancelation.controller.ts | 3 --- .../validator/reservation-cancelation.validator.ts | 2 +- 7 files changed, 20 insertions(+), 21 deletions(-) diff --git a/vet_nest/config/config.ts b/vet_nest/config/config.ts index 2c1d443..d89879b 100644 --- a/vet_nest/config/config.ts +++ b/vet_nest/config/config.ts @@ -14,12 +14,13 @@ export default () => ({ type: process.env.DB_TYPE === 'mariadb' ? 'mariadb' : 'mysql', host: process.env.REACT_APP_ENV === 'local' - ? process.env.DB_HOST + ? '127.0.0.1' : process.env.DB_HOST, port: parseInt(process.env.DB_PORT), username: process.env.DB_USERNAME, password: process.env.DB_PASSWORD, database: process.env.DB_DATABASE, + timezone: '+00:00', // entities: ['dist/**/*.entity.js'], logging: Boolean(JSON.parse(process.env.DB_LOGGING)), synchronize: process.env.DB_SYNCHRONIZE === 'true' ? true : false, diff --git a/vet_nest/src/database/providers/database.provider.ts b/vet_nest/src/database/providers/database.provider.ts index 17b3158..b8d81cb 100644 --- a/vet_nest/src/database/providers/database.provider.ts +++ b/vet_nest/src/database/providers/database.provider.ts @@ -116,7 +116,7 @@ export async function dbInitializeCallback(db: DataSource) { id: 1, receptionMethod: ReceptionMethod.RESERVATION, status: TreatmentStatus.RESERVATION_COMPLETED, - reservedAt: moment(new Date()).add(1.5, 'hours').add(9, 'hours').toDate(), + reservedAt: moment(new Date()).add(1.5, 'hours').toDate(), vetId: 1, slotId: 1, petId: '263df66a-c1e0-4ad3-94e7-bf8236ec3f09', @@ -126,9 +126,9 @@ export async function dbInitializeCallback(db: DataSource) { }, { id: 2, - receptionMethod: ReceptionMethod.ON_SITE, + receptionMethod: ReceptionMethod.RESERVATION, status: TreatmentStatus.RESERVATION_COMPLETED, - reservedAt: moment().add(0.5, 'hours').add(9, 'hours').toDate(), + reservedAt: moment().add(0.5, 'hours').toDate(), vetId: 1, slotId: 1, petId: '263df66a-c1e0-4ad3-94e7-bf8236ec3f09', @@ -139,8 +139,8 @@ export async function dbInitializeCallback(db: DataSource) { { id: 3, receptionMethod: ReceptionMethod.RESERVATION, - status: TreatmentStatus.RESERVATION_COMPLETED, - reservedAt: moment(new Date()).add(1.5, 'hours').add(9, 'hours').toDate(), + status: TreatmentStatus.RESERVATION_CANCELED, + reservedAt: moment(new Date()).add(1.5, 'hours').toDate(), vetId: 1, slotId: 1, petId: '263df66a-c1e0-4ad3-94e7-bf8236ec3f09', diff --git a/vet_nest/src/database/typeorm-maria-testing.module.ts b/vet_nest/src/database/typeorm-maria-testing.module.ts index 8fa11dd..542d8c4 100644 --- a/vet_nest/src/database/typeorm-maria-testing.module.ts +++ b/vet_nest/src/database/typeorm-maria-testing.module.ts @@ -6,7 +6,7 @@ import { User, UserLevel, UserStatus } from '../users/entity/users.entity'; import { Vet } from '../vets/entity/vet.entity'; import { TimeSlot } from '../vets/entity/timeslot.entity'; import { Pet } from '../pets/entity/pet.entity'; -import { TreatmentResult } from '@/diagnosis/entity/TreatmentResult.entity'; +import { TreatmentResult } from '../diagnosis/entity/TreatmentResult.entity'; export const testDbDataSource: DataSourceOptions = { type: 'mariadb', @@ -17,7 +17,7 @@ export const testDbDataSource: DataSourceOptions = { database: 'test', synchronize: true, logging: true, - timezone: '+09:00', + timezone: '+00:00', entities: [Reservation, Payment, Vet, TimeSlot, Pet, User, TreatmentResult], }; diff --git a/vet_nest/src/reservations/__test__/reservation-cancelation.controller.spec.ts b/vet_nest/src/reservations/__test__/reservation-cancelation.controller.spec.ts index fa67b65..59a872b 100644 --- a/vet_nest/src/reservations/__test__/reservation-cancelation.controller.spec.ts +++ b/vet_nest/src/reservations/__test__/reservation-cancelation.controller.spec.ts @@ -5,7 +5,7 @@ import { } from '@nestjs/common'; import * as request from 'supertest'; -describe('ReservationCancelationController', () => { +describe('예약취소 컨트롤러 - ReservationCancelationController', () => { let app: INestApplication; beforeAll(async () => { @@ -42,9 +42,10 @@ describe('ReservationCancelationController', () => { //Arrange const reservationId = 2; //Act - const res = await request('http://localhost:3001/') + const res = await request('http://localhost:3001') .get(`/reservation-cancelation/${reservationId}`); //Assert + console.log(`error:${JSON.stringify(res)}`); expect(res.status).toBe(HttpStatus.FORBIDDEN); }); diff --git a/vet_nest/src/reservations/__test__/reservation-cancelation.service.spec.ts b/vet_nest/src/reservations/__test__/reservation-cancelation.service.spec.ts index bfb5b7e..b413c59 100644 --- a/vet_nest/src/reservations/__test__/reservation-cancelation.service.spec.ts +++ b/vet_nest/src/reservations/__test__/reservation-cancelation.service.spec.ts @@ -6,7 +6,6 @@ import { Reservation, TreatmentStatus } from '../entity/reservation.entity'; import { ReservationReposiotory } from '../repository/reservation-repository'; import { MockReservationRepository } from '../repository/reservation-repository.mock'; import ReservationCancelationValidator from '../validator/reservation-cancelation.validator'; -import { ForbiddenException, NotFoundException } from '@nestjs/common'; describe('예약취소 서비스 - ReservationCancelationService', () => { let dataSource: DataSource; @@ -43,33 +42,34 @@ describe('예약취소 서비스 - ReservationCancelationService', () => { }); describe('예약취소 정책', () => { - it('예약 Id에 해당하는 예약 정보가 없을 경우, NotFoundException을 발생 시킨다.', () => { + it('예약 Id에 해당하는 예약 정보가 없을 경우, 404 Error가 발생된다.', () => { try { ReservationCancelationValidator.validate(null); } catch (e) { - expect(e.name).toEqual(NotFoundException.name); + console.log(`e: ${JSON.stringify(e)}`); + expect(e.stack).toEqual('404'); expect(e.message).toEqual('예약정보를 찾을 수 없습니다.'); } }); - it('예약 시간까지 남은 시간이 한 시간 이내인 경우 ForbiddenException을 발생시킨다.', async () => { + it('예약 시간까지 남은 시간이 한 시간 이내인 경우 403 Error가 발생된다.', async () => { const reservation = await repository.getReservationById(2); try { ReservationCancelationValidator.validate(reservation); throw Error(''); } catch (e) { - expect(e.name).toEqual(ForbiddenException.name); + expect(e.stack).toEqual('403'); expect(e.message).toEqual('취소 가능 시간이 아닙니다.'); } }); - it('예약완료 상태가 아닌 경우 ForbiddenException을 발생시킨다.', async () => { + it('예약완료 상태가 아닌 경우 403 Error가 발생된다.', async () => { const reservation = await repository.getReservationById(3); try { ReservationCancelationValidator.validate(reservation); throw Error(''); } catch (e) { - expect(e.name).toEqual(ForbiddenException.name); + expect(e.stack).toEqual('403'); expect(e.message).toEqual('취소 가능 상태가 아닙니다.'); } }); diff --git a/vet_nest/src/reservations/reservation-cancelation.controller.ts b/vet_nest/src/reservations/reservation-cancelation.controller.ts index 89d31de..8dfdd3b 100644 --- a/vet_nest/src/reservations/reservation-cancelation.controller.ts +++ b/vet_nest/src/reservations/reservation-cancelation.controller.ts @@ -1,8 +1,6 @@ import { Controller, Get, - HttpException, - HttpStatus, Param } from '@nestjs/common'; import { DataSource } from 'typeorm'; @@ -15,7 +13,6 @@ import { ReservationFacade } from './reservation-facade'; @ApiTags('Reservation-cancelation') export class ReservationCancelationController { constructor( - // private reservationCancelationService: ReservationCancelationService, private reservationFacadeService: ReservationFacade ) {} diff --git a/vet_nest/src/reservations/validator/reservation-cancelation.validator.ts b/vet_nest/src/reservations/validator/reservation-cancelation.validator.ts index 0d4e869..407900e 100644 --- a/vet_nest/src/reservations/validator/reservation-cancelation.validator.ts +++ b/vet_nest/src/reservations/validator/reservation-cancelation.validator.ts @@ -1,6 +1,6 @@ import * as moment from "moment"; import { Reservation, TreatmentStatus } from "../entity/reservation.entity"; -import { BusinessException } from "util/exception.util"; +import { BusinessException } from "../../../util/exception.util"; export default class ReservationCancelationValidator { From b318c1ed43de70364e647301f1baaa80685ece0d Mon Sep 17 00:00:00 2001 From: mklee-mac Date: Tue, 18 Jul 2023 00:37:43 +0900 Subject: [PATCH 12/14] =?UTF-8?q?getPaymentsByUserId=20-=20=EC=9E=91?= =?UTF-8?q?=EC=97=85=20=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../database/providers/database.provider.ts | 3 +- .../__test__/payments.controller.spec.ts | 132 ++++++++++-------- .../src/payments/dto/search-payment.dto.ts | 15 +- .../src/payments/entity/payments.entity.ts | 10 +- .../payments/payments-service.interface.ts | 2 +- vet_nest/src/payments/payments.controller.ts | 38 +++-- vet_nest/src/payments/payments.service.ts | 18 +++ .../reservation-cancelation.controller.ts | 3 - 8 files changed, 145 insertions(+), 76 deletions(-) diff --git a/vet_nest/src/database/providers/database.provider.ts b/vet_nest/src/database/providers/database.provider.ts index b8d81cb..9b4136a 100644 --- a/vet_nest/src/database/providers/database.provider.ts +++ b/vet_nest/src/database/providers/database.provider.ts @@ -169,7 +169,8 @@ export async function dbInitializeCallback(db: DataSource) { method: PaymentMethod.CARD, amount: 5000, status: PaymentStatus.COMPLETE, - reservationId: 1 + reservationId: 1, + userId: 1 }, ]); } diff --git a/vet_nest/src/payments/__test__/payments.controller.spec.ts b/vet_nest/src/payments/__test__/payments.controller.spec.ts index 036a575..06478ca 100644 --- a/vet_nest/src/payments/__test__/payments.controller.spec.ts +++ b/vet_nest/src/payments/__test__/payments.controller.spec.ts @@ -4,77 +4,95 @@ import * as request from 'supertest'; const LOCAL_HOST = 'http://localhost:3001'; -describe('CREATE PAYMENT', () => { +describe('결제 컨트롤러 - PaymentConctroller' , () => { let app: INestApplication; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({}).compile(); app = module.createNestApplication(); - await app.init; + await app.init(); }); + + describe('GET /payments', () => { + + it('사용자의 결제 목록을 조회할 경우, Payment[]를 반환한다.', async() => { + //Arrange + + //Act + const res = await request('http://localhost:3001').get(`/payments`); + + //Assert + expect(res.status).toBe(HttpStatus.OK); + // expect(res.data) + + + }) + }); + +}); - test('POST /payments creates a new payment', () => { - const createPaymentDto = { - reservationId: 1, - amount: 100, - }; +// test('POST /payments creates a new payment', () => { +// const createPaymentDto = { +// reservationId: 1, +// amount: 100, +// }; - request(LOCAL_HOST) - .post('/payments') - .send(createPaymentDto) - .then((res: request.Response) => { - expect(res.statusCode).toEqual(HttpStatus.CREATED); - }); - }); +// request(LOCAL_HOST) +// .post('/payments') +// .send(createPaymentDto) +// .then((res: request.Response) => { +// expect(res.statusCode).toEqual(HttpStatus.CREATED); +// }); +// }); - test('POST /payments fails with invalid data', () => { - const invalidDto = { - amount: 100, - }; +// test('POST /payments fails with invalid data', () => { +// const invalidDto = { +// amount: 100, +// }; - request(LOCAL_HOST) - .post('/payments') - .send(invalidDto) - .then((res: request.Response) => { - expect(res.statusCode).toEqual(HttpStatus.BAD_REQUEST); - expect(res.body.message).toEqual('invalid data'); - }); - }); -}); +// request(LOCAL_HOST) +// .post('/payments') +// .send(invalidDto) +// .then((res: request.Response) => { +// expect(res.statusCode).toEqual(HttpStatus.BAD_REQUEST); +// expect(res.body.message).toEqual('invalid data'); +// }); +// }); +// }); -describe('REFUND PAYMENT', () => { - let app: INestApplication; +// describe('REFUND PAYMENT', () => { +// let app: INestApplication; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({}).compile(); +// beforeEach(async () => { +// const module: TestingModule = await Test.createTestingModule({}).compile(); - app = module.createNestApplication(); - await app.init; - }); +// app = module.createNestApplication(); +// await app.init; +// }); - test('POST /payments/refund refunds', () => { - const refundPaymentDto = { reservationId: 1 }; +// test('POST /payments/refund refunds', () => { +// const refundPaymentDto = { reservationId: 1 }; - request(LOCAL_HOST) - .post('/payments/refund') - .send(refundPaymentDto) - .then((res: request.Response) => { - expect(res.statusCode).toEqual(HttpStatus.OK); - }); - }); +// request(LOCAL_HOST) +// .post('/payments/refund') +// .send(refundPaymentDto) +// .then((res: request.Response) => { +// expect(res.statusCode).toEqual(HttpStatus.OK); +// }); +// }); - test('POST /payments/refund fails with invalid data', () => { - const invalidDto = { - amount: 100, - }; - - request(LOCAL_HOST) - .post('/payments/refund') - .send(invalidDto) - .then((res: request.Response) => { - expect(res.statusCode).toEqual(HttpStatus.BAD_REQUEST); - expect(res.body.message).toEqual('paymentId is required'); - }); - }); -}); +// test('POST /payments/refund fails with invalid data', () => { +// const invalidDto = { +// amount: 100, +// }; + +// request(LOCAL_HOST) +// .post('/payments/refund') +// .send(invalidDto) +// .then((res: request.Response) => { +// expect(res.statusCode).toEqual(HttpStatus.BAD_REQUEST); +// expect(res.body.message).toEqual('paymentId is required'); +// }); +// }); +// }); diff --git a/vet_nest/src/payments/dto/search-payment.dto.ts b/vet_nest/src/payments/dto/search-payment.dto.ts index 4cec0ee..49e2e22 100644 --- a/vet_nest/src/payments/dto/search-payment.dto.ts +++ b/vet_nest/src/payments/dto/search-payment.dto.ts @@ -1,4 +1,17 @@ +import { ApiProperty } from "@nestjs/swagger"; +import { IsOptional } from "class-validator"; export class SearchPaymentDto { - + @ApiProperty({ + type: 'string', + description: '조회 시작일(YYYY-MM-DD)' + }) + @IsOptional() + startDate: string; + @ApiProperty({ + type: 'string', + description: '조회 종료일(YYYY-MM-DD)' + }) + @IsOptional() + endDate: string; } \ No newline at end of file diff --git a/vet_nest/src/payments/entity/payments.entity.ts b/vet_nest/src/payments/entity/payments.entity.ts index d1ed05b..a265c77 100644 --- a/vet_nest/src/payments/entity/payments.entity.ts +++ b/vet_nest/src/payments/entity/payments.entity.ts @@ -1,5 +1,6 @@ -import { PrimaryGeneratedColumn, Entity, Column, ManyToOne } from 'typeorm'; +import { PrimaryGeneratedColumn, Entity, Column, ManyToOne, JoinColumn } from 'typeorm'; import { Reservation } from '../../reservations/entity/reservation.entity'; +import { User } from '../../users/entity/users.entity'; @Entity() export class Payment { @@ -31,12 +32,19 @@ export class Payment { @Column() reservationId: number; + @Column() + userId: number; + @ManyToOne(() => Reservation, (reservation) => reservation.payments, { nullable: false, onDelete: 'CASCADE', }) reservation: Reservation; + @ManyToOne(() => User, (user) => user) + @JoinColumn({ name: 'id' }) + userInfo?: User; + isCanceled(): boolean { return this.status == PaymentStatus.CANCELD; } diff --git a/vet_nest/src/payments/payments-service.interface.ts b/vet_nest/src/payments/payments-service.interface.ts index f24e99b..0060fcd 100644 --- a/vet_nest/src/payments/payments-service.interface.ts +++ b/vet_nest/src/payments/payments-service.interface.ts @@ -5,7 +5,7 @@ import { PgCancelPaymentRequest } from "./dto/pg-cancel-payment.request"; import { PgCancelPaymentResponse } from "./dto/pg-cancel-payment.response"; import { PgPaymentResponse } from "./dto/pg-payment.response"; export interface IPaymentService { - // getPaymentsByUserId(userId: number, searchOption: SearchPaymentDto); + getPaymentsByUserId(userId: number, searchOption: SearchPaymentDto): Promise; // getPaymentsByVetId(vetId: number, searchOption: SearchPaymentDto); // getPaymentsByReservationId(reservationId: number): Promise; // createPayment(createPaymentDto: object): Promise; diff --git a/vet_nest/src/payments/payments.controller.ts b/vet_nest/src/payments/payments.controller.ts index 93052f6..862526d 100644 --- a/vet_nest/src/payments/payments.controller.ts +++ b/vet_nest/src/payments/payments.controller.ts @@ -1,27 +1,41 @@ -import { Controller, Post, HttpException, Body } from '@nestjs/common'; +import { Controller, Post, HttpException, Body, Req, Get, Query, Patch, Param, HttpStatus } from '@nestjs/common'; import { PaymentsService } from './payments.service'; +import { SearchPaymentDto } from './dto/search-payment.dto'; +import { ApiTags } from '@nestjs/swagger'; +import { CreatePaymentDto } from './dto/create-payment.dto'; @Controller('payments') +@ApiTags('PaymentController') export class PaymentsController { - constructor(private PaymentsService: PaymentsService) {} + constructor(private paymentsService: PaymentsService) {} + @Get() + async getPaymentsByUserId(@Query() searchParam: SearchPaymentDto) { + //TODO: -> Requeset에서 Auth 정보 가져오기; + const userId = 1; + try { + //TODO: SearchParam Validation + //TODO: Payment -> PaymentResponse + return await this.paymentsService.getPaymentsByUserId(userId, searchParam); + } + catch (e) { + throw e; + } + } + @Post() - async create(@Body() createPaymentDto) { - const result = await this.PaymentsService.create(createPaymentDto).catch( + async postPayment(@Body() createPaymentDto: CreatePaymentDto) { + const result = await this.paymentsService.create(createPaymentDto).catch( (error) => { throw new HttpException({ result: false, message: error.message }, 400); }, ); - return { result: result, code: 200, message: '/payments' }; + return {status: HttpStatus.CREATED}; } - @Post('refund') - async refund(@Body() refundPaymentDto) { - // await this.PaymentsService.refund(refundPaymentDto).catch((error) => { - // throw new HttpException({ result: false, message: error.message }, 400); - // }); - - return { result: true, code: 200, message: '/payments/refund' }; + @Patch('{id}/cancel') + async cancelPayment(@Param('id') id: number) { + return id; } } diff --git a/vet_nest/src/payments/payments.service.ts b/vet_nest/src/payments/payments.service.ts index be5b033..b0f0b54 100644 --- a/vet_nest/src/payments/payments.service.ts +++ b/vet_nest/src/payments/payments.service.ts @@ -5,6 +5,7 @@ import { IPaymentService } from './payments-service.interface'; import { PgApiCaller } from './pg-api-caller'; import { BusinessException } from 'util/exception.util'; import { CreatePaymentDto } from './dto/create-payment.dto'; +import { SearchPaymentDto } from './dto/search-payment.dto'; @Injectable() export class PaymentsService implements IPaymentService { @@ -14,6 +15,23 @@ export class PaymentsService implements IPaymentService { private readonly pgApiCaller: PgApiCaller ) {} + async getPaymentsByUserId(userId: number, searchParam: SearchPaymentDto): Promise { + let query = await this.paymentsRepository + .createQueryBuilder('payments') + .where(`payments.userId = :id`, {id: userId}); + + if (searchParam.startDate && searchParam.endDate) { + // query = query + // .andWhere(`paymenets.createdAt >= Date(:startDate)`, + // {startDate: searchParam.startDate}); + // query = query + // .andWhere(`Date(paymenets.createdAt) <= Date(:endDate)`, + // {endDate: searchParam.endDate}); + } + return query.getMany(); + } + + async create(dto: CreatePaymentDto) { if (!(dto.reservationId && dto.amount)) { diff --git a/vet_nest/src/reservations/reservation-cancelation.controller.ts b/vet_nest/src/reservations/reservation-cancelation.controller.ts index 8dfdd3b..1bf4ecb 100644 --- a/vet_nest/src/reservations/reservation-cancelation.controller.ts +++ b/vet_nest/src/reservations/reservation-cancelation.controller.ts @@ -3,9 +3,6 @@ import { Get, Param } from '@nestjs/common'; -import { DataSource } from 'typeorm'; -import { Reservation } from './entity/reservation.entity'; -import { ReservationCancelationService } from './reservation-cancelation.service'; import { ApiTags } from '@nestjs/swagger'; import { ReservationFacade } from './reservation-facade'; From 2ce6df4afff6896f372b95de6d6c3f723cf97f36 Mon Sep 17 00:00:00 2001 From: mklee-mac Date: Tue, 18 Jul 2023 00:47:10 +0900 Subject: [PATCH 13/14] =?UTF-8?q?fix-reservation=20dto=20treatmentStatus?= =?UTF-8?q?=20=ED=83=80=EC=9E=85=20=EB=B3=80=EA=B2=BD,=20=EA=B7=B8?= =?UTF-8?q?=EC=99=B8=20import=20=EA=B2=BD=EB=A1=9C=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vet_nest/src/reservations/dto/reservations.dto.ts | 4 ++-- vet_nest/src/reservations/reservations.controller.ts | 12 +----------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/vet_nest/src/reservations/dto/reservations.dto.ts b/vet_nest/src/reservations/dto/reservations.dto.ts index 3b75b4a..c9ca515 100644 --- a/vet_nest/src/reservations/dto/reservations.dto.ts +++ b/vet_nest/src/reservations/dto/reservations.dto.ts @@ -149,8 +149,8 @@ export class ReservastionsDto { name: 'treatmentStatus', description: '예약종류', }) - @IsEnum(TreatmentStatus) - treatmentStatus: TreatmentStatus; + @IsEnum(DignosisCategory) + treatmentStatus: DignosisCategory; @ApiProperty({ default: 30000, diff --git a/vet_nest/src/reservations/reservations.controller.ts b/vet_nest/src/reservations/reservations.controller.ts index 3f896bc..1d39d1c 100644 --- a/vet_nest/src/reservations/reservations.controller.ts +++ b/vet_nest/src/reservations/reservations.controller.ts @@ -1,30 +1,20 @@ import { - BadRequestException, Body, Controller, Get, HttpCode, - HttpException, - HttpStatus, Logger, - Param, Post, Query, - UseFilters, - UseInterceptors, } from '@nestjs/common'; import { - ReservastionsDto, ReservationProcessDto as ReservationProcessCommand, } from './dto/reservations.dto'; import { ReservationService } from './reservations.service'; import { Reservation } from './entity/reservation.entity'; import { ReservationSearchDto } from './dto/reservation-search.dto'; -import * as moment from 'moment'; -import { MapPipe } from '@automapper/nestjs'; import { - BisunessException, - NotEnoughParameterError, + BusinessException } from 'util/exception.util'; import { ApiParam, ApiQuery, ApiTags } from '@nestjs/swagger'; import { CheckingDateCommand, SetTimeSlotCommand } from './dto/timeslot.dto'; From c802eb68ee8d2cbdff36b95e58d4b5d5e2533334 Mon Sep 17 00:00:00 2001 From: mklee-mac Date: Tue, 18 Jul 2023 01:01:52 +0900 Subject: [PATCH 14/14] =?UTF-8?q?logger=20=EC=98=A4=EB=A5=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vet_nest/src/reservations/reservations.service.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vet_nest/src/reservations/reservations.service.ts b/vet_nest/src/reservations/reservations.service.ts index dd957d5..8a5c10d 100644 --- a/vet_nest/src/reservations/reservations.service.ts +++ b/vet_nest/src/reservations/reservations.service.ts @@ -8,11 +8,10 @@ import { CheckingDateCommand, SetTimeSlotCommand } from './dto/timeslot.dto'; import { TimeSlotReposiotory } from './repository/timeslot-repository'; import { FailedPost } from '../../util/exception.util'; import { Payment } from '@/payments/entity/payments.entity'; -import { Logger } from 'winston'; @Injectable() export class ReservationService { - logger = new Logger(); + constructor( private readonly reservationRepository: ReservationReposiotory, private readonly timeSlotRepository: TimeSlotReposiotory,