Skip to content

Commit

Permalink
Merge pull request #27 from 9oormthonUniv-seoultech/feat/#25
Browse files Browse the repository at this point in the history
Feat/#25 Album Register API
  • Loading branch information
Jeongh00 authored Oct 2, 2024
2 parents 22f3163 + 204f602 commit 322411a
Show file tree
Hide file tree
Showing 35 changed files with 663 additions and 78 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.pocket.core.aop.annotation;

import org.springframework.stereotype.Service;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Service
public @interface AdapterService {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.pocket.core.aop.annotation;

import org.springframework.stereotype.Service;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Service
public @interface DomainService {
}
32 changes: 32 additions & 0 deletions core/src/main/java/com/pocket/core/util/DistanceCalculator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.pocket.core.util;

public class DistanceCalculator {

private static final double EARTH_RADIUS_KM = 6371.0;

/**
* 두 지점 간의 거리를 계산합니다. (단위: 킬로미터)
*
* @param lat1 첫 번째 지점의 위도
* @param lon1 첫 번째 지점의 경도
* @param lat2 두 번째 지점의 위도
* @param lon2 두 번째 지점의 경도
* @return 두 지점 간의 거리 (킬로미터)
*/
public static double haversineDistance(double lat1, double lon1, double lat2, double lon2) {
// 위도와 경도를 라디안으로 변환
double dLat = Math.toRadians(lat2 - lat1);
double dLon = Math.toRadians(lon2 - lon1);

double radLat1 = Math.toRadians(lat1);
double radLat2 = Math.toRadians(lat2);

// Haversine 공식 적용
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(radLat1) * Math.cos(radLat2) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
double c = 2 * Math.asin(Math.sqrt(a));

return EARTH_RADIUS_KM * c;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.pocket.domain.dto.image;

import java.util.List;

public record AlbumRegisterRequestDto(
Long photoboothId,
String year,
String month,
String date,
List<String> hashtag,
String memo,
String imageName, // 이미지 이름
String prefix // S3 버킷 내에 저장할 경로
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.pocket.domain.dto.photobooth;

public record NearPhotoBoothInfo(
Long id,
String name
) {
}
16 changes: 16 additions & 0 deletions domain/src/main/java/com/pocket/domain/entity/album/HashTag.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.pocket.domain.entity.album;

import jakarta.persistence.Embeddable;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@Embeddable
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class HashTag {

private String content;
}
16 changes: 16 additions & 0 deletions domain/src/main/java/com/pocket/domain/entity/album/Memo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.pocket.domain.entity.album;

import jakarta.persistence.Embeddable;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@Embeddable
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class Memo {

private String content;
}
13 changes: 13 additions & 0 deletions domain/src/main/java/com/pocket/domain/entity/image/Image.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.pocket.domain.entity.image;

import com.pocket.domain.dto.image.AlbumRegisterRequestDto;
import com.pocket.domain.entity.BaseEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
Expand All @@ -21,7 +22,19 @@ public class Image extends BaseEntity {
@Column(name = "image_url")
private String imageUrl;

private String year;
private String month;
private String date;

public Image(ImageType type) {
this.type = type;
}

public void makeImage(AlbumRegisterRequestDto dto, String filePath) {
this.type = ImageType.PHOTO;
this.imageUrl = filePath;
this.year = dto.year();
this.month = dto.month();
this.date = dto.date();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.pocket.domain.port.album;

import com.pocket.domain.dto.image.AlbumRegisterRequestDto;
import com.pocket.domain.entity.User;

public interface AlbumRegisterPort {

String registerPhoto(AlbumRegisterRequestDto albumRegisterRequestDto, String name);

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
package com.pocket.domain.port.photobooth;

import com.pocket.domain.dto.photobooth.NearPhotoBoothInfo;
import com.pocket.domain.dto.photobooth.PhotoBoothFindResponseDto;
import com.pocket.domain.entity.photobooth.PhotoBoothBrand;

import java.util.List;

public interface PhotoBoothFindPort {

PhotoBoothFindResponseDto findById(Long id);

List<NearPhotoBoothInfo> getPhotoboothWithin2Km(double currentLat, double currentLon, PhotoBoothBrand brand);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.pocket.domain.service.album;

import com.pocket.core.aop.annotation.DomainService;
import com.pocket.domain.dto.image.AlbumRegisterRequestDto;
import com.pocket.domain.port.album.AlbumRegisterPort;
import com.pocket.domain.usecase.image.AlbumRegisterUseCase;
import lombok.RequiredArgsConstructor;

@DomainService
@RequiredArgsConstructor
public class AlbumService implements AlbumRegisterUseCase {

private final AlbumRegisterPort albumRegisterPort;

public String registerPhotoResponse(AlbumRegisterRequestDto albumRegisterRequestDto, String name) {
return albumRegisterPort.registerPhoto(albumRegisterRequestDto, name);
}

}
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
package com.pocket.domain.service.photobooth;

import com.pocket.domain.dto.photobooth.NearPhotoBoothInfo;
import com.pocket.domain.dto.photobooth.PhotoBoothFindResponseDto;
import com.pocket.domain.entity.photobooth.PhotoBoothBrand;
import com.pocket.domain.port.photobooth.PhotoBoothFindPort;
import com.pocket.domain.usecase.photobooth.PhotoBoothFindUseCase;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;


@Service
@RequiredArgsConstructor
public class PhotoBoothFindService implements PhotoBoothFindUseCase {

private final PhotoBoothFindPort photoBoothFindPort;

public PhotoBoothFindResponseDto getPhotoBoothFindResponse(Long id) {
public PhotoBoothFindResponseDto findPhotoBoothResponse(Long id) {
return photoBoothFindPort.findById(id);
}

public List<NearPhotoBoothInfo> findNearPhotoBooth(double lat, double lon, PhotoBoothBrand brand) {
return photoBoothFindPort.getPhotoboothWithin2Km(lat, lon, brand);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.pocket.domain.usecase.image;

import com.pocket.domain.dto.image.AlbumRegisterRequestDto;

public interface AlbumRegisterUseCase {

String registerPhotoResponse(AlbumRegisterRequestDto requestDto, String name);

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
package com.pocket.domain.usecase.photobooth;

import com.pocket.domain.dto.photobooth.NearPhotoBoothInfo;
import com.pocket.domain.dto.photobooth.PhotoBoothFindResponseDto;
import com.pocket.domain.entity.photobooth.PhotoBoothBrand;

import java.util.List;

public interface PhotoBoothFindUseCase {

PhotoBoothFindResponseDto getPhotoBoothFindResponse(Long id);
PhotoBoothFindResponseDto findPhotoBoothResponse(Long id);

List<NearPhotoBoothInfo> findNearPhotoBooth(double lat, double lon, PhotoBoothBrand brand);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.pocket.inbounds.album.presentation;

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

@Tag(name = "Album", description = "Album API")
public interface AlbumContollerDocs {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.pocket.inbounds.album.presentation;

import com.pocket.core.exception.common.ApplicationResponse;
import com.pocket.domain.dto.image.AlbumRegisterRequestDto;
import com.pocket.domain.dto.user.UserInfoDTO;
import com.pocket.domain.usecase.image.AlbumRegisterUseCase;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/album")
public class AlbumController implements AlbumContollerDocs{

private final AlbumRegisterUseCase albumRegisterUseCase;

@PostMapping
public ApplicationResponse<String> postPhoto(
@RequestBody AlbumRegisterRequestDto requestDto,
@AuthenticationPrincipal UserInfoDTO user) {

String url = albumRegisterUseCase.registerPhotoResponse(requestDto, user.name());
return ApplicationResponse.ok(url);// presigned Url을 리턴해줘야 함.
}

}
Original file line number Diff line number Diff line change
@@ -1,36 +1,38 @@
package com.pocket.inbounds.photobooth.presentation;


import com.pocket.core.exception.common.ApplicationResponse;
import com.pocket.domain.dto.photobooth.NearPhotoBoothInfo;
import com.pocket.domain.dto.photobooth.PhotoBoothFindResponseDto;
import com.pocket.domain.entity.photobooth.PhotoBoothBrand;
import com.pocket.domain.usecase.photobooth.PhotoBoothFindUseCase;
import com.pocket.inbounds.photobooth.response.PhotoBoothResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RequiredArgsConstructor
@RestController
@RequiredArgsConstructor
@RequestMapping("/v1/photobooth")
public class PhotoBoothController implements PhotoBoothControllerDocs {

private final PhotoBoothFindUseCase photoBoothFindUseCase;

@GetMapping("{id}")
public ApplicationResponse<PhotoBoothFindResponseDto> getPhotoBoothById(@PathVariable("id") Long id) {

@GetMapping("/api/v1/photobooth/{id}")
public ApplicationResponse<PhotoBoothResponse> getPhotoBooth(@PathVariable("id") Long id) {
PhotoBoothFindResponseDto dto = photoBoothFindUseCase.getPhotoBoothFindResponse(id);
PhotoBoothFindResponseDto response = photoBoothFindUseCase.findPhotoBoothResponse(id);
return ApplicationResponse.ok(response);
}

// 여기서 dto를 response로 변환
PhotoBoothResponse response = new PhotoBoothResponse(
dto.name(),
dto.road(),
dto.x(),
dto.y(),
dto.photoBoothBrand()
);
@GetMapping()
public ApplicationResponse<List<NearPhotoBoothInfo>> getAllPhotoBooth(
@RequestParam("lat") double lat,
@RequestParam("lon") double lon,
@RequestParam(value = "brand", required = false) PhotoBoothBrand brand
) {

return ApplicationResponse.ok(response);
List<NearPhotoBoothInfo> responses = photoBoothFindUseCase.findNearPhotoBooth(lat, lon, brand);
return ApplicationResponse.ok(responses);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,19 @@

import com.nimbusds.oauth2.sdk.ErrorResponse;
import com.pocket.core.exception.common.ApplicationResponse;
import com.pocket.inbounds.photobooth.response.PhotoBoothResponse;
import com.pocket.domain.dto.photobooth.NearPhotoBoothInfo;
import com.pocket.domain.dto.photobooth.PhotoBoothFindResponseDto;
import com.pocket.domain.entity.photobooth.PhotoBoothBrand;
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.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;

@Tag(name = "PhotoBooth", description = "PhotoBooth API")
public interface PhotoBoothControllerDocs {
Expand All @@ -22,7 +27,21 @@ public interface PhotoBoothControllerDocs {
@ApiResponse(responseCode = "500", description = "INTERNAL SERVER ERROR",
content = {@Content(schema = @Schema(implementation = ErrorResponse.class))})
})
@Operation(summary = "포토부스 정보 제공", description = "포토부스 정보 전달 API")
ApplicationResponse<PhotoBoothResponse> getPhotoBooth(
@Operation(summary = "해당 id 의 포토부스 정보 제공", description = "해당 id 의 포토부스 정보 전달 API")
ApplicationResponse<PhotoBoothFindResponseDto> getPhotoBoothById(
@PathVariable("id") Long id);

@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "400", description = "BAD REQUEST",
content = {@Content(schema = @Schema(implementation = ErrorResponse.class))}),
@ApiResponse(responseCode = "500", description = "INTERNAL SERVER ERROR",
content = {@Content(schema = @Schema(implementation = ErrorResponse.class))})
})
@Operation(summary = "근처 전체 포토부스 정보 제공", description = "id 와 name 만 제공")
ApplicationResponse<List<NearPhotoBoothInfo>> getAllPhotoBooth(
@RequestParam("lat") double lat,
@RequestParam("lon") double lon,
@RequestParam(value = "brand", required = false) PhotoBoothBrand brand
);
}
Loading

0 comments on commit 322411a

Please sign in to comment.