Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package devkor.com.teamcback.domain.common.entity;

public enum Weekday {
MON, TUE, WED, THU, FRI, SAT, SUN
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package devkor.com.teamcback.domain.course.controller;

import devkor.com.teamcback.domain.course.dto.response.GetCourseListRes;
import devkor.com.teamcback.domain.course.service.CourseService;
import devkor.com.teamcback.domain.place.dto.response.GetPlaceListRes;
import devkor.com.teamcback.global.response.CommonResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/places")
public class CourseController {
private final CourseService courseService;

@GetMapping("/{placeId}/courses")
@Operation(summary = "장소 id로 강의 리스트 검색",
description = "강의 list 반환")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "정상 처리 되었습니다."),
@ApiResponse(responseCode = "404", description = "장소를 찾을 수 없습니다.",
content = @Content(schema = @Schema(implementation = CommonResponse.class))),
@ApiResponse(responseCode = "401", description = "권한이 없습니다.",
content = @Content(schema = @Schema(implementation = CommonResponse.class))),
})
public CommonResponse<GetCourseListRes> getCourseList(@Parameter(name = "placeId", description = "장소 ID", example = "4424", required = true) @PathVariable Long placeId) {
return CommonResponse.success(courseService.getCourseList(placeId));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package devkor.com.teamcback.domain.course.dto.response;

import devkor.com.teamcback.domain.common.entity.Weekday;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;

import java.util.List;
import java.util.Map;

@Schema(description = "강의 List 조회 응답 dto")
@Getter
public class GetCourseListRes {
private Long placeId;
private String placeName;
private Map<Weekday, List<GetCourseRes>> courses;

public GetCourseListRes(Long placeId, String placeName, Map<Weekday, List<GetCourseRes>> courses) {
this.placeId = placeId;
this.placeName = placeName;
this.courses = courses;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package devkor.com.teamcback.domain.course.dto.response;

import devkor.com.teamcback.domain.course.entity.Course;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;

@Schema(description = "강의 응답 dto")
@Getter
public class GetCourseRes {
private Long courseId;
private int year;
private String term;
private String subject;
private int unit;
private String code;
private String section;
private String type;
private String department;
private String professor;
private String weekday;
private int classTime;

public GetCourseRes(Course course, String weekday, int classTime) {
this.courseId = course.getId();
this.year = course.getYear();
this.term = course.getTerm().toString();
this.subject = course.getSubject();
this.unit = course.getUnit();
this.code = course.getCode();
this.section = course.getSection();
this.type = course.getType();
this.department = course.getDepartment();
this.professor = course.getProfessor();
this.weekday = weekday;
this.classTime = classTime;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package devkor.com.teamcback.domain.course.entity;

import devkor.com.teamcback.domain.common.entity.BaseEntity;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@Table(name = "tb_course")
@NoArgsConstructor
public class Course extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(nullable = false)
private int year;

@Column(nullable = false)
@Enumerated(EnumType.STRING)
private Term term;

@Column(nullable = false)
private String subject;

@Column(nullable = false)
private int unit;

@Column(nullable = false)
private String code;

@Column(nullable = false)
private String section;

@Column(nullable = false)
private String type;

@Column(nullable = false)
private String department;

@Column(nullable = false)
private String professor;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package devkor.com.teamcback.domain.course.entity;

import devkor.com.teamcback.domain.common.entity.BaseEntity;
import devkor.com.teamcback.domain.common.entity.Weekday;
import devkor.com.teamcback.domain.place.entity.Place;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Entity
@Getter
@Table(name = "tb_course_detail")
@NoArgsConstructor
public class CourseDetail extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column
@Enumerated(EnumType.STRING)
private Weekday weekday;

@Column(nullable = false)
private int start;

@Column(nullable = false)
private int end;

@Column
private String placeName;

@ManyToOne
@JoinColumn(name = "course_id")
private Course course;

@Setter
@OneToOne
@JoinColumn(name = "place_id")
private Place place;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package devkor.com.teamcback.domain.course.entity;

public enum Term {
SPRING, SUMMER, FALL, WINTER
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package devkor.com.teamcback.domain.course.repository;

import devkor.com.teamcback.domain.course.entity.CourseDetail;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import java.util.List;

public interface CourseDetailRepository extends JpaRepository<CourseDetail, Long> {
@Query(value = "SELECT c FROM CourseDetail c WHERE c.place IS NULL ORDER BY c.id asc LIMIT :count")
List<CourseDetail> findLimitByPlaceIdIsNull(int count);

List<CourseDetail> findByPlaceId(Long placeId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package devkor.com.teamcback.domain.course.repository;

import devkor.com.teamcback.domain.course.entity.Course;
import org.springframework.data.jpa.repository.JpaRepository;

public interface CourseRepository extends JpaRepository<Course, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package devkor.com.teamcback.domain.course.scheduler;

import devkor.com.teamcback.domain.common.LocationType;
import devkor.com.teamcback.domain.course.entity.CourseDetail;
import devkor.com.teamcback.domain.course.repository.CourseDetailRepository;
import devkor.com.teamcback.domain.place.entity.Place;
import devkor.com.teamcback.domain.place.repository.PlaceRepository;
import devkor.com.teamcback.domain.search.dto.response.GlobalSearchListRes;
import devkor.com.teamcback.domain.search.service.SearchService;
import devkor.com.teamcback.global.redis.RedisLockUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Slf4j(topic = "Course Scheduler")
@Component
@RequiredArgsConstructor
public class CourseScheduler {
private final RedisLockUtil redisLockUtil;
private final CourseDetailRepository courseDetailRepository;
private final PlaceRepository placeRepository;
private final SearchService searchService;

//@EventListener(ApplicationReadyEvent.class)
//@Transactional
public void updateCourseDetails() {
redisLockUtil.executeWithLock("course_lock", 1, 300, () -> {

log.info("강의 장소 업데이트");

List<CourseDetail> courseDetails = courseDetailRepository.findLimitByPlaceIdIsNull(500);

for (CourseDetail courseDetail : courseDetails) {
String placeName = courseDetail.getPlaceName();
if(placeName.equals("장소정보없음")) continue;

GlobalSearchListRes resList = searchService.globalSearch(placeName, null);

if(!resList.getList().isEmpty() && resList.getList().get(0).getLocationType() == LocationType.PLACE) {
Place place = placeRepository.findById(resList.getList().get(0).getId()).orElseThrow();
courseDetail.setPlace(place);
}

}
return null;
});

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package devkor.com.teamcback.domain.course.service;

import devkor.com.teamcback.domain.common.entity.Weekday;
import devkor.com.teamcback.domain.course.dto.response.GetCourseListRes;
import devkor.com.teamcback.domain.course.dto.response.GetCourseRes;
import devkor.com.teamcback.domain.course.entity.CourseDetail;
import devkor.com.teamcback.domain.course.entity.Term;
import devkor.com.teamcback.domain.course.repository.CourseDetailRepository;
import devkor.com.teamcback.domain.course.repository.CourseRepository;
import devkor.com.teamcback.domain.place.entity.Place;
import devkor.com.teamcback.domain.place.repository.PlaceRepository;
import devkor.com.teamcback.domain.schoolcalendar.repository.SchoolCalendarRepository;
import devkor.com.teamcback.global.exception.exception.GlobalException;
import devkor.com.teamcback.global.response.ResultCode;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.Year;
import java.util.*;

@Service
@RequiredArgsConstructor
public class CourseService {

private final PlaceRepository placeRepository;
private final CourseRepository courseRepository;
private final CourseDetailRepository courseDetailRepository;
private final SchoolCalendarRepository schoolCalendarRepository;

public GetCourseListRes getCourseList(Long placeId) {

int year = Year.now().getValue();
Term term = getTerm();

Place place = getPlaceById(placeId);

List<CourseDetail> courseDetailList = courseDetailRepository.findByPlaceId(placeId);

Map<Weekday, List<GetCourseRes>> map = new LinkedHashMap<>();
for(Weekday weekday : Weekday.values()) {
map.put(weekday, new ArrayList<>());
for(CourseDetail courseDetail : courseDetailList.stream().filter(courseDetail -> courseDetail.getWeekday() == weekday).sorted(Comparator.comparing(CourseDetail::getStart)).toList()) {
if(courseDetail.getCourse().getYear() == year && courseDetail.getCourse().getTerm() == term) {
for(int i = courseDetail.getStart(); i <= courseDetail.getEnd(); i++) {
map.get(weekday).add(new GetCourseRes(courseDetail.getCourse(), weekday.name(), i));
}
}
}
}

return new GetCourseListRes(placeId, place.getBuilding().getName() + " " + place.getName(), map);
}

private Term getTerm() {
return schoolCalendarRepository.findById(3L).orElseThrow(() -> new GlobalException(ResultCode.NOT_FOUND_SCHOOL_CALENDAR)).getTerm();
}

private Place getPlaceById(Long id) {
return placeRepository.findById(id).orElseThrow(() -> new GlobalException(ResultCode.NOT_FOUND_PLACE));
}

/* private Course getCourseById(Long id) {
return courseRepository.findById(id).orElseThrow(() -> new GlobalException(ResultCode.NOT_FOUND_COURSE));
}*/
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package devkor.com.teamcback.domain.schoolcalendar.controller;

import devkor.com.teamcback.domain.schoolcalendar.dto.request.UpdateSchoolCalendarTermReq;
import devkor.com.teamcback.domain.schoolcalendar.dto.response.UpdateSchoolCalendarRes;
import devkor.com.teamcback.domain.schoolcalendar.service.SchoolCalendarService;
import devkor.com.teamcback.global.response.CommonResponse;
Expand Down Expand Up @@ -47,4 +48,18 @@ public CommonResponse<UpdateSchoolCalendarRes> updateKoyeonActive() {
return CommonResponse.success(schoolCalendarService.updateKoyeonActive());
}

/***
* 학기 수정
*/
@PutMapping("/term")
@Operation(summary = "학기", description = "학기")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "정상 처리 되었습니다."),
@ApiResponse(responseCode = "404", description = "Not Found",
content = @Content(schema = @Schema(implementation = CommonResponse.class))),
})
public CommonResponse<UpdateSchoolCalendarRes> updateTerm(UpdateSchoolCalendarTermReq req) {
return CommonResponse.success(schoolCalendarService.updateTerm(req));
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package devkor.com.teamcback.domain.schoolcalendar.controller;

import devkor.com.teamcback.domain.schoolcalendar.dto.response.GetSchoolCalendarRes;
import devkor.com.teamcback.domain.schoolcalendar.dto.response.GetSchoolCalendarTermRes;
import devkor.com.teamcback.domain.schoolcalendar.service.SchoolCalendarService;
import devkor.com.teamcback.global.response.CommonResponse;
import io.swagger.v3.oas.annotations.Operation;
Expand Down Expand Up @@ -47,4 +48,18 @@ public CommonResponse<GetSchoolCalendarRes> isKoyeon() {
return CommonResponse.success(schoolCalendarService.isKoyeon());
}

/***
* 학기 반환
*/
@GetMapping("/term")
@Operation(summary = "현재 학기 반환", description = "1학기/여름계절/2학기/겨울계절")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "정상 처리 되었습니다."),
@ApiResponse(responseCode = "404", description = "Not Found",
content = @Content(schema = @Schema(implementation = CommonResponse.class))),
})
public CommonResponse<GetSchoolCalendarTermRes> getTerm() {
return CommonResponse.success(schoolCalendarService.getTerm());
}

}
Loading