Skip to content

Commit

Permalink
Merge pull request #126 from IT-Cotato/release
Browse files Browse the repository at this point in the history
[Main] V2.2024.08.22.01
  • Loading branch information
Youthhing authored Aug 22, 2024
2 parents c595b50 + ac3351e commit 1f45487
Show file tree
Hide file tree
Showing 100 changed files with 2,738 additions and 459 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

public record MemberEnrollInfoResponse(
Long memberId,
String memberName,
String name,
MemberPosition position,
Integer generationNumber,
MemberRole role
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

public record MemberInfoResponse(
Long memberId,
String memberName,
String name,
String backFourNumber,
MemberRole role
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package org.cotato.csquiz.api.attendance.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.cotato.csquiz.api.attendance.dto.AttendResponse;
import org.cotato.csquiz.api.attendance.dto.AttendanceRecordResponse;
import org.cotato.csquiz.api.attendance.dto.AttendancesResponse;
import org.cotato.csquiz.api.attendance.dto.MemberAttendanceRecordsResponse;
import org.cotato.csquiz.api.attendance.dto.OfflineAttendanceRequest;
import org.cotato.csquiz.api.attendance.dto.OnlineAttendanceRequest;
import org.cotato.csquiz.api.attendance.dto.UpdateAttendanceRequest;
import org.cotato.csquiz.api.attendance.dto.AttendanceTimeResponse;
import org.cotato.csquiz.domain.attendance.service.AttendanceAdminService;
import org.cotato.csquiz.domain.attendance.service.AttendanceRecordService;
import org.cotato.csquiz.domain.attendance.service.AttendanceService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@Tag(name = "출석 정보", description = "출석 관련 API 입니다.")
@RestController
@Validated
@RequiredArgsConstructor
@RequestMapping("/v2/api/attendances")
public class AttendanceController {

private final AttendanceAdminService attendanceAdminService;
private final AttendanceService attendanceService;
private final AttendanceRecordService attendanceRecordService;

@Operation(summary = "출석 정보 변경 API")
@PatchMapping
public ResponseEntity<Void> updateAttendance(@RequestBody @Valid UpdateAttendanceRequest request) {
attendanceAdminService.updateAttendanceByAttendanceId(request);
return ResponseEntity.noContent().build();
}

@Operation(summary = "세션 시간 반환 API")
@GetMapping("/info")
public ResponseEntity<AttendanceTimeResponse> findAttendanceTimeInfo(@RequestParam("sessionId") Long sessionId) {
return ResponseEntity.status(HttpStatus.OK).body(attendanceService.findAttendanceTimeInfo(sessionId));
}

@Operation(summary = "회원 출결사항 기간 단위 조회 API")
@GetMapping("/records")
public ResponseEntity<List<AttendanceRecordResponse>> findAttendanceRecords(
@RequestParam(name = "generationId") Long generationId,
@RequestParam(name = "month", required = false) @Min(value = 1, message = "달은 1 이상이어야 합니다.") @Max(value = 12, message = "달은 12 이하이어야 합니다") Integer month
) {
return ResponseEntity.ok().body(attendanceAdminService.findAttendanceRecords(generationId, month));
}

@Operation(summary = "회원 출결사항 출석 단위 조회 API")
@GetMapping("/{attendance-id}/records")
public ResponseEntity<List<AttendanceRecordResponse>> findAttendanceRecordsByAttendance(
@PathVariable("attendance-id") Long attendanceId) {
return ResponseEntity.ok().body(attendanceAdminService.findAttendanceRecordsByAttendance(attendanceId));
}

@Operation(summary = "기수별 출석 목록 조회 API")
@GetMapping
public ResponseEntity<AttendancesResponse> findAttendancesByGeneration(@RequestParam("generationId") Long generationId) {
return ResponseEntity.ok().body(attendanceService.findAttendancesByGenerationId(generationId));
}

@Operation(summary = "대면 출결 입력 API",
responses = {
@ApiResponse(
responseCode = "200",
description = "성공"
),
@ApiResponse(
responseCode = "409",
description = "이미 출석을 완료함"
),
@ApiResponse(
responseCode = "400",
description = "출석 시간이 아님"
)
}
)
@PostMapping(value = "/records/offline")
public ResponseEntity<AttendResponse> submitOfflineAttendanceRecord(@RequestBody @Valid OfflineAttendanceRequest request,
@AuthenticationPrincipal Long memberId) {
return ResponseEntity.ok().body(attendanceRecordService.submitRecord(request, memberId));
}

@Operation(summary = "비대면 출결 입력 API",
responses = {
@ApiResponse(
responseCode = "200",
description = "성공"
),
@ApiResponse(
responseCode = "409",
description = "이미 출석을 완료함"
),
@ApiResponse(
responseCode = "400",
description = "출석 시간이 아님"
)
})
@PostMapping(value = "/records/online")
public ResponseEntity<AttendResponse> submitOnlineAttendanceRecord(@RequestBody @Valid OnlineAttendanceRequest request,
@AuthenticationPrincipal Long memberId) {
return ResponseEntity.ok().body(attendanceRecordService.submitRecord(request, memberId));
}

@Operation(summary = "부원의 기수별 출결 기록 반환 API")
@GetMapping("/records/members")
public ResponseEntity<MemberAttendanceRecordsResponse> findAllRecordsByGeneration(@RequestParam("generationId") Long generationId ,
@AuthenticationPrincipal Long memberId) {
return ResponseEntity.ok().body(attendanceRecordService.findAllRecordsBy(generationId, memberId));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.cotato.csquiz.api.attendance.dto;

import org.cotato.csquiz.domain.attendance.enums.AttendanceResult;

public record AttendResponse(
AttendanceResult status,
String message
) {
public static AttendResponse from(AttendanceResult status) {
return new AttendResponse(
status,
status.getMessage()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.cotato.csquiz.api.attendance.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalTime;
import java.util.Objects;
import lombok.Builder;
import org.cotato.csquiz.domain.attendance.enums.DeadLine;

public record AttendanceDeadLineDto(
@Schema(example = "19:05:00")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm:ss")
LocalTime attendanceDeadLine,
@Schema(example = "19:20:00")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm:ss")
LocalTime lateDeadLine
) {

@Builder
public AttendanceDeadLineDto {
if (Objects.isNull(attendanceDeadLine)) {
attendanceDeadLine = DeadLine.DEFAULT_ATTENDANCE_DEADLINE.getTime();
}
if (Objects.isNull(lateDeadLine)) {
lateDeadLine = DeadLine.DEFAULT_LATE_DEADLINE.getTime();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.cotato.csquiz.api.attendance.dto;

import java.time.LocalDateTime;
import org.cotato.csquiz.domain.attendance.enums.AttendanceType;

public interface AttendanceParams {

AttendanceType attendanceType();

Long attendanceId();

LocalDateTime requestTime();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.cotato.csquiz.api.attendance.dto;

import org.cotato.csquiz.domain.auth.entity.Member;
import org.cotato.csquiz.domain.auth.enums.MemberPosition;


public record AttendanceRecordResponse(
AttendanceMemberInfo memberInfo,
AttendanceStatistic statistic
) {
public static AttendanceRecordResponse of(Member member, AttendanceStatistic attendanceStatistic) {
return new AttendanceRecordResponse(
AttendanceMemberInfo.from(member),
attendanceStatistic
);
}

public record AttendanceMemberInfo(
Long memberId,
String memberName,
MemberPosition position
){
static AttendanceMemberInfo from(Member member) {
return new AttendanceMemberInfo(
member.getId(),
member.getName(),
member.getPosition()
);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.cotato.csquiz.api.attendance.dto;

import java.time.LocalDate;
import lombok.Builder;
import org.cotato.csquiz.domain.attendance.enums.AttendanceOpenStatus;

@Builder
public record AttendanceResponse(
Long sessionId,
Long attendanceId,
String sessionTitle,
LocalDate sessionDate,
AttendanceOpenStatus openStatus
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.cotato.csquiz.api.attendance.dto;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.cotato.csquiz.domain.attendance.entity.AttendanceRecord;
import org.cotato.csquiz.domain.attendance.enums.AttendanceResult;
import org.cotato.csquiz.domain.attendance.enums.AttendanceType;

public record AttendanceStatistic(
Integer online,
Integer offline,
Integer late,
Integer absent
) {
public static AttendanceStatistic of(List<AttendanceRecord> attendanceRecords, Integer totalAttendance) {
Map<AttendanceResult, List<AttendanceRecord>> countByStatus = attendanceRecords.stream()
.collect(Collectors.groupingBy(AttendanceRecord::getAttendanceResult));
List<AttendanceRecord> presentRecords = countByStatus.getOrDefault(AttendanceResult.PRESENT, List.of());

int onlineCount = (int) presentRecords.stream()
.filter(record -> AttendanceType.ONLINE == record.getAttendanceType())
.count();
int offLineCount = (int) presentRecords.stream()
.filter(record -> AttendanceType.OFFLINE == record.getAttendanceType())
.count();

return new AttendanceStatistic(
onlineCount,
offLineCount,
countByStatus.getOrDefault(AttendanceResult.LATE, List.of()).size(),
totalAttendance - attendanceRecords.size()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.cotato.csquiz.api.attendance.dto;

import java.time.LocalDateTime;
import java.time.LocalTime;

public record AttendanceTimeResponse(
Long sessionId,
LocalTime attendanceDeadLine,
LocalTime lateDeadLine
) {
public static AttendanceTimeResponse of(Long sessionId, LocalDateTime attendanceDeadLine, LocalDateTime lateDeadLine) {
return new AttendanceTimeResponse(
sessionId,
attendanceDeadLine.toLocalTime(),
lateDeadLine.toLocalTime()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.cotato.csquiz.api.attendance.dto;

import java.util.List;
import lombok.Builder;

@Builder
public record AttendancesResponse(
Long generationId,
Long generationNumber,
List<AttendanceResponse> attendances
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package org.cotato.csquiz.api.attendance.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDate;
import org.cotato.csquiz.domain.attendance.entity.Attendance;
import org.cotato.csquiz.domain.attendance.entity.AttendanceRecord;
import org.cotato.csquiz.domain.attendance.enums.AttendanceOpenStatus;
import org.cotato.csquiz.domain.attendance.enums.AttendanceResult;
import org.cotato.csquiz.domain.attendance.enums.AttendanceType;
import org.cotato.csquiz.domain.generation.entity.Session;

public record MemberAttendResponse(
@Schema(description = "세션 PK")
Long sessionId,
@Schema(description = "출석 PK")
Long attendanceId,
@Schema(description = "멤버 PK")
Long memberId,
@Schema(description = "세션 타이틀", example = "3주차 세션")
String sessionTitle,
@Schema(description = "세션 날짜")
LocalDate sessionDate,
@Schema(description = "출결 진행 여부", examples = {
"CLOSED", "OPEN"
})
AttendanceOpenStatus isOpened,
@Schema(description = "출결 형식", nullable = true)
AttendanceType attendanceType,
@Schema(description = "마감된 출석에 대한 출결 결과", nullable = true)
AttendanceResult attendanceResult
) {
public static MemberAttendResponse closedAttendanceResponse(Session session, AttendanceRecord attendanceRecord) {
return new MemberAttendResponse(
session.getId(),
attendanceRecord.getAttendance().getId(),
attendanceRecord.getMemberId(),
session.getTitle(),
session.getSessionDate(),
AttendanceOpenStatus.CLOSED,
attendanceRecord.getAttendanceType(),
attendanceRecord.getAttendanceResult()
);
}

public static MemberAttendResponse openedAttendanceResponse(Attendance attendance, Session session, Long memberId) {
return new MemberAttendResponse(
session.getId(),
attendance.getId(),
memberId,
session.getTitle(),
session.getSessionDate(),
AttendanceOpenStatus.OPEN,
null,
null
);
}
}
Loading

0 comments on commit 1f45487

Please sign in to comment.