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

[BE] 이근표 로그인 #4

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
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
15 changes: 15 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,21 @@ repositories {
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
runtimeOnly 'com.mysql:mysql-connector-j'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'io.projectreactor:reactor-test'
testImplementation 'org.springframework.security:spring-security-test'
}

tasks.named('test') {
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/leets/attendance/AttendanceApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;


@SpringBootApplication
public class AttendanceApplication {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package leets.attendance.domain.attendance.Repository;

import leets.attendance.domain.attendance.domain.Attendance;
import leets.attendance.domain.user.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;
import java.util.Optional;

public interface AttendanceRepository extends JpaRepository<Attendance,Long> {
Optional<Attendance> findByAttendanceId(Long attendanceId);
Optional<Attendance> findByWeekAndUser(Integer week, User user);
List<Attendance> findByUser(User user);
List<Attendance> findByUserAndIsAttend(User user, Boolean isAttend);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package leets.attendance.domain.attendance.application;


import leets.attendance.domain.attendance.Repository.AttendanceRepository;
import leets.attendance.domain.attendance.domain.Attendance;
import leets.attendance.domain.attendance.dto.AttendanceInfo;
import leets.attendance.domain.attendance.dto.AttendanceResponseDto;
import leets.attendance.domain.attendance.exception.InvalidDayException;
import leets.attendance.domain.attendance.presentation.AttendanceMessageEnum;
import leets.attendance.domain.user.domain.User;
import leets.attendance.domain.user.repository.UserRepository;
import leets.attendance.global.DateEnum;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class AttendanceService {
private final AttendanceRepository attendanceRepository;
private final UserRepository userRepository;

public void createInitialAttendance(User user) {
for (int i = 1; i <= DateEnum.values().length; i++) {
Attendance attendance = Attendance.builder()
.isAttend(false)
.week(i)
.attendanceTime(DateEnum.getByWeekNumber(i).getStartDate())
.user(user)
.build();
attendanceRepository.save(attendance);
}
}

public String updateAttendance(Authentication authentication) {
String id = authentication.getName();
User user = userRepository.findById(id).get();
LocalDateTime date = LocalDateTime.now();
DateEnum dateEnum = isValidWeek(date);
Attendance attendance = attendanceRepository.findByWeekAndUser(parseWeek(dateEnum),user).get();
Attendance newAttendance = Attendance.builder()
.attendanceId(attendance.getAttendanceId())
.isAttend(true)
.user(user)
.week(attendance.getWeek())
.build();
attendanceRepository.save(newAttendance);
return AttendanceMessageEnum.UPDATE_SUCCESS.getMessage();
}

public DateEnum isValidWeek(LocalDateTime today) {
try {
if (today.getHour() != 19 || !(today.getDayOfWeek() == DayOfWeek.THURSDAY)) {
throw new InvalidDayException();
}
LocalDate validDate = today.with(DayOfWeek.THURSDAY).toLocalDate();
return DateEnum.getByDate(validDate);
} catch (IllegalArgumentException e) {
throw new InvalidDayException();
}
}

public Integer parseWeek(DateEnum dateEnum) {
String weekNumberStr = dateEnum.name().replace("WEEK_", "");
return Integer.parseInt(weekNumberStr);
}

public AttendanceResponseDto getAttendances(Authentication authentication) {
User user = userRepository.findById(authentication.getName()).get();
List<Attendance> attendances = attendanceRepository.findByUser(user);
List<AttendanceInfo> attendanceInfos = attendances.stream()
.map(a -> new AttendanceInfo(a.getWeek(), a.getIsAttend()))
.collect(Collectors.toList());

return AttendanceResponseDto.builder()
.attendanceList(attendanceInfos)
.name(user.getName())
.date(LocalDate.now())
.build();
}

public int dateToInt(LocalDateTime date) {
LocalDate localDate = date.with(DayOfWeek.THURSDAY).toLocalDate();
String weekNumberStr = DateEnum.getByDate(localDate).name().replace("WEEK_", "");
return Integer.parseInt(weekNumberStr);
}

public String getAttendanceRates(Authentication authentication) {
User user = userRepository.findById(authentication.getName()).get();
LocalDateTime date = LocalDateTime.now();
double trueValue = attendanceRepository.findByUserAndIsAttend(user,true).size();
double dateSize = attendanceRepository.findByUser(user).stream().filter(a -> a.getWeek() <= dateToInt(date)).toList().size();
double result = (trueValue / dateSize) * 100;
return (int) result + "%";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package leets.attendance.domain.attendance.domain;


import jakarta.persistence.*;
import leets.attendance.domain.user.domain.User;
import leets.attendance.global.BaseTimeEntity;
import lombok.*;

import java.time.LocalDate;
import java.time.LocalDateTime;


@Setter
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table
public class Attendance extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column
private Long attendanceId;

@Column(nullable = false)
private Integer week;

@Column(nullable = false)
private Boolean isAttend;

@Column
private LocalDate attendanceTime;

@ManyToOne
@JoinColumn(name = "user_id")
private User user;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package leets.attendance.domain.attendance.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@AllArgsConstructor
@Builder
@NoArgsConstructor
public class AttendanceInfo {
private int week;
private boolean isAttend;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package leets.attendance.domain.attendance.dto;


import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDate;
import java.util.List;

@Builder
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class AttendanceResponseDto {
private String name;
private LocalDate date;
private List<AttendanceInfo> attendanceList;

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package leets.attendance.domain.attendance.exception;

import leets.attendance.global.error.ErrorCode;
import leets.attendance.global.error.ServiceException;

public class InvalidDayException extends ServiceException {
public InvalidDayException(){
super(ErrorCode.INVALID_TIME.getHttpStatus(),ErrorCode.INVALID_TIME.getMessage());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package leets.attendance.domain.attendance.presentation;


import leets.attendance.domain.attendance.application.AttendanceService;
import leets.attendance.domain.attendance.dto.AttendanceResponseDto;
import leets.attendance.global.dto.ResponseDto;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import static leets.attendance.domain.attendance.presentation.AttendanceMessageEnum.GET_SUCCESS;
import static org.springframework.http.HttpStatus.OK;

@RestController
@RequestMapping("/attendances")
public class AttendanceController {

private final AttendanceService attendanceService;

public AttendanceController(AttendanceService attendanceService) {
this.attendanceService = attendanceService;
}

@PatchMapping
public ResponseDto<String> updateAttendance(Authentication authentication) {
return ResponseDto.of(OK.value(), attendanceService.updateAttendance(authentication));
}

@GetMapping
public ResponseDto<AttendanceResponseDto> getAttendances(Authentication authentication) {
return ResponseDto.of(OK.value(),GET_SUCCESS.getMessage(),attendanceService.getAttendances(authentication));
}

@GetMapping(value = "/rates")
public ResponseDto<String> getAttendanceRates(Authentication authentication) {
return ResponseDto.of(OK.value(),GET_SUCCESS.getMessage(),attendanceService.getAttendanceRates(authentication));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package leets.attendance.domain.attendance.presentation;

import lombok.AllArgsConstructor;
import lombok.Getter;

@AllArgsConstructor
@Getter
public enum AttendanceMessageEnum {
UPDATE_SUCCESS("출석 갱신에 성공하였습니다."),
GET_SUCCESS("목록조회에 성공하였습니다");
private String message;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package leets.attendance.domain.user.application;


import leets.attendance.domain.attendance.application.AttendanceService;
import leets.attendance.domain.user.domain.User;
import leets.attendance.domain.user.dto.LoginRequest;
import leets.attendance.domain.user.dto.UserRequest;
import leets.attendance.domain.user.dto.UserResponse;
import leets.attendance.domain.user.exception.InvalidIdException;
import leets.attendance.domain.user.exception.InvalidPasswordException;
import leets.attendance.domain.user.exception.ConflictIdException;
import leets.attendance.domain.user.repository.UserRepository;
import leets.attendance.global.jwt.TokenProvider;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
private final AttendanceService attendanceService;
private final TokenProvider tokenProvider;
public UserResponse register(UserRequest userRequest) throws Exception{
String id = userRequest.getId();
if(userRepository.findById(id).isPresent()){
throw new ConflictIdException();
}
User user = User.builder()
.id(id)
.name(userRequest.getName())
.part(userRequest.getPart())
.password(userRequest.getPassword())
.build();
userRepository.save(user);
attendanceService.createInitialAttendance(user);
return UserResponse.builder()
.userId(user.getUserId())
.name(user.getName())
.part(user.getPart())
.build();
}

public UserResponse login(LoginRequest loginRequest) throws Exception{
String id = loginRequest.getId();
if(!userRepository.findById(id).isPresent()){
throw new InvalidIdException();
}
String password = loginRequest.getPassword();
User user = userRepository.findById(id).orElseThrow(Exception::new);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.orElseThrow(UserNotFoundExcepiton::new); 으로 고치시면 좀 더 확실한 에러처리가 될것 같아요!
exception에 잘 구현하신거 같은데 UserNotFoundExcepiton 추가하시면 됩니다~

if(!user.getPassword().equals(password)){
throw new InvalidPasswordException();
}
String token = tokenProvider.createToken(user.getId());
return UserResponse.builder()
.userId(user.getUserId())
.name(user.getName())
.part(user.getPart())
.token(token)
.build();
}

public String checkDuplicateId(String id) throws Exception{
if(userRepository.findById(id).isPresent()){
throw new ConflictIdException();
}
return id;
}
}
31 changes: 31 additions & 0 deletions src/main/java/leets/attendance/domain/user/domain/User.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package leets.attendance.domain.user.domain;

import jakarta.persistence.*;
import lombok.*;
import java.util.UUID;

@Setter
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setter는 보통 1.객체 일관성 유지 어려움 2.변경 의도 파악 어려움 등으로 지양하고 있는데, 안쓰신다면 지우시는게 좋을것 같아요!

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

User 는 예약어로 충돌될수 있기 때문에 name = ""을 활용해서 users라고 해주는 것이 어떨까요?

public class User {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
@Column
private UUID userId;

@Column(nullable = false)
private String id;

@Column(nullable = false)
private String password;

@Column(nullable = false)
private String name;

@Column(nullable = false)
private String part;
}
Loading