From 478dbc39958f514d19058e47dec51da037d4a9a6 Mon Sep 17 00:00:00 2001 From: yeop0740 Date: Sat, 18 Nov 2023 00:48:06 +0900 Subject: [PATCH 01/13] =?UTF-8?q?feat:=20=EB=8C=80=ED=95=99,=20=EA=B0=80?= =?UTF-8?q?=EA=B2=8C,=20=EC=9A=B4=EC=98=81=EC=8B=9C=EA=B0=84,=20=ED=94=BD,?= =?UTF-8?q?=20=EA=B3=84=EC=95=BD,=20=ED=98=9C=ED=83=9D=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EC=97=94=ED=8B=B0=ED=8B=B0=EC=99=80=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=EB=90=9C=20enum=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- settings.gradle | 2 +- .../com/backend/common/domain/BaseEntity.java | 25 ++++++++++ .../domain/benefit/entity/Benefit.java | 26 +++++++++++ .../domain/benefit/entity/BenefitType.java | 7 +++ .../domain/contract/entity/Contract.java | 41 +++++++++++++++++ .../contract/entity/ContractStatus.java | 5 ++ .../domain/store/entity/BusinessDay.java | 26 +++++++++++ .../domain/store/entity/BusinessHour.java | 39 ++++++++++++++++ .../backend/domain/store/entity/Category.java | 16 +++++++ .../com/backend/domain/store/entity/Pick.java | 21 +++++++++ .../backend/domain/store/entity/Store.java | 46 +++++++++++++++++++ .../domain/university/entity/University.java | 33 +++++++++++++ .../com/backend/domain/user/entity/User.java | 15 +++++- 13 files changed, 300 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/backend/common/domain/BaseEntity.java create mode 100644 src/main/java/com/backend/domain/benefit/entity/Benefit.java create mode 100644 src/main/java/com/backend/domain/benefit/entity/BenefitType.java create mode 100644 src/main/java/com/backend/domain/contract/entity/Contract.java create mode 100644 src/main/java/com/backend/domain/contract/entity/ContractStatus.java create mode 100644 src/main/java/com/backend/domain/store/entity/BusinessDay.java create mode 100644 src/main/java/com/backend/domain/store/entity/BusinessHour.java create mode 100644 src/main/java/com/backend/domain/store/entity/Category.java create mode 100644 src/main/java/com/backend/domain/store/entity/Pick.java create mode 100644 src/main/java/com/backend/domain/store/entity/Store.java create mode 100644 src/main/java/com/backend/domain/university/entity/University.java diff --git a/settings.gradle b/settings.gradle index 0f5036d..ab6c67b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -rootProject.name = 'backend' +rootProject.name = 'Backend' diff --git a/src/main/java/com/backend/common/domain/BaseEntity.java b/src/main/java/com/backend/common/domain/BaseEntity.java new file mode 100644 index 0000000..ae4b77c --- /dev/null +++ b/src/main/java/com/backend/common/domain/BaseEntity.java @@ -0,0 +1,25 @@ +package com.backend.common.domain; + +import jakarta.persistence.EntityListeners; +import jakarta.persistence.MappedSuperclass; +import lombok.Getter; +import lombok.ToString; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; + +import java.time.LocalDateTime; + +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +@Getter +public abstract class BaseEntity { + + @CreatedDate + private LocalDateTime createdTime; + + @LastModifiedDate + private LocalDateTime modifiedTime; + +} diff --git a/src/main/java/com/backend/domain/benefit/entity/Benefit.java b/src/main/java/com/backend/domain/benefit/entity/Benefit.java new file mode 100644 index 0000000..521e2d7 --- /dev/null +++ b/src/main/java/com/backend/domain/benefit/entity/Benefit.java @@ -0,0 +1,26 @@ +package com.backend.domain.benefit.entity; + +import com.backend.common.domain.BaseEntity; +import com.backend.domain.contract.entity.Contract; +import jakarta.persistence.*; +import lombok.Getter; + +@Entity +@Getter +public class Benefit extends BaseEntity { + + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long benefitId; + + @Enumerated(EnumType.STRING) + private BenefitType type; + + private int amount; + + private String content; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "contract_id") + private Contract contract; + +} diff --git a/src/main/java/com/backend/domain/benefit/entity/BenefitType.java b/src/main/java/com/backend/domain/benefit/entity/BenefitType.java new file mode 100644 index 0000000..77e59bf --- /dev/null +++ b/src/main/java/com/backend/domain/benefit/entity/BenefitType.java @@ -0,0 +1,7 @@ +package com.backend.domain.benefit.entity; + +public enum BenefitType { + + FIX, RATE, MENU + +} diff --git a/src/main/java/com/backend/domain/contract/entity/Contract.java b/src/main/java/com/backend/domain/contract/entity/Contract.java new file mode 100644 index 0000000..01b36ba --- /dev/null +++ b/src/main/java/com/backend/domain/contract/entity/Contract.java @@ -0,0 +1,41 @@ +package com.backend.domain.contract.entity; + +import com.backend.domain.benefit.entity.Benefit; +import com.backend.common.domain.BaseEntity; +import com.backend.domain.store.entity.Store; +import com.backend.domain.university.entity.University; +import jakarta.persistence.*; +import lombok.*; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Contract extends BaseEntity { + + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long contractId; + + private LocalDate startDate; + + private LocalDate endDate; + + private String manager; + + @OneToMany(mappedBy = "contract", cascade = CascadeType.PERSIST) + private List benefits = new ArrayList<>(); + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "university_id") + private University university; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "store_id") + private Store store; + +} diff --git a/src/main/java/com/backend/domain/contract/entity/ContractStatus.java b/src/main/java/com/backend/domain/contract/entity/ContractStatus.java new file mode 100644 index 0000000..fc187b3 --- /dev/null +++ b/src/main/java/com/backend/domain/contract/entity/ContractStatus.java @@ -0,0 +1,5 @@ +package com.backend.domain.contract.entity; + +public enum ContractStatus { + AVAILABLE, EXPIRATION +} diff --git a/src/main/java/com/backend/domain/store/entity/BusinessDay.java b/src/main/java/com/backend/domain/store/entity/BusinessDay.java new file mode 100644 index 0000000..97be010 --- /dev/null +++ b/src/main/java/com/backend/domain/store/entity/BusinessDay.java @@ -0,0 +1,26 @@ +package com.backend.domain.store.entity; + +import lombok.Getter; + +@Getter +public enum BusinessDay { + + MONDAY(1, "월"), + TUESDAY(2, "화"), + WEDNESDAY(3, "수"), + THURSDAY(4, "목"), + FRIDAY(5, "금"), + SATURDAY(6, "토"), + SUNDAY(7, "일"), + EVERYDAY(100, "매일"), + NONE(101, "없음"); + + private final int value; + private final String dayOfWeek; + + BusinessDay(int value, String dayOfWeek) { + this.value = value; + this.dayOfWeek = dayOfWeek; + } + +} diff --git a/src/main/java/com/backend/domain/store/entity/BusinessHour.java b/src/main/java/com/backend/domain/store/entity/BusinessHour.java new file mode 100644 index 0000000..1a2d4ec --- /dev/null +++ b/src/main/java/com/backend/domain/store/entity/BusinessHour.java @@ -0,0 +1,39 @@ +package com.backend.domain.store.entity; + +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class BusinessHour { + + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long businessHourId; + + @Enumerated(EnumType.STRING) + private BusinessDay dayOfWeek; + + private String openingTime; + + private String closingTime; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "store_id") + private Store store; + + @Builder + public BusinessHour(BusinessDay dayOfWeek, String openingTime, String closingTime) { + this.dayOfWeek = dayOfWeek; + this.openingTime = openingTime; + this.closingTime = closingTime; + } + + public void setStore(Store store) { + this.store = store; + } + +} diff --git a/src/main/java/com/backend/domain/store/entity/Category.java b/src/main/java/com/backend/domain/store/entity/Category.java new file mode 100644 index 0000000..8683d7f --- /dev/null +++ b/src/main/java/com/backend/domain/store/entity/Category.java @@ -0,0 +1,16 @@ +package com.backend.domain.store.entity; + +import lombok.Getter; + +@Getter +public enum Category { + + FOOD("음식점"), CAFE("카페"), BEAUTY("미용"), CULTURE("문화"), ETC("기타"), NONE("없음"); + + private final String categoryName; + + Category(String categoryName) { + this.categoryName = categoryName; + } + +} diff --git a/src/main/java/com/backend/domain/store/entity/Pick.java b/src/main/java/com/backend/domain/store/entity/Pick.java new file mode 100644 index 0000000..ed7807b --- /dev/null +++ b/src/main/java/com/backend/domain/store/entity/Pick.java @@ -0,0 +1,21 @@ +package com.backend.domain.store.entity; + +import com.backend.common.domain.BaseEntity; +import com.backend.domain.user.entity.User; +import jakarta.persistence.*; + +@Entity +public class Pick extends BaseEntity { + + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long pickId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "store_id") + private Store store; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + +} diff --git a/src/main/java/com/backend/domain/store/entity/Store.java b/src/main/java/com/backend/domain/store/entity/Store.java new file mode 100644 index 0000000..60207cc --- /dev/null +++ b/src/main/java/com/backend/domain/store/entity/Store.java @@ -0,0 +1,46 @@ +package com.backend.domain.store.entity; + +import com.backend.common.domain.BaseEntity; +import com.backend.domain.contract.entity.Contract; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Store extends BaseEntity { + + @Id @GeneratedValue + private Long storeId; + + private String name; + + private String address; + + private String description; + + private Double latitude; + + private Double longitude; + + @Enumerated(EnumType.STRING) + private Category category; + + private String contact; + + private String mapUrl; + + private String phoneNumber; + + @OneToMany(mappedBy = "store") + private List contracts = new ArrayList<>(); + + @OneToMany(mappedBy = "store") + private List picks = new ArrayList<>(); + +} diff --git a/src/main/java/com/backend/domain/university/entity/University.java b/src/main/java/com/backend/domain/university/entity/University.java new file mode 100644 index 0000000..f99634b --- /dev/null +++ b/src/main/java/com/backend/domain/university/entity/University.java @@ -0,0 +1,33 @@ +package com.backend.domain.university.entity; + +import com.backend.domain.contract.entity.Contract; +import com.backend.domain.user.entity.User; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class University { + + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long universityId; + + private String name; + + private Double latitude; + + private Double longitude; + + @OneToMany(mappedBy = "university") + private List contracts = new ArrayList<>(); + + @OneToOne(mappedBy = "university") + private User user; + +} diff --git a/src/main/java/com/backend/domain/user/entity/User.java b/src/main/java/com/backend/domain/user/entity/User.java index 0e63fbb..d4b69bc 100644 --- a/src/main/java/com/backend/domain/user/entity/User.java +++ b/src/main/java/com/backend/domain/user/entity/User.java @@ -1,16 +1,22 @@ package com.backend.domain.user.entity; +import com.backend.common.domain.BaseEntity; +import com.backend.domain.store.entity.Pick; +import com.backend.domain.university.entity.University; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import java.util.ArrayList; +import java.util.List; + @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Table(name = "users") -public class User { +public class User extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "user_id") @@ -29,6 +35,13 @@ public class User { private String proofImageUrl; + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "university_id") + private University university; + + @OneToMany(mappedBy = "user") + private List picks = new ArrayList<>(); + @Builder public User(String email, String password, GroupType type, String typeName, String refreshToken, String proofImageUrl) { this.email = email; From cb0f2f953a6126560e93603f70eead05b562cf7c Mon Sep 17 00:00:00 2001 From: yeop0740 Date: Sat, 18 Nov 2023 00:50:30 +0900 Subject: [PATCH 02/13] =?UTF-8?q?feat:=20=EC=83=9D=EC=84=B1=20=EC=8B=9C?= =?UTF-8?q?=EA=B0=84,=20=EC=88=98=EC=A0=95=20=EC=8B=9C=EA=B0=84=EC=9D=84?= =?UTF-8?q?=20=EA=B8=B0=EB=A1=9D=ED=95=98=EA=B8=B0=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/backend/BackendApplication.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/backend/BackendApplication.java b/src/main/java/com/backend/BackendApplication.java index 2bd17d8..747708a 100644 --- a/src/main/java/com/backend/BackendApplication.java +++ b/src/main/java/com/backend/BackendApplication.java @@ -2,7 +2,9 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +@EnableJpaAuditing @SpringBootApplication public class BackendApplication { From af7b4ebeef54da197f3dde60eaff8f8466b59cdf Mon Sep 17 00:00:00 2001 From: yeop0740 Date: Sat, 18 Nov 2023 01:14:50 +0900 Subject: [PATCH 03/13] =?UTF-8?q?feat:=20Store=20=EB=93=B1=EB=A1=9D=20API?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/backend/common/dto/ResponseDto.java | 6 ++ .../store/controller/StoreController.java | 23 +++++++ .../store/dto/CreateBusinessHourDto.java | 26 +++++++ .../domain/store/dto/CreateStoreDto.java | 68 +++++++++++++++++++ .../domain/store/dto/CreateStoreRequest.java | 19 ++++++ .../domain/store/dto/HoursInfoDto.java | 16 +++++ .../backend/domain/store/dto/LocationDto.java | 16 +++++ .../com/backend/domain/store/dto/MenuDto.java | 16 +++++ .../domain/store/entity/BusinessDay.java | 9 +++ .../backend/domain/store/entity/Store.java | 6 +- .../store/repository/StoreRepository.java | 7 ++ .../domain/store/service/StoreService.java | 32 +++++++++ 12 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/backend/domain/store/controller/StoreController.java create mode 100644 src/main/java/com/backend/domain/store/dto/CreateBusinessHourDto.java create mode 100644 src/main/java/com/backend/domain/store/dto/CreateStoreDto.java create mode 100644 src/main/java/com/backend/domain/store/dto/CreateStoreRequest.java create mode 100644 src/main/java/com/backend/domain/store/dto/HoursInfoDto.java create mode 100644 src/main/java/com/backend/domain/store/dto/LocationDto.java create mode 100644 src/main/java/com/backend/domain/store/dto/MenuDto.java create mode 100644 src/main/java/com/backend/domain/store/repository/StoreRepository.java create mode 100644 src/main/java/com/backend/domain/store/service/StoreService.java diff --git a/src/main/java/com/backend/common/dto/ResponseDto.java b/src/main/java/com/backend/common/dto/ResponseDto.java index 5d373b0..3792dc2 100644 --- a/src/main/java/com/backend/common/dto/ResponseDto.java +++ b/src/main/java/com/backend/common/dto/ResponseDto.java @@ -16,6 +16,12 @@ public static ResponseEntity created(T data) { .body(data); } + public static ResponseEntity created() { + return ResponseEntity + .status(HttpStatus.CREATED) + .build(); + } + public static ResponseEntity noContent() { return ResponseEntity .status(HttpStatus.NO_CONTENT) diff --git a/src/main/java/com/backend/domain/store/controller/StoreController.java b/src/main/java/com/backend/domain/store/controller/StoreController.java new file mode 100644 index 0000000..2a768c0 --- /dev/null +++ b/src/main/java/com/backend/domain/store/controller/StoreController.java @@ -0,0 +1,23 @@ +package com.backend.domain.store.controller; + +import com.backend.common.dto.ResponseDto; +import com.backend.domain.store.dto.*; +import com.backend.domain.store.service.StoreService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/store") +public class StoreController { + + private final StoreService storeService; + + @PostMapping + public ResponseEntity createStore(@RequestBody CreateStoreRequest request) { + storeService.createStore(request); + return ResponseDto.created(); + } + +} diff --git a/src/main/java/com/backend/domain/store/dto/CreateBusinessHourDto.java b/src/main/java/com/backend/domain/store/dto/CreateBusinessHourDto.java new file mode 100644 index 0000000..955f4d9 --- /dev/null +++ b/src/main/java/com/backend/domain/store/dto/CreateBusinessHourDto.java @@ -0,0 +1,26 @@ +package com.backend.domain.store.dto; + +import com.backend.domain.store.entity.BusinessDay; +import com.backend.domain.store.entity.BusinessHour; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class CreateBusinessHourDto { + + private String dayOfWeek; + + private HoursInfoDto hoursInfo; + + public BusinessHour toEntity() { + return BusinessHour.builder() + .dayOfWeek(BusinessDay.convert(dayOfWeek)) + .openingTime(hoursInfo.getOpeningTime()) + .closingTime(hoursInfo.getClosingTime()) + .build(); + } + +} diff --git a/src/main/java/com/backend/domain/store/dto/CreateStoreDto.java b/src/main/java/com/backend/domain/store/dto/CreateStoreDto.java new file mode 100644 index 0000000..b6ebc95 --- /dev/null +++ b/src/main/java/com/backend/domain/store/dto/CreateStoreDto.java @@ -0,0 +1,68 @@ +package com.backend.domain.store.dto; + +import com.backend.domain.store.entity.Category; +import com.backend.domain.store.entity.Store; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class CreateStoreDto { + + private String storeName; + private String genre; + private String phoneNumber; + private String address; + private LocationDto location; + private List businessHours = new ArrayList<>(); + private List menu = new ArrayList<>(); + + public Store toEntity(Category category) { + return Store.builder() + .name(storeName) + .address(address) + .description(getDescription()) + .latitude(getLatitude()) + .longitude(getLongitude()) + .category(category) + .contact(phoneNumber) + .phoneNumber(phoneNumber) + .businessHours( + businessHours.stream() + .filter(Objects::nonNull) + .map(CreateBusinessHourDto::toEntity) + .toList() + ) + .build(); + } + + public String getDescription() { + if (genre != null) { + return genre; + } + if (!menu.isEmpty()) { + return menu.stream() + .map(MenuDto::getName) + .limit(3) + .collect(Collectors.joining(", ")); + } + return null; + } + + + public Double getLongitude() { + return location == null ? null : location.getLongitude(); + } + + public Double getLatitude() { + return location == null ? null : location.getLatitude(); + } + +} diff --git a/src/main/java/com/backend/domain/store/dto/CreateStoreRequest.java b/src/main/java/com/backend/domain/store/dto/CreateStoreRequest.java new file mode 100644 index 0000000..999deaa --- /dev/null +++ b/src/main/java/com/backend/domain/store/dto/CreateStoreRequest.java @@ -0,0 +1,19 @@ +package com.backend.domain.store.dto; + +import com.backend.domain.store.entity.Category; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class CreateStoreRequest { + + private Category category; + + private List data; + +} diff --git a/src/main/java/com/backend/domain/store/dto/HoursInfoDto.java b/src/main/java/com/backend/domain/store/dto/HoursInfoDto.java new file mode 100644 index 0000000..0300cd4 --- /dev/null +++ b/src/main/java/com/backend/domain/store/dto/HoursInfoDto.java @@ -0,0 +1,16 @@ +package com.backend.domain.store.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class HoursInfoDto { + + private String openingTime; + + private String closingTime; + +} diff --git a/src/main/java/com/backend/domain/store/dto/LocationDto.java b/src/main/java/com/backend/domain/store/dto/LocationDto.java new file mode 100644 index 0000000..0cbe4f3 --- /dev/null +++ b/src/main/java/com/backend/domain/store/dto/LocationDto.java @@ -0,0 +1,16 @@ +package com.backend.domain.store.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class LocationDto { + + private Double latitude; + + private Double longitude; + +} diff --git a/src/main/java/com/backend/domain/store/dto/MenuDto.java b/src/main/java/com/backend/domain/store/dto/MenuDto.java new file mode 100644 index 0000000..0b45cf1 --- /dev/null +++ b/src/main/java/com/backend/domain/store/dto/MenuDto.java @@ -0,0 +1,16 @@ +package com.backend.domain.store.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class MenuDto { + + private String name; + + private String price; + +} diff --git a/src/main/java/com/backend/domain/store/entity/BusinessDay.java b/src/main/java/com/backend/domain/store/entity/BusinessDay.java index 97be010..8cef97b 100644 --- a/src/main/java/com/backend/domain/store/entity/BusinessDay.java +++ b/src/main/java/com/backend/domain/store/entity/BusinessDay.java @@ -2,6 +2,8 @@ import lombok.Getter; +import java.util.Arrays; + @Getter public enum BusinessDay { @@ -23,4 +25,11 @@ public enum BusinessDay { this.dayOfWeek = dayOfWeek; } + public static BusinessDay convert(String dayOfWeek) { + return Arrays.stream(BusinessDay.values()) + .filter(b -> b.getDayOfWeek().equals(dayOfWeek)) + .findFirst() + .orElse(BusinessDay.NONE); + } + } diff --git a/src/main/java/com/backend/domain/store/entity/Store.java b/src/main/java/com/backend/domain/store/entity/Store.java index 60207cc..c4164d0 100644 --- a/src/main/java/com/backend/domain/store/entity/Store.java +++ b/src/main/java/com/backend/domain/store/entity/Store.java @@ -15,7 +15,8 @@ @AllArgsConstructor public class Store extends BaseEntity { - @Id @GeneratedValue + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long storeId; private String name; @@ -37,6 +38,9 @@ public class Store extends BaseEntity { private String phoneNumber; + @OneToMany(mappedBy = "store", cascade = CascadeType.PERSIST, orphanRemoval = true) + private List businessHours = new ArrayList<>(); + @OneToMany(mappedBy = "store") private List contracts = new ArrayList<>(); diff --git a/src/main/java/com/backend/domain/store/repository/StoreRepository.java b/src/main/java/com/backend/domain/store/repository/StoreRepository.java new file mode 100644 index 0000000..8591a71 --- /dev/null +++ b/src/main/java/com/backend/domain/store/repository/StoreRepository.java @@ -0,0 +1,7 @@ +package com.backend.domain.store.repository; + +import com.backend.domain.store.entity.Store; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface StoreRepository extends JpaRepository { +} diff --git a/src/main/java/com/backend/domain/store/service/StoreService.java b/src/main/java/com/backend/domain/store/service/StoreService.java new file mode 100644 index 0000000..df56a86 --- /dev/null +++ b/src/main/java/com/backend/domain/store/service/StoreService.java @@ -0,0 +1,32 @@ +package com.backend.domain.store.service; + +import com.backend.domain.store.dto.CreateStoreRequest; +import com.backend.domain.store.entity.Category; +import com.backend.domain.store.entity.Store; +import com.backend.domain.store.repository.StoreRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@Transactional +@RequiredArgsConstructor +public class StoreService { + + private final StoreRepository storeRepository; + + public void createStore(CreateStoreRequest request) { + Category category = request.getCategory(); + List stores = request.getData().stream() + .map(dto -> dto.toEntity(category)) + .peek(store -> { + store.getBusinessHours() + .forEach(businessHour -> businessHour.setStore(store)); + }) + .toList(); + storeRepository.saveAll(stores); + } + +} From e0c8ea74d6205c09c3733584f71c987d6c227054 Mon Sep 17 00:00:00 2001 From: yeop0740 Date: Sat, 18 Nov 2023 01:31:25 +0900 Subject: [PATCH 04/13] =?UTF-8?q?feat:=20Store=20=EC=83=81=EC=84=B8=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=A1=B0=ED=9A=8C=20API=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../store/controller/StoreController.java | 8 +++ .../domain/store/dto/BusinessHourDto.java | 29 ++++++++++ .../domain/store/dto/ReadStoreDetailsDto.java | 54 +++++++++++++++++++ .../domain/store/dto/StoreDetailsDto.java | 26 +++++++++ .../repository/BusinessHourRepository.java | 12 +++++ .../store/repository/StoreRepository.java | 29 ++++++++++ .../domain/store/service/StoreService.java | 18 +++++++ 7 files changed, 176 insertions(+) create mode 100644 src/main/java/com/backend/domain/store/dto/BusinessHourDto.java create mode 100644 src/main/java/com/backend/domain/store/dto/ReadStoreDetailsDto.java create mode 100644 src/main/java/com/backend/domain/store/dto/StoreDetailsDto.java create mode 100644 src/main/java/com/backend/domain/store/repository/BusinessHourRepository.java diff --git a/src/main/java/com/backend/domain/store/controller/StoreController.java b/src/main/java/com/backend/domain/store/controller/StoreController.java index 2a768c0..7429add 100644 --- a/src/main/java/com/backend/domain/store/controller/StoreController.java +++ b/src/main/java/com/backend/domain/store/controller/StoreController.java @@ -1,6 +1,8 @@ package com.backend.domain.store.controller; import com.backend.common.dto.ResponseDto; +import com.backend.domain.auth.dto.Login; +import com.backend.domain.auth.dto.LoginUser; import com.backend.domain.store.dto.*; import com.backend.domain.store.service.StoreService; import lombok.RequiredArgsConstructor; @@ -20,4 +22,10 @@ public ResponseEntity createStore(@RequestBody CreateStoreRequest request) return ResponseDto.created(); } + // TODO useremail을 바탕으로 university의 longitude, latitude 정보를 가져와서 이용한다. + @GetMapping("/details/{storeId}") + public ResponseEntity readStoreDetails(@Login LoginUser loginUser, @PathVariable Long storeId) { + return ResponseDto.ok(storeService.readStoreDetails(loginUser, storeId)); + } + } diff --git a/src/main/java/com/backend/domain/store/dto/BusinessHourDto.java b/src/main/java/com/backend/domain/store/dto/BusinessHourDto.java new file mode 100644 index 0000000..30760e5 --- /dev/null +++ b/src/main/java/com/backend/domain/store/dto/BusinessHourDto.java @@ -0,0 +1,29 @@ +package com.backend.domain.store.dto; + +import com.backend.domain.store.entity.BusinessHour; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class BusinessHourDto { + + private String dayOfWeek; + + private String openingTime; + + private String closingTime; + + public static BusinessHourDto from(BusinessHour businessHour) { + return BusinessHourDto.builder() + .dayOfWeek(businessHour.getDayOfWeek().getDayOfWeek()) + .openingTime(businessHour.getOpeningTime()) + .closingTime(businessHour.getClosingTime()) + .build(); + } + +} diff --git a/src/main/java/com/backend/domain/store/dto/ReadStoreDetailsDto.java b/src/main/java/com/backend/domain/store/dto/ReadStoreDetailsDto.java new file mode 100644 index 0000000..5563568 --- /dev/null +++ b/src/main/java/com/backend/domain/store/dto/ReadStoreDetailsDto.java @@ -0,0 +1,54 @@ +package com.backend.domain.store.dto; + +import com.backend.domain.store.entity.BusinessHour; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ReadStoreDetailsDto { + + private Long storeId; + + private String storeName; + + private String category; + + private String description; + + private String address; + + private List businessHours; + + private String phoneNumber; + + private Double distance; + + private String mapUrl; + + private boolean isPicked; + + public static ReadStoreDetailsDto from(StoreDetailsDto store, List businessHours) { + return ReadStoreDetailsDto.builder() + .storeId(store.getStoreId()) + .storeName(store.getStoreName()) + .category(store.getCategory().getCategoryName()) + .description(store.getDescription()) + .address(store.getAddress()) + .phoneNumber(store.getPhoneNumber()) + .distance(store.getDistance()) + .mapUrl(store.getMapUrl()) + .isPicked(store.getIsPicked()) + .businessHours(businessHours.stream() + .map(BusinessHourDto::from) + .toList()) + .build(); + } + +} diff --git a/src/main/java/com/backend/domain/store/dto/StoreDetailsDto.java b/src/main/java/com/backend/domain/store/dto/StoreDetailsDto.java new file mode 100644 index 0000000..b4d2564 --- /dev/null +++ b/src/main/java/com/backend/domain/store/dto/StoreDetailsDto.java @@ -0,0 +1,26 @@ +package com.backend.domain.store.dto; + + +import com.backend.domain.store.entity.Category; + +public interface StoreDetailsDto { + + Long getStoreId(); + + String getStoreName(); + + String getDescription(); + + Boolean getIsPicked(); + + Category getCategory(); + + String getAddress(); + + String getPhoneNumber(); + + Double getDistance(); + + String getMapUrl(); + +} diff --git a/src/main/java/com/backend/domain/store/repository/BusinessHourRepository.java b/src/main/java/com/backend/domain/store/repository/BusinessHourRepository.java new file mode 100644 index 0000000..d5970fc --- /dev/null +++ b/src/main/java/com/backend/domain/store/repository/BusinessHourRepository.java @@ -0,0 +1,12 @@ +package com.backend.domain.store.repository; + +import com.backend.domain.store.entity.BusinessHour; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface BusinessHourRepository extends JpaRepository { + + List findByStoreStoreId(Long storeId); + +} diff --git a/src/main/java/com/backend/domain/store/repository/StoreRepository.java b/src/main/java/com/backend/domain/store/repository/StoreRepository.java index 8591a71..88fd0c7 100644 --- a/src/main/java/com/backend/domain/store/repository/StoreRepository.java +++ b/src/main/java/com/backend/domain/store/repository/StoreRepository.java @@ -1,7 +1,36 @@ package com.backend.domain.store.repository; +import com.backend.domain.store.dto.StoreDetailsDto; import com.backend.domain.store.entity.Store; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.Optional; public interface StoreRepository extends JpaRepository { + + @Query( + value = + "SELECT" + + " s.store_id AS storeId," + + " s.name as storeName," + + " s.description as description," + + " IF(p.pick_id IS NOT NULL, 'true', 'false') AS isPicked," + + " s.category as category," + + " s.address as address," + + " s.phone_number as phoneNumber," + + " ST_Distance_Sphere(point(s.longitude, s.latitude), point(:longitude, :latitude)) as distance," + + " s.map_url as mapUrl" + + " FROM store s" + + " LEFT JOIN pick p ON s.store_id = p.store_id AND p.user_id = :userId" + + " LEFT JOIN contract c ON s.store_id = c.store_id" + + " WHERE c.contract_id IS NULL AND s.store_id = :storeId", + nativeQuery = true + ) + Optional findStoreDetailById(@Param("userId") Long userId, + @Param("storeId") Long storeId, + @Param("latitude") Double latitude, + @Param("longitude") Double longitude); + } diff --git a/src/main/java/com/backend/domain/store/service/StoreService.java b/src/main/java/com/backend/domain/store/service/StoreService.java index df56a86..4624343 100644 --- a/src/main/java/com/backend/domain/store/service/StoreService.java +++ b/src/main/java/com/backend/domain/store/service/StoreService.java @@ -1,9 +1,16 @@ package com.backend.domain.store.service; +import com.backend.domain.auth.dto.LoginUser; import com.backend.domain.store.dto.CreateStoreRequest; +import com.backend.domain.store.dto.ReadStoreDetailsDto; +import com.backend.domain.store.dto.StoreDetailsDto; +import com.backend.domain.store.entity.BusinessHour; import com.backend.domain.store.entity.Category; import com.backend.domain.store.entity.Store; +import com.backend.domain.store.repository.BusinessHourRepository; import com.backend.domain.store.repository.StoreRepository; +import com.backend.domain.user.entity.User; +import com.backend.domain.user.repository.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -17,6 +24,10 @@ public class StoreService { private final StoreRepository storeRepository; + private final BusinessHourRepository businessHourRepository; + + private final UserRepository userRepository; + public void createStore(CreateStoreRequest request) { Category category = request.getCategory(); List stores = request.getData().stream() @@ -29,4 +40,11 @@ public void createStore(CreateStoreRequest request) { storeRepository.saveAll(stores); } + public ReadStoreDetailsDto readStoreDetails(LoginUser loginUser, Long storeId) { + User user = userRepository.findByEmail(loginUser.getEmail()).orElseThrow(RuntimeException::new); + StoreDetailsDto storeDetail = storeRepository.findStoreDetailById(user.getId(), storeId, user.getUniversity().getLatitude(), user.getUniversity().getLongitude()).orElseThrow(RuntimeException::new); + List businessHours = businessHourRepository.findByStoreStoreId(storeId); + return ReadStoreDetailsDto.from(storeDetail, businessHours); + } + } From 2087677b7d74e1113f50b501ebe4a26bdbef8509 Mon Sep 17 00:00:00 2001 From: yeop0740 Date: Sat, 18 Nov 2023 01:40:51 +0900 Subject: [PATCH 05/13] =?UTF-8?q?feat:=20Pick=20=EB=93=B1=EB=A1=9D=20API?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/store/controller/StoreController.java | 6 ++++++ .../domain/store/dto/CreatePickRequest.java | 14 ++++++++++++++ .../java/com/backend/domain/store/entity/Pick.java | 12 ++++++++++++ .../com/backend/domain/store/entity/Store.java | 4 ++++ .../domain/store/repository/PickRepository.java | 13 +++++++++++++ .../backend/domain/store/service/StoreService.java | 14 ++++++++++++++ .../java/com/backend/domain/user/entity/User.java | 12 ++++++++++++ 7 files changed, 75 insertions(+) create mode 100644 src/main/java/com/backend/domain/store/dto/CreatePickRequest.java create mode 100644 src/main/java/com/backend/domain/store/repository/PickRepository.java diff --git a/src/main/java/com/backend/domain/store/controller/StoreController.java b/src/main/java/com/backend/domain/store/controller/StoreController.java index 7429add..1f5b504 100644 --- a/src/main/java/com/backend/domain/store/controller/StoreController.java +++ b/src/main/java/com/backend/domain/store/controller/StoreController.java @@ -28,4 +28,10 @@ public ResponseEntity readStoreDetails(@Login LoginUser log return ResponseDto.ok(storeService.readStoreDetails(loginUser, storeId)); } + @PostMapping("/pick") + public ResponseEntity createPick(@Login LoginUser loginUser, @RequestBody CreatePickRequest request) { + storeService.createPick(loginUser, request); + return ResponseDto.created(); + } + } diff --git a/src/main/java/com/backend/domain/store/dto/CreatePickRequest.java b/src/main/java/com/backend/domain/store/dto/CreatePickRequest.java new file mode 100644 index 0000000..5a4d773 --- /dev/null +++ b/src/main/java/com/backend/domain/store/dto/CreatePickRequest.java @@ -0,0 +1,14 @@ +package com.backend.domain.store.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class CreatePickRequest { + + private Long storeId; + +} diff --git a/src/main/java/com/backend/domain/store/entity/Pick.java b/src/main/java/com/backend/domain/store/entity/Pick.java index ed7807b..75c5f6c 100644 --- a/src/main/java/com/backend/domain/store/entity/Pick.java +++ b/src/main/java/com/backend/domain/store/entity/Pick.java @@ -3,8 +3,14 @@ import com.backend.common.domain.BaseEntity; import com.backend.domain.user.entity.User; import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; @Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) public class Pick extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -18,4 +24,10 @@ public class Pick extends BaseEntity { @JoinColumn(name = "user_id") private User user; + @Builder + public Pick(Store store, User user) { + this.store = store; + this.user = user; + } + } diff --git a/src/main/java/com/backend/domain/store/entity/Store.java b/src/main/java/com/backend/domain/store/entity/Store.java index c4164d0..e3fc8cf 100644 --- a/src/main/java/com/backend/domain/store/entity/Store.java +++ b/src/main/java/com/backend/domain/store/entity/Store.java @@ -47,4 +47,8 @@ public class Store extends BaseEntity { @OneToMany(mappedBy = "store") private List picks = new ArrayList<>(); + public void add(Pick pick) { + picks.add(pick); + } + } diff --git a/src/main/java/com/backend/domain/store/repository/PickRepository.java b/src/main/java/com/backend/domain/store/repository/PickRepository.java new file mode 100644 index 0000000..b9f91d1 --- /dev/null +++ b/src/main/java/com/backend/domain/store/repository/PickRepository.java @@ -0,0 +1,13 @@ +package com.backend.domain.store.repository; + +import com.backend.domain.store.entity.Pick; +import com.backend.domain.store.entity.Store; +import com.backend.domain.user.entity.User; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface PickRepository extends JpaRepository { + Optional findByUserAndStore(User user, Store store); + +} diff --git a/src/main/java/com/backend/domain/store/service/StoreService.java b/src/main/java/com/backend/domain/store/service/StoreService.java index 4624343..5707eaf 100644 --- a/src/main/java/com/backend/domain/store/service/StoreService.java +++ b/src/main/java/com/backend/domain/store/service/StoreService.java @@ -1,13 +1,16 @@ package com.backend.domain.store.service; import com.backend.domain.auth.dto.LoginUser; +import com.backend.domain.store.dto.CreatePickRequest; import com.backend.domain.store.dto.CreateStoreRequest; import com.backend.domain.store.dto.ReadStoreDetailsDto; import com.backend.domain.store.dto.StoreDetailsDto; import com.backend.domain.store.entity.BusinessHour; import com.backend.domain.store.entity.Category; +import com.backend.domain.store.entity.Pick; import com.backend.domain.store.entity.Store; import com.backend.domain.store.repository.BusinessHourRepository; +import com.backend.domain.store.repository.PickRepository; import com.backend.domain.store.repository.StoreRepository; import com.backend.domain.user.entity.User; import com.backend.domain.user.repository.UserRepository; @@ -28,6 +31,8 @@ public class StoreService { private final UserRepository userRepository; + private final PickRepository pickRepository; + public void createStore(CreateStoreRequest request) { Category category = request.getCategory(); List stores = request.getData().stream() @@ -47,4 +52,13 @@ public ReadStoreDetailsDto readStoreDetails(LoginUser loginUser, Long storeId) { return ReadStoreDetailsDto.from(storeDetail, businessHours); } + public void createPick(LoginUser loginUser, CreatePickRequest request) { + User user = userRepository.findByEmail(loginUser.getEmail()).orElseThrow(RuntimeException::new); + Store store = storeRepository.findById(request.getStoreId()).orElseThrow(RuntimeException::new); + pickRepository.findByUserAndStore(user, store).ifPresent(pick -> { + throw new RuntimeException(); + }); + Pick pick = user.createPick(store); + pickRepository.save(pick); + } } diff --git a/src/main/java/com/backend/domain/user/entity/User.java b/src/main/java/com/backend/domain/user/entity/User.java index d4b69bc..a60eb07 100644 --- a/src/main/java/com/backend/domain/user/entity/User.java +++ b/src/main/java/com/backend/domain/user/entity/User.java @@ -2,6 +2,7 @@ import com.backend.common.domain.BaseEntity; import com.backend.domain.store.entity.Pick; +import com.backend.domain.store.entity.Store; import com.backend.domain.university.entity.University; import jakarta.persistence.*; import lombok.AccessLevel; @@ -63,4 +64,15 @@ public void invalidateRefreshToken() { public void deleteProofImage() { this.proofImageUrl = null; } + + public Pick createPick(Store store) { + Pick pick = Pick.builder() + .user(this) + .store(store) + .build(); + picks.add(pick); + store.add(pick); + return pick; + } + } \ No newline at end of file From 93fa12dc367d7bde981a3e437f68961ff290ac2d Mon Sep 17 00:00:00 2001 From: yeop0740 Date: Sat, 18 Nov 2023 01:52:56 +0900 Subject: [PATCH 06/13] =?UTF-8?q?feat:=20Pick=20=EC=B7=A8=EC=86=8C=20API?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/backend/common/dto/ResponseDto.java | 6 ++++++ .../domain/store/controller/StoreController.java | 8 +++++++- .../{CreatePickRequest.java => PickRequest.java} | 2 +- .../java/com/backend/domain/store/entity/Pick.java | 6 ++++++ .../java/com/backend/domain/store/entity/Store.java | 4 ++++ .../backend/domain/store/service/StoreService.java | 13 +++++++++++-- .../java/com/backend/domain/user/entity/User.java | 5 +++++ 7 files changed, 40 insertions(+), 4 deletions(-) rename src/main/java/com/backend/domain/store/dto/{CreatePickRequest.java => PickRequest.java} (85%) diff --git a/src/main/java/com/backend/common/dto/ResponseDto.java b/src/main/java/com/backend/common/dto/ResponseDto.java index 3792dc2..4ab8300 100644 --- a/src/main/java/com/backend/common/dto/ResponseDto.java +++ b/src/main/java/com/backend/common/dto/ResponseDto.java @@ -10,6 +10,12 @@ public static ResponseEntity ok(T data) { return ResponseEntity.ok(data); } + public static ResponseEntity ok() { + return ResponseEntity + .status(HttpStatus.CREATED) + .build(); + } + public static ResponseEntity created(T data) { return ResponseEntity .status(HttpStatus.CREATED) diff --git a/src/main/java/com/backend/domain/store/controller/StoreController.java b/src/main/java/com/backend/domain/store/controller/StoreController.java index 1f5b504..da4823b 100644 --- a/src/main/java/com/backend/domain/store/controller/StoreController.java +++ b/src/main/java/com/backend/domain/store/controller/StoreController.java @@ -29,9 +29,15 @@ public ResponseEntity readStoreDetails(@Login LoginUser log } @PostMapping("/pick") - public ResponseEntity createPick(@Login LoginUser loginUser, @RequestBody CreatePickRequest request) { + public ResponseEntity createPick(@Login LoginUser loginUser, @RequestBody PickRequest request) { storeService.createPick(loginUser, request); return ResponseDto.created(); } + @DeleteMapping("/pick") + public ResponseEntity deletePick(@Login LoginUser loginUser, @RequestBody PickRequest request) { + storeService.deletePick(loginUser, request); + return ResponseDto.ok(); + } + } diff --git a/src/main/java/com/backend/domain/store/dto/CreatePickRequest.java b/src/main/java/com/backend/domain/store/dto/PickRequest.java similarity index 85% rename from src/main/java/com/backend/domain/store/dto/CreatePickRequest.java rename to src/main/java/com/backend/domain/store/dto/PickRequest.java index 5a4d773..3c35545 100644 --- a/src/main/java/com/backend/domain/store/dto/CreatePickRequest.java +++ b/src/main/java/com/backend/domain/store/dto/PickRequest.java @@ -7,7 +7,7 @@ @Data @NoArgsConstructor @AllArgsConstructor -public class CreatePickRequest { +public class PickRequest { private Long storeId; diff --git a/src/main/java/com/backend/domain/store/entity/Pick.java b/src/main/java/com/backend/domain/store/entity/Pick.java index 75c5f6c..9b207d5 100644 --- a/src/main/java/com/backend/domain/store/entity/Pick.java +++ b/src/main/java/com/backend/domain/store/entity/Pick.java @@ -30,4 +30,10 @@ public Pick(Store store, User user) { this.user = user; } + public void delete() { + this.store.delete(this); + this.store = null; + this.user = null; + } + } diff --git a/src/main/java/com/backend/domain/store/entity/Store.java b/src/main/java/com/backend/domain/store/entity/Store.java index e3fc8cf..d395317 100644 --- a/src/main/java/com/backend/domain/store/entity/Store.java +++ b/src/main/java/com/backend/domain/store/entity/Store.java @@ -51,4 +51,8 @@ public void add(Pick pick) { picks.add(pick); } + public void delete(Pick pick) { + picks.remove(pick); + } + } diff --git a/src/main/java/com/backend/domain/store/service/StoreService.java b/src/main/java/com/backend/domain/store/service/StoreService.java index 5707eaf..d7af5ec 100644 --- a/src/main/java/com/backend/domain/store/service/StoreService.java +++ b/src/main/java/com/backend/domain/store/service/StoreService.java @@ -1,7 +1,7 @@ package com.backend.domain.store.service; import com.backend.domain.auth.dto.LoginUser; -import com.backend.domain.store.dto.CreatePickRequest; +import com.backend.domain.store.dto.PickRequest; import com.backend.domain.store.dto.CreateStoreRequest; import com.backend.domain.store.dto.ReadStoreDetailsDto; import com.backend.domain.store.dto.StoreDetailsDto; @@ -52,7 +52,7 @@ public ReadStoreDetailsDto readStoreDetails(LoginUser loginUser, Long storeId) { return ReadStoreDetailsDto.from(storeDetail, businessHours); } - public void createPick(LoginUser loginUser, CreatePickRequest request) { + public void createPick(LoginUser loginUser, PickRequest request) { User user = userRepository.findByEmail(loginUser.getEmail()).orElseThrow(RuntimeException::new); Store store = storeRepository.findById(request.getStoreId()).orElseThrow(RuntimeException::new); pickRepository.findByUserAndStore(user, store).ifPresent(pick -> { @@ -61,4 +61,13 @@ public void createPick(LoginUser loginUser, CreatePickRequest request) { Pick pick = user.createPick(store); pickRepository.save(pick); } + + public void deletePick(LoginUser loginUser, PickRequest request) { + User user = userRepository.findByEmail(loginUser.getEmail()).orElseThrow(RuntimeException::new); + Store store = storeRepository.findById(request.getStoreId()).orElseThrow(RuntimeException::new); + Pick pick = pickRepository.findByUserAndStore(user, store).orElseThrow(RuntimeException::new); + user.delete(pick); + pickRepository.delete(pick); + } + } diff --git a/src/main/java/com/backend/domain/user/entity/User.java b/src/main/java/com/backend/domain/user/entity/User.java index a60eb07..3fb1f3e 100644 --- a/src/main/java/com/backend/domain/user/entity/User.java +++ b/src/main/java/com/backend/domain/user/entity/User.java @@ -75,4 +75,9 @@ public Pick createPick(Store store) { return pick; } + public void delete(Pick pick) { + pick.delete(); + picks.remove(pick); + } + } \ No newline at end of file From 3676f6a17f2e15143e19bee6441365f132ff746c Mon Sep 17 00:00:00 2001 From: yeop0740 Date: Sat, 18 Nov 2023 02:14:47 +0900 Subject: [PATCH 07/13] =?UTF-8?q?feat:=20Store=20=EB=AA=A9=EB=A1=9D=20?= =?UTF-8?q?=EA=B2=80=EC=83=89=20=EB=B0=8F=20=EC=A1=B0=ED=9A=8C=20API=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../store/controller/StoreController.java | 5 + .../domain/store/dto/ReadStoresDto.java | 34 +++++ .../domain/store/dto/ReadStoresRequest.java | 36 +++++ .../backend/domain/store/dto/StoresDto.java | 21 +++ .../store/repository/StoreRepository.java | 133 +++++++++++++++++- .../domain/store/service/StoreService.java | 33 ++++- 6 files changed, 251 insertions(+), 11 deletions(-) create mode 100644 src/main/java/com/backend/domain/store/dto/ReadStoresDto.java create mode 100644 src/main/java/com/backend/domain/store/dto/ReadStoresRequest.java create mode 100644 src/main/java/com/backend/domain/store/dto/StoresDto.java diff --git a/src/main/java/com/backend/domain/store/controller/StoreController.java b/src/main/java/com/backend/domain/store/controller/StoreController.java index da4823b..ad59209 100644 --- a/src/main/java/com/backend/domain/store/controller/StoreController.java +++ b/src/main/java/com/backend/domain/store/controller/StoreController.java @@ -28,6 +28,11 @@ public ResponseEntity readStoreDetails(@Login LoginUser log return ResponseDto.ok(storeService.readStoreDetails(loginUser, storeId)); } + @GetMapping("/search") + public ResponseEntity readStores(@Login LoginUser loginUser, @ModelAttribute ReadStoresRequest request) { + return ResponseDto.ok(storeService.readStores(loginUser, request)); + } + @PostMapping("/pick") public ResponseEntity createPick(@Login LoginUser loginUser, @RequestBody PickRequest request) { storeService.createPick(loginUser, request); diff --git a/src/main/java/com/backend/domain/store/dto/ReadStoresDto.java b/src/main/java/com/backend/domain/store/dto/ReadStoresDto.java new file mode 100644 index 0000000..9f9c379 --- /dev/null +++ b/src/main/java/com/backend/domain/store/dto/ReadStoresDto.java @@ -0,0 +1,34 @@ +package com.backend.domain.store.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.data.domain.Page; + +import java.util.List; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ReadStoresDto { + + private List stores; + + private int pageNumber; + + private Long totalCount; + + private boolean hasNext; + + public static ReadStoresDto from(Page stores) { + return ReadStoresDto.builder() + .stores(stores.getContent()) + .pageNumber(stores.getNumber()) + .totalCount(stores.getTotalElements()) + .hasNext(stores.hasNext()) + .build(); + } + +} diff --git a/src/main/java/com/backend/domain/store/dto/ReadStoresRequest.java b/src/main/java/com/backend/domain/store/dto/ReadStoresRequest.java new file mode 100644 index 0000000..78a8376 --- /dev/null +++ b/src/main/java/com/backend/domain/store/dto/ReadStoresRequest.java @@ -0,0 +1,36 @@ +package com.backend.domain.store.dto; + +import com.backend.domain.store.entity.Category; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ReadStoresRequest { + + private Boolean isPicked; + + private String name; + + private Category category; + + private int pageSize; + + private int pageNumber; + + { + pageSize = 40; + pageNumber = 0; + category = Category.NONE; + isPicked = false; + } + + public String getName() { + return name == null ? "" : name; + } + +} + + diff --git a/src/main/java/com/backend/domain/store/dto/StoresDto.java b/src/main/java/com/backend/domain/store/dto/StoresDto.java new file mode 100644 index 0000000..8e9bacf --- /dev/null +++ b/src/main/java/com/backend/domain/store/dto/StoresDto.java @@ -0,0 +1,21 @@ +package com.backend.domain.store.dto; + +import com.backend.domain.store.entity.Category; + +public interface StoresDto { + + Long getStoreId(); + + String getStoreName(); + + String getDescription(); + + String getAddress(); + + Category getCategory(); + + Double getDistance(); + + Boolean getIsPicked(); + +} diff --git a/src/main/java/com/backend/domain/store/repository/StoreRepository.java b/src/main/java/com/backend/domain/store/repository/StoreRepository.java index 88fd0c7..d723d48 100644 --- a/src/main/java/com/backend/domain/store/repository/StoreRepository.java +++ b/src/main/java/com/backend/domain/store/repository/StoreRepository.java @@ -1,7 +1,10 @@ package com.backend.domain.store.repository; import com.backend.domain.store.dto.StoreDetailsDto; +import com.backend.domain.store.dto.StoresDto; import com.backend.domain.store.entity.Store; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -14,14 +17,14 @@ public interface StoreRepository extends JpaRepository { value = "SELECT" + " s.store_id AS storeId," + - " s.name as storeName," + - " s.description as description," + + " s.name AS storeName," + + " s.description AS description," + " IF(p.pick_id IS NOT NULL, 'true', 'false') AS isPicked," + - " s.category as category," + - " s.address as address," + - " s.phone_number as phoneNumber," + - " ST_Distance_Sphere(point(s.longitude, s.latitude), point(:longitude, :latitude)) as distance," + - " s.map_url as mapUrl" + + " s.category AS category," + + " s.address AS address," + + " s.phone_number AS phoneNumber," + + " ST_Distance_Sphere(point(s.longitude, s.latitude), point(:longitude, :latitude)) AS distance," + + " s.map_url AS mapUrl" + " FROM store s" + " LEFT JOIN pick p ON s.store_id = p.store_id AND p.user_id = :userId" + " LEFT JOIN contract c ON s.store_id = c.store_id" + @@ -33,4 +36,120 @@ Optional findStoreDetailById(@Param("userId") Long userId, @Param("latitude") Double latitude, @Param("longitude") Double longitude); + @Query( + value = + "SELECT" + + " s.store_id AS storeId," + + " s.name AS storeName," + + " s.description AS description," + + " IF(p.pick_id IS NOT NULL, 'true', 'false') AS isPicked," + + " s.category AS category," + + " s.address AS address," + + " ST_Distance_Sphere(point(s.longitude, s.latitude), point(:longitude, :latitude)) AS distance" + + " FROM store s" + + " JOIN pick p ON s.store_id = p.store_id AND p.user_id = :userId" + + " LEFT JOIN contract c ON s.store_id = c.store_id" + + " WHERE c.contract_id IS NULL AND s.name LIKE :name" + + " ORDER BY distance IS NULL, distance", + countQuery = + "SELECT" + + " count(s.store_id) AS totalElements" + + " FROM store s" + + " JOIN pick p ON s.store_id = p.store_id AND p.user_id = :userId" + + " LEFT JOIN contract c ON s.store_id = c.store_id" + + " WHERE c.contract_id IS NULL AND s.name LIKE :name", + nativeQuery = true) + Page findAllContainsNameAndPicked(@Param("userId") Long userId, + @Param("longitude") Double longitude, + @Param("latitude") Double latitude, + @Param("name") String name, + Pageable pageable); + + @Query( + value = + "SELECT" + + " s.store_id AS storeId," + + " s.name AS storeName," + + " s.description AS description," + + " IF(p.pick_id IS NOT NULL, 'true', 'false') AS isPicked," + + " s.category AS category," + + " s.address AS address," + + " ST_Distance_Sphere(point(s.longitude, s.latitude), point(:longitude, :latitude)) AS distance" + + " FROM store s" + + " JOIN pick p ON s.store_id = p.store_id AND p.user_id = :userId" + + " LEFT JOIN contract c ON s.store_id = c.store_id" + + " WHERE c.contract_id IS NULL AND s.name LIKE :name AND s.category = :category" + + " ORDER BY distance IS NULL, distance", + countQuery = + "SELECT" + + " count(s.store_id) AS totalElements" + + " FROM store s" + + " JOIN pick p ON s.store_id = p.store_id AND p.user_id = :userId" + + " LEFT JOIN contract c ON s.store_id = c.store_id" + + " WHERE c.contract_id IS NULL AND s.name LIKE :name AND s.category = :category", + nativeQuery = true) + Page findAllContainsNameAndPickedAndCategory(@Param("userId") Long userId, + @Param("longitude") Double longitude, + @Param("latitude") Double latitude, + @Param("name") String name, + @Param("category") String category, + Pageable pageable); + + @Query( + value = + "SELECT" + + " s.store_id AS storeId," + + " s.name AS storeName," + + " s.description AS description," + + " IF(p.pick_id IS NOT NULL, 'true', 'false') AS isPicked," + + " s.category AS category," + + " s.address AS address," + + " ST_Distance_Sphere(point(s.longitude, s.latitude), point(:longitude, :latitude)) AS distance" + + " FROM store s" + + " LEFT JOIN pick p ON s.store_id = p.store_id AND p.user_id = :userId" + + " LEFT JOIN contract c ON s.store_id = c.store_id" + + " WHERE c.contract_id IS NULL AND s.name LIKE :name" + + " ORDER BY distance IS NULL, distance", + countQuery = + "SELECT" + + " count(s.store_id) AS totalElements" + + " FROM store s" + + " LEFT JOIN contract c ON s.store_id = c.store_id" + + " WHERE c.contract_id IS NULL AND s.name LIKE :name", + nativeQuery = true) + Page findAllContainsName(@Param("userId") Long userId, + @Param("longitude") Double longitude, + @Param("latitude") Double latitude, + @Param("name") String name, + Pageable pageable); + + @Query( + value = + "SELECT" + + " s.store_id AS storeId," + + " s.name AS storeName," + + " s.description AS description," + + " IF(p.pick_id IS NOT NULL, 'true', 'false') AS isPicked," + + " s.category AS category," + + " s.address AS address," + + " ST_Distance_Sphere(point(s.longitude, s.latitude), point(:longitude, :latitude)) AS distance" + + " FROM store s" + + " LEFT JOIN pick p ON s.store_id = p.store_id AND p.user_id = :userId" + + " LEFT JOIN contract c ON s.store_id = c.store_id" + + " WHERE c.contract_id IS NULL AND s.name LIKE :name AND s.category = :category" + + " ORDER BY distance IS NULL, distance", + countQuery = + "SELECT" + + " count(s.store_id) AS totalElements" + + " FROM store s" + + " LEFT JOIN contract c ON s.store_id = c.store_id" + + " WHERE c.contract_id IS NULL AND s.name LIKE :name AND s.category = :category", + nativeQuery = true) + Page findAllContainsNameAndCategory(@Param("userId") Long userId, + @Param("longitude") Double longitude, + @Param("latitude") Double latitude, + @Param("name") String name, + @Param("category") String category, + Pageable pageable); + } diff --git a/src/main/java/com/backend/domain/store/service/StoreService.java b/src/main/java/com/backend/domain/store/service/StoreService.java index d7af5ec..ff107ab 100644 --- a/src/main/java/com/backend/domain/store/service/StoreService.java +++ b/src/main/java/com/backend/domain/store/service/StoreService.java @@ -1,10 +1,7 @@ package com.backend.domain.store.service; import com.backend.domain.auth.dto.LoginUser; -import com.backend.domain.store.dto.PickRequest; -import com.backend.domain.store.dto.CreateStoreRequest; -import com.backend.domain.store.dto.ReadStoreDetailsDto; -import com.backend.domain.store.dto.StoreDetailsDto; +import com.backend.domain.store.dto.*; import com.backend.domain.store.entity.BusinessHour; import com.backend.domain.store.entity.Category; import com.backend.domain.store.entity.Pick; @@ -12,9 +9,12 @@ import com.backend.domain.store.repository.BusinessHourRepository; import com.backend.domain.store.repository.PickRepository; import com.backend.domain.store.repository.StoreRepository; +import com.backend.domain.university.entity.University; import com.backend.domain.user.entity.User; import com.backend.domain.user.repository.UserRepository; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -70,4 +70,29 @@ public void deletePick(LoginUser loginUser, PickRequest request) { pickRepository.delete(pick); } + public ReadStoresDto readStores(LoginUser loginUser, ReadStoresRequest request) { + User user = userRepository.findByEmail(loginUser.getEmail()).orElseThrow(RuntimeException::new); + University university = user.getUniversity(); + PageRequest pageRequest = PageRequest.of(request.getPageNumber(), request.getPageSize()); + String keyword = getKeyword(request); + if (request.getIsPicked()) { + if (request.getCategory().equals(Category.NONE)) { + Page stores = storeRepository.findAllContainsNameAndPicked(user.getId(), university.getLongitude(), university.getLatitude(), keyword, pageRequest); + return ReadStoresDto.from(stores); + } + Page stores = storeRepository.findAllContainsNameAndPickedAndCategory(user.getId(), university.getLongitude(), university.getLatitude(), keyword, request.getCategory().name(), pageRequest); + return ReadStoresDto.from(stores); + } + if (request.getCategory().equals(Category.NONE)) { + Page stores = storeRepository.findAllContainsName(user.getId(), university.getLongitude(), university.getLatitude(), keyword, pageRequest); + return ReadStoresDto.from(stores); + } + Page stores = storeRepository.findAllContainsNameAndCategory(user.getId(), university.getLongitude(), university.getLatitude(), keyword, request.getCategory().name(), pageRequest); + return ReadStoresDto.from(stores); + } + + private String getKeyword(ReadStoresRequest request) { + return "%" + request.getName() + "%"; + } + } From be2e7d50c8716058f549fae706097705a44dfa7a Mon Sep 17 00:00:00 2001 From: yeop0740 Date: Sat, 18 Nov 2023 13:53:56 +0900 Subject: [PATCH 08/13] =?UTF-8?q?feat:=20Swagger=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../store/controller/StoreController.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/main/java/com/backend/domain/store/controller/StoreController.java b/src/main/java/com/backend/domain/store/controller/StoreController.java index ad59209..94ffad3 100644 --- a/src/main/java/com/backend/domain/store/controller/StoreController.java +++ b/src/main/java/com/backend/domain/store/controller/StoreController.java @@ -5,6 +5,11 @@ import com.backend.domain.auth.dto.LoginUser; import com.backend.domain.store.dto.*; import com.backend.domain.store.service.StoreService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -12,6 +17,7 @@ @RestController @RequiredArgsConstructor @RequestMapping("/store") +@Tag(name = "가게", description = "가게 관련 API") public class StoreController { private final StoreService storeService; @@ -24,22 +30,46 @@ public ResponseEntity createStore(@RequestBody CreateStoreRequest request) // TODO useremail을 바탕으로 university의 longitude, latitude 정보를 가져와서 이용한다. @GetMapping("/details/{storeId}") + @Operation( + summary = "가게 상세 정보 조회", + responses = { + @ApiResponse( + responseCode = "200", + content = @Content(schema = @Schema(implementation = ReadStoreDetailsDto.class))) + }) public ResponseEntity readStoreDetails(@Login LoginUser loginUser, @PathVariable Long storeId) { return ResponseDto.ok(storeService.readStoreDetails(loginUser, storeId)); } @GetMapping("/search") + @Operation( + summary = "가게 목록 검색 및 조회", + responses = { + @ApiResponse( + responseCode = "200", + content = @Content(schema = @Schema(implementation = ReadStoresDto.class))) + }) public ResponseEntity readStores(@Login LoginUser loginUser, @ModelAttribute ReadStoresRequest request) { return ResponseDto.ok(storeService.readStores(loginUser, request)); } @PostMapping("/pick") + @Operation( + summary = "픽 등록", + responses = { + @ApiResponse(responseCode = "201") + }) public ResponseEntity createPick(@Login LoginUser loginUser, @RequestBody PickRequest request) { storeService.createPick(loginUser, request); return ResponseDto.created(); } @DeleteMapping("/pick") + @Operation( + summary = "픽 취소", + responses = { + @ApiResponse(responseCode = "200") + }) public ResponseEntity deletePick(@Login LoginUser loginUser, @RequestBody PickRequest request) { storeService.deletePick(loginUser, request); return ResponseDto.ok(); From 4b7c3980bf0fc197ae22622244daba2a43614f79 Mon Sep 17 00:00:00 2001 From: yeop0740 Date: Sat, 18 Nov 2023 15:46:27 +0900 Subject: [PATCH 09/13] =?UTF-8?q?fix:=20=EB=AC=BC=EB=A6=AC=EC=A0=81=20?= =?UTF-8?q?=EC=97=94=ED=8B=B0=ED=8B=B0=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/backend/domain/benefit/entity/Benefit.java | 3 +++ src/main/java/com/backend/domain/contract/entity/Contract.java | 1 + .../java/com/backend/domain/store/entity/BusinessHour.java | 1 + src/main/java/com/backend/domain/store/entity/Pick.java | 1 + src/main/java/com/backend/domain/store/entity/Store.java | 1 + .../java/com/backend/domain/university/entity/University.java | 1 + 6 files changed, 8 insertions(+) diff --git a/src/main/java/com/backend/domain/benefit/entity/Benefit.java b/src/main/java/com/backend/domain/benefit/entity/Benefit.java index 521e2d7..53228aa 100644 --- a/src/main/java/com/backend/domain/benefit/entity/Benefit.java +++ b/src/main/java/com/backend/domain/benefit/entity/Benefit.java @@ -3,10 +3,13 @@ import com.backend.common.domain.BaseEntity; import com.backend.domain.contract.entity.Contract; import jakarta.persistence.*; +import lombok.AccessLevel; import lombok.Getter; +import lombok.NoArgsConstructor; @Entity @Getter +@Table(name = "benefit") public class Benefit extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/com/backend/domain/contract/entity/Contract.java b/src/main/java/com/backend/domain/contract/entity/Contract.java index 01b36ba..feb4205 100644 --- a/src/main/java/com/backend/domain/contract/entity/Contract.java +++ b/src/main/java/com/backend/domain/contract/entity/Contract.java @@ -16,6 +16,7 @@ @Builder @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor +@Table(name = "contract") public class Contract extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/com/backend/domain/store/entity/BusinessHour.java b/src/main/java/com/backend/domain/store/entity/BusinessHour.java index 1a2d4ec..c361e2d 100644 --- a/src/main/java/com/backend/domain/store/entity/BusinessHour.java +++ b/src/main/java/com/backend/domain/store/entity/BusinessHour.java @@ -9,6 +9,7 @@ @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) +@Table(name = "businesshour") public class BusinessHour { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/com/backend/domain/store/entity/Pick.java b/src/main/java/com/backend/domain/store/entity/Pick.java index 9b207d5..0202bca 100644 --- a/src/main/java/com/backend/domain/store/entity/Pick.java +++ b/src/main/java/com/backend/domain/store/entity/Pick.java @@ -11,6 +11,7 @@ @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) +@Table(name = "pick") public class Pick extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/com/backend/domain/store/entity/Store.java b/src/main/java/com/backend/domain/store/entity/Store.java index d395317..87b859d 100644 --- a/src/main/java/com/backend/domain/store/entity/Store.java +++ b/src/main/java/com/backend/domain/store/entity/Store.java @@ -13,6 +13,7 @@ @Builder @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor +@Table(name = "store") public class Store extends BaseEntity { @Id diff --git a/src/main/java/com/backend/domain/university/entity/University.java b/src/main/java/com/backend/domain/university/entity/University.java index f99634b..058c4bf 100644 --- a/src/main/java/com/backend/domain/university/entity/University.java +++ b/src/main/java/com/backend/domain/university/entity/University.java @@ -13,6 +13,7 @@ @Builder @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor +@Table(name = "university") public class University { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) From 180a976945ece7a682d29f9efb3b15d2e5aa1348 Mon Sep 17 00:00:00 2001 From: yeop0740 Date: Sat, 18 Nov 2023 16:43:15 +0900 Subject: [PATCH 10/13] =?UTF-8?q?fix:=20native=20query=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/store/repository/StoreRepository.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/backend/domain/store/repository/StoreRepository.java b/src/main/java/com/backend/domain/store/repository/StoreRepository.java index d723d48..7fd516a 100644 --- a/src/main/java/com/backend/domain/store/repository/StoreRepository.java +++ b/src/main/java/com/backend/domain/store/repository/StoreRepository.java @@ -19,7 +19,7 @@ public interface StoreRepository extends JpaRepository { " s.store_id AS storeId," + " s.name AS storeName," + " s.description AS description," + - " IF(p.pick_id IS NOT NULL, 'true', 'false') AS isPicked," + + " CASE WHEN p.pick_id IS NOT NULL THEN 'TRUE' ELSE 'FALSE' END AS isPicked," + " s.category AS category," + " s.address AS address," + " s.phone_number AS phoneNumber," + @@ -42,7 +42,7 @@ Optional findStoreDetailById(@Param("userId") Long userId, " s.store_id AS storeId," + " s.name AS storeName," + " s.description AS description," + - " IF(p.pick_id IS NOT NULL, 'true', 'false') AS isPicked," + + " CASE WHEN p.pick_id IS NOT NULL THEN 'TRUE' ELSE 'FALSE' END AS isPicked," + " s.category AS category," + " s.address AS address," + " ST_Distance_Sphere(point(s.longitude, s.latitude), point(:longitude, :latitude)) AS distance" + @@ -71,7 +71,7 @@ Page findAllContainsNameAndPicked(@Param("userId") Long userId, " s.store_id AS storeId," + " s.name AS storeName," + " s.description AS description," + - " IF(p.pick_id IS NOT NULL, 'true', 'false') AS isPicked," + + " CASE WHEN p.pick_id IS NOT NULL THEN 'TRUE' ELSE 'FALSE' END AS isPicked," + " s.category AS category," + " s.address AS address," + " ST_Distance_Sphere(point(s.longitude, s.latitude), point(:longitude, :latitude)) AS distance" + @@ -101,7 +101,7 @@ Page findAllContainsNameAndPickedAndCategory(@Param("userId") Long us " s.store_id AS storeId," + " s.name AS storeName," + " s.description AS description," + - " IF(p.pick_id IS NOT NULL, 'true', 'false') AS isPicked," + + " CASE WHEN p.pick_id IS NOT NULL THEN 'TRUE' ELSE 'FALSE' END AS isPicked," + " s.category AS category," + " s.address AS address," + " ST_Distance_Sphere(point(s.longitude, s.latitude), point(:longitude, :latitude)) AS distance" + @@ -129,7 +129,7 @@ Page findAllContainsName(@Param("userId") Long userId, " s.store_id AS storeId," + " s.name AS storeName," + " s.description AS description," + - " IF(p.pick_id IS NOT NULL, 'true', 'false') AS isPicked," + + " CASE WHEN p.pick_id IS NOT NULL THEN 'TRUE' ELSE 'FALSE' END AS isPicked," + " s.category AS category," + " s.address AS address," + " ST_Distance_Sphere(point(s.longitude, s.latitude), point(:longitude, :latitude)) AS distance" + From d8d149ca357913e59a10ed3bbe53df77671fed32 Mon Sep 17 00:00:00 2001 From: yeop0740 Date: Sat, 18 Nov 2023 22:44:09 +0900 Subject: [PATCH 11/13] =?UTF-8?q?feat:=20Swagger=20=EA=B3=84=EC=A0=95=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EA=B0=9D=EC=B2=B4=20=EC=A0=9C=EC=99=B8,?= =?UTF-8?q?=20=EC=9D=B8=EC=A6=9D=20=ED=97=A4=EB=8D=94=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../store/controller/StoreController.java | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/backend/domain/store/controller/StoreController.java b/src/main/java/com/backend/domain/store/controller/StoreController.java index 94ffad3..6eb3d88 100644 --- a/src/main/java/com/backend/domain/store/controller/StoreController.java +++ b/src/main/java/com/backend/domain/store/controller/StoreController.java @@ -6,9 +6,11 @@ import com.backend.domain.store.dto.*; import com.backend.domain.store.service.StoreService; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -17,6 +19,7 @@ @RestController @RequiredArgsConstructor @RequestMapping("/store") +@SecurityRequirement(name = "bearer-key") @Tag(name = "가게", description = "가게 관련 API") public class StoreController { @@ -29,17 +32,17 @@ public ResponseEntity createStore(@RequestBody CreateStoreRequest request) } // TODO useremail을 바탕으로 university의 longitude, latitude 정보를 가져와서 이용한다. - @GetMapping("/details/{storeId}") - @Operation( - summary = "가게 상세 정보 조회", - responses = { - @ApiResponse( - responseCode = "200", - content = @Content(schema = @Schema(implementation = ReadStoreDetailsDto.class))) - }) - public ResponseEntity readStoreDetails(@Login LoginUser loginUser, @PathVariable Long storeId) { - return ResponseDto.ok(storeService.readStoreDetails(loginUser, storeId)); - } + @GetMapping("/details/{storeId}") + @Operation( + summary = "가게 상세 정보 조회", + responses = { + @ApiResponse( + responseCode = "200", + content = @Content(schema = @Schema(implementation = ReadStoreDetailsDto.class))) + }) + public ResponseEntity readStoreDetails(@Parameter(hidden = true) @Login LoginUser loginUser, @Parameter(name = "storeId") @PathVariable Long storeId) { + return ResponseDto.ok(storeService.readStoreDetails(loginUser, storeId)); + } @GetMapping("/search") @Operation( @@ -49,7 +52,7 @@ public ResponseEntity readStoreDetails(@Login LoginUser log responseCode = "200", content = @Content(schema = @Schema(implementation = ReadStoresDto.class))) }) - public ResponseEntity readStores(@Login LoginUser loginUser, @ModelAttribute ReadStoresRequest request) { + public ResponseEntity readStores(@Parameter(hidden = true) @Login LoginUser loginUser, @ModelAttribute ReadStoresRequest request) { return ResponseDto.ok(storeService.readStores(loginUser, request)); } @@ -59,7 +62,7 @@ public ResponseEntity readStores(@Login LoginUser loginUser, @Mod responses = { @ApiResponse(responseCode = "201") }) - public ResponseEntity createPick(@Login LoginUser loginUser, @RequestBody PickRequest request) { + public ResponseEntity createPick(@Parameter(hidden = true) @Login LoginUser loginUser, @RequestBody PickRequest request) { storeService.createPick(loginUser, request); return ResponseDto.created(); } @@ -70,7 +73,7 @@ public ResponseEntity createPick(@Login LoginUser loginUser, @RequestBody responses = { @ApiResponse(responseCode = "200") }) - public ResponseEntity deletePick(@Login LoginUser loginUser, @RequestBody PickRequest request) { + public ResponseEntity deletePick(@Parameter(hidden = true) @Login LoginUser loginUser, @RequestBody PickRequest request) { storeService.deletePick(loginUser, request); return ResponseDto.ok(); } From 695d1bf371f3e8ec9867dcda2ca4c4f552d2b617 Mon Sep 17 00:00:00 2001 From: yeop0740 Date: Sun, 19 Nov 2023 17:18:57 +0900 Subject: [PATCH 12/13] =?UTF-8?q?feat:=20Swagger=20=EC=9A=94=EC=B2=AD?= =?UTF-8?q?=EC=8B=9C=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EB=B6=80?= =?UTF-8?q?=EC=97=B0=20=EC=84=A4=EB=AA=85=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/store/controller/StoreController.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/backend/domain/store/controller/StoreController.java b/src/main/java/com/backend/domain/store/controller/StoreController.java index 6eb3d88..6570453 100644 --- a/src/main/java/com/backend/domain/store/controller/StoreController.java +++ b/src/main/java/com/backend/domain/store/controller/StoreController.java @@ -31,7 +31,6 @@ public ResponseEntity createStore(@RequestBody CreateStoreRequest request) return ResponseDto.created(); } - // TODO useremail을 바탕으로 university의 longitude, latitude 정보를 가져와서 이용한다. @GetMapping("/details/{storeId}") @Operation( summary = "가게 상세 정보 조회", @@ -47,6 +46,13 @@ public ResponseEntity readStoreDetails(@Parameter(hidden = @GetMapping("/search") @Operation( summary = "가게 목록 검색 및 조회", + description = + "

{url}/store/search?isPicked=true&name=건&category=FOOD&pageSize=40&pageNumber=0

" + + "

isPicked = true/false, default = false

" + + "

name = String 타입의 가게 명, 입력하지 않아도 사용 가능

" + + "

category = [FOOD, CAFE, BEAUTY, CULTURE, ETC, NONE] 중 하나, default = NONE(카테고리 검색X)

" + + "

pageSize = int 값, default = 40

" + + "

pageNumber = 0부터 int 값, default = 0

", responses = { @ApiResponse( responseCode = "200", From a55912d7677e89f5ac3a7180a7267553d4b6a620 Mon Sep 17 00:00:00 2001 From: yeop0740 Date: Sun, 19 Nov 2023 17:55:49 +0900 Subject: [PATCH 13/13] =?UTF-8?q?feat:=20swagger=20=EC=84=9C=EB=B2=84=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/backend/config/SwaggerConfig.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/com/backend/config/SwaggerConfig.java b/src/main/java/com/backend/config/SwaggerConfig.java index a7c78d9..c76ed11 100644 --- a/src/main/java/com/backend/config/SwaggerConfig.java +++ b/src/main/java/com/backend/config/SwaggerConfig.java @@ -5,18 +5,28 @@ import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.security.SecurityScheme; +import io.swagger.v3.oas.models.servers.Server; import org.springdoc.core.utils.SpringDocUtils; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.time.LocalTime; import java.time.format.DateTimeFormatter; +import java.util.List; + +import static org.springdoc.core.utils.Constants.DEFAULT_SERVER_DESCRIPTION; @Configuration public class SwaggerConfig { + + @Value("${swagger.request-server}") + private String SERVER_BASE_URL; + @Bean public OpenAPI openAPI() { return new OpenAPI() + .servers(List.of(new Server().url(SERVER_BASE_URL).description(DEFAULT_SERVER_DESCRIPTION))) .components(new Components() .addSecuritySchemes("bearer-key", new SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("bearer").bearerFormat("JWT")))