Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.blackcompany.eeos.program.application.dto.request;

import com.blackcompany.eeos.common.support.dto.AbstractApplicationDto;
import jakarta.validation.constraints.NotNull;
import java.sql.Timestamp;

public record CalendarApplicationCommand(
@NotNull(message = "시작 날짜는 필수입니다") Timestamp startDate,
@NotNull(message = "종료 날짜는 필수입니다") Timestamp endDate)
implements AbstractApplicationDto {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.blackcompany.eeos.program.application.dto.response;

import com.blackcompany.eeos.common.support.dto.AbstractApplicationDto;
import java.sql.Timestamp;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@AllArgsConstructor
@NoArgsConstructor
public class CalendarPeriodApplicationQuery implements AbstractApplicationDto {
private Timestamp startDate;
private Timestamp endDate;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.blackcompany.eeos.program.application.model;

import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.Month;
import java.time.Year;
import lombok.*;
import lombok.extern.slf4j.Slf4j;

@Getter
@ToString
@AllArgsConstructor
@Builder(toBuilder = true)
@Slf4j
public class CalendarModel {
private Timestamp startDate;
private Timestamp endDate;

public CalendarModel() {
LocalDate now = LocalDate.now();

// 9월 이후이면 9월 1일부터 다음 해 2월 말까지
if (now.getMonthValue() >= Month.SEPTEMBER.getValue()) {
startDate = Timestamp.valueOf(LocalDate.of(now.getYear(), Month.SEPTEMBER, 1).atStartOfDay());
endDate =
Timestamp.valueOf(
LocalDate.of(
now.getYear() + 1,
Month.FEBRUARY,
Month.FEBRUARY.length(Year.isLeap(now.getYear() + 1)))
.atTime(23, 59, 59));
} else {
// 3월 이후이면 3월 1일부터 8월 말까지
startDate = Timestamp.valueOf(LocalDate.of(now.getYear(), Month.MARCH, 1).atStartOfDay());
endDate = Timestamp.valueOf(LocalDate.of(now.getYear(), Month.AUGUST, 31).atTime(23, 59, 59));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.blackcompany.eeos.program.application.repository;

import com.blackcompany.eeos.program.application.model.CalendarModel;
import java.util.Optional;

public interface CalendarRepository {
Optional<CalendarModel> getCalendar();

CalendarModel updateCalendar(CalendarModel model);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.blackcompany.eeos.program.application.service;

import com.blackcompany.eeos.program.application.dto.request.CalendarApplicationCommand;
import com.blackcompany.eeos.program.application.dto.response.CalendarPeriodApplicationQuery;
import com.blackcompany.eeos.program.application.model.CalendarModel;
import com.blackcompany.eeos.program.application.repository.CalendarRepository;
import com.blackcompany.eeos.program.application.support.CalendarProvider;
import com.blackcompany.eeos.program.application.usecase.GetCalendarUsecase;
import com.blackcompany.eeos.program.application.usecase.UpdateCalendarUsecase;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class CalendarService implements GetCalendarUsecase, UpdateCalendarUsecase {
private final CalendarRepository calendarRepository;
private final CalendarProvider calendarProvider;

@Override
public CalendarPeriodApplicationQuery getCalendar() {
CalendarModel model = calendarProvider.getCalendar();
return new CalendarPeriodApplicationQuery(model.getStartDate(), model.getEndDate());
}

@Override
@Transactional
public CalendarPeriodApplicationQuery updateCalendar(CalendarApplicationCommand command) {
CalendarModel model =
calendarRepository.updateCalendar(
new CalendarModel(command.startDate(), command.endDate()));
return new CalendarPeriodApplicationQuery(model.getStartDate(), model.getEndDate());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.blackcompany.eeos.program.application.support;

import com.blackcompany.eeos.program.application.model.CalendarModel;
import com.blackcompany.eeos.program.application.repository.CalendarRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class CalendarProvider {
private final CalendarRepository calendarRepository;

public CalendarModel getCalendar() {
return calendarRepository.getCalendar().orElse(new CalendarModel());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.blackcompany.eeos.program.application.usecase;

import com.blackcompany.eeos.program.application.dto.response.CalendarPeriodApplicationQuery;

public interface GetCalendarUsecase {
CalendarPeriodApplicationQuery getCalendar();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.blackcompany.eeos.program.application.usecase;

import com.blackcompany.eeos.program.application.dto.request.CalendarApplicationCommand;
import com.blackcompany.eeos.program.application.dto.response.CalendarPeriodApplicationQuery;

public interface UpdateCalendarUsecase {
CalendarPeriodApplicationQuery updateCalendar(CalendarApplicationCommand command);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.blackcompany.eeos.program.persistence;

import com.blackcompany.eeos.common.persistence.BaseEntity;
import jakarta.persistence.*;
import java.sql.Timestamp;
import lombok.*;
import lombok.experimental.SuperBuilder;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@ToString
@SuperBuilder(toBuilder = true)
@Entity
@Table(
name = CalendarEntity.ENTITY_PREFIX,
indexes = {
@Index(
name = "idx_calendar_created_date_id",
columnList = "createdDate DESC, calendar_id DESC")
})
@SQLDelete(sql = "UPDATE calendar SET is_deleted=true where calendar_id=?")
@Where(clause = "is_deleted=false")
public class CalendarEntity extends BaseEntity {
public static final String ENTITY_PREFIX = "calendar";

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = ENTITY_PREFIX + "_id", nullable = false)
private Long id;

@Column(name = ENTITY_PREFIX + "_start_date", nullable = false)
private Timestamp startDate;

@Column(name = ENTITY_PREFIX + "_end_date", nullable = false)
private Timestamp endDate;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.blackcompany.eeos.program.persistence;

import com.blackcompany.eeos.program.application.model.CalendarModel;
import com.blackcompany.eeos.program.application.repository.CalendarRepository;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

@Repository
@RequiredArgsConstructor
public class CalendarRepositoryImpl implements CalendarRepository {
private final JpaCalendarRepository jpaCalendarRepository;

@Override
public Optional<CalendarModel> getCalendar() {
return jpaCalendarRepository.findTopByOrderByCreatedDateDesc().map(this::toModel);
}

@Override
public CalendarModel updateCalendar(CalendarModel model) {
CalendarEntity entity = toEntity(model);
CalendarEntity savedEntity = jpaCalendarRepository.save(entity);
return toModel(savedEntity);
}

private CalendarModel toModel(CalendarEntity entity) {
return CalendarModel.builder()
.startDate(entity.getStartDate())
.endDate(entity.getEndDate())
.build();
}

private CalendarEntity toEntity(CalendarModel model) {
return CalendarEntity.builder()
.startDate(model.getStartDate())
.endDate(model.getEndDate())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.blackcompany.eeos.program.persistence;

import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;

public interface JpaCalendarRepository extends JpaRepository<CalendarEntity, Long> {
Optional<CalendarEntity> findTopByOrderByCreatedDateDesc();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.blackcompany.eeos.program.presentation.controller;

import com.blackcompany.eeos.common.presentation.response.ApiResponse;
import com.blackcompany.eeos.common.presentation.response.ApiResponseBody;
import com.blackcompany.eeos.common.presentation.response.ApiResponseGenerator;
import com.blackcompany.eeos.common.presentation.response.MessageCode;
import com.blackcompany.eeos.program.application.dto.request.CalendarApplicationCommand;
import com.blackcompany.eeos.program.application.dto.response.CalendarPeriodApplicationQuery;
import com.blackcompany.eeos.program.application.usecase.GetCalendarUsecase;
import com.blackcompany.eeos.program.application.usecase.UpdateCalendarUsecase;
import com.blackcompany.eeos.program.presentation.dto.UpdateCalendarRequest;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api")
public class CalendarController {
private final GetCalendarUsecase getCalendarUsecase;
private final UpdateCalendarUsecase updateCalendarUsecase;

@PutMapping("/admin/calendars") // TODO : 인터셉터 단에서 어드민 검증
public ApiResponse<ApiResponseBody.SuccessBody<CalendarPeriodApplicationQuery>> updateCalendar(
@RequestBody @Valid UpdateCalendarRequest request) {
CalendarPeriodApplicationQuery response =
updateCalendarUsecase.updateCalendar(
new CalendarApplicationCommand(request.startDate(), request.endDate()));
return ApiResponseGenerator.success(response, HttpStatus.CREATED, MessageCode.CREATE);
}

@GetMapping("/calendars")
public ApiResponse<ApiResponseBody.SuccessBody<CalendarPeriodApplicationQuery>> getCalendar() {
CalendarPeriodApplicationQuery response = getCalendarUsecase.getCalendar();
return ApiResponseGenerator.success(response, HttpStatus.OK, MessageCode.GET);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.blackcompany.eeos.program.presentation.dto;

import jakarta.validation.constraints.AssertTrue;
import jakarta.validation.constraints.NotNull;
import java.sql.Timestamp;

public record UpdateCalendarRequest(
@NotNull(message = "시작일은 필수값입니다.") Timestamp startDate,
@NotNull(message = "종료일은 필수값입니다.") Timestamp endDate) {

@AssertTrue(message = "종료일은 시작일 이후여야 합니다.")
public boolean isEndDateAfterStartDate() {
return endDate.getTime() > startDate.getTime();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.blackcompany.eeos.program.application.model.ProgramModel;
import com.blackcompany.eeos.program.application.model.converter.ProgramEntityConverter;
import com.blackcompany.eeos.program.application.service.ProgramDateRangeService;
import com.blackcompany.eeos.program.application.support.CalendarProvider;
import com.blackcompany.eeos.program.persistence.ProgramRepository;
import com.blackcompany.eeos.target.application.dto.AttendInfoActiveStatusResponse;
import com.blackcompany.eeos.target.application.dto.AttendInfoResponse;
Expand Down Expand Up @@ -45,9 +46,6 @@
import com.blackcompany.eeos.target.persistence.ProgramRankCounterEntity;
import com.blackcompany.eeos.target.persistence.ProgramRankCounterRepository;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
Expand Down Expand Up @@ -89,6 +87,7 @@ public class AttendService
private final AttendCountCalculate attendCountCalculate;
private final AttendPenaltyResponseConverter attendPenaltyResponseConverter;
private final ProgramRankCounterRepository programRankCounterRepository;
private final CalendarProvider calendarProvider;

@Override
public List<AttendInfoResponse> findAttendInfo(final Long programId) {
Expand Down Expand Up @@ -248,6 +247,9 @@ public PageResponse<AttendInfoWithProgramResponse> findMyAttendInfo(
public AttendSummaryInfoResponse getMyAttendSummary(Long startDate, Long endDate) {
Long memberId = RequestScope.getMemberId();

if (startDate == null) startDate = calendarProvider.getCalendar().getStartDate().getTime();
if (endDate == null) endDate = calendarProvider.getCalendar().getEndDate().getTime();

List<ProgramModel> programs = programDateRangeService.getPrograms(startDate, endDate);

List<AttendModel> attends = findMyAttends(programs);
Expand Down Expand Up @@ -275,10 +277,8 @@ public PageResponse<AttendPenaltyResponse> getPenaltyInfos(int page, int size, S
Pageable pageable = PageRequest.of(page - 1, size, Sort.by(order));

// TODO: startDate 와 endDate 시간 설정하기
Timestamp startDate =
Timestamp.valueOf(LocalDateTime.of(LocalDate.of(2024, 3, 1), LocalTime.of(0, 0)));
Timestamp endDate =
Timestamp.valueOf(LocalDateTime.of(LocalDate.of(2025, 8, 1), LocalTime.of(0, 0)));
Timestamp startDate = calendarProvider.getCalendar().getStartDate();
Timestamp endDate = calendarProvider.getCalendar().getEndDate();
Long limit = 10L;

Page<Object[]> pages = attendRepository.findByPenaltyPointSum(startDate, endDate, pageable);
Expand Down