From 2c4a95005d6e54fb90f5de29869a910c774395b6 Mon Sep 17 00:00:00 2001 From: Lee-won-hyeok Date: Mon, 19 Feb 2024 07:58:17 +0000 Subject: [PATCH] feat: fix create & update logic --- .../src/announcement/announcement.resolver.ts | 11 ++++--- .../announcement/announcement.service.spec.ts | 2 ++ .../src/announcement/announcement.service.ts | 30 +++++++++++++------ .../announcement/dto/announcement.input.ts | 5 +++- .../admin/src/contest/contest.resolver.ts | 4 +-- .../admin/src/contest/contest.service.spec.ts | 6 ++-- .../apps/admin/src/contest/contest.service.ts | 2 +- .../apps/admin/src/group/group.resolver.ts | 2 +- .../admin/src/group/group.service.spec.ts | 4 +-- .../apps/admin/src/group/model/group.input.ts | 2 +- .../admin/src/group/model/group.output.ts | 2 +- .../admin/src/notice/model/notice.input.ts | 2 +- .../apps/admin/src/notice/notice.resolver.ts | 2 +- .../admin/src/notice/notice.service.spec.ts | 2 +- backend/apps/admin/src/problem/mock/mock.ts | 4 +-- .../admin/src/problem/model/problem.input.ts | 2 +- .../admin/src/problem/model/template.input.ts | 2 +- .../admin/src/problem/problem.resolver.ts | 7 ++++- .../admin/src/problem/problem.service.spec.ts | 14 ++++----- .../apps/admin/src/problem/problem.service.ts | 8 ++--- backend/apps/admin/src/user/user.resolver.ts | 4 +-- backend/apps/admin/src/user/user.service.ts | 2 +- .../client/src/problem/problem.repository.ts | 2 +- backend/tsconfig.json | 2 +- 24 files changed, 72 insertions(+), 51 deletions(-) diff --git a/backend/apps/admin/src/announcement/announcement.resolver.ts b/backend/apps/admin/src/announcement/announcement.resolver.ts index 89ad6cc422..d23a665f6c 100644 --- a/backend/apps/admin/src/announcement/announcement.resolver.ts +++ b/backend/apps/admin/src/announcement/announcement.resolver.ts @@ -33,10 +33,12 @@ export class AnnouncementResolver { @Query(() => [Announcement], { name: 'getAnnouncementsByProblemId' }) async getAnnouncementsByProblemId( - @Args('problemId', { type: () => Int }) problemId: number + @Args('contestId', { type: () => Int }) contestId: number, + @Args('problemId', { type: () => Int, nullable: true }) problemId?: number ) { try { return await this.announcementService.getAnnouncementsByProblemId( + contestId, problemId ) } catch (error) { @@ -61,13 +63,10 @@ export class AnnouncementResolver { @Mutation(() => Announcement) async updateAnnouncement( @Args('id', { type: () => Int }) id: number, - @Args('announcementInput') announcementInput: AnnouncementInput + @Args('content', { type: () => String }) content: string ) { try { - return await this.announcementService.updateAnnouncement( - id, - announcementInput - ) + return await this.announcementService.updateAnnouncement(id, content) } catch (error) { if (error instanceof EntityNotExistException) { throw error.convert2HTTPException() diff --git a/backend/apps/admin/src/announcement/announcement.service.spec.ts b/backend/apps/admin/src/announcement/announcement.service.spec.ts index dd1b9625d2..7ab0d52164 100644 --- a/backend/apps/admin/src/announcement/announcement.service.spec.ts +++ b/backend/apps/admin/src/announcement/announcement.service.spec.ts @@ -11,9 +11,11 @@ import { PrismaService } from '@libs/prisma' import { AnnouncementService } from './announcement.service' const problemId = faker.number.int() +const contestId = faker.number.int() const id = faker.number.int() const announcementInput = { problemId, + contestId, content: faker.string.sample() } diff --git a/backend/apps/admin/src/announcement/announcement.service.ts b/backend/apps/admin/src/announcement/announcement.service.ts index 1d3ff6a20b..a025b47731 100644 --- a/backend/apps/admin/src/announcement/announcement.service.ts +++ b/backend/apps/admin/src/announcement/announcement.service.ts @@ -16,40 +16,52 @@ export class AnnouncementService { async createAnnouncement(announcementInput: AnnouncementInput) { const announcement = await this.prisma.announcement.findFirst({ where: { - problemId: announcementInput.problemId, + ...(announcementInput.problemId && { + problemId: announcementInput.problemId + }), + contestId: announcementInput.contestId, content: announcementInput.content } }) if (announcement) throw new DuplicateFoundException('announcement') - await this.prisma.problem + await this.prisma.contestProblem .findFirstOrThrow({ where: { - id: announcementInput.problemId + contestId: announcementInput.contestId, + ...(announcementInput.problemId && { + problemId: announcementInput.problemId + }) } }) .catch((error) => { if (error.name == 'NotFoundError') { - throw new EntityNotExistException('problem') + throw new EntityNotExistException('contestProblem') } }) return await this.prisma.announcement.create({ data: { - problemId: announcementInput.problemId, + ...(announcementInput.problemId && { + problemId: announcementInput.problemId + }), + contestId: announcementInput.contestId, content: announcementInput.content } }) } - async getAnnouncementsByProblemId(problemId: number) { + //getAnnouncements + async getAnnouncementsByProblemId(contestId: number, problemId?: number) { return await this.prisma.announcement.findMany({ where: { - problemId + ...(problemId && { problemId }), + contestId } }) } + //getAnnouncementById async getAnnouncement(id: number) { const announcement = await this.prisma.announcement .findFirstOrThrow({ @@ -65,11 +77,11 @@ export class AnnouncementService { return announcement } - async updateAnnouncement(id: number, announcementInput: AnnouncementInput) { + async updateAnnouncement(id: number, content: string) { try { return await this.prisma.announcement.update({ where: { id }, - data: announcementInput + data: { content } }) } catch (error) { if (error instanceof PrismaClientKnownRequestError) { diff --git a/backend/apps/admin/src/announcement/dto/announcement.input.ts b/backend/apps/admin/src/announcement/dto/announcement.input.ts index e36924c869..650431212a 100644 --- a/backend/apps/admin/src/announcement/dto/announcement.input.ts +++ b/backend/apps/admin/src/announcement/dto/announcement.input.ts @@ -2,8 +2,11 @@ import { InputType, Int, Field } from '@nestjs/graphql' @InputType() export class AnnouncementInput { + @Field({ nullable: true }) + problemId?: number + @Field(() => Int) - problemId: number + contestId: number @Field(() => String) content: string diff --git a/backend/apps/admin/src/contest/contest.resolver.ts b/backend/apps/admin/src/contest/contest.resolver.ts index 6dbc9338ce..f4e2516eaa 100644 --- a/backend/apps/admin/src/contest/contest.resolver.ts +++ b/backend/apps/admin/src/contest/contest.resolver.ts @@ -5,8 +5,6 @@ import { ParseBoolPipe } from '@nestjs/common' import { Args, Context, Int, Mutation, Query, Resolver } from '@nestjs/graphql' -import { ContestProblem } from '@generated' -import { Contest } from '@generated' import { PrismaClientKnownRequestError } from '@prisma/client/runtime/library' import { AuthenticatedRequest, UseRolesGuard } from '@libs/auth' import { OPEN_SPACE_ID } from '@libs/constants' @@ -16,6 +14,8 @@ import { UnprocessableDataException } from '@libs/exception' import { CursorValidationPipe, GroupIDPipe, RequiredIntPipe } from '@libs/pipe' +import { ContestProblem } from '@admin/@generated' +import { Contest } from '@admin/@generated' import { ContestService } from './contest.service' import { ContestWithParticipants } from './model/contest-with-participants.model' import { CreateContestInput } from './model/contest.input' diff --git a/backend/apps/admin/src/contest/contest.service.spec.ts b/backend/apps/admin/src/contest/contest.service.spec.ts index 4b6f0f4ca9..e90ec0aa82 100644 --- a/backend/apps/admin/src/contest/contest.service.spec.ts +++ b/backend/apps/admin/src/contest/contest.service.spec.ts @@ -1,8 +1,5 @@ import { CACHE_MANAGER } from '@nestjs/cache-manager' import { Test, type TestingModule } from '@nestjs/testing' -import { ContestProblem, Group } from '@generated' -import { Problem } from '@generated' -import { Contest } from '@generated' import { faker } from '@faker-js/faker' import { Prisma } from '@prisma/client' import type { Cache } from 'cache-manager' @@ -10,6 +7,9 @@ import { expect } from 'chai' import { stub } from 'sinon' import { EntityNotExistException } from '@libs/exception' import { PrismaService } from '@libs/prisma' +import { ContestProblem, Group } from '@admin/@generated' +import { Problem } from '@admin/@generated' +import { Contest } from '@admin/@generated' import { ContestService } from './contest.service' import type { ContestWithParticipants } from './model/contest-with-participants.model' import type { diff --git a/backend/apps/admin/src/contest/contest.service.ts b/backend/apps/admin/src/contest/contest.service.ts index d0b1e86bab..1f27db61aa 100644 --- a/backend/apps/admin/src/contest/contest.service.ts +++ b/backend/apps/admin/src/contest/contest.service.ts @@ -4,7 +4,6 @@ import { Injectable, UnprocessableEntityException } from '@nestjs/common' -import type { Contest } from '@generated' import type { ContestProblem } from '@prisma/client' import { Cache } from 'cache-manager' import { @@ -18,6 +17,7 @@ import { UnprocessableDataException } from '@libs/exception' import { PrismaService } from '@libs/prisma' +import type { Contest } from '@admin/@generated' import type { CreateContestInput } from './model/contest.input' import type { UpdateContestInput } from './model/contest.input' import type { PublicizingRequest } from './model/publicizing-request.model' diff --git a/backend/apps/admin/src/group/group.resolver.ts b/backend/apps/admin/src/group/group.resolver.ts index b1eadf30be..ca0a829d73 100644 --- a/backend/apps/admin/src/group/group.resolver.ts +++ b/backend/apps/admin/src/group/group.resolver.ts @@ -1,6 +1,5 @@ import { InternalServerErrorException, Logger } from '@nestjs/common' import { Args, Int, Query, Mutation, Resolver, Context } from '@nestjs/graphql' -import { Group } from '@generated' import { Role } from '@prisma/client' import { AuthenticatedRequest, UseRolesGuard } from '@libs/auth' import { @@ -9,6 +8,7 @@ import { ForbiddenAccessException } from '@libs/exception' import { CursorValidationPipe, GroupIDPipe } from '@libs/pipe' +import { Group } from '@admin/@generated' import { GroupService } from './group.service' import { CreateGroupInput, UpdateGroupInput } from './model/group.input' import { DeletedUserGroup, FindGroup } from './model/group.output' diff --git a/backend/apps/admin/src/group/group.service.spec.ts b/backend/apps/admin/src/group/group.service.spec.ts index 35e35d9cb8..8af848f534 100644 --- a/backend/apps/admin/src/group/group.service.spec.ts +++ b/backend/apps/admin/src/group/group.service.spec.ts @@ -1,7 +1,5 @@ import { CACHE_MANAGER } from '@nestjs/cache-manager' import { Test, type TestingModule } from '@nestjs/testing' -import type { Group } from '@generated' -import type { User } from '@generated' import { faker } from '@faker-js/faker' import { Role } from '@prisma/client' import type { Cache } from 'cache-manager' @@ -15,6 +13,8 @@ import { ForbiddenAccessException } from '@libs/exception' import { PrismaService } from '@libs/prisma' +import type { Group } from '@admin/@generated' +import type { User } from '@admin/@generated' import { GroupService } from './group.service' const userId = faker.number.int() diff --git a/backend/apps/admin/src/group/model/group.input.ts b/backend/apps/admin/src/group/model/group.input.ts index d3cda6a923..a1783c1795 100644 --- a/backend/apps/admin/src/group/model/group.input.ts +++ b/backend/apps/admin/src/group/model/group.input.ts @@ -1,6 +1,6 @@ import { Field } from '@nestjs/graphql' import { InputType } from '@nestjs/graphql' -import { GroupCreateInput, GroupUpdateInput } from '@generated' +import { GroupCreateInput, GroupUpdateInput } from '@admin/@generated' @InputType() class Config { diff --git a/backend/apps/admin/src/group/model/group.output.ts b/backend/apps/admin/src/group/model/group.output.ts index 7016da3465..c539c5cfe4 100644 --- a/backend/apps/admin/src/group/model/group.output.ts +++ b/backend/apps/admin/src/group/model/group.output.ts @@ -1,6 +1,6 @@ import { Field, Int } from '@nestjs/graphql' import { ObjectType } from '@nestjs/graphql' -import { Group } from '@generated' +import { Group } from '@admin/@generated' @ObjectType() export class FindGroup extends Group { diff --git a/backend/apps/admin/src/notice/model/notice.input.ts b/backend/apps/admin/src/notice/model/notice.input.ts index d80cf33f82..f0333401f3 100644 --- a/backend/apps/admin/src/notice/model/notice.input.ts +++ b/backend/apps/admin/src/notice/model/notice.input.ts @@ -1,5 +1,5 @@ import { InputType, PartialType, PickType } from '@nestjs/graphql' -import { NoticeCreateInput } from '@generated' +import { NoticeCreateInput } from '@admin/@generated' @InputType() export class CreateNoticeInput extends PickType(NoticeCreateInput, [ diff --git a/backend/apps/admin/src/notice/notice.resolver.ts b/backend/apps/admin/src/notice/notice.resolver.ts index 49be1822fa..99a9aee6df 100644 --- a/backend/apps/admin/src/notice/notice.resolver.ts +++ b/backend/apps/admin/src/notice/notice.resolver.ts @@ -13,10 +13,10 @@ import { ResolveField, Parent } from '@nestjs/graphql' -import { Group, Notice, User } from '@generated' import { AuthenticatedRequest } from '@libs/auth' import { EntityNotExistException } from '@libs/exception' import { CursorValidationPipe, GroupIDPipe, IDValidationPipe } from '@libs/pipe' +import { Group, Notice, User } from '@admin/@generated' import { GroupService } from '@admin/group/group.service' import { UserService } from '@admin/user/user.service' import { CreateNoticeInput, UpdateNoticeInput } from './model/notice.input' diff --git a/backend/apps/admin/src/notice/notice.service.spec.ts b/backend/apps/admin/src/notice/notice.service.spec.ts index e9b689adbf..047b9a7fb7 100644 --- a/backend/apps/admin/src/notice/notice.service.spec.ts +++ b/backend/apps/admin/src/notice/notice.service.spec.ts @@ -1,11 +1,11 @@ import { Test, type TestingModule } from '@nestjs/testing' -import type { Notice } from '@generated' import { faker } from '@faker-js/faker' import { PrismaClientKnownRequestError } from '@prisma/client/runtime/library' import { expect } from 'chai' import { stub } from 'sinon' import { EntityNotExistException } from '@libs/exception' import { PrismaService } from '@libs/prisma' +import type { Notice } from '@admin/@generated' import type { CreateNoticeInput, UpdateNoticeInput } from './model/notice.input' import { NoticeService } from './notice.service' diff --git a/backend/apps/admin/src/problem/mock/mock.ts b/backend/apps/admin/src/problem/mock/mock.ts index 12974ba5a4..cb7a737879 100644 --- a/backend/apps/admin/src/problem/mock/mock.ts +++ b/backend/apps/admin/src/problem/mock/mock.ts @@ -1,7 +1,7 @@ -import { Language, Level } from '@generated' -import type { Problem } from '@generated' import { faker } from '@faker-js/faker' import { createReadStream } from 'fs' +import { Language, Level } from '@admin/@generated' +import type { Problem } from '@admin/@generated' import type { FileUploadDto } from '../dto/file-upload.dto' import type { UploadFileInput } from '../model/problem.input' import type { Template } from '../model/template.input' diff --git a/backend/apps/admin/src/problem/model/problem.input.ts b/backend/apps/admin/src/problem/model/problem.input.ts index b227ed7340..a063bdf018 100644 --- a/backend/apps/admin/src/problem/model/problem.input.ts +++ b/backend/apps/admin/src/problem/model/problem.input.ts @@ -1,7 +1,7 @@ import { Field, InputType, Int } from '@nestjs/graphql' -import { Language, Level } from '@generated' import { ValidatePromise } from 'class-validator' import { GraphQLUpload } from 'graphql-upload' +import { Language, Level } from '@admin/@generated' import type { FileUploadDto } from '../dto/file-upload.dto' import { Template } from './template.input' import { Testcase } from './testcase.input' diff --git a/backend/apps/admin/src/problem/model/template.input.ts b/backend/apps/admin/src/problem/model/template.input.ts index e19a5ede98..c20b976eff 100644 --- a/backend/apps/admin/src/problem/model/template.input.ts +++ b/backend/apps/admin/src/problem/model/template.input.ts @@ -1,5 +1,5 @@ import { Field, InputType, Int } from '@nestjs/graphql' -import { Language } from '@generated' +import { Language } from '@admin/@generated' @InputType() class Snippet { diff --git a/backend/apps/admin/src/problem/problem.resolver.ts b/backend/apps/admin/src/problem/problem.resolver.ts index a3273986ca..c9cc50ee9d 100644 --- a/backend/apps/admin/src/problem/problem.resolver.ts +++ b/backend/apps/admin/src/problem/problem.resolver.ts @@ -8,7 +8,6 @@ import { ValidationPipe } from '@nestjs/common' import { Args, Context, Query, Int, Mutation, Resolver } from '@nestjs/graphql' -import { ContestProblem, Problem, Tag, WorkbookProblem } from '@generated' import { Prisma } from '@prisma/client' import { AuthenticatedRequest } from '@libs/auth' import { OPEN_SPACE_ID } from '@libs/constants' @@ -18,6 +17,12 @@ import { UnprocessableDataException } from '@libs/exception' import { CursorValidationPipe, GroupIDPipe, RequiredIntPipe } from '@libs/pipe' +import { + ContestProblem, + Problem, + Tag, + WorkbookProblem +} from '@admin/@generated' import { CreateProblemInput, UploadFileInput, diff --git a/backend/apps/admin/src/problem/problem.service.spec.ts b/backend/apps/admin/src/problem/problem.service.spec.ts index 7ee800308e..7a1eb6acb8 100644 --- a/backend/apps/admin/src/problem/problem.service.spec.ts +++ b/backend/apps/admin/src/problem/problem.service.spec.ts @@ -1,12 +1,5 @@ import { ConfigService } from '@nestjs/config' import { Test, type TestingModule } from '@nestjs/testing' -import type { - Workbook, - WorkbookProblem, - Contest, - ContestProblem -} from '@generated' -import { Level } from '@generated' import { expect } from 'chai' import { spy, stub } from 'sinon' import { @@ -14,6 +7,13 @@ import { UnprocessableDataException } from '@libs/exception' import { PrismaService } from '@libs/prisma' +import type { + Workbook, + WorkbookProblem, + Contest, + ContestProblem +} from '@admin/@generated' +import { Level } from '@admin/@generated' import { S3Provider } from '@admin/storage/s3.provider' import { StorageService } from '@admin/storage/storage.service' import { diff --git a/backend/apps/admin/src/problem/problem.service.ts b/backend/apps/admin/src/problem/problem.service.ts index 71feeafac5..5546a7e31f 100644 --- a/backend/apps/admin/src/problem/problem.service.ts +++ b/backend/apps/admin/src/problem/problem.service.ts @@ -1,8 +1,4 @@ import { Injectable } from '@nestjs/common' -import { Language } from '@generated' -import type { ContestProblem, Tag, WorkbookProblem } from '@generated' -import { Level } from '@generated' -import type { ProblemWhereInput } from '@generated' import { Workbook } from 'exceljs' import { DuplicateFoundException, @@ -10,6 +6,10 @@ import { UnprocessableFileDataException } from '@libs/exception' import { PrismaService } from '@libs/prisma' +import { Language } from '@admin/@generated' +import type { ContestProblem, Tag, WorkbookProblem } from '@admin/@generated' +import { Level } from '@admin/@generated' +import type { ProblemWhereInput } from '@admin/@generated' import { StorageService } from '@admin/storage/storage.service' import { ImportedProblemHeader } from './model/problem.constants' import type { diff --git a/backend/apps/admin/src/user/user.resolver.ts b/backend/apps/admin/src/user/user.resolver.ts index 45ca9465b3..c437cfbe24 100644 --- a/backend/apps/admin/src/user/user.resolver.ts +++ b/backend/apps/admin/src/user/user.resolver.ts @@ -6,10 +6,10 @@ import { NotFoundException } from '@nestjs/common' import { Resolver, Query, Mutation, Args, Int } from '@nestjs/graphql' -import { UserGroup } from '@generated' -import { User } from '@generated' import { OPEN_SPACE_ID } from '@libs/constants' import { CursorValidationPipe, GroupIDPipe, RequiredIntPipe } from '@libs/pipe' +import { UserGroup } from '@admin/@generated' +import { User } from '@admin/@generated' import { GroupMember } from './model/groupMember.model' import { UserService } from './user.service' diff --git a/backend/apps/admin/src/user/user.service.ts b/backend/apps/admin/src/user/user.service.ts index 173e0363c2..0ddc65ba7f 100644 --- a/backend/apps/admin/src/user/user.service.ts +++ b/backend/apps/admin/src/user/user.service.ts @@ -6,7 +6,6 @@ import { Injectable, NotFoundException } from '@nestjs/common' -import type { UserGroup } from '@generated' import { Role } from '@prisma/client' import { Cache } from 'cache-manager' import { joinGroupCacheKey } from '@libs/cache' @@ -14,6 +13,7 @@ import { JOIN_GROUP_REQUEST_EXPIRE_TIME } from '@libs/constants' import { EntityNotExistException } from '@libs/exception' import { PrismaService } from '@libs/prisma' import type { GroupJoinRequest } from '@libs/types' +import type { UserGroup } from '@admin/@generated' @Injectable() export class UserService { diff --git a/backend/apps/client/src/problem/problem.repository.ts b/backend/apps/client/src/problem/problem.repository.ts index a7b1c52c5a..b16f52f15d 100644 --- a/backend/apps/client/src/problem/problem.repository.ts +++ b/backend/apps/client/src/problem/problem.repository.ts @@ -1,8 +1,8 @@ /* eslint-disable @typescript-eslint/naming-convention */ import { Injectable } from '@nestjs/common' -import type { CodeDraftUpdateInput } from '@generated' import type { Problem, Tag, CodeDraft, Prisma } from '@prisma/client' import { PrismaService } from '@libs/prisma' +import type { CodeDraftUpdateInput } from '@admin/@generated' import type { CreateTemplateDto } from './dto/create-code-draft.dto' import type { ProblemOrder } from './schema/problem-order.schema' diff --git a/backend/tsconfig.json b/backend/tsconfig.json index f54c34e134..38d0ce4995 100644 --- a/backend/tsconfig.json +++ b/backend/tsconfig.json @@ -20,7 +20,7 @@ "paths": { "@admin/*": ["./apps/admin/src/*"], "@client/*": ["./apps/client/src/*"], - "@generated": ["./apps/admin/src/@generated"], + "@generated": ["apps/admin/src/@generated"], "@libs/prisma": ["./libs/prisma/src/index.ts"], "@libs/cache": ["./libs/cache/src/index.ts"], "@libs/auth": ["./libs/auth/src/index.ts"],