diff --git a/src/main/java/org/jullaene/walkmong_back/api/board/domain/Board.java b/src/main/java/org/jullaene/walkmong_back/api/board/domain/Board.java index d0ee707..f37fccf 100644 --- a/src/main/java/org/jullaene/walkmong_back/api/board/domain/Board.java +++ b/src/main/java/org/jullaene/walkmong_back/api/board/domain/Board.java @@ -26,9 +26,6 @@ public class Board extends BaseEntity { @Comment("반려동물 아이디") private Long dogId; - @Comment("반려인 아이디") - private Long ownerId; - @Comment("반려인 주소 아이디") private Long ownerAddressId; @@ -57,5 +54,18 @@ public class Board extends BaseEntity { @Enumerated(EnumType.STRING) private WalkingStatus walkingStatus; + @Builder + public Board (BoardRequestDto boardRequestDto, String content) { + this.dogId = boardRequestDto.getDogId(); + this.ownerAddressId = boardRequestDto.getAddressId(); + this.content = content; + this.matchingYn = "N"; + this.startTime = boardRequestDto.getStartTime(); + this.endTime = boardRequestDto.getEndTime(); + this.locationNegotiationYn = boardRequestDto.getLocationNegotiationYn(); + this.preMeetAvailableYn = boardRequestDto.getPreMeetAvailableYn(); + this.walkingStatus = WalkingStatus.BEFORE; + } + } diff --git a/src/main/java/org/jullaene/walkmong_back/api/board/dto/req/BoardRequestDto.java b/src/main/java/org/jullaene/walkmong_back/api/board/dto/req/BoardRequestDto.java new file mode 100644 index 0000000..17ecd3b --- /dev/null +++ b/src/main/java/org/jullaene/walkmong_back/api/board/dto/req/BoardRequestDto.java @@ -0,0 +1,28 @@ +package org.jullaene.walkmong_back.api.board.dto.req; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.time.LocalDateTime; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class BoardRequestDto { + private Long dogId; + + private Long addressId; + + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") + private LocalDateTime startTime; + + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") + private LocalDateTime endTime; + + private String locationNegotiationYn; + + private String preMeetAvailableYn; +} + diff --git a/src/main/java/org/jullaene/walkmong_back/api/board/dto/res/.gitkeep b/src/main/java/org/jullaene/walkmong_back/api/board/dto/res/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/org/jullaene/walkmong_back/api/board/dto/res/BoardDetailResponseDto.java b/src/main/java/org/jullaene/walkmong_back/api/board/dto/res/BoardDetailResponseDto.java new file mode 100644 index 0000000..e3cbfef --- /dev/null +++ b/src/main/java/org/jullaene/walkmong_back/api/board/dto/res/BoardDetailResponseDto.java @@ -0,0 +1,38 @@ +package org.jullaene.walkmong_back.api.board.dto.res; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.jullaene.walkmong_back.api.dog.domain.enums.DogSize; +import org.jullaene.walkmong_back.common.enums.Gender; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class BoardDetailResponseDto { + + private Long dogId; + private String dogName; + private String dogProfile; + private Gender dogGender; + private Integer dogAge; + private String breed; + private Double weight; + private DogSize dogSize; + private String dongAddress; + private Double distance; + private String date; + private String startTime; + private String endTime; + private String locationNegotiationYn; + private String preMeetAvailableYn; + private String walkNote; + private String walkRequest; + private String additionalRequest; + private String ownerName; + private Integer ownerAge; + private Gender ownerGender; + private String ownerProfile; +} diff --git a/src/main/java/org/jullaene/walkmong_back/api/board/dto/res/BoardResponseDto.java b/src/main/java/org/jullaene/walkmong_back/api/board/dto/res/BoardResponseDto.java new file mode 100644 index 0000000..9b34e4b --- /dev/null +++ b/src/main/java/org/jullaene/walkmong_back/api/board/dto/res/BoardResponseDto.java @@ -0,0 +1,18 @@ +package org.jullaene.walkmong_back.api.board.dto.res; + +import lombok.Builder; +import org.jullaene.walkmong_back.api.dog.domain.enums.DogSize; +import org.jullaene.walkmong_back.common.enums.Gender; + +import java.time.LocalDateTime; + +public record BoardResponseDto(Long boardId, String startTime, String endTime, String matchingYn, + String dogName, String dogProfile, + Gender dogGender, String breed, Double weight, + DogSize dogSize, String content, + String dongAddress, Double distance, LocalDateTime createdAt) { + + @Builder + public BoardResponseDto { + } +} diff --git a/src/main/java/org/jullaene/walkmong_back/api/board/repository/BoardRepository.java b/src/main/java/org/jullaene/walkmong_back/api/board/repository/BoardRepository.java index b27a723..e5a67a1 100644 --- a/src/main/java/org/jullaene/walkmong_back/api/board/repository/BoardRepository.java +++ b/src/main/java/org/jullaene/walkmong_back/api/board/repository/BoardRepository.java @@ -5,5 +5,6 @@ import org.springframework.stereotype.Repository; @Repository -public interface BoardRepository extends JpaRepository { +public interface BoardRepository extends JpaRepository, BoardRepositoryCustom { + } diff --git a/src/main/java/org/jullaene/walkmong_back/api/board/repository/BoardRepositoryCustom.java b/src/main/java/org/jullaene/walkmong_back/api/board/repository/BoardRepositoryCustom.java new file mode 100644 index 0000000..f7a0edb --- /dev/null +++ b/src/main/java/org/jullaene/walkmong_back/api/board/repository/BoardRepositoryCustom.java @@ -0,0 +1,17 @@ +package org.jullaene.walkmong_back.api.board.repository; + +import org.jullaene.walkmong_back.api.board.dto.res.BoardDetailResponseDto; +import org.jullaene.walkmong_back.api.board.dto.res.BoardResponseDto; +import org.jullaene.walkmong_back.api.dog.domain.enums.DogSize; +import org.jullaene.walkmong_back.api.member.domain.Address; +import org.jullaene.walkmong_back.api.member.domain.enums.DistanceRange; + +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; + +public interface BoardRepositoryCustom { + List getBoardsWithFilters(LocalDate date, Address walkerAddress, DistanceRange distance, DogSize dogSize, String matchingYn); + boolean existsByBoardIdAndMemberIdAndDelYn(Long boardId, Long memberId, String delYn); + Optional getBoardDetailResponse(Long boardId, Long memberId, String delYn); +} diff --git a/src/main/java/org/jullaene/walkmong_back/api/board/repository/impl/BoardRepositoryImpl.java b/src/main/java/org/jullaene/walkmong_back/api/board/repository/impl/BoardRepositoryImpl.java new file mode 100644 index 0000000..663123b --- /dev/null +++ b/src/main/java/org/jullaene/walkmong_back/api/board/repository/impl/BoardRepositoryImpl.java @@ -0,0 +1,233 @@ +package org.jullaene.walkmong_back.api.board.repository.impl; + +import com.querydsl.core.BooleanBuilder; +import com.querydsl.core.types.Ops; +import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.core.types.dsl.Expressions; +import com.querydsl.core.types.dsl.NumberTemplate; +import com.querydsl.core.types.dsl.StringTemplate; +import com.querydsl.jpa.JPAExpressions; +import com.querydsl.jpa.impl.JPAQueryFactory; +import lombok.extern.slf4j.Slf4j; +import org.jullaene.walkmong_back.api.board.domain.QBoard; +import org.jullaene.walkmong_back.api.board.dto.res.BoardDetailResponseDto; +import org.jullaene.walkmong_back.api.board.dto.res.BoardResponseDto; +import org.jullaene.walkmong_back.api.board.repository.BoardRepositoryCustom; +import org.jullaene.walkmong_back.api.dog.domain.QDog; +import org.jullaene.walkmong_back.api.dog.domain.enums.DogSize; +import org.jullaene.walkmong_back.api.member.domain.Address; +import org.jullaene.walkmong_back.api.member.domain.QAddress; +import org.jullaene.walkmong_back.api.member.domain.QMember; +import org.jullaene.walkmong_back.api.member.domain.enums.DistanceRange; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +import static com.querydsl.core.types.dsl.Expressions.numberTemplate; + +@Slf4j +public class BoardRepositoryImpl implements BoardRepositoryCustom { + + private final JPAQueryFactory queryFactory; + + public BoardRepositoryImpl(JPAQueryFactory queryFactory) { + this.queryFactory = queryFactory; + } + + @Override + public List getBoardsWithFilters(LocalDate date, Address walkerAddress, DistanceRange distance, DogSize dogSize, String matchingYn) { + QBoard board = QBoard.board; + QDog dog = QDog.dog; + QAddress ownerAddress = QAddress.address; + + BooleanBuilder builder = new BooleanBuilder(); + + // date가 null이면 당일을 조건에 삽입 + if (date == null) { + date = LocalDate.now(); + } + LocalDateTime startOfDay = date.atStartOfDay(); + LocalDateTime endOfDay = date.atTime(23, 59, 59, 999_999_999); + + builder.and(board.startTime.between(startOfDay, endOfDay)); + + if (dogSize != null) { + builder.and(board.dogId.in( + JPAExpressions.select(dog.dogId) + .from(dog) + .where(dog.dogSize.eq(dogSize)))); + } + + if (matchingYn != null) { + builder.and(board.matchingYn.eq(matchingYn)); + } + + if (distance == null) { + distance = walkerAddress.getDistanceRange(); + } + + // 거리 계산 + NumberTemplate distanceExpression = numberTemplate( + Double.class, + "ST_Distance_Sphere(point({0}, {1}), point({2}, {3}))", + JPAExpressions.select(ownerAddress.longitude) + .from(ownerAddress) + .where(ownerAddress.addressId.eq(board.ownerAddressId)), + JPAExpressions.select(ownerAddress.latitude) + .from(ownerAddress) + .where(ownerAddress.addressId.eq(board.ownerAddressId)), + walkerAddress.getLongitude(), + walkerAddress.getLatitude() + ); + + BooleanExpression isWithinRange = distanceExpression.lt(distance.getRange()); + + StringTemplate startTimeExpression = Expressions.stringTemplate( + "DATE_FORMAT({0}, '%H:%i')", + board.startTime + ); + StringTemplate endTimeExpression = Expressions.stringTemplate( + "DATE_FORMAT({0}, '%H:%i')", + board.endTime + ); + + + // 필터링된 board들을 바로 결과로 조회 + return queryFactory.select( + Projections.constructor(BoardResponseDto.class, + board.boardId.as("boardId"), + startTimeExpression.as("startTime"), + endTimeExpression.as("endTime"), + board.matchingYn.as("matchingYn"), + dog.name.as("dogName"), + dog.profile.as("dogProfile"), + dog.gender.as("dogGender"), + dog.breed.as("breed"), + dog.weight.as("weight"), + dog.dogSize.as("dogSize"), + board.content.as("content"), + ownerAddress.dongAddress.as("dongAddress"), + distanceExpression.as("distance"), + board.createdAt.as("createdAt") + ) + ) + .from(board) + .leftJoin(dog).on(dog.dogId.eq(board.dogId)) + .leftJoin(ownerAddress).on(ownerAddress.addressId.eq(board.ownerAddressId)) + .where(builder) + .where(isWithinRange) + .orderBy(board.startTime.asc()) + .fetch(); + } + + /** + * boardId와 memberId를 기준으로 해당 게시글의 작성자인지 확인 + * */ + @Override + public boolean existsByBoardIdAndMemberIdAndDelYn(Long boardId, Long memberId, String delYn) { + QBoard board = QBoard.board; + QDog dog = QDog.dog; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(board.boardId.eq(boardId)); + builder.and(board.delYn.eq(delYn)); + builder.and(dog.memberId.eq(memberId)); + + long count = queryFactory + .selectFrom(board) + .join(dog).on(board.dogId.eq(dog.dogId).and(dog.delYn.eq(delYn))) + .where(builder) + .fetch() + .size(); + + return count > 0; + } + + + @Override + public Optional getBoardDetailResponse(Long boardId, Long memberId, String delYn) { + QDog dog= QDog.dog; + QAddress address=QAddress.address; + QBoard board= QBoard.board; + QMember member=QMember.member; + int currentYear = LocalDate.now().getYear() + 1; + + + StringTemplate startTimeExpression = Expressions.stringTemplate( + "DATE_FORMAT({0}, '%H:%i')", + board.startTime + ); + StringTemplate endTimeExpression = Expressions.stringTemplate( + "DATE_FORMAT({0}, '%H:%i')", + board.endTime + ); + + StringTemplate dateExpression = Expressions.stringTemplate( + "DATE_FORMAT({0}, '%Y-%m-%d')", + board.startTime + ); + + // 숫자 형식의 생년월일에서 연도 추출 (YYYYMMDD / 10000 = YYYY) + NumberTemplate birthYearExpression = Expressions.numberTemplate(Integer.class, + "FLOOR({0} / 10000)", + member.birthDate + ); + +// // 거리 계산 +// NumberTemplate distanceExpression = numberTemplate( +// Double.class, +// "ST_Distance_Sphere(point({0}, {1}), point({2}, {3}))", +// JPAExpressions.select(ownerAddress.longitude) +// .from(ownerAddress) +// .where(ownerAddress.addressId.eq(board.ownerAddressId)), +// JPAExpressions.select(ownerAddress.latitude) +// .from(ownerAddress) +// .where(ownerAddress.addressId.eq(board.ownerAddressId)), +// walkerAddress.getLongitude(), +// walkerAddress.getLatitude() +// ); + double distance = 500; + + System.out.println(currentYear); + return + Optional.ofNullable(queryFactory.select( + Projections.constructor(BoardDetailResponseDto.class, + dog.dogId.as("dogId"), + dog.name.as("dogName"), + dog.profile.as("dogProfile"), + dog.gender.as("dogGender"), + Expressions.numberOperation(Integer.class, Ops.SUB, + Expressions.constant(currentYear), dog.birthYear).as("dogAge"), + dog.breed.as("breed"), + dog.weight.as("weight"), + dog.dogSize.as("dogSize"), + address.dongAddress.as("dongAddress"), + Expressions.constant(distance), + dateExpression.as("date"), + startTimeExpression.as("startTime"), + endTimeExpression.as("endTime"), + board.locationNegotiationYn.as("locationNegotiationYn"), + board.preMeetAvailableYn.as("preMeetAvailableYn"), + dog.walkNote.as("walkNote"), + dog.walkRequest.as("walkRequest"), + dog.additionalRequest.as("additionalRequest"), + member.name.as("ownerName"), + Expressions.numberOperation(Integer.class, Ops.SUB, + Expressions.constant(currentYear), + birthYearExpression).as("ownerAge"), + member.gender.as("ownerGender"), + member.profile.as("ownerProfile") + + )) + .from(board) + .leftJoin(dog).on(dog.dogId.eq(board.dogId)) + .leftJoin(member).on(dog.memberId.eq(member.memberId)) + .leftJoin(address).on(address.addressId.eq(board.ownerAddressId)) + .where(board.boardId.eq(boardId) + .and(board.delYn.eq(delYn))) + .fetchOne()); + } +} diff --git a/src/main/java/org/jullaene/walkmong_back/api/board/rest/BoardController.java b/src/main/java/org/jullaene/walkmong_back/api/board/rest/BoardController.java index dad0f9b..6187ce4 100644 --- a/src/main/java/org/jullaene/walkmong_back/api/board/rest/BoardController.java +++ b/src/main/java/org/jullaene/walkmong_back/api/board/rest/BoardController.java @@ -2,9 +2,18 @@ import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import org.jullaene.walkmong_back.api.board.dto.req.BoardRequestDto; +import org.jullaene.walkmong_back.api.board.dto.res.BoardDetailResponseDto; +import org.jullaene.walkmong_back.api.board.dto.res.BoardResponseDto; import org.jullaene.walkmong_back.api.board.service.BoardService; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.jullaene.walkmong_back.api.dog.domain.enums.DogSize; +import org.jullaene.walkmong_back.api.member.domain.enums.DistanceRange; +import org.jullaene.walkmong_back.common.BasicResponse; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDate; +import java.util.List; @Tag(name = "Board", description = "게시글 정보 관련 api 입니다.") @RestController @@ -12,4 +21,26 @@ @RequestMapping("/api/v1/board") public class BoardController { private final BoardService boardService; + + @GetMapping("/list") + public ResponseEntity>> getBoards ( + @RequestParam(name = "date", required = false) LocalDate date, + @RequestParam(name = "addressId", required = false) Long addressId, + @RequestParam(name = "distance", required = false) DistanceRange distance, + @RequestParam(name = "dogSize", required = false) DogSize dogSize, + @RequestParam(name = "matchingYn", required = false) String matchingYn + ) { + return ResponseEntity.ok(BasicResponse.ofSuccess(boardService.getBoards(date, addressId, distance, dogSize, matchingYn))); + } + + @GetMapping("/detail/{boardId}") + public ResponseEntity> getBoardDetails(@PathVariable("boardId") Long boardId){ + return ResponseEntity.ok(BasicResponse.ofSuccess(boardService.getBoardDetail(boardId))); + } + + @PostMapping("/register") + public ResponseEntity> createBoard(@RequestBody BoardRequestDto boardRequestDto) { + return ResponseEntity.ok(BasicResponse.ofCreateSuccess(boardService.createBoard(boardRequestDto))); + } + } diff --git a/src/main/java/org/jullaene/walkmong_back/api/board/service/BoardService.java b/src/main/java/org/jullaene/walkmong_back/api/board/service/BoardService.java index 689c391..080369b 100644 --- a/src/main/java/org/jullaene/walkmong_back/api/board/service/BoardService.java +++ b/src/main/java/org/jullaene/walkmong_back/api/board/service/BoardService.java @@ -1,11 +1,100 @@ package org.jullaene.walkmong_back.api.board.service; +import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; +import org.jullaene.walkmong_back.api.board.domain.Board; +import org.jullaene.walkmong_back.api.board.dto.req.BoardRequestDto; +import org.jullaene.walkmong_back.api.board.dto.res.BoardDetailResponseDto; +import org.jullaene.walkmong_back.api.board.dto.res.BoardResponseDto; import org.jullaene.walkmong_back.api.board.repository.BoardRepository; +import org.jullaene.walkmong_back.api.dog.domain.Dog; +import org.jullaene.walkmong_back.api.dog.domain.enums.DogSize; +import org.jullaene.walkmong_back.api.dog.repository.DogRepository; +import org.jullaene.walkmong_back.api.member.domain.Address; +import org.jullaene.walkmong_back.api.member.domain.Member; +import org.jullaene.walkmong_back.api.member.domain.enums.DistanceRange; +import org.jullaene.walkmong_back.api.member.repository.AddressRepository; +import org.jullaene.walkmong_back.api.member.service.MemberService; +import org.jullaene.walkmong_back.common.exception.CustomException; +import org.jullaene.walkmong_back.common.exception.ErrorType; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; +import java.time.LocalDate; +import java.util.List; + @Service @RequiredArgsConstructor public class BoardService { private final BoardRepository boardRepository; + private final AddressRepository addressRepository; + private final MemberService memberService; + private final DogRepository dogRepository; + + /** + * 게시글 리스트 조회 + * */ + public List getBoards(LocalDate date, Long addressId, DistanceRange distance, DogSize dogSize, String matchingYn) { + Member member = memberService.getMemberFromUserDetail(); + + // 주소 id가 null이면 기본 주소 반환, 주소 id가 null이 아니면 해당 id를 가진 주소 반환 + Address address; + if (addressId == null) { + address = getBasicAddressAndDelYn(member.getMemberId(), "N"); + } + else { + address = getAddressByIdAndDelYn(addressId, "N"); + } + return boardRepository.getBoardsWithFilters(date, address, distance, dogSize, matchingYn); + } + + public BoardDetailResponseDto getBoardDetail(Long boardId) { + Member member = memberService.getMemberFromUserDetail(); + + return boardRepository.getBoardDetailResponse(boardId,member.getMemberId(), "N") + .orElseThrow(()->new CustomException(HttpStatus.BAD_REQUEST,ErrorType.INVALID_ADDRESS)); + } + + /** + * 주어진 멤버가 가진 기본 address를 반환 + * */ + private Address getBasicAddressAndDelYn(Long memberId, String delYn) { + return addressRepository.findByMemberIdAndBasicAddressYnAndDelYn(memberId,"Y", delYn) + .orElseThrow(() -> new CustomException(HttpStatus.NOT_FOUND, ErrorType.INVALID_ADDRESS)); + } + + /** + * 주어진 addressId를 이용하여 address 반환 + * */ + private Address getAddressByIdAndDelYn (Long addressId, String delYn) { + + return addressRepository.findByAddressIdAndDelYn(addressId, delYn) + .orElseThrow(() -> new CustomException(HttpStatus.NOT_FOUND, ErrorType.INVALID_ADDRESS)); + + } + + @Transactional + public Long createBoard(BoardRequestDto boardRequestDto) { + Member member = memberService.getMemberFromUserDetail(); + + List
addresses = addressRepository.findByMemberIdAndDelYn(member.getMemberId(), "N"); + + boolean isAddressValid = addresses.stream() + .anyMatch(address -> address.getAddressId().equals(boardRequestDto.getAddressId())); + + if (!isAddressValid) { + throw new CustomException(HttpStatus.NOT_FOUND, ErrorType.INVALID_ADDRESS); + } + + Dog dog = dogRepository.findByDogIdAndDelYn(boardRequestDto.getDogId(), "N") + .orElseThrow(() -> new CustomException(HttpStatus.NOT_FOUND, ErrorType.DOG_NOT_FOUND)); + + Board board = Board.builder() + .boardRequestDto(boardRequestDto) + .content(dog.getWalkRequestContent()) + .build(); + + return boardRepository.save(board).getBoardId(); + } + } diff --git a/src/main/java/org/jullaene/walkmong_back/api/dog/domain/Dog.java b/src/main/java/org/jullaene/walkmong_back/api/dog/domain/Dog.java index 21055b3..9d83225 100644 --- a/src/main/java/org/jullaene/walkmong_back/api/dog/domain/Dog.java +++ b/src/main/java/org/jullaene/walkmong_back/api/dog/domain/Dog.java @@ -2,10 +2,17 @@ import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.Table; +import java.time.LocalDate; + +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; import org.hibernate.annotations.Comment; import org.hibernate.annotations.DynamicUpdate; import org.jullaene.walkmong_back.api.dog.domain.enums.DogSize; @@ -14,9 +21,11 @@ @Table(name = "dog") @Entity +@NoArgsConstructor @DynamicUpdate public class Dog extends BaseEntity { @Id + @Getter @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "dog_id") private Long dogId; @@ -28,6 +37,7 @@ public class Dog extends BaseEntity { private String name; @Comment("성별") + @Enumerated(EnumType.STRING) private Gender gender; @Comment("출생년도") @@ -40,6 +50,7 @@ public class Dog extends BaseEntity { private String breed; @Comment("사이즈") + @Enumerated(EnumType.STRING) private DogSize dogSize; @Comment("프로필 url") @@ -74,4 +85,32 @@ public class Dog extends BaseEntity { @Comment("추가 안내 사항") private String additionalRequest; + + public final String getWalkRequestContent() { + return this.walkRequest; + } + + @Builder + public Dog(Long memberId,String name, + DogSize dogSize, String profile, + Gender gender, Integer birthYear, + String breed, Double weight, + String neuteringYn, String bite, + String friendly, String barking, + String rabiesYn, String adultYn){ + this.name=name; + this.memberId=memberId; + this.dogSize=dogSize; + this.profile=profile; + this.gender=gender; + this.birthYear=birthYear; + this.breed=breed; + this.weight=weight; + this.neuteringYn=neuteringYn; + this.bite = bite; + this.friendly=friendly; + this.barking = barking; + this.rabiesYn=rabiesYn; + this.adultYn=adultYn; + } } diff --git a/src/main/java/org/jullaene/walkmong_back/api/dog/repository/DogRepository.java b/src/main/java/org/jullaene/walkmong_back/api/dog/repository/DogRepository.java index 04e7fb4..7544fbc 100644 --- a/src/main/java/org/jullaene/walkmong_back/api/dog/repository/DogRepository.java +++ b/src/main/java/org/jullaene/walkmong_back/api/dog/repository/DogRepository.java @@ -4,6 +4,9 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository public interface DogRepository extends JpaRepository { + Optional findByDogIdAndDelYn(Long dogId, String delYn); } diff --git a/src/main/java/org/jullaene/walkmong_back/api/member/domain/Address.java b/src/main/java/org/jullaene/walkmong_back/api/member/domain/Address.java index 89ae4f7..7dbb1b0 100644 --- a/src/main/java/org/jullaene/walkmong_back/api/member/domain/Address.java +++ b/src/main/java/org/jullaene/walkmong_back/api/member/domain/Address.java @@ -1,14 +1,11 @@ package org.jullaene.walkmong_back.api.member.domain; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.Table; +import jakarta.persistence.*; +import lombok.Getter; import org.hibernate.annotations.Comment; import org.hibernate.annotations.DynamicUpdate; import org.jullaene.walkmong_back.api.member.domain.enums.DistanceRange; +import org.jullaene.walkmong_back.api.member.dto.res.AddressResponseDto; import org.jullaene.walkmong_back.common.BaseEntity; @Table(name = "address") @@ -16,6 +13,7 @@ @DynamicUpdate public class Address extends BaseEntity { @Id + @Getter @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "address_id") private Long addressId; @@ -23,9 +21,11 @@ public class Address extends BaseEntity { @Comment("사용자 아이디") private Long memberId; + @Getter @Comment("위도") private Double latitude; + @Getter @Comment("경도") private Double longitude; @@ -35,6 +35,8 @@ public class Address extends BaseEntity { @Comment("동 주소") private String dongAddress; + @Getter + @Enumerated(EnumType.STRING) @Comment("거리 범위") private DistanceRange distanceRange; @@ -42,4 +44,11 @@ public class Address extends BaseEntity { @Column(columnDefinition = "VARCHAR(1) default 'Y'") private String basicAddressYn; + public final AddressResponseDto toAddressResponseDto() { + return AddressResponseDto.builder() + .addressId(this.addressId) + .dongAddress(this.dongAddress) + .build(); + } + } diff --git a/src/main/java/org/jullaene/walkmong_back/api/member/domain/enums/DistanceRange.java b/src/main/java/org/jullaene/walkmong_back/api/member/domain/enums/DistanceRange.java index 8493ab1..09340d4 100644 --- a/src/main/java/org/jullaene/walkmong_back/api/member/domain/enums/DistanceRange.java +++ b/src/main/java/org/jullaene/walkmong_back/api/member/domain/enums/DistanceRange.java @@ -1,9 +1,9 @@ package org.jullaene.walkmong_back.api.member.domain.enums; public enum DistanceRange { - SMALL(0.5), - MEDIUM(1.0), - BIG(1.5), + SMALL(500.0), + MEDIUM(1000.0), + BIG(1500.0), ; private final Double range; diff --git a/src/main/java/org/jullaene/walkmong_back/api/member/dto/res/AddressResponseDto.java b/src/main/java/org/jullaene/walkmong_back/api/member/dto/res/AddressResponseDto.java new file mode 100644 index 0000000..9e8cc38 --- /dev/null +++ b/src/main/java/org/jullaene/walkmong_back/api/member/dto/res/AddressResponseDto.java @@ -0,0 +1,11 @@ +package org.jullaene.walkmong_back.api.member.dto.res; + +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class AddressResponseDto { + private Long addressId; + private String dongAddress; +} diff --git a/src/main/java/org/jullaene/walkmong_back/api/member/repository/AddressRepository.java b/src/main/java/org/jullaene/walkmong_back/api/member/repository/AddressRepository.java index 676f36b..a24a329 100644 --- a/src/main/java/org/jullaene/walkmong_back/api/member/repository/AddressRepository.java +++ b/src/main/java/org/jullaene/walkmong_back/api/member/repository/AddressRepository.java @@ -1,9 +1,15 @@ package org.jullaene.walkmong_back.api.member.repository; +import java.util.List; import org.jullaene.walkmong_back.api.member.domain.Address; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository public interface AddressRepository extends JpaRepository { + Optional
findByAddressIdAndDelYn(Long addressId, String delYn); + Optional
findByMemberIdAndBasicAddressYnAndDelYn(Long memberId, String basicAddressYn, String delYn); + List
findByMemberIdAndDelYn(Long memberId, String delYn); } diff --git a/src/main/java/org/jullaene/walkmong_back/api/member/rest/AddressController.java b/src/main/java/org/jullaene/walkmong_back/api/member/rest/AddressController.java index 5007828..ae939e5 100644 --- a/src/main/java/org/jullaene/walkmong_back/api/member/rest/AddressController.java +++ b/src/main/java/org/jullaene/walkmong_back/api/member/rest/AddressController.java @@ -1,8 +1,15 @@ package org.jullaene.walkmong_back.api.member.rest; import io.swagger.v3.oas.annotations.tags.Tag; +import java.util.List; import lombok.RequiredArgsConstructor; +import org.jullaene.walkmong_back.api.member.domain.Member; +import org.jullaene.walkmong_back.api.member.dto.res.AddressResponseDto; import org.jullaene.walkmong_back.api.member.service.AddressService; +import org.jullaene.walkmong_back.api.member.service.MemberService; +import org.jullaene.walkmong_back.common.BasicResponse; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -12,4 +19,11 @@ @RequestMapping("/api/v1/address") public class AddressController { private final AddressService addressService; + private final MemberService memberService; + + @GetMapping("/list") + public ResponseEntity>> getAddressList() { + Member member = memberService.getMemberFromUserDetail(); + return ResponseEntity.ok(BasicResponse.ofSuccess(addressService.getAddresses(member.getMemberId()))); + } } diff --git a/src/main/java/org/jullaene/walkmong_back/api/member/service/AddressService.java b/src/main/java/org/jullaene/walkmong_back/api/member/service/AddressService.java index 2edca05..b669feb 100644 --- a/src/main/java/org/jullaene/walkmong_back/api/member/service/AddressService.java +++ b/src/main/java/org/jullaene/walkmong_back/api/member/service/AddressService.java @@ -1,6 +1,10 @@ package org.jullaene.walkmong_back.api.member.service; +import java.util.List; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; +import org.jullaene.walkmong_back.api.member.domain.Address; +import org.jullaene.walkmong_back.api.member.dto.res.AddressResponseDto; import org.jullaene.walkmong_back.api.member.repository.AddressRepository; import org.springframework.stereotype.Service; @@ -8,4 +12,11 @@ @RequiredArgsConstructor public class AddressService { private final AddressRepository addressRepository; + + public List getAddresses(Long memberId) { + List
addresses = addressRepository.findByMemberIdAndDelYn(memberId, "N"); + return addresses.stream() + .map(Address::toAddressResponseDto) + .collect(Collectors.toList()); + } } diff --git a/src/main/java/org/jullaene/walkmong_back/api/member/service/MemberService.java b/src/main/java/org/jullaene/walkmong_back/api/member/service/MemberService.java index bf50eab..a91e894 100644 --- a/src/main/java/org/jullaene/walkmong_back/api/member/service/MemberService.java +++ b/src/main/java/org/jullaene/walkmong_back/api/member/service/MemberService.java @@ -1,11 +1,31 @@ package org.jullaene.walkmong_back.api.member.service; import lombok.RequiredArgsConstructor; +import org.jullaene.walkmong_back.api.member.domain.Member; import org.jullaene.walkmong_back.api.member.repository.MemberRepository; +import org.jullaene.walkmong_back.common.exception.CustomException; +import org.jullaene.walkmong_back.common.user.CustomUserDetail; +import org.springframework.http.HttpStatus; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; +import static org.jullaene.walkmong_back.common.exception.ErrorType.USER_NOT_AUTHENTICATED; + @Service @RequiredArgsConstructor public class MemberService { private final MemberRepository memberRepository; + + /** + * CustomUserDetail에서 member 가져오기 + * */ + public Member getMemberFromUserDetail () { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + if (authentication != null && authentication.getPrincipal() instanceof CustomUserDetail customUserDetail) { + return customUserDetail.getMember(); // member 객체 가져오기 + } + throw new CustomException(HttpStatus.UNAUTHORIZED, USER_NOT_AUTHENTICATED); + } } diff --git a/src/main/java/org/jullaene/walkmong_back/common/exception/ErrorType.java b/src/main/java/org/jullaene/walkmong_back/common/exception/ErrorType.java index 3a81491..c01bf27 100644 --- a/src/main/java/org/jullaene/walkmong_back/common/exception/ErrorType.java +++ b/src/main/java/org/jullaene/walkmong_back/common/exception/ErrorType.java @@ -18,6 +18,8 @@ public enum ErrorType { INVALID_TOKEN("유효하지 않은 토큰입니다."), INTERNAL_SERVER("서버 오류입니다."), UNAUTHORIZED_UPDATE("수정 권한이 없는 유저입니다."), + DOG_NOT_FOUND("존재하지 않는 강아지입니다."), + INVALID_ADDRESS("유효하지 않은 주소입니다."), ; private String message; diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index e3dd542..d4b2aba 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,3 +1,3 @@ spring: application.name: walkmong_back - profiles.active: local \ No newline at end of file + profiles.active: dev \ No newline at end of file