Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: [POST]card 생성 api swagger 적용 #58

Merged
merged 3 commits into from
Jul 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 28 additions & 32 deletions packages/service-backend/src/core/database/Deck.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,41 @@
import {HydratedDocument} from "mongoose";
import {Prop, Schema} from "@nestjs/mongoose";
import {TimestampKey} from "../../types";
import {v4 as uuidv4} from "uuid";
import { HydratedDocument } from 'mongoose';
import { Prop, Schema } from '@nestjs/mongoose';
import { TimestampKey } from '../../types';
import { v4 as uuidv4 } from 'uuid';
import { DeckCategory } from '../../modules/deck/DeckConstant';

export type Deck = {
id : string;
name : string
// TODO category m:n relation
category : DeckCategory[],
// TODO card 1:n relation and aggregate card count
cardIds : string[]
// TODO card 1:n relation and aggregate card count
totalCardCount : number
// TODO user m:n relation fk
userId : string
}
id: string;
name: string;
// TODO category m:n relation
category: DeckCategory[];
// TODO card 1:n relation and aggregate card count
cardIds: string[];
// TODO card 1:n relation and aggregate card count
totalCardCount: number;
// TODO user m:n relation fk
userId: string;
};

@Schema({ collection: 'Deck', timestamps: true })
export class DeckCollection implements Omit<Deck, TimestampKey> {
@Prop({ default: uuidv4, unique: true })
id: string;

@Prop({ required: true })
name: string;
@Prop({ default: uuidv4, unique: true })
id: string;

@Prop({ optional: true })
cardIds : string[]
@Prop({ required: true })
name: string;

// TODO category change enum type
// service-backend/src/modules/deck/DeckConstant.ts
@Prop({ optional: true })
cardIds: string[];

// NOTE : select category flow is decision card list
@Prop({ optional: true })
category: DeckCategory[]
@Prop({ optional: true })
category: DeckCategory[];

@Prop({ optional: true })
totalCardCount: number;
@Prop({ optional: true })
totalCardCount: number;

@Prop({ required: true })
userId: string;
@Prop({ required: true })
userId: string;
}

export type DeckDocument = HydratedDocument<DeckCollection>;
export type DeckDocument = HydratedDocument<DeckCollection>;
23 changes: 16 additions & 7 deletions packages/service-backend/src/modules/card/CardController.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,39 @@
import { Controller, Post, Body, Get, Param, Delete, Patch } from '@nestjs/common';
import { CardService } from './CardService';
import { Card } from '../../core/database';
import { ApiTags } from '@nestjs/swagger';
import { createCardDto } from './dto/createCardDto';
import { ApiBody, ApiCreatedResponse, ApiOperation, ApiQuery, ApiTags } from '@nestjs/swagger';
import { CreateCardDto, CardList } from './dto/createCardDto';

// TODO 다른 api에서 swagger docs쓸때 query로 쓰면 됨
// @ApiQuery({
// name: 'deckId',
// description: '덱 ID',
// example: 'deckId',
// type: String,
// })
@ApiTags('cards')
@Controller('cards')
export class CardController {
constructor(private readonly cardService: CardService) {}

@ApiTags('card')
@ApiOperation({ summary: '카드 생성 API', description: '카드 bulk upload' })
@ApiCreatedResponse({ description: '카드를 생성한다.', type: CreateCardDto })
@ApiBody({ type: CreateCardDto })
@Post()
async CreateCard(
@Body('cardList') cardDto: createCardDto[],
@Body('cardList') createCardList: CardList[],
@Body('deckId') deckId: string
): Promise<any> {
const result = await this.cardService.create(cardDto, deckId);
const result = await this.cardService.create(createCardList, deckId);
return { result: result };
}

@ApiTags('card')
@Delete(':id')
async deleteCard(@Param('id') id: string): Promise<any> {
await this.cardService.deleteCard(id);
return { message: '카드가 삭제되었습니다.' };
}

@ApiTags('card')
@Patch(':id')
async updateCard(
@Param('id') id: string,
Expand Down
9 changes: 4 additions & 5 deletions packages/service-backend/src/modules/card/CardRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import { Injectable, InternalServerErrorException, NotFoundException } from '@ne
import { assert } from 'typia';
import { InjectModel, Card, CardDocument } from '../../core/database';
import { SoftDeleteModel } from 'soft-delete-plugin-mongoose';
import { CreateDeckDto } from '../deck/dto/CreateDeckDto';
import { createCardDto } from './dto/createCardDto';
import { CardList } from './dto/createCardDto';

@Injectable()
export class CardRepository {
Expand All @@ -12,12 +11,12 @@ export class CardRepository {
private readonly cardModel: SoftDeleteModel<CardDocument>
) {}

async create(cardDtoList: createCardDto[], deckId: string): Promise<boolean> {
async create(cardList: CardList[], deckId: string): Promise<boolean> {
try {
await Promise.all(
cardDtoList.map(async (cardDto, index) => {
cardList.map(async (card, index) => {
try {
await this.cardModel.create({ content: cardDto.content, deckId: deckId });
await this.cardModel.create({ content: card.content, deckId: deckId });
} catch (error) {
throw new InternalServerErrorException(
`error create card row ${index} \n reason is : error: ${error}`
Expand Down
6 changes: 3 additions & 3 deletions packages/service-backend/src/modules/card/CardService.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import { CardRepository } from './CardRepository';
import { Card } from '../../core/database';
import { createCardDto } from './dto/createCardDto';
import { CreateCardDto, CardList } from './dto/createCardDto';

@Injectable()
export class CardService {
constructor(private readonly cardRepository: CardRepository) {}

async create(cardDto: createCardDto[], deckId: string): Promise<boolean> {
return await this.cardRepository.create(cardDto, deckId);
async create(cardList: CardList[], deckId: string): Promise<boolean> {
return await this.cardRepository.create(cardList, deckId);
}

async deleteCard(id: string): Promise<object> {
Expand Down
22 changes: 21 additions & 1 deletion packages/service-backend/src/modules/card/dto/createCardDto.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
export class createCardDto {
import { ApiProperty } from '@nestjs/swagger';
import { ArrayNotEmpty, IsNotEmpty, IsString, ValidateNested } from 'class-validator';
import { Type } from 'class-transformer';

export class CreateCardDto {
@IsString()
@IsNotEmpty()
@ApiProperty({ example: '덱 ID', required: true })
deckId: string;

@ValidateNested({ each: true })
@Type(() => CardList)
@ArrayNotEmpty()
@ApiProperty({ example: '[{content: "sdfsd"},{content: "sdfs"}]', required: true })
cardList: CardList[];
}

export class CardList {
@IsString()
@IsNotEmpty()
@ApiProperty({ example: '카드내용', required: true })
content: string;
}