-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add return module #114
- Loading branch information
Showing
11 changed files
with
517 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import Lent from 'src/entities/lent.entity'; | ||
import CabinetStatusType from 'src/enums/cabinet.status.type.enum'; | ||
import LentType from 'src/enums/lent.type.enum'; | ||
|
||
/** | ||
* 캐비넷을 대여하기 전 캐비넷에 대한 최소 정보 | ||
*/ | ||
export class ReturnCabinetDataDto { | ||
status: CabinetStatusType; // 사물함의 상태 | ||
lent_type: LentType; // 사물함의 타입 | ||
lents: Lent[]; // 해당 사물함을 대여하고 있는 lent 배열 | ||
} |
46 changes: 45 additions & 1 deletion
46
backend/src/v3/return/repository/return.repository.interface.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,46 @@ | ||
import Lent from "src/entities/lent.entity"; | ||
import { UserDto } from "src/v3/lent/dto/user.dto"; | ||
import { ReturnCabinetDataDto } from "../dto/return.cabinet.data.dto"; | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-empty-interface | ||
export interface IReturnRepository {} | ||
export interface IReturnRepository { | ||
/** | ||
* 해당 유저가 존재하는지 확인합니다. | ||
* @param user_id | ||
*/ | ||
getUserIfExist(user_id: number): Promise<UserDto>; | ||
|
||
/** | ||
* 대여중인 사물함을 반납하기 위해 사물함에 대한 정보를 가져옴. | ||
* @param cabinet_id | ||
* @return ReturnCabinetDataDto | ||
**/ | ||
getReturnCabinetData(cabinet_id: number): Promise<ReturnCabinetDataDto>; | ||
|
||
/** | ||
* cabinet title, memo를 null로 설정함. | ||
* @param cabinet_id | ||
*/ | ||
clearCabinetInfo(cabinet_id: number): Promise<void>; | ||
|
||
/** | ||
* user_id에 대응하는 Lent값을 삭제합니다. | ||
* 해당 Lent 값을 반환합니다. | ||
* @param user_id | ||
* @return void | ||
*/ | ||
deleteLentByLentId(lent_id: number): Promise<void>; | ||
|
||
/** | ||
* 기존 lent 정보를 lent log에 추가합니다. | ||
* @param Lent | ||
* @return void | ||
*/ | ||
addLentLog(lent: Lent, user: UserDto, cabinet_id: number): Promise<void>; | ||
|
||
/** | ||
* 해당 캐비넷을 대여중인 유저들의 user_id를 반환합니다. | ||
* @param cabinet_id | ||
*/ | ||
getUsersByCabinetId(cabinet_id: number): Promise<number[]>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,133 @@ | ||
import { InjectRepository } from '@nestjs/typeorm'; | ||
import Cabinet from 'src/entities/cabinet.entity'; | ||
import Lent from 'src/entities/lent.entity'; | ||
import LentLog from 'src/entities/lent.log.entity'; | ||
import User from 'src/entities/user.entity'; | ||
import { UserDto } from 'src/v3/lent/dto/user.dto'; | ||
import { Repository } from 'typeorm'; | ||
import { IsolationLevel, Propagation, Transactional } from 'typeorm-transactional'; | ||
import { ReturnCabinetDataDto } from '../dto/return.cabinet.data.dto'; | ||
import { IReturnRepository } from './return.repository.interface'; | ||
|
||
export class ReturnRepository implements IReturnRepository { | ||
constructor( | ||
@InjectRepository(Cabinet) private cabinetRepository: Repository<Cabinet>, | ||
@InjectRepository(User) private userRepository: Repository<User>, | ||
@InjectRepository(Lent) private lentRepository: Repository<Lent>, | ||
@InjectRepository(LentLog) private lentLogRepository: Repository<LentLog>, | ||
) {} | ||
|
||
async getUserIfExist(user_id: number): Promise<UserDto> { | ||
const result = await this.userRepository.findOne({ | ||
where: { | ||
user_id: user_id, | ||
} | ||
}) | ||
if (!result) { | ||
return null; | ||
} | ||
return { | ||
user_id: result.user_id, | ||
intra_id: result.intra_id, | ||
}; | ||
} | ||
|
||
@Transactional({ | ||
propagation: Propagation.REQUIRED, | ||
isolationLevel: IsolationLevel.SERIALIZABLE, | ||
}) | ||
async getReturnCabinetData( | ||
cabinet_id: number, | ||
): Promise<ReturnCabinetDataDto> { | ||
const result = await this.cabinetRepository.find({ | ||
relations: { | ||
lent: true, | ||
}, | ||
select: { | ||
status: true, | ||
lent_type: true, | ||
lent: true, | ||
}, | ||
where: { | ||
cabinet_id: cabinet_id, | ||
}, | ||
lock: { | ||
mode: 'pessimistic_write', | ||
}, | ||
}); | ||
if (result.length === 0) { | ||
return null; | ||
} | ||
return { | ||
status: result[0].status, | ||
lent_type: result[0].lent_type, | ||
lents: result[0].lent, | ||
}; | ||
} | ||
|
||
@Transactional({ | ||
propagation: Propagation.REQUIRED, | ||
isolationLevel: IsolationLevel.SERIALIZABLE, | ||
}) | ||
async clearCabinetInfo(cabinet_id: number): Promise<void> { | ||
await this.cabinetRepository | ||
.createQueryBuilder() | ||
.update({ | ||
title: null, | ||
memo: null, | ||
}) | ||
.where({ | ||
cabinet_id: cabinet_id, | ||
}) | ||
.execute(); | ||
} | ||
|
||
@Transactional({ | ||
propagation: Propagation.REQUIRED, | ||
isolationLevel: IsolationLevel.SERIALIZABLE, | ||
}) | ||
async deleteLentByLentId(lent_id: number): Promise<void> { | ||
await this.lentRepository | ||
.createQueryBuilder(this.deleteLentByLentId.name) | ||
.delete() | ||
.from(Lent) | ||
.where({ | ||
lent_id: lent_id, | ||
}) | ||
.execute(); | ||
} | ||
|
||
async addLentLog( | ||
lent: Lent, | ||
user: UserDto, | ||
cabinet_id: number, | ||
): Promise<void> { | ||
await this.lentLogRepository | ||
.createQueryBuilder(this.addLentLog.name) | ||
.insert() | ||
.into(LentLog) | ||
.values({ | ||
log_user_id: user.user_id, | ||
log_intra_id: user.intra_id, | ||
log_cabinet_id: cabinet_id, | ||
lent_time: lent.lent_time, | ||
return_time: new Date(), | ||
}) | ||
.execute(); | ||
} | ||
|
||
async getUsersByCabinetId(cabinet_id: number): Promise<number[]> { | ||
const result = await this.lentRepository.find({ | ||
select: { | ||
lent_user_id: true, | ||
}, | ||
where: { | ||
lent_cabinet_id: cabinet_id, | ||
} | ||
}); | ||
if (result.length === 0) { | ||
return null; | ||
} | ||
return result.map((lent) => lent.lent_user_id); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import { forwardRef, Inject, Injectable, Logger } from "@nestjs/common"; | ||
import { ConfigService } from "@nestjs/config"; | ||
import Lent from "src/entities/lent.entity"; | ||
import CabinetStatusType from "src/enums/cabinet.status.type.enum"; | ||
import { LentService } from "src/lent/lent.service"; | ||
import { ILentRepository } from "src/lent/repository/lent.repository.interface"; | ||
import { IsolationLevel, Propagation, runOnTransactionComplete, Transactional } from "typeorm-transactional"; | ||
import { CabinetService } from "../cabinet/cabinet.service"; | ||
import { UserDto } from "../lent/dto/user.dto"; | ||
import { IReturnRepository } from "./repository/return.repository.interface"; | ||
import { ReturnService } from "./return.service"; | ||
|
||
@Injectable() | ||
export class ReturnTools { | ||
private logger = new Logger(ReturnTools.name); | ||
constructor( | ||
@Inject('IReturnRepository') | ||
private returnRepository: IReturnRepository, | ||
private cabinetService: CabinetService, | ||
@Inject(forwardRef(() => ReturnService)) | ||
private lentService: LentService, | ||
// private banService: BanService, | ||
@Inject(ConfigService) private configService: ConfigService, | ||
) {} | ||
|
||
@Transactional({ | ||
propagation: Propagation.REQUIRED, | ||
isolationLevel: IsolationLevel.SERIALIZABLE, | ||
}) | ||
async clearCabinetInfo(cabinet_id: number): Promise<void> { | ||
this.logger.debug(`Called ${ReturnTools.name} ${this.clearCabinetInfo.name}`); | ||
await this.returnRepository.clearCabinetInfo(cabinet_id); | ||
} | ||
|
||
@Transactional({ | ||
propagation: Propagation.REQUIRED, | ||
isolationLevel: IsolationLevel.SERIALIZABLE, | ||
}) | ||
async returnStateTransition( | ||
cabinet_id: number, | ||
user: UserDto, | ||
): Promise<Lent> { | ||
this.logger.debug( | ||
`Called ${ReturnTools.name} ${this.returnStateTransition.name}`, | ||
); | ||
// 대여하고 있는 유저들의 대여 정보를 포함하는 cabinet 정보를 가져옴. | ||
// 가져오는 정보 : 캐비넷 상태, 캐비넷 대여타입, 캐비넷을 빌린 사람들의 인원 수 | ||
const cabinet = await this.returnRepository.getReturnCabinetData(cabinet_id); | ||
const lent = cabinet.lents.filter( | ||
(lent) => lent.lent_user_id === user.user_id, | ||
)[0]; | ||
const lent_count = cabinet.lents.length; | ||
// 2. cabinet_status에 따라 처리. | ||
switch (cabinet.status) { | ||
case CabinetStatusType.AVAILABLE: | ||
if (lent_count - 1 === 0) { | ||
await this.clearCabinetInfo(cabinet_id); | ||
} | ||
break; | ||
case CabinetStatusType.SET_EXPIRE_FULL: | ||
// TODO: Cabinet 모듈이 구현되면 해당 모듈에서 가져와서 사용. | ||
// await this.cabinetInfoService.updateCabinetStatus( | ||
// cabinet_id, | ||
// CabinetStatusType.SET_EXPIRE_AVAILABLE, | ||
// ); | ||
case CabinetStatusType.SET_EXPIRE_AVAILABLE: | ||
if (lent_count - 1 === 0) { | ||
// TODO: Cabinet 모듈이 구현되면 해당 모듈에서 가져와서 사용. | ||
// await this.cabinetInfoService.updateCabinetStatus( | ||
// cabinet_id, | ||
// CabinetStatusType.AVAILABLE, | ||
// ); | ||
await this.clearCabinetInfo(cabinet_id); | ||
} | ||
break; | ||
case CabinetStatusType.BANNED: | ||
case CabinetStatusType.EXPIRED: | ||
// TODO: 해당 상태에서 반납을 했을 때 메인에서는 연체 누적 연체 일수만큼 패널티를 주게 되는데 | ||
// 이 부분은 어드민에서도 유지를 하는게 좋을까요? | ||
// const overdue = await this.banService.calDateDiff( | ||
// lent.expire_time, | ||
// new Date(), | ||
// ); | ||
// const cumulative = await this.banService.addOverdueDays(user.user_id); | ||
// await this.banService.blockingUser(lent, overdue + cumulative, false); | ||
// if ( | ||
// cabinet.status === CabinetStatusType.EXPIRED && | ||
// lent_count - 1 === 0 | ||
// ) { | ||
// // TODO: Cabinet 모듈이 구현되면 해당 모듈에서 가져와서 사용. | ||
// // await this.cabinetInfoService.updateCabinetStatus( | ||
// // cabinet_id, | ||
// // CabinetStatusType.AVAILABLE, | ||
// // ); | ||
// } | ||
break; | ||
} | ||
// 3. Lent Table에서 값 제거. | ||
await this.returnRepository.deleteLentByLentId(lent.lent_id); | ||
runOnTransactionComplete((err) => err && this.logger.error(err)); | ||
return lent; | ||
} | ||
} |
Oops, something went wrong.