Skip to content

Commit

Permalink
Merge pull request #215 from yunuo46/BE/feat/location
Browse files Browse the repository at this point in the history
[์†กํ˜„์šฐ] update location api ์™„์„ฑ
  • Loading branch information
yunuo46 authored Dec 6, 2023
2 parents d9b3a9c + 5954116 commit 2d47f8a
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 90 deletions.
22 changes: 0 additions & 22 deletions back/src/common/interceptors/sample.intercepotr.ts

This file was deleted.

5 changes: 5 additions & 0 deletions back/src/modules/message/dto/update-message-location.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ import { IsNotEmpty, IsNumber, Min, Max } from '@nestjs/class-validator';
import { ApiProperty } from '@nestjs/swagger';

export class UpdateMessageLocationDto {
@IsNumber()
@IsNotEmpty()
@ApiProperty({ type: Number, description: '๋ฉ”์„ธ์ง€ ID' })
readonly message_id: number;

@IsNumber()
@Min(1)
@Max(72)
Expand Down
15 changes: 15 additions & 0 deletions back/src/modules/message/dto/update-message-locations.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ValidateNested } from '@nestjs/class-validator';
import { ApiProperty } from '@nestjs/swagger';
import { UpdateMessageLocationDto } from './update-message-location.dto';
import { Expose, Type } from 'class-transformer';

export class UpdateMessageLocationsDto {
@Expose()
@Type(() => UpdateMessageLocationDto)
@ValidateNested({ each: true })
@ApiProperty({
type: [UpdateMessageLocationDto],
description: '์—…๋ฐ์ดํŠธ ํ•  ๋ฉ”์„ธ์ง€ ์œ„์น˜ ๋ฆฌ์ŠคํŠธ'
})
readonly location_list: UpdateMessageLocationDto[];
}
6 changes: 3 additions & 3 deletions back/src/modules/message/entity/message.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ export class MessageEntity {
@Column({ length: 16 })
sender: string;

@Column({ default: false })
is_deleted: boolean;
@CreateDateColumn({ default: `${process.env.DATE_DEFAULT}` })
is_deleted: Date;

@Column()
location: number;
Expand All @@ -50,7 +50,7 @@ export class MessageEntity {
@Column()
confidence: number;

@CreateDateColumn({ default: null })
@CreateDateColumn({ nullable: true, default: null })
opened: Date | null;

@CreateDateColumn()
Expand Down
16 changes: 6 additions & 10 deletions back/src/modules/message/message.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ import {
import { ResCreateMessageDto } from './dto/response/res-create-message.dto';
import { MessageDto } from './dto/message.dto';
import { JWTGuard } from 'src/common/guards/jwt.guard';
import { UpdateMessageLocationDto } from './dto/update-message-location.dto';
import { JWTRequest } from 'src/common/interface/request.interface';
import { ClovaService } from './clova.service';
import { UpdateMessageLocationsDto } from './dto/update-message-locations.dto';
@ApiTags('Message API')
@Controller('message')
export class MessageController {
Expand Down Expand Up @@ -149,14 +149,14 @@ export class MessageController {

@UseGuards(JWTGuard)
@ApiCookieAuth('access_token')
@Put('/:message_id/location')
@Put('/location')
@ApiOperation({
summary: '๋ฉ”์„ธ์ง€ ์œ„์น˜ ๋ณ€๊ฒฝ',
description: '๋ฉ”์‹œ์ง€์˜ ์œ„์น˜๋ฅผ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.'
})
@ApiResponse({
status: 200,
type: MessageDto
type: UpdateMessageLocationsDto
})
@ApiBadRequestResponse({
description: '์ž˜๋ชป๋œ ์š”์ฒญ์ž…๋‹ˆ๋‹ค.'
Expand All @@ -171,12 +171,8 @@ export class MessageController {
description: '๋ชฉํ‘œ ์œ„์น˜๊ฐ€ ๋น„์–ด์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.'
})
async updateMessageLocation(
@Param('message_id') message_id: number,
@Body() updateMessageLocationDto: UpdateMessageLocationDto
): Promise<UpdateMessageLocationDto> {
return await this.messageService.updateMessageLocation(
message_id,
updateMessageLocationDto
);
@Body() updateDtos: UpdateMessageLocationsDto
): Promise<UpdateMessageLocationsDto> {
return await this.messageService.updateMessageLocations(updateDtos);
}
}
8 changes: 7 additions & 1 deletion back/src/modules/message/message.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,15 @@ import { JWTGuard } from '../../common/guards/jwt.guard';
import { ClovaService } from './clova.service';
import { LetterEntity } from './entity/letter.entity';
import { SnowballEntity } from '../snowball/entity/snowball.entity';
import { DecorationPrefixEntity } from '../snowball/entity/decoration-prefix.entity';
@Module({
imports: [
TypeOrmModule.forFeature([MessageEntity, SnowballEntity, LetterEntity])
TypeOrmModule.forFeature([
MessageEntity,
SnowballEntity,
LetterEntity,
DecorationPrefixEntity
])
],
controllers: [MessageController],
providers: [MessageService, ClovaService, JWTGuard],
Expand Down
160 changes: 106 additions & 54 deletions back/src/modules/message/message.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
NotFoundException
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { DataSource, Repository } from 'typeorm';
import { ReqCreateMessageDto } from './dto/request/req-create-message.dto';
import { MessageEntity } from './entity/message.entity';
import { ResCreateMessageDto } from './dto/response/res-create-message.dto';
Expand All @@ -17,6 +17,8 @@ import { plainToInstance, instanceToPlain } from 'class-transformer';
import { LetterEntity } from './entity/letter.entity';
import { ResClovaSentiment } from './clova.service';
import { SnowballEntity } from '../snowball/entity/snowball.entity';
import { DecorationPrefixEntity } from '../snowball/entity/decoration-prefix.entity';
import { UpdateMessageLocationsDto } from './dto/update-message-locations.dto';

@Injectable()
export class MessageService {
Expand All @@ -26,14 +28,18 @@ export class MessageService {
@InjectRepository(SnowballEntity)
private readonly snowballRepository: Repository<SnowballEntity>,
@InjectRepository(LetterEntity)
private readonly letterRepository: Repository<LetterEntity>
private readonly letterRepository: Repository<LetterEntity>,
@InjectRepository(DecorationPrefixEntity)
private readonly decorationPrefixRepository: Repository<DecorationPrefixEntity>,
private readonly dataSource: DataSource
) {}
async createMessage(
createMessageDto: ReqCreateMessageDto,
resClovaSentiment: ResClovaSentiment,
snowball_id: number
): Promise<ResCreateMessageDto> {
await this.isInsertAllowed(snowball_id);
await this.doesDecoIdExist(createMessageDto.decoration_id);
await this.doesLetterIdExist(createMessageDto.letter_id);

const user_id = await this.findUserId(snowball_id);
Expand All @@ -42,10 +48,8 @@ export class MessageService {
user_id: user_id,
snowball_id: snowball_id,
location: location,
opened: null,
...resClovaSentiment,
...createMessageDto
// is_deleted๋ž‘ created๋Š” ์ž๋™์œผ๋กœ ์„ค์ •
});
try {
await this.messageRepository.save(messageEntity, {
Expand All @@ -69,13 +73,25 @@ export class MessageService {

async isInsertAllowed(snowball_id: number): Promise<void> {
const messageCount = await this.messageRepository.count({
where: { snowball_id: snowball_id, is_deleted: false }
where: {
snowball_id: snowball_id,
is_deleted: new Date(`${process.env.DATE_DEFAULT}`)
}
});
if (messageCount >= 30) {
throw new ConflictException('๋ฉ”์„ธ์ง€ ๊ฐฏ์ˆ˜๊ฐ€ 30๊ฐœ๋ฅผ ์ดˆ๊ณผํ–ˆ์Šต๋‹ˆ๋‹ค');
}
}

async doesDecoIdExist(decoration_id: number): Promise<void> {
const decoration = await this.decorationPrefixRepository.findOne({
where: { id: decoration_id, active: true }
});
if (!decoration) {
throw new NotFoundException('์กด์žฌํ•˜์ง€ ์•Š๋Š” decoration id์ž…๋‹ˆ๋‹ค');
}
}

async doesLetterIdExist(letter_id: number): Promise<void> {
const letter = await this.letterRepository.findOne({
where: { id: letter_id, active: true }
Expand All @@ -86,36 +102,35 @@ export class MessageService {
}

async deleteMessage(user_id: number, message_id: number): Promise<void> {
try {
const message = await this.messageRepository.findOne({
where: { id: message_id },
select: ['user_id', 'is_deleted']
});
if (message.user_id !== user_id) {
throw new ForbiddenException(
`${message_id} ๋ฉ”์‹œ์ง€๋Š” ํ•ด๋‹น ์œ ์ €์˜ ๋ฉ”์‹œ์ง€๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.`
);
}
if (!message) {
throw new NotFoundException(
`${message_id} ๋ฉ”์‹œ์ง€๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.`
);
}
if (message.is_deleted) {
throw new GoneException(`${message_id}๋Š” ์ด๋ฏธ ์‚ญ์ œ๋œ ๋ฉ”์‹œ์ง€์ž…๋‹ˆ๋‹ค.`);
}
await this.messageRepository.save(
{ id: message_id, is_deleted: true },
{ reload: false }
const message = await this.messageRepository.findOne({
where: { id: message_id },
select: ['user_id', 'is_deleted']
});
if (message.user_id !== user_id) {
throw new ForbiddenException(
`${message_id} ๋ฉ”์‹œ์ง€๋Š” ํ•ด๋‹น ์œ ์ €์˜ ๋ฉ”์‹œ์ง€๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.`
);
} catch (err) {
throw new BadRequestException('์„œ๋ฒ„ ์˜ค๋ฅ˜');
}
if (!message) {
throw new NotFoundException(`${message_id} ๋ฉ”์‹œ์ง€๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.`);
}
console.log(message.is_deleted.getTime());

if (message.is_deleted.getTime() !== Number(process.env.TIME_DEFAULT)) {
throw new GoneException(`${message_id}๋Š” ์ด๋ฏธ ์‚ญ์ œ๋œ ๋ฉ”์‹œ์ง€์ž…๋‹ˆ๋‹ค.`);
}
await this.messageRepository.save(
{ id: message_id, is_deleted: new Date() },
{ reload: false }
);
}

async getAllMessages(user_id: number): Promise<MessageDto[]> {
const messageEntities = await this.messageRepository.find({
where: { user_id: user_id, is_deleted: false }
where: {
user_id: user_id,
is_deleted: new Date(`${process.env.DATE_DEFAULT}`)
}
});
if (!messageEntities) {
throw new NotFoundException(`User with id ${user_id} not found`);
Expand All @@ -130,7 +145,10 @@ export class MessageService {

async openMessage(message_id: number): Promise<MessageDto> {
const messageEntity = await this.messageRepository.findOne({
where: { id: message_id, is_deleted: false }
where: {
id: message_id,
is_deleted: new Date(`${process.env.DATE_DEFAULT}`)
}
});
if (!messageEntity) {
throw new NotFoundException(
Expand All @@ -143,7 +161,7 @@ export class MessageService {
);
}
await this.messageRepository.save(
{ id: message_id, opened: Date() },
{ id: message_id, opened: new Date() },
{ reload: false }
);
const messageDto = plainToInstance(
Expand All @@ -154,30 +172,59 @@ export class MessageService {
return messageDto;
}

async updateMessageLocations(
updateDtos: UpdateMessageLocationsDto
): Promise<UpdateMessageLocationsDto> {
const result: UpdateMessageLocationDto[] = [];
console.log(updateDtos.location_list);
for (const updateDto of updateDtos.location_list) {
const success = await this.updateMessageLocation(updateDto);
if (success) result.push(updateDto);
}
const instance = { location_list: result };
return plainToInstance(UpdateMessageLocationsDto, {
instance
});
}

async updateMessageLocation(
message_id: number,
updateMessageLocationDto: UpdateMessageLocationDto
): Promise<UpdateMessageLocationDto> {
const { location } = updateMessageLocationDto;
const updateResult = await this.messageRepository
.createQueryBuilder()
.update(MessageEntity)
.set({
location
})
.where('id = :id', { id: message_id, is_deleted: false })
.execute();
if (!updateResult.affected) {
throw new NotFoundException('์—…๋ฐ์ดํŠธ๋ฅผ ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค');
} else if (updateResult.affected > 1) {
throw new BadRequestException('๋ฐ์ดํ„ฐ ์ค‘๋ณต ์˜ค๋ฅ˜');
updateDto: UpdateMessageLocationDto
): Promise<boolean> {
const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction('READ COMMITTED');

const { message_id, location } = updateDto;

try {
await queryRunner.manager
.createQueryBuilder()
.update(MessageEntity)
.set({
location
})
.where('id = :id', {
id: message_id,
is_deleted: new Date(`${process.env.DATE_DEFAULT}`)
})
.execute();
await queryRunner.commitTransaction();
} catch (err) {
await queryRunner.rollbackTransaction();
console.log(err.sqlMessage);
return false;
} finally {
await queryRunner.release();
}
return updateMessageLocationDto;
return true;
}

async getMessageCount(user_id: number): Promise<number> {
return this.messageRepository.count({
where: { user_id: user_id, is_deleted: false }
where: {
user_id: user_id,
is_deleted: new Date(`${process.env.DATE_DEFAULT}`)
}
});
}

Expand All @@ -186,7 +233,10 @@ export class MessageService {
groups: string
): Promise<MessageDto[]> {
const messageEntities = await this.messageRepository.find({
where: { snowball_id: snowball_id, is_deleted: false }
where: {
snowball_id: snowball_id,
is_deleted: new Date(`${process.env.DATE_DEFAULT}`)
}
});

const messageDtos = messageEntities.map(entity =>
Expand All @@ -212,12 +262,14 @@ export class MessageService {
}

async findLocation(snowball_id: number): Promise<number> {
const findLocations = this.messageRepository
.createQueryBuilder('message')
const locations = await this.messageRepository
.createQueryBuilder()
.select('location')
.where('snowball_id = :snowball_id', { snowball_id })
.andWhere('is_deleted = false');
const locations = await findLocations.getRawMany();
.andWhere('is_deleted =:is_deleted', {
is_deleted: `${process.env.DATE_DEFAULT}`
})
.getRawMany();

let firstEmptyLocation: number | null = null;
for (let i = 1; i <= 30; i++) {
Expand Down

0 comments on commit 2d47f8a

Please sign in to comment.