From b195362621b5bccf3537063248bd632d95e0a5fa Mon Sep 17 00:00:00 2001 From: gabang2 Date: Sun, 14 Jul 2024 18:11:26 +0900 Subject: [PATCH] =?UTF-8?q?=EC=B6=94=EA=B0=80:=20=ED=8B=B0=EC=BC=93=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CategoryController.java | 9 - .../domain/category/entity/Category.java | 1 - .../controller/CulturalEventController.java | 2 +- .../culturalevent/entity/CulturalEvent.java | 4 - .../service/CulturalEventBatchService.java | 5 - .../CulturalEventEvaluationController.java | 44 --- .../dto/CulturalEventEvaluationListDto.java | 22 -- .../entity/CulturalEventEvaluation.java | 54 ---- .../entity/EvaluationType.java | 15 - .../mapper/CulturalEventEvaluationMapper.java | 25 -- .../CulturalEventEvaluationRepository.java | 7 - .../CulturalEventEvaluationService.java | 122 ------- .../CulturalEventCategoryController.java | 2 +- .../backend/domain/jwt/filter/JwtFilter.java | 3 +- .../media/controller/MediaController.java | 4 +- .../media/controller/MediasController.java | 8 +- .../domain/media/dto/MediaCreateDto.java | 12 + .../backend/domain/media/dto/MediaDto.java | 4 +- .../backend/domain/media/entity/Media.java | 37 ++- .../domain/media/mapper/MediaMapper.java | 4 +- .../media/repository/MediaRepository.java | 3 + .../domain/media/service/MediaService.java | 19 +- .../member/controller/MemberController.java | 2 +- .../domain/member/dto/MemberInfoDto.java | 2 +- .../backend/domain/member/entity/Member.java | 7 +- .../MemberTicketLikeController.java | 94 ------ .../dto/MemberTicketLikePostRequestDto.java | 21 -- .../dto/MemberTicketLikeResponseDto.java | 15 - .../entity/MemberTicketLike.java | 52 --- .../mapper/MemberTicketLikeMapper.java | 12 - .../MemberTicketLikeRepository.java | 14 - .../service/MemberTicketLikeService.java | 86 ----- .../notice/controller/FcmController2.java | 15 - .../backend/domain/place/entity/Place.java | 4 + .../ticket/controller/TicketController.java | 305 +----------------- .../domain/ticket/dto/TicketCreateDto.java | 53 +++ .../ticket/dto/TicketPatchRequestDto.java | 40 --- .../ticket/dto/TicketPostRequestDto.java | 44 --- .../domain/ticket/dto/TicketResponseDto.java | 33 -- .../domain/ticket/dto/TicketRetrieveDto.java | 22 ++ .../dto/TicketStatusPostRequestDto.java | 20 -- .../domain/ticket/entity/IsPrivate.java | 16 - .../backend/domain/ticket/entity/Ticket.java | 88 ++--- .../domain/ticket/mapper/TicketMapper.java | 10 +- .../repository/TicketRepositoryCustom.java | 14 +- .../repository/TicketRepositoryImpl.java | 304 ++++++++--------- .../domain/ticket/service/TicketService.java | 151 ++------- .../global/annotation/ValidDateFormat.java | 19 ++ .../global/error/exception/ErrorCode.java | 8 +- .../global/validator/DateFormatValidator.java | 32 ++ 50 files changed, 434 insertions(+), 1455 deletions(-) delete mode 100644 src/main/java/project/backend/domain/culturaleventevalutaion/controller/CulturalEventEvaluationController.java delete mode 100644 src/main/java/project/backend/domain/culturaleventevalutaion/dto/CulturalEventEvaluationListDto.java delete mode 100644 src/main/java/project/backend/domain/culturaleventevalutaion/entity/CulturalEventEvaluation.java delete mode 100644 src/main/java/project/backend/domain/culturaleventevalutaion/entity/EvaluationType.java delete mode 100644 src/main/java/project/backend/domain/culturaleventevalutaion/mapper/CulturalEventEvaluationMapper.java delete mode 100644 src/main/java/project/backend/domain/culturaleventevalutaion/repository/CulturalEventEvaluationRepository.java delete mode 100644 src/main/java/project/backend/domain/culturaleventevalutaion/service/CulturalEventEvaluationService.java create mode 100644 src/main/java/project/backend/domain/media/dto/MediaCreateDto.java delete mode 100644 src/main/java/project/backend/domain/memberTicketLike/controller/MemberTicketLikeController.java delete mode 100644 src/main/java/project/backend/domain/memberTicketLike/dto/MemberTicketLikePostRequestDto.java delete mode 100644 src/main/java/project/backend/domain/memberTicketLike/dto/MemberTicketLikeResponseDto.java delete mode 100644 src/main/java/project/backend/domain/memberTicketLike/entity/MemberTicketLike.java delete mode 100644 src/main/java/project/backend/domain/memberTicketLike/mapper/MemberTicketLikeMapper.java delete mode 100644 src/main/java/project/backend/domain/memberTicketLike/repository/MemberTicketLikeRepository.java delete mode 100644 src/main/java/project/backend/domain/memberTicketLike/service/MemberTicketLikeService.java delete mode 100644 src/main/java/project/backend/domain/notice/controller/FcmController2.java create mode 100644 src/main/java/project/backend/domain/ticket/dto/TicketCreateDto.java delete mode 100644 src/main/java/project/backend/domain/ticket/dto/TicketPatchRequestDto.java delete mode 100644 src/main/java/project/backend/domain/ticket/dto/TicketPostRequestDto.java delete mode 100644 src/main/java/project/backend/domain/ticket/dto/TicketResponseDto.java create mode 100644 src/main/java/project/backend/domain/ticket/dto/TicketRetrieveDto.java delete mode 100644 src/main/java/project/backend/domain/ticket/dto/TicketStatusPostRequestDto.java delete mode 100644 src/main/java/project/backend/domain/ticket/entity/IsPrivate.java create mode 100644 src/main/java/project/backend/global/annotation/ValidDateFormat.java create mode 100644 src/main/java/project/backend/global/validator/DateFormatValidator.java diff --git a/src/main/java/project/backend/domain/category/controller/CategoryController.java b/src/main/java/project/backend/domain/category/controller/CategoryController.java index e30aff9..fa5b321 100644 --- a/src/main/java/project/backend/domain/category/controller/CategoryController.java +++ b/src/main/java/project/backend/domain/category/controller/CategoryController.java @@ -13,18 +13,9 @@ import project.backend.domain.category.entity.Category; import project.backend.domain.category.mapper.CategoryMapper; import project.backend.domain.category.service.CategoryService; -import project.backend.domain.ticket.dto.TicketPostRequestDto; -import project.backend.domain.ticket.entity.Ticket; -import project.backend.global.error.exception.BusinessException; -import project.backend.global.error.exception.ErrorCode; import project.backend.global.s3.service.ImageService; import javax.validation.Valid; -import javax.validation.constraints.Positive; - -import java.awt.image.BufferedImage; - -import static project.backend.global.validator.LocalDateTimeValidation.convertStringToLocalDateTime; @RestController @RequestMapping("/api/categorys") diff --git a/src/main/java/project/backend/domain/category/entity/Category.java b/src/main/java/project/backend/domain/category/entity/Category.java index ae75256..37c0c3b 100644 --- a/src/main/java/project/backend/domain/category/entity/Category.java +++ b/src/main/java/project/backend/domain/category/entity/Category.java @@ -6,7 +6,6 @@ import lombok.RequiredArgsConstructor; import project.backend.domain.category.dto.CategoryPatchRequestDto; import project.backend.domain.common.entity.BaseEntity; -import project.backend.domain.memberTicketLike.entity.MemberTicketLike; import project.backend.domain.onboardingmembercategory.entity.OnboardingMemberCategory; import project.backend.domain.ticket.entity.Ticket; diff --git a/src/main/java/project/backend/domain/culturalevent/controller/CulturalEventController.java b/src/main/java/project/backend/domain/culturalevent/controller/CulturalEventController.java index 8802d75..23a695c 100644 --- a/src/main/java/project/backend/domain/culturalevent/controller/CulturalEventController.java +++ b/src/main/java/project/backend/domain/culturalevent/controller/CulturalEventController.java @@ -29,7 +29,7 @@ import java.util.List; import java.util.stream.IntStream; -@Api(tags = "A. 문화생활") +@Api(tags = "CulturalEvent - 문화생활") @RestController @RequestMapping("/api/cultural-events") @RequiredArgsConstructor diff --git a/src/main/java/project/backend/domain/culturalevent/entity/CulturalEvent.java b/src/main/java/project/backend/domain/culturalevent/entity/CulturalEvent.java index 46177a7..2b054ba 100644 --- a/src/main/java/project/backend/domain/culturalevent/entity/CulturalEvent.java +++ b/src/main/java/project/backend/domain/culturalevent/entity/CulturalEvent.java @@ -2,7 +2,6 @@ import lombok.*; import project.backend.domain.common.entity.BaseEntity; -import project.backend.domain.culturaleventevalutaion.entity.CulturalEventEvaluation; import project.backend.domain.like.entity.CulturalEventLike; import project.backend.domain.culturalevnetcategory.entity.CulturalEventCategory; import project.backend.domain.culturalevnetinfo.entity.CulturalEventInfo; @@ -73,9 +72,6 @@ public class CulturalEvent extends BaseEntity { @OneToMany(mappedBy = "culturalEvent", cascade = {CascadeType.PERSIST, CascadeType.REMOVE}) public List ticketingSiteList = new ArrayList<>(); - @OneToMany(mappedBy = "culturalEvent", cascade = {CascadeType.PERSIST, CascadeType.REMOVE}) - public List culturalEventEvaluationList = new ArrayList<>(); - @OneToMany(mappedBy = "culturalEvent", cascade = {CascadeType.PERSIST, CascadeType.REMOVE}) public List culturalEventLikeList = new ArrayList<>(); diff --git a/src/main/java/project/backend/domain/culturalevent/service/CulturalEventBatchService.java b/src/main/java/project/backend/domain/culturalevent/service/CulturalEventBatchService.java index b94af41..bfe871e 100644 --- a/src/main/java/project/backend/domain/culturalevent/service/CulturalEventBatchService.java +++ b/src/main/java/project/backend/domain/culturalevent/service/CulturalEventBatchService.java @@ -17,7 +17,6 @@ import project.backend.domain.culturalevent.entity.CulturalEvent; import project.backend.domain.culturalevent.mapper.CulturalEventMapper; import project.backend.domain.culturalevent.repository.CulturalEventRepository; -import project.backend.domain.culturaleventevalutaion.service.CulturalEventEvaluationService; import project.backend.domain.culturalevnetcategory.entity.CategoryTitle; import project.backend.domain.culturalevnetcategory.entity.CulturalEventCategory; import project.backend.domain.culturalevnetcategory.service.CulturalEventCategoryService; @@ -43,7 +42,6 @@ public class CulturalEventBatchService { private final CulturalEventCategoryService culturalEventCategoryService; private final CulturalEventInfoService culturalEventInfoService; private final TicketingSiteService ticketingSiteService; - private final CulturalEventEvaluationService culturalEventEvaluationService; /** * CulturalEvent 생성 @@ -98,9 +96,6 @@ public CulturalEvent createCulturalEvent(String goodsCode, CulturalEventCreateDt // 저장 CulturalEvent savedCulturalEvent = culturalEventRepository.save(culturalEvent); - // CulturalEventEvaluation 연관관계 매핑 - culturalEventEvaluationService.createCulturalEventEvaluations(goodsCode, savedCulturalEvent); - // CulturalEventInfo 연관관계 매핑 List imageUrlList = culturalEventInfoService.extractImageUrlList(culturalEventCreateDto.getInformation()); for (int i = 0; i < imageUrlList.size(); i++) { diff --git a/src/main/java/project/backend/domain/culturaleventevalutaion/controller/CulturalEventEvaluationController.java b/src/main/java/project/backend/domain/culturaleventevalutaion/controller/CulturalEventEvaluationController.java deleted file mode 100644 index bfac8b3..0000000 --- a/src/main/java/project/backend/domain/culturaleventevalutaion/controller/CulturalEventEvaluationController.java +++ /dev/null @@ -1,44 +0,0 @@ -package project.backend.domain.culturaleventevalutaion.controller; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; -import project.backend.domain.culturalevent.dto.CulturalEventRetrieveDto; -import project.backend.domain.culturalevent.entity.CulturalEvent; -import project.backend.domain.culturalevent.mapper.CulturalEventMapper; -import project.backend.domain.culturalevent.service.CulturalEventService; -import project.backend.domain.culturaleventevalutaion.dto.CulturalEventEvaluationListDto; -import project.backend.domain.culturaleventevalutaion.mapper.CulturalEventEvaluationMapper; -import project.backend.domain.culturaleventevalutaion.service.CulturalEventEvaluationService; -import project.backend.domain.culturalevnetcategory.entity.CategoryTitle; -import project.backend.domain.culturalevnetinfo.service.CulturalEventInfoService; -import project.backend.domain.ticketingsite.mapper.TicketingSiteMapper; - -import javax.validation.constraints.Positive; -import java.util.List; - -@Api(tags = "A. 문화생활 - 평가") -@RestController -@RequestMapping("/api/cultural-event-evaluations") -@RequiredArgsConstructor -public class CulturalEventEvaluationController { - - private final CulturalEventEvaluationService culturalEventEvaluationService; - private final CulturalEventEvaluationMapper culturalEventEvaluationMapper; - - @ApiOperation(value = "문화생활 평가 리스트 조회") - @GetMapping - public ResponseEntity getCulturalEventEvaluationList( - @RequestParam(defaultValue = "0") int page, - @RequestParam(defaultValue = "10") int size - ) { - List culturalEventEvaluationListDtoList = culturalEventEvaluationMapper - .culturalEventEvaluationToCulturalEventEvaluationListDtos(culturalEventEvaluationService.getCulturalEventEvaluations(page, size)); - return ResponseEntity.status(HttpStatus.OK).body(culturalEventEvaluationListDtoList); - } -} - - diff --git a/src/main/java/project/backend/domain/culturaleventevalutaion/dto/CulturalEventEvaluationListDto.java b/src/main/java/project/backend/domain/culturaleventevalutaion/dto/CulturalEventEvaluationListDto.java deleted file mode 100644 index 9d34ab6..0000000 --- a/src/main/java/project/backend/domain/culturaleventevalutaion/dto/CulturalEventEvaluationListDto.java +++ /dev/null @@ -1,22 +0,0 @@ -package project.backend.domain.culturaleventevalutaion.dto; - -import lombok.*; -import project.backend.domain.culturalevent.entity.CulturalEvent; -import project.backend.domain.culturaleventevalutaion.entity.EvaluationType; - -import java.time.LocalDateTime; -import java.util.Date; - -@Getter -@Setter -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class CulturalEventEvaluationListDto { - private String title; - private String content; - private Integer score; - private EvaluationType type; - private Long culturalEventId; - private String culturalEventTitle; -} diff --git a/src/main/java/project/backend/domain/culturaleventevalutaion/entity/CulturalEventEvaluation.java b/src/main/java/project/backend/domain/culturaleventevalutaion/entity/CulturalEventEvaluation.java deleted file mode 100644 index d9ae783..0000000 --- a/src/main/java/project/backend/domain/culturaleventevalutaion/entity/CulturalEventEvaluation.java +++ /dev/null @@ -1,54 +0,0 @@ -package project.backend.domain.culturaleventevalutaion.entity; - -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import project.backend.domain.common.entity.BaseEntity; -import project.backend.domain.culturalevent.entity.CulturalEvent; - -import javax.persistence.*; -import java.util.Optional; - -@Entity -@Getter -@RequiredArgsConstructor(access = AccessLevel.PROTECTED) -public class CulturalEventEvaluation extends BaseEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - public Long id; - - public String title; - - @Column(columnDefinition = "TEXT") - public String content; - - public Integer score; - - @Enumerated(value = EnumType.STRING) - public EvaluationType type; - - - @ManyToOne(fetch = FetchType.LAZY) - public CulturalEvent culturalEvent; - - @Builder - public CulturalEventEvaluation(String title, String content, Integer score, EvaluationType type, CulturalEvent culturalEvent) { - this.title = title; - this.content = content; - this.score = score; - this.type = type; - this.culturalEvent = culturalEvent; - } - - // == 연관관계 매핑 == // - public void setCulturalEvent(CulturalEvent culturalEvent) { - if (this.culturalEvent != null) { - if (this.culturalEvent.getCulturalEventEvaluationList().contains(this)) { - this.culturalEvent.getCulturalEventEvaluationList().remove(this); - } - } - this.culturalEvent = Optional.ofNullable(culturalEvent).orElse(this.culturalEvent); - this.culturalEvent.getCulturalEventEvaluationList().add(this); - } -} diff --git a/src/main/java/project/backend/domain/culturaleventevalutaion/entity/EvaluationType.java b/src/main/java/project/backend/domain/culturaleventevalutaion/entity/EvaluationType.java deleted file mode 100644 index 1fc88b3..0000000 --- a/src/main/java/project/backend/domain/culturaleventevalutaion/entity/EvaluationType.java +++ /dev/null @@ -1,15 +0,0 @@ -package project.backend.domain.culturaleventevalutaion.entity; - -import lombok.Getter; - -@Getter -public enum EvaluationType { - EXPECT("기대평"), - REVIEW("관람평"); - - private final String name; - - EvaluationType(String name) { - this.name = name; - } -} diff --git a/src/main/java/project/backend/domain/culturaleventevalutaion/mapper/CulturalEventEvaluationMapper.java b/src/main/java/project/backend/domain/culturaleventevalutaion/mapper/CulturalEventEvaluationMapper.java deleted file mode 100644 index 2924acb..0000000 --- a/src/main/java/project/backend/domain/culturaleventevalutaion/mapper/CulturalEventEvaluationMapper.java +++ /dev/null @@ -1,25 +0,0 @@ -package project.backend.domain.culturaleventevalutaion.mapper; - -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.ReportingPolicy; -import org.mapstruct.factory.Mappers; -import project.backend.domain.culturalevent.dto.CulturalEventCreateDto; -import project.backend.domain.culturalevent.dto.CulturalEventListDto; -import project.backend.domain.culturalevent.dto.CulturalEventRetrieveDto; -import project.backend.domain.culturalevent.entity.CulturalEvent; -import project.backend.domain.culturaleventevalutaion.dto.CulturalEventEvaluationListDto; -import project.backend.domain.culturaleventevalutaion.entity.CulturalEventEvaluation; - -import java.time.LocalDateTime; -import java.util.List; - -@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface CulturalEventEvaluationMapper { - - @Mapping(source = "culturalEvent.id", target = "culturalEventId") - @Mapping(source = "culturalEvent.title", target = "culturalEventTitle") - CulturalEventEvaluationListDto culturalEventEvaluationToCulturalEventEvaluationListDto(CulturalEventEvaluation CulturalEventEvaluation); - - List culturalEventEvaluationToCulturalEventEvaluationListDtos(List CulturalEventEvaluationList); -} diff --git a/src/main/java/project/backend/domain/culturaleventevalutaion/repository/CulturalEventEvaluationRepository.java b/src/main/java/project/backend/domain/culturaleventevalutaion/repository/CulturalEventEvaluationRepository.java deleted file mode 100644 index 41057d1..0000000 --- a/src/main/java/project/backend/domain/culturaleventevalutaion/repository/CulturalEventEvaluationRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package project.backend.domain.culturaleventevalutaion.repository; - -import org.springframework.data.jpa.repository.JpaRepository; -import project.backend.domain.culturaleventevalutaion.entity.CulturalEventEvaluation; - -public interface CulturalEventEvaluationRepository extends JpaRepository { -} diff --git a/src/main/java/project/backend/domain/culturaleventevalutaion/service/CulturalEventEvaluationService.java b/src/main/java/project/backend/domain/culturaleventevalutaion/service/CulturalEventEvaluationService.java deleted file mode 100644 index 16b9e84..0000000 --- a/src/main/java/project/backend/domain/culturaleventevalutaion/service/CulturalEventEvaluationService.java +++ /dev/null @@ -1,122 +0,0 @@ -package project.backend.domain.culturaleventevalutaion.service; - -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.RequiredArgsConstructor; -import org.json.JSONArray; -import org.json.JSONObject; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.client.RestTemplate; -import org.springframework.web.util.UriComponentsBuilder; -import project.backend.domain.culturalevent.entity.CulturalEvent; -import project.backend.domain.culturaleventevalutaion.entity.CulturalEventEvaluation; -import project.backend.domain.culturaleventevalutaion.entity.EvaluationType; -import project.backend.domain.culturaleventevalutaion.repository.CulturalEventEvaluationRepository; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -@Service -@RequiredArgsConstructor -@Transactional -public class CulturalEventEvaluationService { - private final CulturalEventEvaluationRepository culturalEventEvaluationRepository; - - - /** - * CulturalEventEvaluation 리스트 조회 - * @param page - * @param size - * @return - */ - public List getCulturalEventEvaluations(int page, int size) { - Pageable pageable = PageRequest.of(page, size); - return culturalEventEvaluationRepository.findAll(pageable).getContent(); - } - - /** - * goodsCode기준 CulturalEventEvaluation 저장 - * - * @param goodsCode - * @param culturalEvent - */ - public void createCulturalEventEvaluations(String goodsCode, CulturalEvent culturalEvent) { - RestTemplate restTemplate = new RestTemplate(); - ObjectMapper objectMapper = new ObjectMapper(); - List evaluations = new ArrayList<>(); - - String baseUrl = "https://api-ticketfront.interpark.com/v1/boards?best=false¬ice=false&page=1&pageSize=60&sort=DESC_WRITE_DATE"; - - // 관람평(62) - UriComponentsBuilder expectEvaluationUriBuilder = UriComponentsBuilder.fromHttpUrl(baseUrl) - .queryParam("boardNo", "62") - .queryParam("goodsCode", goodsCode); - - ResponseEntity expectEvaluationResponse = restTemplate.exchange( - expectEvaluationUriBuilder.toUriString(), - HttpMethod.GET, - null, - String.class); - - String jsonResponse = expectEvaluationResponse.getBody(); - try { - String data = objectMapper.readTree(jsonResponse).get("data").toString(); - JSONArray expectEvaluationJsonArray = new JSONArray(data); - - for (int i = 0; i < expectEvaluationJsonArray.length(); i++) { - JSONObject jsonObject = expectEvaluationJsonArray.getJSONObject(i); - CulturalEventEvaluation culturalEventEvaluation = CulturalEventEvaluation.builder() - .title(jsonObject.getString("title")) - .content(jsonObject.getString("content")) - .culturalEvent(culturalEvent) - .type(EvaluationType.EXPECT).build(); - - // 객체를 리스트에 추가 - evaluations.add(culturalEventEvaluation); - } - } catch (IOException e) { - e.printStackTrace(); - } - - - // 기대평 (boardNo : 10) - baseUrl = "https://api-ticketfront.interpark.com/v1/boards?best=false¬ice=false&page=1&pageSize=40&sort=DESC_WRITE_DATE"; - UriComponentsBuilder reviewEvaluationUriBuilder = UriComponentsBuilder.fromHttpUrl(baseUrl) - .queryParam("boardNo", "10") - .queryParam("goodsCode", goodsCode); - - ResponseEntity reviewEvaluationResponse = restTemplate.exchange( - reviewEvaluationUriBuilder.toUriString(), - HttpMethod.GET, - null, - String.class); - - String reviewJsonResponse = reviewEvaluationResponse.getBody(); - - try { - String data = objectMapper.readTree(reviewJsonResponse).get("data").toString(); - JSONArray jsonArray = new JSONArray(data); - - for (int i = 0; i < jsonArray.length(); i++) { - JSONObject jsonObject = jsonArray.getJSONObject(i); - CulturalEventEvaluation culturalEventEvaluation = CulturalEventEvaluation.builder() - .title(jsonObject.getString("title")) - .content(jsonObject.getString("content")) - .score(jsonObject.getInt("boomupCount")) - .culturalEvent(culturalEvent) - .type(EvaluationType.REVIEW).build(); - - evaluations.add(culturalEventEvaluation); - } - } catch (IOException e) { - e.printStackTrace(); - } - - List culturalEventEvaluationList = culturalEventEvaluationRepository.saveAll(evaluations); - } -} diff --git a/src/main/java/project/backend/domain/culturalevnetcategory/controller/CulturalEventCategoryController.java b/src/main/java/project/backend/domain/culturalevnetcategory/controller/CulturalEventCategoryController.java index 805826b..e3268bb 100644 --- a/src/main/java/project/backend/domain/culturalevnetcategory/controller/CulturalEventCategoryController.java +++ b/src/main/java/project/backend/domain/culturalevnetcategory/controller/CulturalEventCategoryController.java @@ -13,7 +13,7 @@ import java.util.List; -@Api(tags = "A. 문화생활 - 카테고리") +@Api(tags = "CulturalEvent - 문화생활 카테고리") @RestController @RequestMapping("/api/categories/cultural-events") @RequiredArgsConstructor diff --git a/src/main/java/project/backend/domain/jwt/filter/JwtFilter.java b/src/main/java/project/backend/domain/jwt/filter/JwtFilter.java index 6efb831..cbe1d8a 100644 --- a/src/main/java/project/backend/domain/jwt/filter/JwtFilter.java +++ b/src/main/java/project/backend/domain/jwt/filter/JwtFilter.java @@ -41,8 +41,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse } if (path.startsWith("/api/auth/login") || path.startsWith("/swagger-ui/") || path.startsWith("/backoffice") - || path.startsWith("/favicon.ico") || path.startsWith("/v3/api-docs") || path.startsWith("/api/tickets") - || path.startsWith("/api/tickets/**") || path.startsWith("/api/categorys")) { + || path.startsWith("/favicon.ico") || path.startsWith("/v3/api-docs") || path.startsWith("/api/categorys")) { filterChain.doFilter(request, response); return; } diff --git a/src/main/java/project/backend/domain/media/controller/MediaController.java b/src/main/java/project/backend/domain/media/controller/MediaController.java index 666ebc2..1275ee5 100644 --- a/src/main/java/project/backend/domain/media/controller/MediaController.java +++ b/src/main/java/project/backend/domain/media/controller/MediaController.java @@ -12,7 +12,7 @@ import project.backend.domain.media.mapper.MediaMapper; import project.backend.domain.media.service.MediaService; -@Api(tags = "C. 미디어") +@Api(tags = "Media - 미디어") @RestController @RequestMapping("/api/media") @RequiredArgsConstructor @@ -27,6 +27,6 @@ public ResponseEntity createMedia( @RequestPart(value = "file", required = true) MultipartFile file ) { Media media = mediaService.createMedia(file); - return ResponseEntity.status(HttpStatus.CREATED).body(mediaMapper.mediaToMediaDto(media)); + return ResponseEntity.status(HttpStatus.CREATED).body(mediaMapper.mediaToMediaCreateDto(media)); } } diff --git a/src/main/java/project/backend/domain/media/controller/MediasController.java b/src/main/java/project/backend/domain/media/controller/MediasController.java index fa3d4f8..4874ccf 100644 --- a/src/main/java/project/backend/domain/media/controller/MediasController.java +++ b/src/main/java/project/backend/domain/media/controller/MediasController.java @@ -11,7 +11,7 @@ import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; -import project.backend.domain.media.dto.MediaDto; +import project.backend.domain.media.dto.MediaCreateDto; import project.backend.domain.media.entity.Media; import project.backend.domain.media.mapper.MediaMapper; import project.backend.domain.media.service.MediaService; @@ -19,7 +19,7 @@ import java.util.List; import java.util.stream.Collectors; -@Api(tags = "C. 미디어") +@Api(tags = "Media - 미디어") @RestController @RequestMapping("/api/medias") @RequiredArgsConstructor @@ -36,8 +36,8 @@ public ResponseEntity createMedias( List medias = files.stream() .map(mediaService::createMedia) .collect(Collectors.toList()); - List mediaDtos = medias.stream() - .map(mediaMapper::mediaToMediaDto) + List mediaDtos = medias.stream() + .map(mediaMapper::mediaToMediaCreateDto) .collect(Collectors.toList()); return ResponseEntity.status(HttpStatus.CREATED).body(mediaDtos); } diff --git a/src/main/java/project/backend/domain/media/dto/MediaCreateDto.java b/src/main/java/project/backend/domain/media/dto/MediaCreateDto.java new file mode 100644 index 0000000..5d6aa37 --- /dev/null +++ b/src/main/java/project/backend/domain/media/dto/MediaCreateDto.java @@ -0,0 +1,12 @@ +package project.backend.domain.media.dto; + +import lombok.*; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MediaCreateDto { + private String mediaUrl; +} \ No newline at end of file diff --git a/src/main/java/project/backend/domain/media/dto/MediaDto.java b/src/main/java/project/backend/domain/media/dto/MediaDto.java index fbd2b28..e3f4c9d 100644 --- a/src/main/java/project/backend/domain/media/dto/MediaDto.java +++ b/src/main/java/project/backend/domain/media/dto/MediaDto.java @@ -8,5 +8,7 @@ @NoArgsConstructor @AllArgsConstructor public class MediaDto { - private String media_url; + private String mediaUrl; + private Integer ordering; + private Boolean isThumbnail; } \ No newline at end of file diff --git a/src/main/java/project/backend/domain/media/entity/Media.java b/src/main/java/project/backend/domain/media/entity/Media.java index dbe4d60..1c3ebcd 100644 --- a/src/main/java/project/backend/domain/media/entity/Media.java +++ b/src/main/java/project/backend/domain/media/entity/Media.java @@ -1,28 +1,43 @@ package project.backend.domain.media.entity; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Getter; -import lombok.RequiredArgsConstructor; +import lombok.*; import project.backend.domain.common.entity.BaseEntity; +import project.backend.domain.place.entity.Place; +import project.backend.domain.ticket.entity.Ticket; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; +import javax.persistence.*; +import java.util.Optional; @Entity @Getter +@Setter @RequiredArgsConstructor(access = AccessLevel.PROTECTED) public class Media extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) public Long id; - public String media_url; + public String mediaUrl; + + public Integer ordering; + + public Boolean isThumbnail; + + @ManyToOne(fetch = FetchType.LAZY) + public Ticket ticket; @Builder - public Media(String media_url){ - this.media_url = media_url; + public Media(String mediaUrl) { + this.mediaUrl = mediaUrl; + } + + public void setTicket(Ticket ticket) { + if (this.ticket != null) { + if (this.ticket.getMedias().contains(this)) { + this.ticket.getMedias().remove(this); + } + } + this.ticket = Optional.ofNullable(ticket).orElse(this.ticket); + this.ticket.getMedias().add(this); } } diff --git a/src/main/java/project/backend/domain/media/mapper/MediaMapper.java b/src/main/java/project/backend/domain/media/mapper/MediaMapper.java index ebaa096..06ac333 100644 --- a/src/main/java/project/backend/domain/media/mapper/MediaMapper.java +++ b/src/main/java/project/backend/domain/media/mapper/MediaMapper.java @@ -2,10 +2,10 @@ import org.mapstruct.Mapper; import org.mapstruct.ReportingPolicy; -import project.backend.domain.media.dto.MediaDto; +import project.backend.domain.media.dto.MediaCreateDto; import project.backend.domain.media.entity.Media; @Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE) public interface MediaMapper { - MediaDto mediaToMediaDto(Media media); + MediaCreateDto mediaToMediaCreateDto(Media media); } diff --git a/src/main/java/project/backend/domain/media/repository/MediaRepository.java b/src/main/java/project/backend/domain/media/repository/MediaRepository.java index c42cc05..a5aef16 100644 --- a/src/main/java/project/backend/domain/media/repository/MediaRepository.java +++ b/src/main/java/project/backend/domain/media/repository/MediaRepository.java @@ -3,5 +3,8 @@ import org.springframework.data.jpa.repository.JpaRepository; import project.backend.domain.media.entity.Media; +import java.util.Optional; + public interface MediaRepository extends JpaRepository { + Optional findFirstByMediaUrl(String mediaUrl); } diff --git a/src/main/java/project/backend/domain/media/service/MediaService.java b/src/main/java/project/backend/domain/media/service/MediaService.java index 76a16ee..bcd9adc 100644 --- a/src/main/java/project/backend/domain/media/service/MediaService.java +++ b/src/main/java/project/backend/domain/media/service/MediaService.java @@ -4,6 +4,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; +import project.backend.domain.media.dto.MediaDto; import project.backend.domain.media.entity.Media; import project.backend.domain.media.mapper.MediaMapper; import project.backend.domain.media.repository.MediaRepository; @@ -12,6 +13,7 @@ import project.backend.global.s3.service.ImageService; import java.util.List; +import java.util.Optional; @Service @RequiredArgsConstructor @@ -22,9 +24,22 @@ public class MediaService { private final ImageService imageService; public Media createMedia(MultipartFile file) { - String media_url = imageService.updateImage(file, "Media", "media_url"); - Media media = Media.builder().media_url(media_url).build(); + String mediaUrl = imageService.updateImage(file, "Media", "mediaUrl"); + Media media = Media.builder().mediaUrl(mediaUrl).build(); mediaRepository.save(media); return media; } + + public Media setOrderThumbnail(MediaDto mediaDto) { + Media media; + Optional optionalMedia = mediaRepository.findFirstByMediaUrl(mediaDto.getMediaUrl()); + if (optionalMedia.isPresent()) { + media = optionalMedia.get(); + } else { + media = Media.builder().mediaUrl(mediaDto.getMediaUrl()).build(); + } + media.setOrdering(mediaDto.getOrdering()); + media.setIsThumbnail(mediaDto.getIsThumbnail()); + return mediaRepository.save(media); + } } diff --git a/src/main/java/project/backend/domain/member/controller/MemberController.java b/src/main/java/project/backend/domain/member/controller/MemberController.java index f7e0069..5050b3a 100644 --- a/src/main/java/project/backend/domain/member/controller/MemberController.java +++ b/src/main/java/project/backend/domain/member/controller/MemberController.java @@ -20,7 +20,7 @@ @RestController @RequestMapping("/api/members") @RequiredArgsConstructor -@Api(tags = "B. 멤버") +@Api(tags = "Member - 멤버") public class MemberController { private final MemberService memberService; diff --git a/src/main/java/project/backend/domain/member/dto/MemberInfoDto.java b/src/main/java/project/backend/domain/member/dto/MemberInfoDto.java index 81c5b48..55f756c 100644 --- a/src/main/java/project/backend/domain/member/dto/MemberInfoDto.java +++ b/src/main/java/project/backend/domain/member/dto/MemberInfoDto.java @@ -37,7 +37,7 @@ public class MemberInfoDto { public Boolean isMarketingAgree; @Schema(description = "프로필 이미지 url", - example = "https://ticats.s3.ap-northeast-2.amazonaws.com/Media/media_url/25910d53-9887-49c8-8e47-c183597c0cd3.jpeg", required = false) + example = "https://ticats.s3.ap-northeast-2.amazonaws.com/Media/mediaUrl/25910d53-9887-49c8-8e47-c183597c0cd3.jpeg", required = false) @URL(message = "유효하지 않은 url 입니다.") public String profileImageUrl; } \ No newline at end of file diff --git a/src/main/java/project/backend/domain/member/entity/Member.java b/src/main/java/project/backend/domain/member/entity/Member.java index 7e0ed9c..01370d6 100644 --- a/src/main/java/project/backend/domain/member/entity/Member.java +++ b/src/main/java/project/backend/domain/member/entity/Member.java @@ -7,8 +7,6 @@ import project.backend.domain.keyword.entity.CulturalEventSearchKeyword; import project.backend.domain.like.entity.CulturalEventLike; import project.backend.domain.member.dto.MemberInfoDto; -import project.backend.domain.member.repository.MemberRepository; -import project.backend.domain.memberTicketLike.entity.MemberTicketLike; import project.backend.domain.common.entity.BaseEntity; import project.backend.domain.onboardingmembercategory.entity.OnboardingMemberCategory; import project.backend.domain.ticket.entity.Ticket; @@ -57,10 +55,7 @@ public class Member extends BaseEntity { public Boolean isMarketingAgree = false; @OneToMany(mappedBy = "member", cascade = {CascadeType.PERSIST, CascadeType.REMOVE}) - private List tickets = new ArrayList<>(); - - @OneToMany(mappedBy = "member", cascade = {CascadeType.PERSIST, CascadeType.REMOVE}) - public List memberTicketLikes = new ArrayList<>(); + public List tickets = new ArrayList<>(); @OneToMany(mappedBy = "member", cascade = {CascadeType.PERSIST, CascadeType.REMOVE}) public List onboardingMemberCategories = new ArrayList<>(); diff --git a/src/main/java/project/backend/domain/memberTicketLike/controller/MemberTicketLikeController.java b/src/main/java/project/backend/domain/memberTicketLike/controller/MemberTicketLikeController.java deleted file mode 100644 index 5a3a3d5..0000000 --- a/src/main/java/project/backend/domain/memberTicketLike/controller/MemberTicketLikeController.java +++ /dev/null @@ -1,94 +0,0 @@ -package project.backend.domain.memberTicketLike.controller; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.RequiredArgsConstructor; - -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.util.ObjectUtils; -import org.springframework.web.bind.annotation.*; -import project.backend.domain.memberTicketLike.dto.MemberTicketLikePostRequestDto; -import project.backend.domain.memberTicketLike.dto.MemberTicketLikeResponseDto; -import project.backend.domain.memberTicketLike.mapper.MemberTicketLikeMapper; -import project.backend.domain.memberTicketLike.service.MemberTicketLikeService; -import project.backend.domain.memberTicketLike.entity.MemberTicketLike; -import project.backend.domain.ticket.dto.TicketResponseDto; -import project.backend.domain.ticket.entity.Ticket; -import project.backend.domain.ticket.mapper.TicketMapper; -import project.backend.global.error.exception.BusinessException; -import project.backend.global.error.exception.ErrorCode; - -import javax.validation.constraints.Positive; -import java.util.List; - -@Api(tags = "찜하기 API") -@RestController -@RequestMapping("/api/likes") -@RequiredArgsConstructor -public class MemberTicketLikeController { - - private final MemberTicketLikeService memberTicketLikeService; - private final MemberTicketLikeMapper memberTicketLikeMapper; - private final TicketMapper ticketMapper; - - - @ApiOperation( - value = "찜하기/찜 취소하기", - notes = " - 찜이 되어있으면 -> 찜을 취소한다.\n" + - " - 찜이 되어있지 않으면 -> 찜을 한다.\n" + - " - 찜 상태 : true\n" + - " - 찜 안하기 상태 : false") - @PostMapping("/{ticketId}") - public ResponseEntity postMemberTicketLike( - @Positive @PathVariable(required = false) Long ticketId, - @RequestHeader(value = "Authorization", required = false) String accessToken) { - if (ObjectUtils.isEmpty(ticketId) || ObjectUtils.isEmpty(accessToken)){ - throw new BusinessException(ErrorCode.MISSING_REQUEST); - } - MemberTicketLikeResponseDto memberTicketLikeResponseDto = MemberTicketLikeResponseDto.builder().status(memberTicketLikeService.changeMemberTicketLike(ticketId, accessToken)).build(); - return ResponseEntity.status(HttpStatus.CREATED).body(memberTicketLikeResponseDto); - } - - @ApiOperation( - value = "찜 상태 확인하기", - notes = " - 찜 상태 : true\n" + - " - 찜 안하기 상태 : false") - @GetMapping("/{ticketId}") - public ResponseEntity getMemberTicketLike( - @Positive @PathVariable(required = false) Long ticketId, - @RequestHeader(value = "Authorization", required = false) String accessToken) { - if (ObjectUtils.isEmpty(ticketId) || ObjectUtils.isEmpty(accessToken)){ - throw new BusinessException(ErrorCode.MISSING_REQUEST); - } - MemberTicketLikeResponseDto memberTicketLikeResponseDto = MemberTicketLikeResponseDto.builder().status(memberTicketLikeService.getMemberTicketLike(ticketId, accessToken)).build(); - return ResponseEntity.status(HttpStatus.OK).body(memberTicketLikeResponseDto); - } - - @ApiOperation( - value = "나의 찜 목록 확인하기", - notes = "나의 찜 목록 확인하기") - @GetMapping - public ResponseEntity getMemberTicketLikeList( - @RequestHeader(value = "Authorization", required = false) String accessToken) { - if (ObjectUtils.isEmpty(accessToken)){ - throw new BusinessException(ErrorCode.MISSING_REQUEST); - } - List ticketList = memberTicketLikeService.getMemberTicketLikeList(accessToken); - List ticketResponseDtoList = ticketMapper.ticketsToTicketResponseDtos(ticketList); - - // 좋아요 여부 추가 - ticketResponseDtoList.forEach(t -> t.setIsLike(memberTicketLikeService.getMemberTicketLike(t.getId(), accessToken))); - - return ResponseEntity.status(HttpStatus.OK).body(ticketResponseDtoList); - } - - @DeleteMapping("/{memberTicketLikeId}") - public ResponseEntity deleteMemberTicketLike(@PathVariable(required = false) Long memberTicketLikeId) { - if (ObjectUtils.isEmpty(memberTicketLikeId)){ - throw new BusinessException(ErrorCode.MISSING_REQUEST); - } - memberTicketLikeService.deleteMemberTicketLike(memberTicketLikeId); - return ResponseEntity.status(HttpStatus.NO_CONTENT).body(null); - } -} diff --git a/src/main/java/project/backend/domain/memberTicketLike/dto/MemberTicketLikePostRequestDto.java b/src/main/java/project/backend/domain/memberTicketLike/dto/MemberTicketLikePostRequestDto.java deleted file mode 100644 index db40efe..0000000 --- a/src/main/java/project/backend/domain/memberTicketLike/dto/MemberTicketLikePostRequestDto.java +++ /dev/null @@ -1,21 +0,0 @@ -package project.backend.domain.memberTicketLike.dto; - -import lombok.*; -import project.backend.domain.member.dto.MemberResponseDto; -import project.backend.domain.member.entity.Member; -import project.backend.domain.ticket.dto.TicketResponseDto; -import project.backend.domain.ticket.entity.Ticket; - -import javax.persistence.FetchType; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; - -@Getter -@Setter -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class MemberTicketLikePostRequestDto { - public Long memberId; - public Long ticketId; -} \ No newline at end of file diff --git a/src/main/java/project/backend/domain/memberTicketLike/dto/MemberTicketLikeResponseDto.java b/src/main/java/project/backend/domain/memberTicketLike/dto/MemberTicketLikeResponseDto.java deleted file mode 100644 index 6061134..0000000 --- a/src/main/java/project/backend/domain/memberTicketLike/dto/MemberTicketLikeResponseDto.java +++ /dev/null @@ -1,15 +0,0 @@ -package project.backend.domain.memberTicketLike.dto; -import lombok.*; -import project.backend.domain.member.dto.MemberResponseDto; -import project.backend.domain.ticket.dto.TicketResponseDto; - -import java.time.LocalDateTime; - -@Getter -@Setter -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class MemberTicketLikeResponseDto { - public Boolean status; -} \ No newline at end of file diff --git a/src/main/java/project/backend/domain/memberTicketLike/entity/MemberTicketLike.java b/src/main/java/project/backend/domain/memberTicketLike/entity/MemberTicketLike.java deleted file mode 100644 index 20a80fc..0000000 --- a/src/main/java/project/backend/domain/memberTicketLike/entity/MemberTicketLike.java +++ /dev/null @@ -1,52 +0,0 @@ -package project.backend.domain.memberTicketLike.entity; - -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import project.backend.domain.ticket.entity.Ticket; -import project.backend.domain.member.entity.Member; - -import javax.persistence.*; -import java.util.Optional; - -@Entity -@Getter -@RequiredArgsConstructor(access = AccessLevel.PROTECTED) -public class MemberTicketLike { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - public Long id; - - @ManyToOne(fetch = FetchType.LAZY) - public Member member; - - @ManyToOne(fetch = FetchType.LAZY) - public Ticket ticket; - - // == 생성자 == // - @Builder - public MemberTicketLike(Member member, Ticket ticket) { - this.member = member; - this.ticket = ticket; - } - - // == 연관관계 매핑 == // - public void setMemberTicket(Member member, Ticket ticket) { - if (this.member != null) { - if (this.member.getMemberTicketLikes().contains(this)) { - this.member.getMemberTicketLikes().remove(this); - } - } - if (this.ticket != null) { - if (this.ticket.getMemberTicketLikes().contains(this)) { - this.ticket.getMemberTicketLikes().remove(this); - } - } - this.member = Optional.ofNullable(member).orElse(this.member); - this.member.getMemberTicketLikes().add(this); - this.ticket = Optional.ofNullable(ticket).orElse(this.ticket); - this.ticket.getMemberTicketLikes().add(this); - } -} diff --git a/src/main/java/project/backend/domain/memberTicketLike/mapper/MemberTicketLikeMapper.java b/src/main/java/project/backend/domain/memberTicketLike/mapper/MemberTicketLikeMapper.java deleted file mode 100644 index 087a06a..0000000 --- a/src/main/java/project/backend/domain/memberTicketLike/mapper/MemberTicketLikeMapper.java +++ /dev/null @@ -1,12 +0,0 @@ -package project.backend.domain.memberTicketLike.mapper; - -import org.mapstruct.Mapper; -import org.mapstruct.ReportingPolicy; -import project.backend.domain.memberTicketLike.dto.MemberTicketLikeResponseDto; -import project.backend.domain.memberTicketLike.entity.MemberTicketLike; - - -@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface MemberTicketLikeMapper { - MemberTicketLikeResponseDto memberTicketLikeToMemberTicketLikeResponseDto(MemberTicketLike memberTicketLike); -} diff --git a/src/main/java/project/backend/domain/memberTicketLike/repository/MemberTicketLikeRepository.java b/src/main/java/project/backend/domain/memberTicketLike/repository/MemberTicketLikeRepository.java deleted file mode 100644 index 6605024..0000000 --- a/src/main/java/project/backend/domain/memberTicketLike/repository/MemberTicketLikeRepository.java +++ /dev/null @@ -1,14 +0,0 @@ -package project.backend.domain.memberTicketLike.repository; - -import org.springframework.data.jpa.repository.JpaRepository; -import project.backend.domain.member.entity.Member; -import project.backend.domain.memberTicketLike.entity.MemberTicketLike; -import project.backend.domain.ticket.entity.Ticket; - -import java.util.List; -import java.util.Optional; - -public interface MemberTicketLikeRepository extends JpaRepository { - - List findByMemberAndTicket(Member member, Ticket ticket); -} diff --git a/src/main/java/project/backend/domain/memberTicketLike/service/MemberTicketLikeService.java b/src/main/java/project/backend/domain/memberTicketLike/service/MemberTicketLikeService.java deleted file mode 100644 index 961a26c..0000000 --- a/src/main/java/project/backend/domain/memberTicketLike/service/MemberTicketLikeService.java +++ /dev/null @@ -1,86 +0,0 @@ -package project.backend.domain.memberTicketLike.service; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import project.backend.domain.jwt.service.JwtService; -import project.backend.domain.member.entity.Member; -import project.backend.domain.memberTicketLike.entity.MemberTicketLike; -import project.backend.domain.memberTicketLike.repository.MemberTicketLikeRepository; -import project.backend.domain.ticket.entity.Ticket; -import project.backend.domain.ticket.service.TicketService; -import project.backend.global.error.exception.BusinessException; -import project.backend.global.error.exception.ErrorCode; - -import java.util.ArrayList; -import java.util.List; - -@Service -@RequiredArgsConstructor -@Transactional -public class MemberTicketLikeService { - private final MemberTicketLikeRepository memberTicketLikeRepository; - private final TicketService ticketService; - private final JwtService jwtService; - - public Boolean changeMemberTicketLike(Long ticketId, String accessToken){ - - // member와 ticket조회 - Member member = jwtService.getMemberFromAccessToken(accessToken); - Ticket ticket = ticketService.verifiedTicket(ticketId); - List memberTicketLikeList = memberTicketLikeRepository.findByMemberAndTicket(member, ticket); - - // 찜하기 삭제 - if (memberTicketLikeList.size() > 0) { - memberTicketLikeRepository.deleteAll(memberTicketLikeList); - return false; - } - - // 찜하기 생성 - else { - MemberTicketLike memberTicketLike = MemberTicketLike.builder() - .member(member) - .ticket(ticket).build(); - memberTicketLike.setMemberTicket(member, ticket); - memberTicketLikeRepository.save(memberTicketLike); - return true; - } - } - - public Boolean getMemberTicketLike(Long ticketId, String accessToken){ - - // member와 ticket조회 - Member member = jwtService.getMemberFromAccessToken(accessToken); - Ticket ticket = ticketService.verifiedTicket(ticketId); - List memberTicketLikeList = memberTicketLikeRepository.findByMemberAndTicket(member, ticket); - - // 찜하기 상태 - if (memberTicketLikeList.size() > 0) { - return true; - } - - // 찜 안하기 상태 - else { - return false; - } - } - - public List getMemberTicketLikeList(String accessToken) { - List memberTicketLikeList = jwtService.getMemberFromAccessToken(accessToken).getMemberTicketLikes(); - List ticketList = new ArrayList<>(); - for (MemberTicketLike memberTicketLike : memberTicketLikeList) { - ticketList.add(memberTicketLike.ticket); - } - return ticketList; - } - - - public void deleteMemberTicketLike(Long id) { - memberTicketLikeRepository.delete(verifiedMemberTicketLike(id)); - } - - private MemberTicketLike verifiedMemberTicketLike(Long id) { - return memberTicketLikeRepository.findById(id).orElseThrow(() -> new BusinessException(ErrorCode.NOTICE_NOT_FOUND)); - } - -} diff --git a/src/main/java/project/backend/domain/notice/controller/FcmController2.java b/src/main/java/project/backend/domain/notice/controller/FcmController2.java deleted file mode 100644 index 0aedebf..0000000 --- a/src/main/java/project/backend/domain/notice/controller/FcmController2.java +++ /dev/null @@ -1,15 +0,0 @@ -package project.backend.domain.notice.controller; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; - -@Controller -@RequiredArgsConstructor -public class FcmController2 { - - @GetMapping("/fcm-test") - public String fcm_test() { - return "index"; - } -} \ No newline at end of file diff --git a/src/main/java/project/backend/domain/place/entity/Place.java b/src/main/java/project/backend/domain/place/entity/Place.java index 2827ce4..4266291 100644 --- a/src/main/java/project/backend/domain/place/entity/Place.java +++ b/src/main/java/project/backend/domain/place/entity/Place.java @@ -6,6 +6,7 @@ import lombok.RequiredArgsConstructor; import project.backend.domain.common.entity.BaseEntity; import project.backend.domain.culturalevent.entity.CulturalEvent; +import project.backend.domain.ticket.entity.Ticket; import javax.persistence.*; import java.util.ArrayList; @@ -30,6 +31,9 @@ public class Place extends BaseEntity { @OneToMany(mappedBy = "place", cascade = {CascadeType.PERSIST, CascadeType.REMOVE}) public List culturalEvents = new ArrayList<>(); + @OneToMany(mappedBy = "place", cascade = {CascadeType.PERSIST, CascadeType.REMOVE}) + public List tickets = new ArrayList<>(); + @Builder public Place(String name, String address, Double latitude, Double longitude) { this.name = name; diff --git a/src/main/java/project/backend/domain/ticket/controller/TicketController.java b/src/main/java/project/backend/domain/ticket/controller/TicketController.java index db2c4cd..c982f40 100644 --- a/src/main/java/project/backend/domain/ticket/controller/TicketController.java +++ b/src/main/java/project/backend/domain/ticket/controller/TicketController.java @@ -5,312 +5,41 @@ import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.util.ObjectUtils; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; -import project.backend.domain.jwt.service.JwtService; +import project.backend.domain.culturalevent.entity.CulturalEvent; import project.backend.domain.member.entity.Member; -import project.backend.domain.memberTicketLike.service.MemberTicketLikeService; -import project.backend.domain.ticket.dto.TicketPatchRequestDto; -import project.backend.domain.ticket.dto.TicketPostRequestDto; -import project.backend.domain.ticket.dto.TicketStatusPostRequestDto; +import project.backend.domain.ticket.dto.TicketCreateDto; import project.backend.domain.ticket.entity.Ticket; import project.backend.domain.ticket.mapper.TicketMapper; import project.backend.domain.ticket.service.TicketService; -import project.backend.domain.ticket.dto.TicketResponseDto; -import project.backend.global.error.exception.BusinessException; -import project.backend.global.error.exception.ErrorCode; -import project.backend.global.s3.service.ImageService; import javax.validation.Valid; import javax.validation.constraints.Positive; -import java.util.List; -import java.util.stream.Collectors; - -import static project.backend.global.validator.LocalDateTimeValidation.convertStringToLocalDateTime; @RestController @RequestMapping("/api/tickets") @RequiredArgsConstructor -@Api(tags = "티켓 API") +@Api(tags = "Ticket - 티켓") public class TicketController { private final TicketService ticketService; private final TicketMapper ticketMapper; - private final ImageService imageService; - private final JwtService jwtService; - private final MemberTicketLikeService memberTicketLikeService; - - - @ApiOperation( - value = "티켓 생성하기", - notes = " - Header['Authorization'] : AccessToken값 입력\n" + - " - image : MultipartFile 입력(사용자가 추가한 이미지)\n" + - " - request : {\n" + - " \"title\" : \"레미제라블\",\n" + - " \"ticketDate\" : \"2023-11-04T16:26:39.098\",\n" + - " \"rating\" : 1,\n" + - " \"memo\" : \"재미없는 공연이였다.(100자 이내 입력)\",\n" + - " \"seat\" : \"E292\",\n" + - " \"location\" : \"서울시 서울스퀘어\",\n" + - " \"price\" : 15000,\n" + - " \"friend\" : \"김가영\",\n" + - " \"color\" : \"#102920\"\n" + - " \"isPrivate\" : \"PUBLIC\",\n" + - " \"categoryName\" : \"기타\"\n" + - " \"ticketType\" : \"A\"\n" + - " \"layoutType\" : \"B\"\n" + - "}\n" + - "1. ticketDate는 다음과 같은 형식으로 추가해주세요\n" + - "2. isPrivate는 PUBLIC, PRIVATE으로만 추가 가능합니다.\n" + - "3. rating은 별점으로, 0 ~ 5까지 소수점으로 입력할 수 있습니다.(n.5 권장)\n" + - "4. request는 application/json 형식입니다.\n" + - "5. 필수 : 제목, 날짜, 메모, 별점, 이미지, 카테고리, 레이아웃 타입") - @RequestMapping(method = RequestMethod.POST, consumes = "multipart/form-data") - public ResponseEntity postTicket( - @RequestHeader(value = "Authorization", required = false) String accessToken, - @RequestPart(value = "image", required = false) MultipartFile image, - @Valid @RequestPart(required = false) TicketPostRequestDto request) { - - if (ObjectUtils.isEmpty(accessToken) || ObjectUtils.isEmpty(request) || (ObjectUtils.isEmpty(image) && ObjectUtils.isEmpty(request.getImageUrl()))){ - throw new BusinessException(ErrorCode.MISSING_REQUEST); - } - - // TicketDate 형식 검사 (ex - 2023-11-01T00:00:00) - request.setTicketLocalDateTime(convertStringToLocalDateTime(request.getTicketDate())); - - if (!ObjectUtils.isEmpty(image)) { - request.setImageUrl(imageService.updateImage(image, "Ticket", "imageUrl")); - } - - // 작성자 등록 - request.setMember(jwtService.getMemberFromAccessToken(accessToken)); - - // Ticket 생성 - Ticket ticket = ticketService.createTicket(request); - return ResponseEntity.status(HttpStatus.CREATED).body(ticketMapper.ticketToTicketResponseDto(ticket)); - } - - @ApiOperation( - value = "티켓 조회하기 - 내 티켓 혹은 전체 공개 티켓만 조회 가능", - notes = " - ticketId는 필수\n" + - " - Authorization Header는 선택") - @GetMapping("/{ticketId}") - public ResponseEntity getTicket( - @Positive @PathVariable(required = false) Long ticketId, - @RequestHeader(value = "Authorization", required = false) String accessToken) { - - if (ObjectUtils.isEmpty(ticketId)){ - throw new BusinessException(ErrorCode.MISSING_REQUEST); - } - - Ticket ticket = ticketService.getTicket(ticketId, accessToken); - TicketResponseDto ticketResponseDto = ticketMapper.ticketToTicketResponseDto(ticket); - return ResponseEntity.status(HttpStatus.OK).body(ticketResponseDto); - } - - /** - * 회원 인증 받지 않아도 조회 가능한 api - * - * @return - */ - @ApiOperation( - value = "둘러보기 티켓 조회 - 전체 공개만 ", - notes = " - ?categorys=영화,뮤지컬\n" + - " - &period=week **[week, month, 6month, day로 조회 가능]**\n" + - " - &start=2023-11-03\n" + - " - &end=2023-11-05\n" + - " - &search=레미제라블\n" + - "- Header['Authorization'] : 토큰 값\n" + - "1. Authorization과 categorys를 입력할 경우, 유저의 온보딩 카테고리보다 categorys로 입력한 카테고리가 필터의 우선순위를 가집니다.\n" + - "2. start, end가 period보다 우선순위를 가집니다.\n" + - "3. start, end 두 값을 동시에 적지 않으면 filter 기능이 동작하지 않습니다.(에러는 발생하지 않습니다.)\n" + - "4. 전체 파라미터와 헤더는 필수 값이 아닙니다.") - @GetMapping("/total") - public ResponseEntity getTotalTicketList( - @RequestParam(value = "categorys", required = false) List categorys, - @RequestParam(value = "period", required = false) String period, // 일주일(week), 한달(month), 6개월(6month), 하루(day) - @RequestParam(value = "start", required = false) String start, - @RequestParam(value = "end", required = false) String end, - @RequestParam(value = "search", required = false) String search, - @RequestHeader(value = "Authorization", required = false) String accessToken - ) { - - if (categorys == null && accessToken != null) { - categorys = jwtService.getMemberFromAccessToken(accessToken).getOnboardingMemberCategories().stream().map(c -> c.getCategory().getName()).collect(Collectors.toList()); - } - - List ticketList = ticketService.getTotalTicketList(categorys, period, start, end, search == null ? "" : search); - List ticketResponseDtoList = ticketMapper.ticketsToTicketResponseDtos(ticketList); - - // 좋아요 여부 추가 - if (accessToken != null) { - for (TicketResponseDto ticketResponseDto : ticketResponseDtoList) { - ticketResponseDtoList.forEach(t -> t.setIsLike(memberTicketLikeService.getMemberTicketLike(t.getId(), accessToken))); - } - } else { - ticketResponseDtoList.forEach(t -> t.setIsLike(false)); - } - return ResponseEntity.status(HttpStatus.OK).body(ticketResponseDtoList); - } - - @ApiOperation( - value = "둘러보기 티켓 조회 - 전체 티켓(전체 공개) & 내 티켓(전체 공개, 비공개)만 ", - notes = " - ?categorys=영화,뮤지컬\n" + - " - &period=week **[week, month, 6month, day로 조회 가능]**\n" + - " - &start=2023-11-03\n" + - " - &end=2023-11-05\n" + - " - &search=레미제라블\n" + - "- Header['Authorization'] : 토큰 값\n" + - "1. Authorization과 categorys를 입력할 경우, 유저의 온보딩 카테고리보다 categorys로 입력한 카테고리가 필터의 우선순위를 가집니다.\n" + - "2. start, end가 period보다 우선순위를 가집니다.\n" + - "3. start, end 두 값을 동시에 적지 않으면 filter 기능이 동작하지 않습니다.(에러는 발생하지 않습니다.)\n" + - "4. Authorization은 필수 값이고, 나머지는 모두 필수 파라미터가 아닙니다.") - @GetMapping("/my-total") - public ResponseEntity getTotalAndMyTicketList( - @RequestParam(value = "categorys", required = false) List categorys, - @RequestParam(value = "period", required = false) String period, // 일주일(week), 한달(month), 6개월(6month), 하루(day) - @RequestParam(value = "start", required = false) String start, - @RequestParam(value = "end", required = false) String end, - @RequestParam(value = "search", required = false) String search, - @RequestHeader(value = "Authorization", required = false) String accessToken - ) { - if (ObjectUtils.isEmpty(accessToken)){ - throw new BusinessException(ErrorCode.MISSING_REQUEST); - } - - Member member = jwtService.getMemberFromAccessToken(accessToken); - - if (categorys == null) { - categorys = member.getOnboardingMemberCategories().stream().map(c -> c.getCategory().getName()).collect(Collectors.toList()); - } - - List ticketList = ticketService.getTotalAndMyTicketList(categorys, period, start, end, search, member); - List ticketResponseDtoList = ticketMapper.ticketsToTicketResponseDtos(ticketList); - - // 좋아요 여부 추가 - ticketResponseDtoList.forEach(t -> t.setIsLike(memberTicketLikeService.getMemberTicketLike(t.getId(), accessToken))); - return ResponseEntity.status(HttpStatus.OK).body(ticketResponseDtoList); - } - - /** - * 회원 인증 받지 않아도 조회 가능한 api - * - * @return - */ - @ApiOperation( - value = "내 티켓 조회 - 내 티켓만 ", - notes = " - ?categorys=영화,뮤지컬\n" + - " - &period=week **[week, month, 6month, day로 조회 가능]**\n" + - " - &start=2023-11-03\n" + - " - &end=2023-11-05\n" + - " - &search=레미제라블\n" + - "- Header['Authorization'] : 토큰 값\n" + - "1. start, end가 period보다 우선순위를 가집니다.\n" + - "2. start, end 두 값을 동시에 적지 않으면 filter 기능이 동작하지 않습니다.(에러는 발생하지 않습니다.)\n" + - "4. 전체 파라미터는 필수 값이 아니고, 헤더는 필수 값입니다.") - @GetMapping("/my") - public ResponseEntity getMyTicketList( - @RequestParam(value = "categorys", required = false) List categorys, - @RequestParam(value = "period", required = false) String period, // 일주일(week), 한달(month), 6개월(6month), 하루(day) - @RequestParam(value = "start", required = false) String start, - @RequestParam(value = "end", required = false) String end, - @RequestParam(value = "search", required = false) String search, - @RequestHeader(value = "Authorization", required = false) String accessToken - ) { - if (ObjectUtils.isEmpty(accessToken)){ - throw new BusinessException(ErrorCode.MISSING_REQUEST); - } - - List ticketList = ticketService.getMyTicketList(categorys, period, start, end, search, jwtService.getMemberFromAccessToken(accessToken)); - List ticketResponseDtoList = ticketMapper.ticketsToTicketResponseDtos(ticketList); - - // 좋아요 여부 추가 - ticketResponseDtoList.forEach(t -> t.setIsLike(memberTicketLikeService.getMemberTicketLike(t.getId(), accessToken))); - - return ResponseEntity.status(HttpStatus.OK).body(ticketResponseDtoList); - } - - @ApiOperation( - value = "티켓 수정하기 - 내 티켓만 수정 가능", - notes = " - Header['Authorization'] : AccessToken값 입력\n" + - " - image : MultipartFile 입력(사용자가 추가한 이미지)\n" + - " - request : {\n" + - " \"title\" : \"레미제라블\",\n" + - " \"ticketDate\" : \"2023-11-04T16:26:39.098\",\n" + - " \"rating\" : 1,\n" + - " \"memo\" : \"재미없는 공연이였다.(100자 이내 입력)\",\n" + - " \"seat\" : \"E292\",\n" + - " \"location\" : \"서울시 서울스퀘어\",\n" + - " \"price\" : 15000,\n" + - " \"friend\" : \"김가영\",\n" + - " \"color\" : \"#102920\"\n" + - " \"isPrivate\" : \"PUBLIC\",\n" + - " \"categoryName\" : \"기타\"\n" + - " \"ticketType\" : \"B유형\"\n" + - " \"layoutType\" : \"A유형\"\n" + - "}\n" + - "1. ticketDate는 다음과 같은 형식으로 추가해주세요\n" + - "2. isPrivate는 PUBLIC, PRIVATE으로만 추가 가능합니다.\n" + - "3. rating은 별점으로, 0 ~ 5까지 소수점으로 입력할 수 있습니다.(n.5 권장)\n" + - "4. request는 application/json 형식입니다.\n" + - "5. 필수 : 제목, 날짜, 메모, 별점, 이미지, 카테고리, 레이아웃 타입") - @PatchMapping("/{ticketId}") - public ResponseEntity patchTicket( - @Positive @PathVariable(required = false) Long ticketId, - @RequestHeader(value = "Authorization", required = false) String accessToken, - @RequestPart(value = "image", required = false) MultipartFile image, - @Valid @RequestPart(required = false) TicketPatchRequestDto request) { - - if (ObjectUtils.isEmpty(ticketId) || ObjectUtils.isEmpty(accessToken) || ObjectUtils.isEmpty(request)){ - throw new BusinessException(ErrorCode.MISSING_REQUEST); - } - - // TicketDate 형식 검사 (ex - 2023-11-01T00:00:00) - request.setTicketLocalDateTime(convertStringToLocalDateTime(request.getTicketDate())); - - // image - if (image != null) { - request.setImageUrl(imageService.updateImage(image, "Ticket", "imageUrl")); - } - - // Ticket 수정 - Ticket ticket = ticketService.patchTicket(ticketId, request, accessToken); - - // Ticket -> ResponseDto - TicketResponseDto ticketResponseDto = ticketMapper.ticketToTicketResponseDto(ticket); - return ResponseEntity.status(HttpStatus.CREATED).body(ticketResponseDto); - } - - @ApiOperation( - value = "티켓 삭제하기 - 내 티켓만 삭제 가능", - notes = "Header의 Authorization 필수") - @DeleteMapping("/{ticketId}") - public ResponseEntity deleteTicket( - @RequestHeader(value = "Authorization", required = false) String accessToken, - @PathVariable(required = false) Long ticketId) { - if (ObjectUtils.isEmpty(accessToken) || ObjectUtils.isEmpty(ticketId)){ - throw new BusinessException(ErrorCode.MISSING_REQUEST); - } - ticketService.deleteTicket(ticketId, jwtService.getMemberFromAccessToken(accessToken)); - return ResponseEntity.status(HttpStatus.NO_CONTENT).body(null); + @ApiOperation(value = "티켓 생성하기") + @PreAuthorize("isAuthenticated()") + @PostMapping + public ResponseEntity create(@Valid @RequestBody TicketCreateDto ticketCreateDto) { + Ticket ticket = ticketService.createTicket(ticketCreateDto); + return ResponseEntity.status(HttpStatus.CREATED).body(ticketMapper.ticketToTicketRetrieveDto(ticket)); } - @ApiOperation( - value = "티켓 나만보기 <-> 전체보기", - notes = "Header의 Authorization 필수") - @PostMapping("/{ticketId}/status") - public ResponseEntity postTicketStatus( - @RequestHeader(value = "Authorization", required = false) String accessToken, - @RequestBody TicketStatusPostRequestDto ticketStatusPostRequestDto, - @PathVariable(required = false) Long ticketId) { - if (ObjectUtils.isEmpty(accessToken) || ObjectUtils.isEmpty(ticketId) || ObjectUtils.isEmpty(ticketStatusPostRequestDto)){ - throw new BusinessException(ErrorCode.MISSING_REQUEST); - } - Ticket ticket = ticketService.postTicketStatus(ticketId, jwtService.getMemberFromAccessToken(accessToken), ticketStatusPostRequestDto); - TicketResponseDto ticketResponseDto = ticketMapper.ticketToTicketResponseDto(ticket); - return ResponseEntity.status(HttpStatus.OK).body(ticketResponseDto); + @ApiOperation(value = "티켓 객체 조회") + @PreAuthorize("isAuthenticated()") + @GetMapping("/{id}") + public ResponseEntity retrieve(@Positive @PathVariable Long id) { + Ticket ticket = ticketService.getTicket(id); + return ResponseEntity.status(HttpStatus.OK).body(ticketMapper.ticketToTicketRetrieveDto(ticket)); } -} +} \ No newline at end of file diff --git a/src/main/java/project/backend/domain/ticket/dto/TicketCreateDto.java b/src/main/java/project/backend/domain/ticket/dto/TicketCreateDto.java new file mode 100644 index 0000000..2baaf26 --- /dev/null +++ b/src/main/java/project/backend/domain/ticket/dto/TicketCreateDto.java @@ -0,0 +1,53 @@ +package project.backend.domain.ticket.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import project.backend.domain.media.dto.MediaDto; +import project.backend.global.annotation.ValidDateFormat; + +import javax.validation.constraints.*; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TicketCreateDto { + // TODO(sprint4) : Category, place 연결 미구현 상태 + + @NotBlank + @NotNull + @Size(min = 1, max = 20, message = "1자 ~ 20자 사이만 입력 가능합니다.") + @Schema(description = "제목", example = "<뮤지컬> 시카고", required = true) + public String title; + + @NotBlank + @NotNull + @Schema(description = "메인 이미지", example = "https://placehold.co/600x400/png", required = true) + public String mainImageUrl; + + @NotNull + @Schema(description = "날짜", example = "2024-01-01", required = true) + public LocalDate date; + + @NotNull + @DecimalMin(value = "1.0", inclusive = false, message = "별점은 1.0 ~ 5.0 사이만 입력 가능합니다") + @DecimalMax(value = "5.0", message = "별점은 1.0 ~ 5.0 사이만 입력 가능합니다") + @Schema(description = "별점", example = "3.5", required = true) + public Float score; + + @Schema(description = "별점", example = "2층 2열 8번", required = false) + public String seat; + + @Schema(description = "가격", example = "156000", required = false) + public Integer price; + + @Size(max = 500, message = "Review must be up to 500 characters") + @Schema(description = "리뷰", example = "정말 재미있었어요", required = false) + private String review; + + public List medias; +} diff --git a/src/main/java/project/backend/domain/ticket/dto/TicketPatchRequestDto.java b/src/main/java/project/backend/domain/ticket/dto/TicketPatchRequestDto.java deleted file mode 100644 index 97cb4e2..0000000 --- a/src/main/java/project/backend/domain/ticket/dto/TicketPatchRequestDto.java +++ /dev/null @@ -1,40 +0,0 @@ -package project.backend.domain.ticket.dto; - -import com.fasterxml.jackson.annotation.JsonFormat; -import lombok.*; -import project.backend.domain.member.entity.Member; -import project.backend.domain.ticket.entity.IsPrivate; - -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; -import java.time.LocalDateTime; - - -@Getter -@Setter -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class TicketPatchRequestDto { - public String title; - public String imageUrl; - public String ticketDate; - @Min(value = 0, message = "0보다 작은 값은 별점으로 설정할 수 없습니다.") - @Max(value = 5, message = "5보다 큰 값은 별점으로 설정할 수 없습니다.") - public Float rating; - @Size(max=100, message = "100자 이내로 입력해주세요.") - public String memo; - public String seat; - public String location; - @Min(value = 0, message = "0보다 작은 가격은 설정할 수 없습니다.") - public Integer price; - public String friend; - public String color; - public IsPrivate isPrivate; - public String categoryName; - public String ticketType; - public String layoutType; - public LocalDateTime ticketLocalDateTime; -} diff --git a/src/main/java/project/backend/domain/ticket/dto/TicketPostRequestDto.java b/src/main/java/project/backend/domain/ticket/dto/TicketPostRequestDto.java deleted file mode 100644 index e3902f1..0000000 --- a/src/main/java/project/backend/domain/ticket/dto/TicketPostRequestDto.java +++ /dev/null @@ -1,44 +0,0 @@ -package project.backend.domain.ticket.dto; - -import lombok.*; -import project.backend.domain.member.entity.Member; -import project.backend.domain.ticket.entity.IsPrivate; - -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; -import java.time.LocalDateTime; - -@Getter -@Setter -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class TicketPostRequestDto { - @NotNull(message = "제목을 입력해야 합니다.") - public String title; - public String imageUrl; - @NotNull(message = "날짜를 입력해야 합니다.") - public String ticketDate; - @Min(value = 0, message = "0보다 작은 값은 별점으로 설정할 수 없습니다.") - @Max(value = 5, message = "5보다 큰 값은 별점으로 설정할 수 없습니다.") - public Float rating; - @Size(max=100, message = "100자 이내로 입력해주세요.") - public String memo; - public String seat; - public String location; - @Min(value = 0, message = "0보다 작은 가격은 설정할 수 없습니다.") - public Integer price; - public String color; - public String friend; - public IsPrivate isPrivate; - public Member member; - @NotNull(message = "카테고리명을 선택해야 합니다.") - public String categoryName; - @NotNull(message = "티켓 타입을 선택해야 합니다.") - public String ticketType; - @NotNull(message = "레이아웃 타입을 선택해야 합니다.") - public String layoutType; - public LocalDateTime ticketLocalDateTime; -} diff --git a/src/main/java/project/backend/domain/ticket/dto/TicketResponseDto.java b/src/main/java/project/backend/domain/ticket/dto/TicketResponseDto.java deleted file mode 100644 index f9ccc58..0000000 --- a/src/main/java/project/backend/domain/ticket/dto/TicketResponseDto.java +++ /dev/null @@ -1,33 +0,0 @@ -package project.backend.domain.ticket.dto; - -import lombok.*; -import project.backend.domain.category.dto.CategoryResponseDto; -import project.backend.domain.member.dto.MemberResponseDto; -import project.backend.domain.ticket.entity.IsPrivate; - -import java.time.LocalDateTime; - -@Getter -@Setter -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class TicketResponseDto { - public Long id; - public String title; - public String imageUrl; - public LocalDateTime ticketDate; - public Float rating; - public String memo; - public String seat; - public String location; - public Integer price; - public String friend; - public String color; - public String ticketType; - public String layoutType; - public Boolean isLike; - public IsPrivate isPrivate; - public CategoryResponseDto category; - public MemberResponseDto member; -} diff --git a/src/main/java/project/backend/domain/ticket/dto/TicketRetrieveDto.java b/src/main/java/project/backend/domain/ticket/dto/TicketRetrieveDto.java new file mode 100644 index 0000000..a7cf879 --- /dev/null +++ b/src/main/java/project/backend/domain/ticket/dto/TicketRetrieveDto.java @@ -0,0 +1,22 @@ +package project.backend.domain.ticket.dto; + +import lombok.*; +import java.time.LocalDateTime; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TicketRetrieveDto { + // TODO(sprint4) : Category, place 연결 미구현 상태 + public Long id; + public String title; + public String mainImageUrl; + public LocalDateTime date; + public Float score; + public String seat; + public Integer price; + private String review; + public String mediasData; +} diff --git a/src/main/java/project/backend/domain/ticket/dto/TicketStatusPostRequestDto.java b/src/main/java/project/backend/domain/ticket/dto/TicketStatusPostRequestDto.java deleted file mode 100644 index b93ee5c..0000000 --- a/src/main/java/project/backend/domain/ticket/dto/TicketStatusPostRequestDto.java +++ /dev/null @@ -1,20 +0,0 @@ -package project.backend.domain.ticket.dto; - -import lombok.*; -import project.backend.domain.member.entity.Member; -import project.backend.domain.ticket.entity.IsPrivate; - -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; -import java.time.LocalDateTime; - -@Getter -@Setter -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class TicketStatusPostRequestDto { - private IsPrivate isPrivate; -} diff --git a/src/main/java/project/backend/domain/ticket/entity/IsPrivate.java b/src/main/java/project/backend/domain/ticket/entity/IsPrivate.java deleted file mode 100644 index ac02965..0000000 --- a/src/main/java/project/backend/domain/ticket/entity/IsPrivate.java +++ /dev/null @@ -1,16 +0,0 @@ -package project.backend.domain.ticket.entity; - -import lombok.Getter; - -@Getter -public enum IsPrivate { - PRIVATE("private"), - PUBLIC("public"); - - private final String status; - - IsPrivate(String status) { - this.status = status; - } - -} diff --git a/src/main/java/project/backend/domain/ticket/entity/Ticket.java b/src/main/java/project/backend/domain/ticket/entity/Ticket.java index a22308e..5e9cd92 100644 --- a/src/main/java/project/backend/domain/ticket/entity/Ticket.java +++ b/src/main/java/project/backend/domain/ticket/entity/Ticket.java @@ -4,13 +4,15 @@ import lombok.Builder; import lombok.Getter; import lombok.RequiredArgsConstructor; -import project.backend.domain.memberTicketLike.entity.MemberTicketLike; import project.backend.domain.category.entity.Category; import project.backend.domain.common.entity.BaseEntity; -import project.backend.domain.ticket.dto.TicketPatchRequestDto; +import project.backend.domain.media.entity.Media; +import project.backend.domain.place.entity.Place; import project.backend.domain.member.entity.Member; +import project.backend.domain.ticketingsite.entity.TicketingSite; import javax.persistence.*; +import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -21,33 +23,15 @@ @RequiredArgsConstructor(access = AccessLevel.PROTECTED) public class Ticket extends BaseEntity { @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) // todo : IDENTITY와 AUTO 차이점이 뭔지? + @GeneratedValue(strategy = GenerationType.IDENTITY) public Long id; - + public String mainImageUrl; public String title; - - public String imageUrl; - - public LocalDateTime ticketDate; - - public Float rating; - - public String memo; - + public LocalDate date; public String seat; - - public String location; - public Integer price; - - public String friend; - public String color; - - public String ticketType; - public String layoutType; - - @Enumerated(EnumType.STRING) - public IsPrivate isPrivate = IsPrivate.PRIVATE; + public String review; + public Float score; @ManyToOne(fetch = FetchType.LAZY) public Member member; @@ -55,44 +39,26 @@ public class Ticket extends BaseEntity { @ManyToOne(fetch = FetchType.LAZY) public Category category; + @ManyToOne(fetch = FetchType.LAZY) + public Place place; + @OneToMany(mappedBy = "ticket", cascade = {CascadeType.PERSIST, CascadeType.REMOVE}) - public List memberTicketLikes = new ArrayList<>(); + public List medias = new ArrayList<>(); @Builder - public Ticket(String title, String imageUrl, LocalDateTime ticketDate, Float rating, String memo, String seat, - String location, Integer price, String friend, String color, IsPrivate isPrivate, String ticketType, String layoutType) { + public Ticket(String title, String mainImageUrl, LocalDate date, Float score, String review, String seat, + Integer price, Member member, Category category, Place place) { this.title = title; - this.imageUrl = imageUrl; - this.ticketDate = ticketDate; - this.rating = rating; - this.memo = memo; + this.mainImageUrl = mainImageUrl; + this.date = date; + this.score = score; + this.review = review; this.seat = seat; - this.location = location; this.price = price; - this.friend = friend; - this.color = color; - this.isPrivate = isPrivate; - this.ticketType = ticketType; - this.layoutType = layoutType; - } - - // Patch - public Ticket patchTicket(TicketPatchRequestDto ticketPatchRequestDto) { - this.title = Optional.ofNullable(ticketPatchRequestDto.getTitle()).orElse(this.title); - this.imageUrl = Optional.ofNullable(ticketPatchRequestDto.getImageUrl()).orElse(this.imageUrl); - this.ticketDate = Optional.ofNullable(ticketPatchRequestDto.getTicketLocalDateTime()).orElse(this.ticketDate); - this.rating = (ticketPatchRequestDto.getRating()!= null && ticketPatchRequestDto.getRating() != 0) ? ticketPatchRequestDto.getRating() : this.rating; - this.memo = Optional.ofNullable(ticketPatchRequestDto.getMemo()).orElse(this.memo); - this.seat = Optional.ofNullable(ticketPatchRequestDto.getSeat()).orElse(this.seat); - this.location = Optional.ofNullable(ticketPatchRequestDto.getLocation()).orElse(this.location); - this.price = (ticketPatchRequestDto.getPrice() != null && ticketPatchRequestDto.getPrice() != 0) ? ticketPatchRequestDto.getPrice() : this.price; - this.friend = Optional.ofNullable(ticketPatchRequestDto.getFriend()).orElse(this.friend); - this.isPrivate = Optional.ofNullable(ticketPatchRequestDto.getIsPrivate()).orElse(this.isPrivate); - this.color = Optional.ofNullable(ticketPatchRequestDto.getColor()).orElse(this.color); - this.ticketType = Optional.ofNullable(ticketPatchRequestDto.getTicketType()).orElse(this.ticketType); - this.layoutType = Optional.ofNullable(ticketPatchRequestDto.getLayoutType()).orElse(this.layoutType); - return this; + this.member = member; + this.category = category; + this.place = place; } // == 연관관계 매핑 == // @@ -115,4 +81,14 @@ public void setCategory(Category category) { this.category = Optional.ofNullable(category).orElse(this.category); this.category.getTickets().add(this); } + + public void setPlace(Place place) { + if (this.place != null) { + if (this.place.getTickets().contains(this)) { + this.place.getTickets().remove(this); + } + } + this.place = Optional.ofNullable(place).orElse(this.place); + this.place.getTickets().add(this); + } } diff --git a/src/main/java/project/backend/domain/ticket/mapper/TicketMapper.java b/src/main/java/project/backend/domain/ticket/mapper/TicketMapper.java index 24b4a5c..027fc75 100644 --- a/src/main/java/project/backend/domain/ticket/mapper/TicketMapper.java +++ b/src/main/java/project/backend/domain/ticket/mapper/TicketMapper.java @@ -2,21 +2,15 @@ import org.mapstruct.Mapper; import org.mapstruct.ReportingPolicy; -import project.backend.domain.ticket.dto.TicketPatchRequestDto; -import project.backend.domain.ticket.dto.TicketPostRequestDto; +import project.backend.domain.ticket.dto.TicketRetrieveDto; import project.backend.domain.ticket.entity.Ticket; -import project.backend.domain.ticket.dto.TicketResponseDto; import java.util.List; // todo: ReportingPolicy.IGNORE은 무슨 뜻일까? @Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE) public interface TicketMapper { - Ticket ticketPostRequestDtoToTicket(TicketPostRequestDto ticketPostRequestDto); - Ticket ticketPatchRequestDtoToTicket(TicketPatchRequestDto ticketPatchRequestDto); + TicketRetrieveDto ticketToTicketRetrieveDto(Ticket ticket); - TicketResponseDto ticketToTicketResponseDto(Ticket ticket); - - List ticketsToTicketResponseDtos(List ticket); } diff --git a/src/main/java/project/backend/domain/ticket/repository/TicketRepositoryCustom.java b/src/main/java/project/backend/domain/ticket/repository/TicketRepositoryCustom.java index 76c4e7c..652c849 100644 --- a/src/main/java/project/backend/domain/ticket/repository/TicketRepositoryCustom.java +++ b/src/main/java/project/backend/domain/ticket/repository/TicketRepositoryCustom.java @@ -7,11 +7,11 @@ import java.util.List; public interface TicketRepositoryCustom { - List getTotalTicketList(List categorys, List startAndEndList, String search); - List getTotalAndMyTicketList(List categorys, List startAndEndList, String search, Member member); - - List getMyTicketList(List categorys, List startAndEndList, String search, Member member); - - List getStatisticsList(Member member, String month); - List getYearStatisticsList(Member member); +// List getTotalTicketList(List categorys, List startAndEndList, String search); +// List getTotalAndMyTicketList(List categorys, List startAndEndList, String search, Member member); +// +// List getMyTicketList(List categorys, List startAndEndList, String search, Member member); +// +// List getStatisticsList(Member member, String month); +// List getYearStatisticsList(Member member); } diff --git a/src/main/java/project/backend/domain/ticket/repository/TicketRepositoryImpl.java b/src/main/java/project/backend/domain/ticket/repository/TicketRepositoryImpl.java index f501ecc..907612a 100644 --- a/src/main/java/project/backend/domain/ticket/repository/TicketRepositoryImpl.java +++ b/src/main/java/project/backend/domain/ticket/repository/TicketRepositoryImpl.java @@ -5,19 +5,14 @@ import com.querydsl.core.types.dsl.*; import com.querydsl.jpa.impl.JPAQueryFactory; import lombok.RequiredArgsConstructor; -import org.hibernate.criterion.Projections; -import org.joda.time.DateTime; import project.backend.domain.member.dto.MemberStatisticsResponseDto; import project.backend.domain.member.dto.MemberYearStatisticsResponseDto; import project.backend.domain.member.entity.Member; -import project.backend.domain.member.entity.QMember; -import project.backend.domain.ticket.entity.IsPrivate; import project.backend.domain.ticket.entity.Ticket; import project.backend.global.error.exception.BusinessException; import project.backend.global.error.exception.ErrorCode; import java.text.DecimalFormat; -import java.text.ParseException; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; @@ -27,8 +22,6 @@ import java.util.List; import java.util.Objects; import java.util.Optional; -import java.util.regex.Pattern; -import java.util.stream.Collectors; import static project.backend.domain.ticket.entity.QTicket.ticket; import static project.backend.domain.member.entity.QMember.member; @@ -37,163 +30,142 @@ public class TicketRepositoryImpl implements TicketRepositoryCustom { private final JPAQueryFactory queryFactory; - @Override - public List getTotalTicketList(List categorys, List startAndEndList, String search) { - search = search==null ? "": search; - if (categorys == null || categorys.size() == 0) { - return queryFactory.selectFrom(ticket) - .where(ticket.isPrivate.eq(IsPrivate.PUBLIC), - ticket.title.contains(search), - ticket.ticketDate.between(startAndEndList.get(0), startAndEndList.get(1)) - ) - .orderBy(ticket.createdDate.desc()) - .fetch(); - } - - else { - return queryFactory.selectFrom(ticket) - .where(ticket.isPrivate.eq(IsPrivate.PUBLIC), - ticket.category.name.in(categorys), - ticket.title.contains(search), - ticket.ticketDate.between(startAndEndList.get(0), startAndEndList.get(1)) - ) - .orderBy(ticket.createdDate.desc()) - .fetch(); - } - } - - @Override - public List getTotalAndMyTicketList(List categorys, List startAndEndList, String search, Member member) { - search = search==null ? "": search; - if (categorys == null || categorys.size() == 0) { - return queryFactory.selectFrom(ticket) - .where(eqMember(ticket.member.id, member), - ticket.title.contains(search), - ticket.ticketDate.between(startAndEndList.get(0), startAndEndList.get(1)) - ) - .orderBy(ticket.createdDate.desc()) - .fetch(); - } - - else { - return queryFactory.selectFrom(ticket) - .where(eqMember(ticket.member.id, member), - ticket.category.name.in(categorys), - ticket.title.contains(search), - ticket.ticketDate.between(startAndEndList.get(0), startAndEndList.get(1)) - ) - .orderBy(ticket.createdDate.desc()) - .fetch(); - } - } - - @Override - public List getMyTicketList(List categorys, List startAndEndList, String search, Member member) { - search = search==null ? "": search; - if (categorys == null || categorys.size() == 0) { - return queryFactory.selectFrom(ticket) - .where(ticket.title.contains(search), - ticket.ticketDate.between(startAndEndList.get(0), startAndEndList.get(1)), - ticket.member.eq(member) - ) - .orderBy(ticket.createdDate.desc()) - .fetch(); - } - - else { - return queryFactory.selectFrom(ticket) - .where(ticket.category.name.in(categorys), - ticket.title.contains(search), - ticket.ticketDate.between(startAndEndList.get(0), startAndEndList.get(1)), - ticket.member.eq(member) - ) - .orderBy(ticket.createdDate.desc()) - .fetch(); - } - } - - @Override - public List getStatisticsList(Member member, String month) { - - DecimalFormat df = new DecimalFormat("0.0"); - DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); - LocalDateTime start = LocalDate.now().minusYears(100).atStartOfDay(); - LocalDateTime end = LocalDate.now().atTime(LocalTime.MAX); - if (month != null) { - try { - LocalDate searchMonth = LocalDate.parse(month+"-01", dateTimeFormatter); - start = searchMonth.withDayOfMonth(1).atStartOfDay(); - end = searchMonth.withDayOfMonth(searchMonth.lengthOfMonth()).atTime(LocalTime.MAX); - } catch (Exception e) { - throw new BusinessException(ErrorCode.MONTH_FORMAT_BAD_REQUEST); - } - } - - List categoryCountList = queryFactory - .select(ticket.category.name, ticket.count()) - .from(ticket) - .groupBy(ticket.category) - .where(ticket.member.eq(member), - ticket.ticketDate.between(start, end)) - .orderBy(ticket.count().desc()) - .fetch(); - - List memberStatisticsResponseDtoList = new ArrayList<>(); - - for(Tuple categoryCount : categoryCountList) { - memberStatisticsResponseDtoList.add(MemberStatisticsResponseDto.builder() - .category(categoryCount.get(0, String.class)) - .categoryCnt(categoryCount.get(1, Long.class)) - .build()); - } - - long resultCnt = memberStatisticsResponseDtoList.stream().mapToLong(MemberStatisticsResponseDto::getCategoryCnt).sum(); - for (int i = 0; memberStatisticsResponseDtoList.size() > i; i++) { - Double percent = (memberStatisticsResponseDtoList.get(i).getCategoryCnt().doubleValue()/resultCnt) * 100; - memberStatisticsResponseDtoList.get(i).setCategoryPercent(Double.parseDouble(df.format(percent))); - } - return memberStatisticsResponseDtoList; - } - - @Override - public List getYearStatisticsList(Member member) { - - LocalDateTime CURRENT_TIME = LocalDateTime.now(); - List memberYearStatisticsResponseDtoList = new ArrayList<>(); - - // 월별 GroupBy를 위한 String Template 이용하기 - StringTemplate formattedDate = Expressions.stringTemplate( - "DATE_FORMAT({0}, {1})", - ticket.ticketDate, - ConstantImpl.create("%Y-%m")); - - // 월별 통계가 있는 경우 Tuple[년, 월, 통계수]를 반환 - List ticketCountList = queryFactory.select(ticket.ticketDate.year(),ticket.ticketDate.month(), ticket.count()) - .from(ticket) - .groupBy(formattedDate) - .where( - ticket.member.eq(member), - ticket.ticketDate.between(CURRENT_TIME.minusYears(10).with(TemporalAdjusters.firstDayOfYear()), CURRENT_TIME.with(TemporalAdjusters.lastDayOfYear()))) - .fetch(); - - // memberYearStatisticsResponseDtoList에 저장 - for (Tuple ticketCount: ticketCountList) { - memberYearStatisticsResponseDtoList.add(MemberYearStatisticsResponseDto.builder() - .year(ticketCount.get(0, Integer.class)) - .month(ticketCount.get(1, Integer.class)) - .count(Long.valueOf(Optional.ofNullable(ticketCount.get(2, Long.class)).orElse(0L)).intValue()).build()); - } - - return memberYearStatisticsResponseDtoList; - } - - - private BooleanExpression eqMember(NumberPath memberId, Member member){ - NumberPath memberIdCompare = Expressions.numberPath(Long.class, member.getId().toString()); - if (Objects.equals(memberIdCompare, memberId)) { - return null; - } - return ticket.isPrivate.eq(IsPrivate.PUBLIC); - } - +// @Override +// public List getTotalTicketList(List categorys, List startAndEndList, String search) { +// search = search==null ? "": search; +// if (categorys == null || categorys.size() == 0) { +// return queryFactory.selectFrom(ticket) +// .where(ticket.title.contains(search)) +// .orderBy(ticket.createdDate.desc()) +// .fetch(); +// } +// +// else { +// return queryFactory.selectFrom(ticket) +// .where(ticket.category.name.in(categorys), +// ticket.title.contains(search) +// ) +// .orderBy(ticket.createdDate.desc()) +// .fetch(); +// } +// } +// +// @Override +// public List getTotalAndMyTicketList(List categorys, List startAndEndList, String search, Member member) { +// search = search==null ? "": search; +// if (categorys == null || categorys.size() == 0) { +// return queryFactory.selectFrom(ticket) +// .where(ticket.title.contains(search) +// ) +// .orderBy(ticket.createdDate.desc()) +// .fetch(); +// } +// +// else { +// return queryFactory.selectFrom(ticket) +// .where(ticket.category.name.in(categorys), +// ticket.title.contains(search) +// ) +// .orderBy(ticket.createdDate.desc()) +// .fetch(); +// } +// } +// +// @Override +// public List getMyTicketList(List categorys, List startAndEndList, String search, Member member) { +// search = search==null ? "": search; +// if (categorys == null || categorys.size() == 0) { +// return queryFactory.selectFrom(ticket) +// .where(ticket.title.contains(search), +// ticket.date.between(startAndEndList.get(0), startAndEndList.get(1)), +// ticket.member.eq(member) +// ) +// .orderBy(ticket.createdDate.desc()) +// .fetch(); +// } +// +// else { +// return queryFactory.selectFrom(ticket) +// .where(ticket.category.name.in(categorys), +// ticket.title.contains(search), +// ticket.date.between(startAndEndList.get(0), startAndEndList.get(1)), +// ticket.member.eq(member) +// ) +// .orderBy(ticket.createdDate.desc()) +// .fetch(); +// } +// } +// +// @Override +// public List getStatisticsList(Member member, String month) { +// +// DecimalFormat df = new DecimalFormat("0.0"); +// DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); +// LocalDateTime start = LocalDate.now().minusYears(100).atStartOfDay(); +// LocalDateTime end = LocalDate.now().atTime(LocalTime.MAX); +// if (month != null) { +// try { +// LocalDate searchMonth = LocalDate.parse(month+"-01", dateTimeFormatter); +// start = searchMonth.withDayOfMonth(1).atStartOfDay(); +// end = searchMonth.withDayOfMonth(searchMonth.lengthOfMonth()).atTime(LocalTime.MAX); +// } catch (Exception e) { +// throw new BusinessException(ErrorCode.MONTH_FORMAT_BAD_REQUEST); +// } +// } +// +// List categoryCountList = queryFactory +// .select(ticket.category.name, ticket.count()) +// .from(ticket) +// .groupBy(ticket.category) +// .where(ticket.member.eq(member), +// ticket.date.between(start, end)) +// .orderBy(ticket.count().desc()) +// .fetch(); +// +// List memberStatisticsResponseDtoList = new ArrayList<>(); +// +// for(Tuple categoryCount : categoryCountList) { +// memberStatisticsResponseDtoList.add(MemberStatisticsResponseDto.builder() +// .category(categoryCount.get(0, String.class)) +// .categoryCnt(categoryCount.get(1, Long.class)) +// .build()); +// } +// +// long resultCnt = memberStatisticsResponseDtoList.stream().mapToLong(MemberStatisticsResponseDto::getCategoryCnt).sum(); +// for (int i = 0; memberStatisticsResponseDtoList.size() > i; i++) { +// Double percent = (memberStatisticsResponseDtoList.get(i).getCategoryCnt().doubleValue()/resultCnt) * 100; +// memberStatisticsResponseDtoList.get(i).setCategoryPercent(Double.parseDouble(df.format(percent))); +// } +// return memberStatisticsResponseDtoList; +// } +// +// @Override +// public List getYearStatisticsList(Member member) { +// +// LocalDateTime CURRENT_TIME = LocalDateTime.now(); +// List memberYearStatisticsResponseDtoList = new ArrayList<>(); +// +// // 월별 GroupBy를 위한 String Template 이용하기 +// StringTemplate formattedDate = Expressions.stringTemplate( +// "DATE_FORMAT({0}, {1})", +// ConstantImpl.create("%Y-%m")); +// +// // 월별 통계가 있는 경우 Tuple[년, 월, 통계수]를 반환 +// List ticketCountList = queryFactory.select(ticket.date.year(),ticket.date.month(), ticket.count()) +// .from(ticket) +// .groupBy(formattedDate) +// .where( +// ticket.member.eq(member) +// .fetch(); +// +// // memberYearStatisticsResponseDtoList에 저장 +// for (Tuple ticketCount: ticketCountList) { +// memberYearStatisticsResponseDtoList.add(MemberYearStatisticsResponseDto.builder() +// .year(ticketCount.get(0, Integer.class)) +// .month(ticketCount.get(1, Integer.class)) +// .count(Long.valueOf(Optional.ofNullable(ticketCount.get(2, Long.class)).orElse(0L)).intValue()).build()); +// } +// +// return memberYearStatisticsResponseDtoList; +// } } diff --git a/src/main/java/project/backend/domain/ticket/service/TicketService.java b/src/main/java/project/backend/domain/ticket/service/TicketService.java index 16d685c..5fd95d0 100644 --- a/src/main/java/project/backend/domain/ticket/service/TicketService.java +++ b/src/main/java/project/backend/domain/ticket/service/TicketService.java @@ -3,151 +3,58 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import project.backend.domain.category.service.CategoryService; -import project.backend.domain.jwt.service.JwtService; +import project.backend.domain.media.dto.MediaDto; +import project.backend.domain.media.entity.Media; +import project.backend.domain.media.service.MediaService; import project.backend.domain.member.entity.Member; -import project.backend.domain.member.entity.SocialType; -import project.backend.domain.ticket.dto.TicketPatchRequestDto; -import project.backend.domain.ticket.dto.TicketPostRequestDto; -import project.backend.domain.ticket.dto.TicketStatusPostRequestDto; -import project.backend.domain.ticket.entity.IsPrivate; +import project.backend.domain.member.service.MemberJwtService; +import project.backend.domain.ticket.dto.TicketCreateDto; import project.backend.domain.ticket.entity.Ticket; -import project.backend.domain.ticket.mapper.TicketMapper; import project.backend.domain.ticket.repository.TicketRepository; import project.backend.global.error.exception.BusinessException; import project.backend.global.error.exception.ErrorCode; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - @Service @RequiredArgsConstructor @Transactional public class TicketService { private final TicketRepository ticketRepository; - private final CategoryService categoryService; - private final JwtService jwtService; + private final MediaService mediaService; + private final MemberJwtService memberJwtService; - public Ticket createTicket(TicketPostRequestDto ticketPostRequestDto) { + public Ticket createTicket(TicketCreateDto ticketCreateDto) { + Media media; Ticket ticket = Ticket.builder() - .title(ticketPostRequestDto.title) - .imageUrl(ticketPostRequestDto.imageUrl) - .ticketDate(ticketPostRequestDto.ticketLocalDateTime) - .rating(ticketPostRequestDto.rating) - .memo(ticketPostRequestDto.memo) - .seat(ticketPostRequestDto.seat) - .location(ticketPostRequestDto.location) - .price(ticketPostRequestDto.price) - .friend(ticketPostRequestDto.friend) - .color(ticketPostRequestDto.color) - .isPrivate(ticketPostRequestDto.isPrivate) - .ticketType(ticketPostRequestDto.ticketType) - .layoutType(ticketPostRequestDto.layoutType) + .title(ticketCreateDto.getTitle()) + .mainImageUrl(ticketCreateDto.getMainImageUrl()) + .date(ticketCreateDto.getDate()) + .score(ticketCreateDto.getScore()) + .review(ticketCreateDto.getReview()) + .seat(ticketCreateDto.getSeat()) + .price(ticketCreateDto.getPrice()) .build(); - // 연관관계 매핑 - ticket.setMember(ticketPostRequestDto.member); - ticket.setCategory(categoryService.verifiedCategory(ticketPostRequestDto.categoryName)); - - // 저장 - ticketRepository.save(ticket); - return ticket; - } - - /** - * 내 티켓 또는 전체공개 티켓만 조회 가능 - * @param id - * @param accessToken - * @return - */ - public Ticket getTicket(Long id, String accessToken) { - Ticket ticket = verifiedTicket(id); - if (ticket.isPrivate == IsPrivate.PUBLIC) { - return ticket; - } else if (accessToken!=null) { - if (ticket.member == jwtService.getMemberFromAccessToken(accessToken)) { - return ticket; - } + // Media 연결 + for (MediaDto mediaDto : ticketCreateDto.medias) { + media = mediaService.setOrderThumbnail(mediaDto); + media.setTicket(ticket); } - throw new BusinessException(ErrorCode.TICKET_VIEW_FAIL); - } - - public List getTotalTicketList(List categorys, String period, String start, String end, String search) { - return ticketRepository.getTotalTicketList(categorys, getStartAndEnd(period, start, end), search); - } - - public List getTotalAndMyTicketList(List categorys, String period, String start, String end, String search, Member member) { - return ticketRepository.getTotalAndMyTicketList(categorys, getStartAndEnd(period, start, end), search, member); - } - - public List getMyTicketList(List categorys, String period, String start, String end, String search, Member member) { - return ticketRepository.getMyTicketList(categorys, getStartAndEnd(period, start, end), search, member); - } - - public Ticket patchTicket(Long id, TicketPatchRequestDto ticketPatchRequestDto, String accessToken) { + ticket.setMember(memberJwtService.getMember()); + ticketRepository.save(ticket); - Ticket ticket = verifiedTicket(id); - if (ticket.member == jwtService.getMemberFromAccessToken(accessToken)) { - ticket.patchTicket(ticketPatchRequestDto); - return ticketRepository.save(ticket); - } - throw new BusinessException(ErrorCode.TICKET_PATCH_FAIL); + return ticket; } - public void deleteTicket(Long id, Member member) { - Ticket ticket = verifiedTicket(id); - if (ticket.member == member) { - ticketRepository.delete(ticket); - } else { - throw new BusinessException(ErrorCode.TICKET_DELETE_FAIL); + public Ticket getTicket(Long id) { + Member member = memberJwtService.getMember(); + Ticket ticket = ticketRepository.findById(id).orElseThrow(() -> new BusinessException(ErrorCode.TICKET_NOT_FOUND)); + if (ticket.member != member) { + throw new BusinessException(ErrorCode.TICKET_VIEW_FAIL); } + return ticket; } public Ticket verifiedTicket(Long id) { return ticketRepository.findById(id).orElseThrow(() -> new BusinessException(ErrorCode.TICKET_NOT_FOUND)); } - - private List getStartAndEnd(String period, String start, String end) { - - DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); - List startAndEndList = new ArrayList<>(); - - if (start != null && end!= null) { - startAndEndList.add(LocalDate.parse(start, dateTimeFormatter).atStartOfDay()); - startAndEndList.add(LocalDate.parse(end, dateTimeFormatter).atTime(LocalTime.MAX)); - } else if (Objects.equals(period, "week")) { - startAndEndList.add(LocalDate.now().minusWeeks(1).atStartOfDay()); - startAndEndList.add(LocalDate.now().atTime(LocalTime.MAX)); - } else if (Objects.equals(period, "month")) { - startAndEndList.add(LocalDate.now().minusMonths(1).atStartOfDay()); - startAndEndList.add(LocalDate.now().atTime(LocalTime.MAX)); - } else if (Objects.equals(period, "6month")) { - startAndEndList.add(LocalDate.now().minusMonths(6).atStartOfDay()); - startAndEndList.add(LocalDate.now().atTime(LocalTime.MAX)); - } else if (Objects.equals(period, "day")) { - startAndEndList.add(LocalDate.now().atStartOfDay()); - startAndEndList.add(LocalDate.now().atTime(LocalTime.MAX)); - } else { - startAndEndList.add(LocalDate.now().minusYears(100).atStartOfDay()); - startAndEndList.add(LocalDate.now().atTime(LocalTime.MAX)); - } - return startAndEndList; - } - - public Ticket postTicketStatus (Long id, Member member, TicketStatusPostRequestDto ticketStatusPostRequestDto) { - Ticket ticket = verifiedTicket(id); - - if (ticket.getMember() == member) { - ticket.patchTicket((TicketPatchRequestDto.builder().isPrivate(ticketStatusPostRequestDto.getIsPrivate()).build())); - } - - return ticket; - } - } diff --git a/src/main/java/project/backend/global/annotation/ValidDateFormat.java b/src/main/java/project/backend/global/annotation/ValidDateFormat.java new file mode 100644 index 0000000..a924c70 --- /dev/null +++ b/src/main/java/project/backend/global/annotation/ValidDateFormat.java @@ -0,0 +1,19 @@ +package project.backend.global.annotation; + +import project.backend.global.validator.DateFormatValidator; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Constraint(validatedBy = DateFormatValidator.class) +@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE }) +@Retention(RetentionPolicy.RUNTIME) +public @interface ValidDateFormat { + String message() default "Invalid date format. Expected format is yyyy-MM-dd'T'HH:mm:ss"; + Class[] groups() default {}; + Class[] payload() default {}; +} \ No newline at end of file diff --git a/src/main/java/project/backend/global/error/exception/ErrorCode.java b/src/main/java/project/backend/global/error/exception/ErrorCode.java index fb0b23f..417aaf3 100644 --- a/src/main/java/project/backend/global/error/exception/ErrorCode.java +++ b/src/main/java/project/backend/global/error/exception/ErrorCode.java @@ -30,10 +30,10 @@ public enum ErrorCode { MEMBER_NICKNAME_CHANGE_MONTH(400, "M009", "한 달에 한 번만 닉네임을 변경할 수 있습니다."), // Ticket - TICKET_NOT_FOUND(400, "T001", "티켓을 찾을 수 없습니다."), - TICKET_DELETE_FAIL(400, "T002", "내 티켓만 삭제할 수 있습니다."), - TICKET_VIEW_FAIL(400, "T003", "내 티켓 또는 전체 공개 티켓만 조회할 수 있습니다."), - TICKET_PATCH_FAIL(400, "T004", "내 티켓만 수정할 수 있습니다."), + TICKET_NOT_FOUND(404, "T001", "티켓을 찾을 수 없습니다."), + TICKET_DELETE_FAIL(403, "T002", "내 티켓만 삭제할 수 있습니다."), + TICKET_VIEW_FAIL(403, "T003", "내 티켓만 조회할 수 있습니다."), + TICKET_PATCH_FAIL(403, "T004", "내 티켓만 수정할 수 있습니다."), // Category CATEGORY_NOT_FOUND(400, "CA001", "카테고리를 찾을 수 없습니다."), diff --git a/src/main/java/project/backend/global/validator/DateFormatValidator.java b/src/main/java/project/backend/global/validator/DateFormatValidator.java new file mode 100644 index 0000000..60c677f --- /dev/null +++ b/src/main/java/project/backend/global/validator/DateFormatValidator.java @@ -0,0 +1,32 @@ +package project.backend.global.validator; + +import project.backend.global.annotation.ValidDateFormat; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; + +public class DateFormatValidator implements ConstraintValidator { + + private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"); + + @Override + public void initialize(ValidDateFormat constraintAnnotation) { + } + + @Override + public boolean isValid(LocalDateTime date, ConstraintValidatorContext context) { + if (date == null) { + return true; // Use @NotNull for null checks + } + try { + String formattedDate = date.format(FORMATTER); + LocalDateTime.parse(formattedDate, FORMATTER); + return true; + } catch (DateTimeParseException e) { + return false; + } + } +} \ No newline at end of file