Skip to content
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
2 changes: 2 additions & 0 deletions src/main/java/com/demo/pteam/PteamApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;


@EnableJpaAuditing
@EnableScheduling
@EnableMethodSecurity
@SpringBootApplication
public class PteamApplication {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package com.demo.pteam.global.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ApplicationConfig {
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
return objectMapper;
}
}
6 changes: 6 additions & 0 deletions src/main/java/com/demo/pteam/global/entity/BaseEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
import jakarta.persistence.MappedSuperclass;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

@Getter
@NoArgsConstructor
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity {
Expand All @@ -21,4 +23,8 @@ public abstract class BaseEntity {
@LastModifiedDate
private LocalDateTime updatedAt;

protected BaseEntity(LocalDateTime createdAt) {
this.createdAt = createdAt;
this.updatedAt = createdAt;
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
package com.demo.pteam.global.entity;

import jakarta.persistence.Column;
import jakarta.persistence.MappedSuperclass;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@MappedSuperclass
public abstract class SoftDeletableEntity extends BaseEntity {
protected SoftDeletableEntity(LocalDateTime createdAt) {
super(createdAt);
}

protected LocalDateTime deletedAt;
@Column(insertable = false)
private LocalDateTime deletedAt;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,28 @@
package com.demo.pteam.schedule.controller;

import com.demo.pteam.global.response.ApiResponse;
import com.demo.pteam.schedule.controller.dto.ReadScheduleRequest;
import com.demo.pteam.schedule.controller.dto.ScheduleResponse;
import com.demo.pteam.schedule.service.ScheduleService;
import com.demo.pteam.security.principal.UserPrincipal;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/schedules")
@RequiredArgsConstructor
public class ScheduleController {
private final ScheduleService scheduleService;

@GetMapping
public ResponseEntity<ApiResponse<List<ScheduleResponse>>> readSchedules(@AuthenticationPrincipal UserPrincipal principal,
@ModelAttribute @Valid ReadScheduleRequest requestParams) {
List<ScheduleResponse> schedules = scheduleService.findAllSchedules(principal.id(), requestParams);
return ResponseEntity.ok(ApiResponse.success("회원정보 조회 성공", schedules));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.demo.pteam.schedule.controller.dto;

import com.demo.pteam.schedule.domain.ScheduleDate;
import com.demo.pteam.schedule.validator.YearRange;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import org.hibernate.validator.constraints.Range;

public record ReadScheduleRequest(
@NotBlank(message = "roleType을 입력해주세요.")
@Pattern(regexp = "^(user|trainer)$", message = "user 또는 trainer만 입력 가능합니다.")
String roleType,
@YearRange
Integer year,
@Range(min = 1, max = 12, message = "1 이상 12 이하인 값으로 입력해주세요.")
Integer month
) {
public ScheduleDate toScheduleDate() {
return ScheduleDate.of(year, month);
}
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.demo.pteam.schedule.controller.dto;

import com.demo.pteam.schedule.domain.Schedule;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Builder;

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

@Builder
public record ScheduleResponse(
Long id,
Long userId,
Long trainerId,
String nickname,
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm")
LocalDateTime startTime,
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm")
LocalDateTime endTime
) {
public static ScheduleResponse from(Schedule schedule) {
return ScheduleResponse.builder()
.id(schedule.getId())
.userId(schedule.getUserId())
.trainerId(schedule.getTrainerId())
.nickname(schedule.getNickname())
.startTime(schedule.getStartTime())
.endTime(schedule.getEndTime())
.build();
}
}
13 changes: 13 additions & 0 deletions src/main/java/com/demo/pteam/schedule/domain/Schedule.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
package com.demo.pteam.schedule.domain;

import lombok.Builder;
import lombok.Getter;

import java.time.LocalDateTime;

@Getter
@Builder
public class Schedule {
private final Long id;
private final Long userId;
private final Long trainerId;
private final String nickname;
private final LocalDateTime startTime;
private final LocalDateTime endTime;
}
40 changes: 40 additions & 0 deletions src/main/java/com/demo/pteam/schedule/domain/ScheduleDate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.demo.pteam.schedule.domain;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Objects;

public class ScheduleDate {
private static final int MIN_YEAR = 1900;
private static final int MAX_YEAR = LocalDate.now().getYear() + 10;

private final int year;
private final int month;

private ScheduleDate(int year, int month) {
if (year < MIN_YEAR || year > MAX_YEAR) {
throw new IllegalArgumentException(
"Year must be between " + MIN_YEAR + " and " + MAX_YEAR + ". Invalid year: " + year);
}
if (month < 1 || month > 12) {
throw new IllegalArgumentException("Invalid month: " + month);
}
this.year = year;
this.month = month;
}

public static ScheduleDate of(Integer year, Integer month) {
LocalDate localDate = LocalDate.now();
int safeYear = Objects.isNull(year) ? localDate.getYear() : year;
int safeMonth = Objects.isNull(month) ? localDate.getMonthValue() : month;
return new ScheduleDate(safeYear, safeMonth);
}

public LocalDateTime getStartOfMonth() {
return LocalDate.of(year, month, 1).atStartOfDay();
}

public LocalDateTime getEndOfMonth() {
return getStartOfMonth().plusMonths(1);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.demo.pteam.schedule.repository;

import com.demo.pteam.schedule.repository.entity.ScheduleEntity;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ScheduleJPARepository extends JpaRepository<ScheduleEntity, Long>, ScheduleJPARepositoryCustom {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.demo.pteam.schedule.repository;

import com.demo.pteam.schedule.repository.dto.ScheduleDto;

import java.time.LocalDateTime;
import java.util.List;

public interface ScheduleJPARepositoryCustom {
List<ScheduleDto> findByUserIdWithinPeriod(Long userId, LocalDateTime start, LocalDateTime end);
List<ScheduleDto> findByTrainerIdWithinPeriod(Long trainerId, LocalDateTime start, LocalDateTime end);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.demo.pteam.schedule.repository;

import com.demo.pteam.schedule.repository.dto.ScheduleDto;
import com.querydsl.core.Tuple;
import com.querydsl.core.types.dsl.NumberPath;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;

import static com.demo.pteam.authentication.repository.entity.QAccountEntity.accountEntity;
import static com.demo.pteam.schedule.repository.entity.QScheduleEntity.scheduleEntity;

@Repository
@RequiredArgsConstructor
public class ScheduleJPARepositoryCustomImpl implements ScheduleJPARepositoryCustom {
private final JPAQueryFactory queryFactory;

@Override
public List<ScheduleDto> findByUserIdWithinPeriod(Long userId, LocalDateTime start, LocalDateTime end) {
return findByAccountRoleWithinPeriod(userId, start, end, scheduleEntity.userAccountEntity.id);
}

@Override
public List<ScheduleDto> findByTrainerIdWithinPeriod(Long trainerId, LocalDateTime start, LocalDateTime end) {
return findByAccountRoleWithinPeriod(trainerId, start, end, scheduleEntity.trainerAccountEntity.id);
}

private List<ScheduleDto> findByAccountRoleWithinPeriod(Long accountId, LocalDateTime start, LocalDateTime end, NumberPath<Long> joinTarget) {
List<Tuple> result = queryFactory
.select(
scheduleEntity.id,
accountEntity.id,
scheduleEntity.userAccountEntity.id,
scheduleEntity.trainerAccountEntity.id,
accountEntity.nickname,
scheduleEntity.startTime,
scheduleEntity.endTime)
.from(accountEntity)
.join(scheduleEntity).on(
joinTarget.eq(accountEntity.id),
scheduleEntity.startTime.goe(start),
scheduleEntity.endTime.lt(end))
.where(accountEntity.id.eq(accountId),
accountEntity.deletedAt.isNull())
.fetch();
return createScheduleDto(result);
}

private List<ScheduleDto> createScheduleDto(List<Tuple> result) {
return result.stream()
.map(tuple -> ScheduleDto.builder()
.id(tuple.get(scheduleEntity.id))
.accountId(tuple.get(accountEntity.id))
.userId(tuple.get(scheduleEntity.userAccountEntity.id))
.trainerId(tuple.get(scheduleEntity.trainerAccountEntity.id))
.nickname(tuple.get(accountEntity.nickname))
.startTime(tuple.get(scheduleEntity.startTime))
.endTime(tuple.get(scheduleEntity.endTime))
.build()
).toList();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
package com.demo.pteam.schedule.repository;

import com.demo.pteam.schedule.repository.dto.ScheduleDto;

import java.time.LocalDateTime;
import java.util.List;

public interface ScheduleRepository {
List<ScheduleDto> findByUserIdWithinPeriod(Long userId, LocalDateTime start, LocalDateTime end);
List<ScheduleDto> findByTrainerIdWithinPeriod(Long trainerId, LocalDateTime start, LocalDateTime end);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.demo.pteam.schedule.repository;

import com.demo.pteam.schedule.repository.dto.ScheduleDto;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;

@Repository
@RequiredArgsConstructor
public class ScheduleRepositoryImpl implements ScheduleRepository {
private final ScheduleJPARepository scheduleJPARepository;

@Override
public List<ScheduleDto> findByUserIdWithinPeriod(Long userId, LocalDateTime start, LocalDateTime end) {
return scheduleJPARepository.findByUserIdWithinPeriod(userId, start, end);
}

@Override
public List<ScheduleDto> findByTrainerIdWithinPeriod(Long trainerId, LocalDateTime start, LocalDateTime end) {
return scheduleJPARepository.findByTrainerIdWithinPeriod(trainerId, start, end);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.demo.pteam.schedule.repository.dto;

import com.demo.pteam.schedule.domain.Schedule;
import lombok.Builder;

import java.time.LocalDateTime;

@Builder
public record ScheduleDto(
Long id,
Long accountId,
Long userId,
Long trainerId,
String nickname,
LocalDateTime startTime,
LocalDateTime endTime
) {
public Schedule toSchedule() {
return Schedule.builder()
.id(id)
.userId(userId)
.trainerId(trainerId)
.nickname(nickname)
.startTime(startTime)
.endTime(endTime)
.build();
}
}
Loading