Skip to content

Commit

Permalink
Merge pull request #112 from PlanIt-Project/BE
Browse files Browse the repository at this point in the history
Be
  • Loading branch information
moonjin-kim authored Mar 27, 2024
2 parents 08027bc + 551c578 commit 5d2a9ef
Show file tree
Hide file tree
Showing 34 changed files with 1,229 additions and 189 deletions.
2 changes: 2 additions & 0 deletions src/main/java/com/sideProject/PlanIT/PlanItApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@EnableScheduling
@SpringBootApplication
public class PlanItApplication {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,19 @@ public enum ErrorCode {
ALREADY_REFUNDED_PROGRAM(400, "이미 환불된 프로그램입니다."),
ALREADY_APPROVE_PROGRAM(400, "이미 등록된 프로그램입니다."),
ALREADY_EXIST_EMAIL(400, "이미 존재하는 이메일입니다."),
NO_EXIST_EMAIL(400, "이메일을 입력해주세요."),
NO_EXIST_PASSWORD(400, "비밀번호를 입력해주세요."),
INVALID_PASSWORD(400, "비밀번호가 틀렸습니다."),
INVALID_EMAIL_AUTH(400, "인증번호가 틀렸습니다."),
NOT_PT(400, "PT이용권이 아닙니다."),
NOT_YOUR_TRAINER(400, "예약 가능한 트레이너가 아닙니다."),
ALREADY_RESERVATION(400, "이미 예약 되어있습니다."),
SAME_PASSWORD(400, "변경 비밀번호가 같습니다."),
INVALID_RESERVATION_TIME(400, "예약 가능한 시간이 아닙니다."),

//401
INVALID_ACCESS_TOKEN(401, "ACCESS TOKEN 오류"),
INVALID_REFRESH_TOKEN(401, "REFRESH TOKEN 오류"),

NO_AUTHORITY(401, "권한이 없습니다."),

//404 Error Not found.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.sideProject.PlanIT.common.scheduler;

import com.sideProject.PlanIT.domain.product.entity.enums.ProductType;
import com.sideProject.PlanIT.domain.program.entity.Program;
import com.sideProject.PlanIT.domain.program.repository.ProgramRepository;
import com.sideProject.PlanIT.domain.user.service.EmailService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

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

@Component
@RequiredArgsConstructor
@Slf4j
public class MemberShipScheduler {
private final ProgramRepository programRepository;
private final EmailService emailService;

@Scheduled(cron = "0 0 0 * * ?")
public void memberShipEndTimeEvent() {
log.info("이메일 전송");
LocalDate nowDate = LocalDate.now();

LocalDate afterOneWeek = nowDate.plusWeeks(1);
LocalDate afterOneMonth = nowDate.plusMonths(1);

sendMailToOneWeekLeft(afterOneWeek);
sendMailToOneMonthLeft(afterOneMonth);
}

private void sendMailToOneWeekLeft(LocalDate afterOneWeek) {
List<Program> oneWeekLefts = programRepository.findMembershipProgramsByEndAtAndProductType(afterOneWeek, ProductType.MEMBERSHIP);

oneWeekLefts.forEach(program -> {
emailService.memberShipEmail(program.getMember().getEmail(), "일주일");
});
}

private void sendMailToOneMonthLeft(LocalDate afterOneMonth) {
List<Program> oneWeekLefts = programRepository.findMembershipProgramsByEndAtAndProductType(afterOneMonth, ProductType.MEMBERSHIP);

oneWeekLefts.forEach(program -> {
emailService.memberShipEmail(program.getMember().getEmail(), "한 달");
});
}



}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
Expand Down Expand Up @@ -55,4 +56,11 @@ public void deleteByValue(String value) {
}
});
}

public void deleteAll() {
redisTemplate.execute((RedisCallback<Object>) connection -> {
connection.serverCommands().flushDb();
return null;
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,9 @@ public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
.exceptionHandling((exceptionHandling) ->
exceptionHandling.authenticationEntryPoint(jwtAuthenticationEntryPoint))
.authorizeHttpRequests((authorizeRequests) -> authorizeRequests
.requestMatchers("/member/signin", "/member/signup", "member/refresh").permitAll()
.requestMatchers("/member/signin", "/member/signup", "/member/refresh", "/member/email/**").permitAll()
.requestMatchers("/admin/**").hasAnyAuthority("ADMIN")
.anyRequest().authenticated()
// .anyRequest().permitAll()
.anyRequest().authenticated()
)
.addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;

@RestController
@RequiredArgsConstructor
@RequestMapping("/file")
public class FileController {
private final FileHandler fileHandler;

Expand All @@ -33,7 +35,7 @@ public ResponseEntity<byte[]> loadImage(@PathVariable String image_name) {
}
}

@GetMapping("/file/{file_name}")
@GetMapping("/{file_name}")
public ResponseEntity<byte[]> loadFile(@PathVariable String file_name) {
try {
byte[] fileBytes = fileHandler.loadFile(file_name);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import java.security.Principal;
Expand All @@ -34,6 +36,7 @@ public ApiResponse<Page<ProgramResponse>> find(
@PageableDefault(size = 10) Pageable pageable,
Principal principal) {
//todo : spring security 개발 후 토큰에서 userID를 전달해 줘야함.
Authentication loggedInUser = SecurityContextHolder.getContext().getAuthentication();
Long id = Long.parseLong(principal.getName());

return ApiResponse.ok(
Expand All @@ -53,6 +56,17 @@ public ApiResponse<Page<ProgramResponse>> find(
);
}

@GetMapping("/{id}")
public ApiResponse<ProgramResponse> find(
@PathVariable("id") Long id) {
Authentication loggedInUser = SecurityContextHolder.getContext().getAuthentication();
Long userId = Long.parseLong(loggedInUser.getName());

return ApiResponse.ok(
programService.findByProgramId(id,userId)
);
}

@DeleteMapping("/{id}")
public ApiResponse<String> refund(@PathVariable("id") Long id) {
LocalDateTime now = LocalDateTime.now();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import com.sideProject.PlanIT.common.response.ApiResponse;
import com.sideProject.PlanIT.domain.program.dto.request.RegistrationRequest;
import com.sideProject.PlanIT.domain.program.dto.response.ProgramResponse;
import com.sideProject.PlanIT.domain.program.dto.response.FindRegistrationResponse;
import com.sideProject.PlanIT.domain.program.dto.response.ProgramResponse;
import com.sideProject.PlanIT.domain.program.entity.enums.ProgramSearchStatus;
import com.sideProject.PlanIT.domain.program.entity.enums.RegistrationSearchStatus;
import com.sideProject.PlanIT.domain.program.service.ProgramService;
Expand Down Expand Up @@ -44,10 +44,8 @@ public ApiResponse<Page<ProgramResponse>> find(
);
}


//어드민이 유저 id로 검색
@GetMapping("/{id}")
public ApiResponse<ProgramResponse> find(
public ApiResponse<ProgramResponse> findById(
@PathVariable("id") Long id,
Principal principal) {
//todo : spring security 개발 후 토큰에서 userID를 전달해 줘야함.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ public void resumeProgram(LocalDate resumeAt,LocalDate endAt) {
}

public void reservation() {
if(this.product.getType() != ProductType.PT) {
throw new CustomException("program " + this.id + " 은 PT권이 아닙니다.", ErrorCode.NOT_PT);
}

if(this.remainedNumber == 0) {
throw new CustomException(this.id + "의 남은 횟수가 없습니다", ErrorCode.EMPLOYEE_NOT_FOUND);
}else if(this.remainedNumber ==1 ){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@ public enum ProgramSearchStatus {
ALL,
VALID,
INVALID

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
package com.sideProject.PlanIT.domain.program.entity.enums;

import java.util.List;

public enum ProgramStatus {
NOT_STARTED,
IN_PROGRESS,
SUSPEND,
REFUND,
EXPIRED
EXPIRED;

public static List<ProgramStatus> forValid() {
return List.of(IN_PROGRESS);
}

public static List<ProgramStatus> forUnValid() {
return List.of(NOT_STARTED,SUSPEND,REFUND,EXPIRED);
}
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
package com.sideProject.PlanIT.domain.program.repository;

import com.sideProject.PlanIT.domain.program.entity.enums.ProgramStatus;
import com.sideProject.PlanIT.domain.product.entity.enums.ProductType;
import com.sideProject.PlanIT.domain.program.entity.Program;
import com.sideProject.PlanIT.domain.program.entity.enums.ProgramStatus;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

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

@Repository
public interface ProgramRepository extends JpaRepository<Program, Long> {
@Query("SELECT o FROM Program o WHERE o.registration.id = :registrationId")
Program findSingleProgramByRegistrationId(@Param("registrationId") Long registrationId);
//status가 IN_PROGRESS인 모든 프로그램 조회
Page<Program> findByMemberId(Long memberId, Pageable pageable);
Page<Program> findByEmployeeId(Long employeeId, Pageable pageable);
Page<Program> findByMemberIdAndStatus(Long memberId, ProgramStatus status, Pageable pageable);
Page<Program> findByMemberIdAndStatusIn(Long memberId, List<ProgramStatus> status, Pageable pageable);
Page<Program> findByEmployeeIdAndStatus(Long employeeId,ProgramStatus status, Pageable pageable);
Page<Program> findByStatus(ProgramStatus status, Pageable pageable);
Page<Program> findByStatusIn(List<ProgramStatus> status, Pageable pageable);

@Query("SELECT p FROM Program p JOIN p.product pr WHERE p.endAt = ?1 AND pr.type = ?2")
List<Program> findMembershipProgramsByEndAtAndProductType(LocalDate endAt, ProductType productType);
}
Original file line number Diff line number Diff line change
Expand Up @@ -317,24 +317,32 @@ public ProgramResponse findByProgramId(long programId, long userId) {
new CustomException("존재하지 않는 회원입니다.", ErrorCode.MEMBER_NOT_FOUND)
);

Program programs = programRepository.findById(programId).orElseThrow(() ->
new CustomException("존재하지 않는 회원입니다.", ErrorCode.MEMBER_NOT_FOUND)
Program program = programRepository.findById(programId).orElseThrow(() ->
new CustomException(programId + "은 존재하지 않는 프로그램입니다.", ErrorCode.PROGRAM_NOT_FOUND)
);

if(member.getRole().equals(MemberRole.TRAINER)) {
Employee employee = employeeRepository.findByMemberId(member.getId()).orElseThrow(() ->
new CustomException("존재하지 않는 직원입니다.", ErrorCode.EMPLOYEE_NOT_FOUND)
);
if(Objects.equals(programs.getEmployee().getId(), employee.getId())) {
throw new CustomException("조회 권한이 없습니다.", ErrorCode.NO_AUTHORITY);
}
validTrainerAccess(member,program);
} else if(member.getRole().equals(MemberRole.MEMBER)){
validMemberAccess(member,program);
}

if(Objects.equals(programs.getMember().getId(), member.getId())) {
return ProgramResponse.of(program);
}

private void validTrainerAccess(Member member, Program program) {
Employee employee = employeeRepository.findByMemberId(member.getId()).orElseThrow(() ->
new CustomException("존재하지 않는 직원입니다.", ErrorCode.EMPLOYEE_NOT_FOUND)
);
if(Objects.equals(program.getEmployee().getId(), employee.getId())) {
throw new CustomException("조회 권한이 없습니다.", ErrorCode.NO_AUTHORITY);
}
}

return ProgramResponse.of(programs);
private void validMemberAccess(Member member, Program program) {
if(Objects.equals(program.getMember().getId(), member.getId())) {
throw new CustomException("조회 권한이 없습니다.", ErrorCode.NO_AUTHORITY);
}
}

private Page<Program> findProgramByEmploy(Member member, ProgramSearchStatus option,Pageable pageable) {
Expand All @@ -353,8 +361,10 @@ private Page<Program> findProgramByUser(Member member, ProgramSearchStatus optio
//ALL이면 모든 상태 조회, VALID이면 IN_PROCESS인 경우만 조회
if(option == ProgramSearchStatus.ALL) {
return programRepository.findByMemberId(member.getId(),pageable);
} else if (option == ProgramSearchStatus.VALID) {
return programRepository.findByMemberIdAndStatusIn(member.getId(), ProgramStatus.forValid(),pageable);
} else {
return programRepository.findByMemberIdAndStatus(member.getId(), ProgramStatus.IN_PROGRESS,pageable);
return programRepository.findByMemberIdAndStatusIn(member.getId(), ProgramStatus.forUnValid(),pageable);
}
}

Expand All @@ -363,9 +373,9 @@ private Page<Program> findProgram(ProgramSearchStatus option,Pageable pageable)
if(option == ProgramSearchStatus.ALL) {
return programRepository.findAll(pageable);
} else if(option == ProgramSearchStatus.VALID) {
return programRepository.findByStatus(ProgramStatus.IN_PROGRESS,pageable);
return programRepository.findByStatusIn(ProgramStatus.forValid(),pageable);
} else {
return programRepository.findByStatus(ProgramStatus.IN_PROGRESS, pageable);
return programRepository.findByStatusIn(ProgramStatus.forUnValid(), pageable);
}
}

Expand Down Expand Up @@ -402,7 +412,7 @@ private Page<FindRegistrationResponse> findAndConvertRegistrations(RegistrationS
registrations = findRegistrationByUser(member, option, pageable);
}

if (registrations.isEmpty()) {
if (registrations == null || registrations.isEmpty()) {
throw new CustomException("조건을 만족하는 Registration이 없습니다.", ErrorCode.REGISTRATION_NOT_FOUND);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ public ApiResponse<String> reservation(
reservationService.reservation(
reservationId,
Long.valueOf(principal.getName()),
request.getProgramId()
request.getProgramId(),
now
)
);
}
Expand All @@ -71,7 +72,7 @@ public ApiResponse<Map<LocalDate, List<ReservationResponse>>> findReservation(
}

@GetMapping("/trainer/{employeeId}")
public ApiResponse<Map<LocalDate, List<ReservationResponse>>> findReservationByEmployee(
public ApiResponse<List<ReservationResponse>> findReservationByEmployee(
@RequestParam(value = "date", required = false)
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date,
@PathVariable("employeeId") Long employeeId
Expand All @@ -92,10 +93,13 @@ public ApiResponse<String> cancelReservation(
@PathVariable("reservationId") Long reservationId,
Principal principal
) {
LocalDateTime now = LocalDateTime.now();

return ApiResponse.ok(
reservationService.cancel(
Long.valueOf(principal.getName()),
reservationId
reservationId,
now
)
);
}
Expand Down
Loading

0 comments on commit 5d2a9ef

Please sign in to comment.