Skip to content

Commit

Permalink
✨feat: 기록하기 API
Browse files Browse the repository at this point in the history
  • Loading branch information
youngreal committed Aug 26, 2024
1 parent 7e7893a commit 26e8614
Show file tree
Hide file tree
Showing 13 changed files with 384 additions and 3 deletions.
20 changes: 18 additions & 2 deletions src/main/java/com/dnd/dndtravel/map/controller/MapController.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
package com.dnd.dndtravel.map.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;

import com.dnd.dndtravel.map.controller.request.RecordRequest;
import com.dnd.dndtravel.map.service.MapService;
import com.dnd.dndtravel.map.service.dto.response.RegionResponse;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;

@RestController
Expand All @@ -23,4 +30,13 @@ public RegionResponse map() {
Long memberId = 1L;
return mapService.allRegions(memberId);
}

@PostMapping("/maps/record")
public void memo(
@RequestPart("photos") List<MultipartFile> photos,
@RequestPart("recordRequest") RecordRequest recordRequest
) {
Long memberId = 1L;
mapService.recordAttraction(recordRequest.toDto(photos), memberId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.dnd.dndtravel.map.controller.request;

import java.time.LocalDate;
import java.util.List;

import org.springframework.web.multipart.MultipartFile;

import com.dnd.dndtravel.map.dto.RecordDto;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;

public record RecordRequest(
String region,

@NotBlank(message = "명소 이름은 필수 입력 사항입니다.")
@Pattern(regexp = "^[가-힣]+$", message = "명소 이름은 한글만 입력 가능합니다.")
@Size(max = 50, message = "명소 이름은 50자 이내여야 합니다.")
String attractionName,

@Size(max = 25, message = "메모는 25자 이내여야 합니다.")
String memo,

@NotNull(message = "날짜는 필수 입력 사항입니다.")
LocalDate localDate
) {
public RecordDto toDto(List<MultipartFile> photos) {
return RecordDto.builder()
.region(this.region)
.attractionName(this.attractionName)
.photos(photos)
.memo(this.memo)
.dateTime(this.localDate)
.build();
}
}
39 changes: 39 additions & 0 deletions src/main/java/com/dnd/dndtravel/map/domain/Attraction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.dnd.dndtravel.map.domain;

import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Attraction {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "region_id")
private Region region;

private String name; // 명소 이름

@Builder
private Attraction(Region region, String name) {
this.region = region;
this.name = name;
}

public static Attraction of(Region region, String attraction) {
return new Attraction(region, attraction);
}
}
69 changes: 69 additions & 0 deletions src/main/java/com/dnd/dndtravel/map/domain/MemberAttraction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.dnd.dndtravel.map.domain;

import java.time.LocalDate;

import com.dnd.dndtravel.member.domain.Member;

import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class MemberAttraction {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member member;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "attraction_id")
private Attraction attraction;

private String memo; // 방문기록 메모
private LocalDate localDate; // 방문 날짜
private String region; // 지역
private int photosCount; // 사진 개수, 필요한가?

@Builder
private MemberAttraction(Member member, Attraction attraction, String memo, LocalDate localDate, String region,
int photosCount) {
this.member = member;
this.attraction = attraction;
this.memo = memo;
this.localDate = localDate;
this.region = region;
this.photosCount = photosCount;
}

public static MemberAttraction of(Member member, Attraction attraction, String memo, LocalDate localDate,
String region) {
return MemberAttraction.builder()
.member(member)
.attraction(attraction)
.memo(memo)
.localDate(localDate)
.region(region)
.build();
}

public void update(String region, String attraction, String memo, LocalDate localDate) {
this.region = region;
// this.attraction = attraction;
this.memo = memo;
this.localDate = localDate;
}
}
37 changes: 37 additions & 0 deletions src/main/java/com/dnd/dndtravel/map/domain/Photo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.dnd.dndtravel.map.domain;

import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Photo {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "memberAttraction_id")
private MemberAttraction memberAttraction;

private String url;

private Photo(MemberAttraction memberAttraction, String url) {
this.memberAttraction = memberAttraction;
this.url = url;
}

public static Photo of(MemberAttraction memberAttraction, String imageUrl) {
return new Photo(memberAttraction, imageUrl);
}
}
20 changes: 20 additions & 0 deletions src/main/java/com/dnd/dndtravel/map/dto/RecordDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.dnd.dndtravel.map.dto;

import java.time.LocalDate;
import java.util.List;

import org.springframework.web.multipart.MultipartFile;

import lombok.Builder;
/**
*
*/
@Builder
public record RecordDto(
String region,
String attractionName,
List<MultipartFile> photos,
String memo,
LocalDate dateTime
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.dnd.dndtravel.map.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.dnd.dndtravel.map.domain.Attraction;

public interface AttractionRepository extends JpaRepository<Attraction, Long> {

Attraction findByName(String name);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.dnd.dndtravel.map.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.dnd.dndtravel.map.domain.MemberAttraction;

public interface MemberAttractionRepository extends JpaRepository<MemberAttraction, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.dnd.dndtravel.map.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.dnd.dndtravel.map.domain.Photo;

public interface PhotoRepository extends JpaRepository<Photo, Long> {

}
39 changes: 39 additions & 0 deletions src/main/java/com/dnd/dndtravel/map/service/MapService.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,20 @@

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.dnd.dndtravel.map.domain.Photo;
import com.dnd.dndtravel.map.dto.RecordDto;
import com.dnd.dndtravel.map.domain.Attraction;
import com.dnd.dndtravel.map.domain.MemberAttraction;
import com.dnd.dndtravel.map.domain.MemberRegion;
import com.dnd.dndtravel.map.domain.Region;
import com.dnd.dndtravel.map.service.dto.RegionDto;
import com.dnd.dndtravel.map.service.dto.response.RegionResponse;
import com.dnd.dndtravel.map.repository.AttractionRepository;
import com.dnd.dndtravel.map.repository.MemberAttractionRepository;
import com.dnd.dndtravel.map.repository.MemberRegionRepository;
import com.dnd.dndtravel.map.repository.PhotoRepository;
import com.dnd.dndtravel.map.repository.RegionRepository;

import com.dnd.dndtravel.member.domain.Member;
Expand All @@ -27,9 +38,13 @@
@RequiredArgsConstructor
@Service
public class MapService {
private final PhotoService photoService;
private final RegionRepository regionRepository;
private final MemberRepository memberRepository;
private final AttractionRepository attractionRepository;
private final MemberAttractionRepository memberAttractionRepository;
private final MemberRegionRepository memberRegionRepository;
private final PhotoRepository photoRepository;

@Transactional(readOnly = true)
public RegionResponse allRegions(Long memberId) {
Expand All @@ -54,6 +69,30 @@ public RegionResponse allRegions(Long memberId) {
member.getSelectedColor()
);
}

@Transactional
public void recordAttraction(RecordDto recordDto, Long memberId) {
// Attraction(명소)가 이미 있으면 save하지않음
Attraction attraction = attractionRepository.findByName(recordDto.attractionName());
Region region = regionRepository.findByName(recordDto.region()).orElseThrow(() -> new RuntimeException("잘못된 지역이름"));

// 명소가 없으면 입력받은 지역과 명소를 통해 새로운 명소를 등록
if (attraction == null) {
attractionRepository.save(Attraction.of(region, recordDto.attractionName()));
}

// 방문 기록을 등록
Member member = memberRepository.findById(memberId).orElseThrow(() -> new RuntimeException("존재하지 않는 유저"));
MemberAttraction memberAttraction = MemberAttraction.of(member, attraction, recordDto.memo(),
recordDto.dateTime(), region.getName());
memberAttractionRepository.save(memberAttraction);

// 사진을 저장
for (MultipartFile photo : recordDto.photos()) {
String imageUrl = photoService.upload(photo);
photoRepository.save(Photo.of(memberAttraction, imageUrl));
}
}
private List<RegionDto> updateRegionDto(List<RegionDto> regions, List<MemberRegion> memberRegions) {
return regions.stream()
.map(regionDto -> {
Expand Down
Loading

0 comments on commit 26e8614

Please sign in to comment.