Skip to content
This repository has been archived by the owner on Dec 16, 2024. It is now read-only.

Commit

Permalink
feat: implements submit survey pages
Browse files Browse the repository at this point in the history
  • Loading branch information
jspark2000 committed Mar 12, 2024
1 parent 79e8a9c commit 71cc6e3
Show file tree
Hide file tree
Showing 25 changed files with 1,002 additions and 10 deletions.
3 changes: 2 additions & 1 deletion backend/app/src/attendance/attendance.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { AttendanceService } from './attendance.service'

@Module({
controllers: [AttendanceController],
providers: [AttendanceService]
providers: [AttendanceService],
exports: [AttendanceService]
})
export class AttendanceModule {}
86 changes: 86 additions & 0 deletions backend/app/src/attendance/attendance.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,93 @@
import { Service } from '@libs/decorator'
import { EntityNotExistException, UnexpectedException } from '@libs/exception'
import { PrismaService } from '@libs/prisma'
import { calculatePaginationOffset } from '@libs/utils'
import { Prisma } from '@prisma/client'
import type {
AttendanceWithRoster,
CreateAttendanceDTO
} from './dto/attendance.dto'

@Service()
export class AttendanceService {
constructor(private readonly prisma: PrismaService) {}

async createAttendances(
rosterId: number,
attendances: CreateAttendanceDTO[]
): Promise<{ count: number }> {
try {
const attendancesWithRosterId = attendances.map((attendance) => {
return {
...attendance,
rosterId
}
})
return await this.prisma.attendance.createMany({
data: attendancesWithRosterId
})
} catch (error) {
if (
error instanceof Prisma.PrismaClientKnownRequestError &&
error.code === 'P2003'
) {
throw new EntityNotExistException('로스터가 존재하지 않습니다')
}
throw new UnexpectedException(error)
}
}

async getAttendances(
scheduleId: number,
searchTerm: string,
page: number,
limit = 10
): Promise<{ attendances: AttendanceWithRoster[] }> {
try {
const attendances = await this.prisma.attendance.findMany({
where: {
scheduleId,
Roster: {
OR: [
{
offPosition: {
contains: searchTerm
},
defPosition: {
contains: searchTerm
},
splPosition: {
contains: searchTerm
}
}
]
}
},
include: {
Roster: {
select: {
id: true,
name: true,
type: true,
registerYear: true,
offPosition: true,
defPosition: true,
splPosition: true
}
}
},
take: limit,
skip: calculatePaginationOffset(page, limit),
orderBy: {
Roster: {
name: 'asc'
}
}
})

return { attendances }
} catch (error) {
throw new UnexpectedException(error)
}
}
}
62 changes: 62 additions & 0 deletions backend/app/src/attendance/dto/attendance.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import {
AttendanceLocation,
AttendanceResponse,
type Attendance,
type RosterType
} from '@prisma/client'
import {
IsEnum,
IsNotEmpty,
IsNumber,
IsOptional,
IsString
} from 'class-validator'

export class CreateAttendanceDTO {
@IsNumber()
@IsNotEmpty()
scheduleId: number

@IsEnum(AttendanceResponse)
@IsNotEmpty()
response: AttendanceResponse

@IsString()
@IsOptional()
reason?: string

@IsEnum(AttendanceLocation)
@IsOptional()
location?: AttendanceLocation
}

export class UpdateAttendanceDTO {
@IsEnum(AttendanceResponse)
@IsOptional()
response: AttendanceResponse

@IsString()
@IsOptional()
reason?: string

@IsEnum(AttendanceLocation)
@IsOptional()
location?: AttendanceLocation

@IsEnum(AttendanceResponse)
@IsOptional()
result: AttendanceResponse
}

export interface AttendanceWithRoster extends Attendance {
// eslint-disable-next-line @typescript-eslint/naming-convention
Roster: {
id: number
name: string
type: RosterType
registerYear: number
offPosition?: string
defPosition?: string
splPosition?: string
}
}
12 changes: 12 additions & 0 deletions backend/app/src/roster/roster.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,18 @@ export class RosterController {
}
}

@Public()
@Get('studentId/:studentId')
async getRostersByStudentId(
@Param('studentId') studentId: string
): Promise<Roster> {
try {
return await this.rosterService.getRosterByStudentId(studentId)
} catch (error) {
BusinessExceptionHandler(error)
}
}

@Roles(Role.Admin)
@Put(':rosterId')
async updateRoster(
Expand Down
3 changes: 2 additions & 1 deletion backend/app/src/roster/roster.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { RosterService } from './roster.service'

@Module({
providers: [RosterService],
controllers: [RosterController]
controllers: [RosterController],
exports: [RosterService]
})
export class RosterModule {}
18 changes: 18 additions & 0 deletions backend/app/src/roster/roster.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,24 @@ export class RosterService {
}
}

async getRosterByStudentId(studentId: string): Promise<Roster> {
try {
return await this.prisma.roster.findUniqueOrThrow({
where: {
studentId
}
})
} catch (error) {
if (
error instanceof Prisma.PrismaClientKnownRequestError &&
error.code === 'P2025'
) {
throw new EntityNotExistException('로스터가 존재하지 않습니다')
}
throw new UnexpectedException(error)
}
}

async getRosters(
page: number,
limit = 10,
Expand Down
14 changes: 13 additions & 1 deletion backend/app/src/survey/dto/surveyGroup.dto.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { CreateAttendanceDTO } from '@/attendance/dto/attendance.dto'
import { Type } from 'class-transformer'
import {
IsBoolean,
IsDate,
IsNotEmpty,
IsOptional,
IsString
IsString,
ValidateNested
} from 'class-validator'

export class CreateSurveyGroupDTO {
Expand Down Expand Up @@ -46,3 +48,13 @@ export class UpdateSurveyGroupDTO {
@IsOptional()
required?: boolean
}

export class SubmitSurveyDTO {
@IsString()
@IsNotEmpty()
studentId: string

@ValidateNested({ each: true })
@Type(() => CreateAttendanceDTO)
attendances: CreateAttendanceDTO[]
}
16 changes: 15 additions & 1 deletion backend/app/src/survey/survey.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import { Role, type Schedule, type SurveyGroup } from '@prisma/client'
import { CreateScheduleDTO, UpdateScheduleDTO } from './dto/schedule.dto'
import {
CreateSurveyGroupDTO,
UpdateSurveyGroupDTO
UpdateSurveyGroupDTO,
SubmitSurveyDTO
} from './dto/surveyGroup.dto'
import { SurveyService } from './survey.service'

Expand Down Expand Up @@ -78,6 +79,19 @@ export class SurveyController {
}
}

@Public()
@Post('/groups/:surveyGroupId/submit')
async submitSurvey(
@Param('surveyGroupId', ParseIntPipe) surveyGroupId: number,
@Body() surveyDTO: SubmitSurveyDTO
): Promise<{ count: number }> {
try {
return await this.surveyService.submitSurvey(surveyGroupId, surveyDTO)
} catch (error) {
BusinessExceptionHandler(error)
}
}

@Roles(Role.Manager)
@Put('/groups/:surveyGroupId')
async updateSurveyGroup(
Expand Down
3 changes: 3 additions & 0 deletions backend/app/src/survey/survey.module.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { Module } from '@nestjs/common'
import { AttendanceModule } from '@/attendance/attendance.module'
import { RosterModule } from '@/roster/roster.module'
import { SurveyController } from './survey.controller'
import { SurveyService } from './survey.service'

@Module({
imports: [RosterModule, AttendanceModule],
controllers: [SurveyController],
providers: [SurveyService]
})
Expand Down
Loading

0 comments on commit 71cc6e3

Please sign in to comment.