# com.eventcafecloud
event
ㄴ controller
ㄴ EventApiController
ㄴ EventController
ㄴ domain
ㄴ type
ㄴ EventCategory
ㄴ Event
ㄴ EventImage
ㄴ dto
ㄴ EventCreateRequestDto
ㄴ EventListResponseDto
ㄴ EventReadResponseDto
ㄴ EventResponseForProfileDto
ㄴ EventUpdateRequestDto
ㄴ EventUpdateResponseDto
ㄴ repository
ㄴEventRepository
ㄴ service
ㄴ EventService
# resources
ㄴ static
ㄴ css
ㄴ event.css
ㄴ eventCreate.css
ㄴ eventDetail.css
ㄴ js
ㄴ event
ㄴ eventCreate.js
ㄴ eventCreate-datepicker.js
ㄴ eventList.js
ㄴ templates
ㄴ event
ㄴ fragments
ㄴ event-create-form.html
ㄴ event-detail.html
ㄴ event-update-modal.html
ㄴ eventCreateForm.html
ㄴ eventDetail.html
ㄴ eventList.html
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Entity
@DynamicUpdate
public class Event extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "event_number")
private Long id;
@Column(nullable = false)
private String eventName;
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private EventCategory eventCategory;
@Column(nullable = false)
private String eventStartDate;
@Column(nullable = false)
private String eventEndDate;
@Column(nullable = false, columnDefinition = "TEXT")
private String eventInfo;
@Column(nullable = false)
private Integer eventPrice;
@Column(nullable = false)
private Boolean eventCancelAvail;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_number")
private User user;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "cafe_number")
private Cafe cafe;
@OneToMany(mappedBy = "event", cascade = CascadeType.ALL) // mappedBy, cascade
private List<EventImage> eventImages = new ArrayList<>();
public Event(EventCreateRequestDto requestDto) {
this.eventName = requestDto.getEventName();
this.eventCategory = requestDto.getEventCategory();
this.eventStartDate = requestDto.getEventStartDate();
this.eventEndDate = requestDto.getEventEndDate();
this.eventInfo = requestDto.getEventInfo();
this.eventPrice = Integer.valueOf(requestDto.getEventPrice());
this.eventCancelAvail = true;
}
메소드와 연관관계 추가
# 메소드
public void updateEvent(EventUpdateRequestDto requestDto) {
this.eventName = requestDto.getEventName();
this.eventInfo = requestDto.getEventInfo();
}
public String getDate() {
SimpleDateFormat today = new SimpleDateFormat("yyyy-MM-dd");
return today.format(new Date());
}
# 연관 관계 편의 메소드
public void addUser(User user) {
this.user = user;
user.getEvents().add(this);
}
public void addCafe(Cafe cafe) {
this.cafe = cafe;
cafe.getEvents().add(this);
}
public void addEventImage(EventImage eventImage) {
eventImages.add(eventImage);
eventImage.addEvent(this);
}
1. create 요청이 들어오면 (@PostMapping)
2. EventCreateRequestDto에 필요정보들을 담아서
3. DB에 저장
EventCreateRequestDto
@Data
public class EventCreateRequestDto {
private String eventName;
private EventCategory eventCategory;
private String eventStartDate;
private String eventEndDate;
private String eventInfo;
private String eventPrice;
private List<MultipartFile> files;
private Long cafeNumber;
}
EventController
@Controller
@RequiredArgsConstructor
public class EventController {
private final EventService eventService;
private final CafeService cafeService;
// 이벤트 예약 폼
@GetMapping("/events/registration") // 해당 Api 로 연결
public String createEventForm(User loginUser, Model model, @RequestParam Long cafeId) throws ParseException {
if (loginUser != null) {
model.addAttribute("userNick", loginUser.getUserNickname());
model.addAttribute("userId", loginUser.getId());
model.addAttribute("cafeId", cafeId); // user가 있을 경우 카페정보와 유저정보를 Model에 담아서 보냄
}
ArrayList<String> dates = cafeService.AllReservationListByCafe(cafeId);
model.addAttribute("dates", dates);
model.addAttribute("cafeName", cafeService.findCafeByIdForDetail(cafeId).getCafeName());
// 휴무일등록시, 등록 정보를 받아올 객체를 넘김
model.addAttribute("requestDto", new CafeScheduleRequestDto());
model.addAttribute("eventCreateRequestDto", new EventCreateRequestDto()); // binding 할 정보 폼
return "event/createEventForm"; // 해당 html과 연결
}
// 이벤트 예약
@PostMapping("/events")
public String createEvent(User loginUser, @Validated @ModelAttribute EventCreateRequestDto requestDto, BindingResult result) {
// requestDto의 정보를 binding
eventService.saveEvent(requestDto, loginUser); // 담아온 정보로 메소드 실행
if (result.hasErrors()) {
return "event/createEventForm";
} else {
return "redirect:/cafes/" + requestDto.getCafeNumber()+ "/detail";
}
}
EventService
@RequiredArgsConstructor
@Service
public class EventService {
private final EventRepository eventRepository;
private final CafeRepository cafeRepository;
private final UserRepository userRepository;
private final S3Service s3Service;
// 이벤트 예약
@Transactional // 메소드 실행
public void saveEvent(EventCreateRequestDto requestDto, User securityUser) {
User user = userRepository.getById(securityUser.getId());
Cafe cafe = cafeRepository.findById(requestDto.getCafeNumber()).orElseThrow(
() -> new IllegalArgumentException(CAFE_NOT_FOUND.getMessage())
);
Event event = new Event(requestDto);
event.addCafe(cafe);
event.addUser(user); // 연관 관계 메소드 실행
List<MultipartFile> files = requestDto.getFiles();
List<String> eventImageUrls = s3Service.upload(files, "eventImage");
// 이벤트 이미지 생성, S3의 URL을 가져와서 하나씩 eventImage로 만듦
MultipartFile file;
String eventImageUrl;
for (int i = 0; i < files.size(); i++) {
file = files.get(i);
eventImageUrl = eventImageUrls.get(i);
EventImage eventImage = new EventImage(file.getOriginalFilename(), eventImageUrl);
event.addEventImage(eventImage); // 연관 관계 메소드 실행
}
eventRepository.save(event); // DB에 저장
}
1. Read 요청이 들어오면 (@GetMapping)
2. EventReadResponseDto, EventListResponseDto에 필요정보들을 담아
3. 해당 api에 응답
EventListResponseDto
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
@Setter
@Getter
public class EventListResponseDto {
private Long eventNumber;
private String eventName;
private EventCategory eventCategory;
private String eventStartDate;
private String eventEndDate;
private List<String> eventImageUrls;
private int eventCmtCount;
private int eventBookmarkCount;
public EventListResponseDto(Event event) {
this.eventNumber = event.getId();
this.eventName = event.getEventName();
this.eventCategory = event.getEventCategory();
this.eventStartDate = event.getEventStartDate();
this.eventEndDate = event.getEventEndDate();
eventImageUrls = event.getEventImages().stream()
.map(i -> i.getEventImageUrl())
.collect(Collectors.toList());
this.eventCmtCount = event.getEventComments().size();
eventBookmarkCount = event.getEventBookmarks().size();
}
}
EventReadResponseDto
@NoArgsConstructor(access = AccessLevel.PROTECTED) // 외부의 접근을 막기 위해
@Setter
@Getter
public class EventReadResponseDto {
private String eventName;
private EventCategory eventCategory;
private String eventStartDate;
private String eventEndDate;
private String eventInfo;
private boolean isCancel;
private Long userNumber;
private String userNickname;
private Long cafeNumber;
private String cafeName;
private Integer cafeZonecode;
private String cafeAddress;
private String cafeAddressDetail;
private double cafeX;
private double cafeY;
private List<String> eventImageUrls;
private String bookmarkByLoginUser;
public EventReadResponseDto(Event event, boolean checkBookmarkByLoginUser) {
this.eventName = event.getEventName();
this.eventCategory = event.getEventCategory();
this.eventStartDate = event.getEventStartDate();
this.eventEndDate = event.getEventEndDate();
this.eventInfo = event.getEventInfo();
this.isCancel = eventCancelAvail(event.getEventStartDate());
this.userNumber = event.getUser().getId();
this.userNickname = event.getUser().getUserNickname();
this.cafeNumber = event.getCafe().getId();
this.cafeName = event.getCafe().getCafeName();
this.cafeZonecode = event.getCafe().getCafeZonecode();
this.cafeAddress = event.getCafe().getCafeAddress();
this.cafeAddressDetail = event.getCafe().getCafeAddressDetail();
this.cafeX = event.getCafe().getCafeX();
this.cafeY = event.getCafe().getCafeY();
eventImageUrls = event.getEventImages().stream()
.map(i -> i.getEventImageUrl())
.collect(Collectors.toList());
bookmarkByLoginUser = String.valueOf(checkBookmarkByLoginUser);
}
public boolean eventCancelAvail(String eventStartDate) {
Date now;
Calendar cal = java.util.Calendar.getInstance();
cal.add(Calendar.DATE, +7);
now = cal.getTime();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String deadline = sdf.format(now);
return eventStartDate.compareTo(deadline) > 0;
}
}
Controller
// 이벤트 리스트 보기
@GetMapping("/events")
public String getEventList(@PageableDefault Pageable pageable,
@RequestParam(required = false, defaultValue = "", value = "keyword") String keyword,
@RequestParam(required = false, value = "eventCategory") EventCategory eventCategory,
User loginUser, Model model) {
if (loginUser != null) {
model.addAttribute("userNick", loginUser.getUserNickname());
model.addAttribute("userId", loginUser.getId());
}
Page<EventListResponseDto> eventListResponseDtos = eventService.toDtoList(keyword, eventCategory, pageable);
model.addAttribute("eventListResponseDtos", eventListResponseDtos);
return "event/eventList";
}
// 이벤트 상세 + 수정 폼
@GetMapping("/events/{eventNumber}/detail")
public String getEventDetail(User loginUser, @PathVariable Long eventNumber, Model model) {
if (loginUser != null) {
model.addAttribute("userNick", loginUser.getUserNickname());
model.addAttribute("userId", loginUser.getId());
}
EventReadResponseDto eventReadResponseDto = eventService.findEventByIdForDetail(eventNumber, loginUser);
model.addAttribute("eventReadResponseDto", eventReadResponseDto);
model.addAttribute("eventUpdateRequestDto", new EventUpdateRequestDto());
model.addAttribute("event", eventService.findEventById(eventNumber));
return "event/eventDetail";
}
Service
// 전체 이벤트 목록
public Page<EventListResponseDto> toDtoList(String keyword, EventCategory eventCategory, Pageable pageable) {
int page = (pageable.getPageNumber() == 0) ? 0 : (pageable.getPageNumber() - 1);
pageable = PageRequest.of(page, 12, Sort.Direction.DESC, "id");
Page<Event> events = null;
if (eventCategory == null) {
events = eventRepository.findByEventNameContaining(keyword, pageable);
} else {
events = eventRepository.findByEventNameContainingAndEventCategory(keyword, eventCategory, pageable);
}
Page<EventListResponseDto> eventListResponseDtos = events.map(EventListResponseDto::new);
return eventListResponseDtos;
}
// 이벤트 상세 + 북마크
public EventReadResponseDto findEventByIdForDetail(Long eventNumber, User loginUser) {
Event event = eventRepository.findById(eventNumber).orElseThrow(
() -> new IllegalArgumentException(EVENT_NOT_FOUND.getMessage()));
boolean checkBookmarkByLoginUser;
if (loginUser != null) {
checkBookmarkByLoginUser = eventBookmarkRepository.existsByEventIdAndUserId(eventNumber, loginUser.getId());
} else {
checkBookmarkByLoginUser = false;
}
return new EventReadResponseDto(event, checkBookmarkByLoginUser);
}
1. update 요청이 들어오면 (@PostMapping)
2. 요청 정보를 RequestDto에 담고 응답 정보를 ResponseDto담아 응답
* 모달이라 따로 페이지 반환하지 않고 Status code 반환
EventUpdateRequestDto
& EventUpdateResponseDto
# RequestDto
@Setter
@Getter
public class EventUpdateRequestDto {
@Length(min = 1,max = 24)
private String eventName;
@Length(min = 1)
private String eventInfo;
}
# ResponseDto
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Setter
public class EventUpdateResponseDto {
private String eventName;
private String eventInfo;
public EventUpdateResponseDto(String eventName, String eventInfo){
this.eventName = eventName;
this.eventInfo = eventInfo;
}
}
controller
# 수정 폼은 상세페이지와 같이 있음
// 이벤트 수정
@PostMapping("/events/{eventNumber}/detail")
public String updateEvent(@PathVariable Long eventNumber, @Validated @ModelAttribute EventUpdateRequestDto requestDto, BindingResult result, User loginUser) {
int statusCode = eventService.modifyEvent(eventNumber, requestDto, loginUser);
if (statusCode == 500) {
return "error/500";
}
return "redirect:/events/{eventNumber}/detail";
}
Service
// 이벤트 수정
@Transactional
public int modifyEvent(Long eventNumber, EventUpdateRequestDto requestDto, User loginUser) {
Event event = eventRepository.findById(eventNumber).orElseThrow(
() -> new IllegalArgumentException(EVENT_NOT_FOUND.getMessage())
);
if (!event.getUser().getId().equals(loginUser.getId())) {
return 500;
}
event.updateEvent(requestDto);
EventUpdateResponseDto eventUpdateResponse = new EventUpdateResponseDto(event.getEventName(), event.getEventInfo());
return 200;
}
1. Delete 요청이 들어오면 (@DeleteMapping)
2. controller, service 거쳐 해당 eventNumber를 가진 event 삭제
controller
// 이벤트 삭제
@DeleteMapping("/events/{eventNumber}/detail")
public String deleteEvent(@PathVariable Long eventNumber) {
boolean result = eventService.isEventCancelAvail(eventNumber);
if (result) {
eventService.removeEvent(eventNumber);
} else {
return "redirect:/events/" + eventNumber + "/detail";
}
return "redirect:/events";
}
Service
// 이벤트 삭제
public void removeEvent(Long eventNumber) {
eventRepository.deleteById(eventNumber);
}