Skip to content

Commit

Permalink
Merge pull request #51 from plus-tdd/feature/counseling
Browse files Browse the repository at this point in the history
HttpExceptionFilter 적용
  • Loading branch information
codeing999 authored Jul 24, 2023
2 parents bb5b3eb + d9cd36d commit ce3fa1d
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 18 deletions.
4 changes: 2 additions & 2 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ import { DoctorEntity } from './module/doctor/data/doctor.entity';
username: process.env.DB_USER,
password: process.env.DB_PW,
database: process.env.DB_SCHEMA,
synchronize: true,
dropSchema: true,
synchronize: process.env.DB_SYNCHRONIZE === 'true',
dropSchema: process.env.DB_DROP_SCHEMA === 'true',
entities: [
CounselingEntity,
PetEntity,
Expand Down
34 changes: 34 additions & 0 deletions src/http-exception.filter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {
ExceptionFilter,
Catch,
ArgumentsHost,
HttpException,
} from '@nestjs/common';
import { Request, Response } from 'express';
import moment from 'moment';

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
const status = exception.getStatus();
const error = exception.getResponse() as
| string
| { error: string; statusCode: number; message: string | string[] };
if (typeof error === 'string') {
response.status(status).json({
timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
path: request.url,
error: error,
});
} else {
response.status(status).json({
timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
path: request.url,
...error,
});
}
}
}
9 changes: 8 additions & 1 deletion src/main.ts
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,21 @@ import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import Logger from './logger';
const moment = require('moment-timezone');
import { HttpExceptionFilter } from './http-exception.filter';
import * as moment from 'moment-timezone';

declare const module: any;

async function bootstrap() {
const logger = new Logger('application.main');
moment.tz.setDefault('Asia/Seoul'); // 서버 시간대를 전역으로 아시아 서울로 설정한다. 매번 리전 안정해줘도됨
const app = await NestFactory.create(AppModule);

// Moment.js를 한국 시간(KST)으로 설정
moment.tz.setDefault('Asia/Seoul');

app.useGlobalFilters(new HttpExceptionFilter());

const port = process.env.PORT || 3000;
const config = new DocumentBuilder()
.setTitle('animalNest Api')
Expand Down
10 changes: 8 additions & 2 deletions src/module/counseling/api/counseling.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,14 @@ import {
InvalidCounselingInfoError,
counselingDataBaseError,
} from './../counseling.error';
import { Response } from './../../../response';

@Controller('counseling')
export class CounselingController {
private response: Response;
constructor(private readonly counselingService: CounselingService) {
this.mapper = new CounselingMapper();
this.response = new Response();
}

private mapper: CounselingMapper;
Expand All @@ -34,9 +37,12 @@ export class CounselingController {
async registerCounseling(@Body() counselingData: CreateCounselingDto) {
try {
const counselingInfo = this.mapper.mapCreateDtoToDomain(counselingData);
return await this.counselingService.registerCounseling(counselingInfo);
const result = await this.counselingService.registerCounseling(
counselingInfo,
);
return this.response.success(result);
} catch (error) {
return { message: error.message };
throw error;
}
}

Expand Down
24 changes: 17 additions & 7 deletions src/module/counseling/data/counseling.db.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { Injectable } from '@nestjs/common';
import {
Injectable,
BadRequestException,
InternalServerErrorException,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Between } from 'typeorm';
import {
Expand All @@ -16,6 +20,8 @@ import {
import { CounselingMapper } from '../counseling.mapper';
import { DoctorEntity } from '../../doctor/data/doctor.entity';
import { PetEntity } from '../../pet/data/pet.entity';
import Logger from './../../../logger';
const logger = new Logger('counseling.db');

//Injectable이 이걸 다른곳에 주입할수있단거 같음.
// Repository !== TypeOrm.Repsository => 완전한 Decoupling 을 달성할 수 있음 ! = > 이게 개발적으로 제가 생각하는 최적의 구조다. by 허재
Expand All @@ -36,21 +42,19 @@ export class CounselingRepositoryImpl implements CounselingRepository {

private mapper: CounselingMapper;

async registerCounselingHistory(
info: CounselingCreateInfo,
): Promise<Counseling> {
async registerCounseling(info: CounselingCreateInfo): Promise<Counseling> {
// User 정보도 가져와야 함 ( 왜 ? Counseling 도메인은 그 상담내역의 대상자 주인 이름이 들어가기 때문 id가 아니라 )

// pet 이 있는지 + 그 user 가 주인이 맞는지 ?
const pet = await this.PetDB.findOne({
where: { id: info.petId },
});
if (pet === null) throw new InvalidCounselingInfoError('애완동물');
if (pet === null) throw new BadRequestException('잘못된 반려동물입니다.');
// doctor 가 있는지 ?
const doctor = await this.DoctorDB.findOne({
where: { id: info.doctorId },
});
if (doctor === null) throw new InvalidCounselingInfoError('의사');
if (doctor === null) throw new BadRequestException('잘못된 의사입니다.');

// // CounselingEntity 만들어서 저장
// const entity = this.CounselingDB.create({
Expand All @@ -69,7 +73,13 @@ export class CounselingRepositoryImpl implements CounselingRepository {
update : 수정 ( id 찾아보고 없으면 터짐 )
save : 조회해보고 생성 or 수정 ( 터지진 않음 )
*/
const result = await this.CounselingDB.insert(entity);
let result;
try {
result = await this.CounselingDB.insert(entity);
} catch (error) {
logger.error('registerCounseling - database error');
throw new InternalServerErrorException();
}

return await this.getOneCounseling(result.identifiers[0].id);
}
Expand Down
2 changes: 1 addition & 1 deletion src/module/counseling/domain/counseling.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const COUNSELING_REPOSITORY = 'Counseling Repository';

export interface CounselingRepository {
// 진료내역을 저장하고, 성공했는지 반환함
registerCounselingHistory(info: CounselingCreateInfo): Promise<Counseling>;
registerCounseling(info: CounselingCreateInfo): Promise<Counseling>;
// start ~ end 사이의 히스토리를 반환함
getCounselingHistories(startDate: Date, endDate: Date): Promise<Counseling[]>;
//예약이나 진료 하나를 반환함
Expand Down
14 changes: 9 additions & 5 deletions src/module/counseling/domain/counseling.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { Inject, Injectable } from '@nestjs/common';
import {
Inject,
Injectable,
BadRequestException,
HttpException,
} from '@nestjs/common';
import {
Counseling,
CounselingCreateInfo,
Expand Down Expand Up @@ -30,15 +35,14 @@ export class CounselingService {
//this.validateRequestInfo(info);
// 1. 등록날짜는 현재 시각보단 작으면 안됨
if (new Date(info.dateTime).getTime() <= Date.now()) {
throw new InvalidCounselingInfoError('날짜');
throw new BadRequestException('잘못된 날짜입니다.');
}

let result: Counseling;
try {
result = await this.repository.registerCounselingHistory(info);
result = await this.repository.registerCounseling(info);
} catch (error) {
logger.error('registerCounseling - database error');
return null;
throw error;
}

// 서비스에서 nest.js 에 의존성을 물고 있는 오류가 있을까 ?
Expand Down
18 changes: 18 additions & 0 deletions src/response.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import moment from 'moment';

// export type BaseResponse = {
// statusCode: number;
// timestamp: String;
// message: String;
// };

export class Response {
success(result?: any) {
return {
statusCode: 200,
timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
message: '성공',
result: result,
};
}
}

0 comments on commit ce3fa1d

Please sign in to comment.