Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] 청첩장 조회 API #34

Merged
merged 9 commits into from
Jan 23, 2025
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package com.wedit.weditapp.domain.bankAccounts.domain.repository;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import com.wedit.weditapp.domain.bankAccounts.domain.BankAccounts;
import com.wedit.weditapp.domain.invitation.domain.Invitation;

public interface BankAccountRepository extends JpaRepository<BankAccounts, Long> {
List<BankAccounts> findByInvitation(Invitation invitation);
}

Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

@Getter
@NoArgsConstructor
public class BankAccountDTO {
public class BankAccountDto {
@NotBlank(message = "side cannot be blank")
private AccountSide side; // 신랑/신부 구분

Expand All @@ -24,15 +24,15 @@ public class BankAccountDTO {
private String accountHolder; // 예금주 이름

@Builder
private BankAccountDTO(AccountSide side, String accountNumber, String bankName, String accountHolder) {
private BankAccountDto(AccountSide side, String accountNumber, String bankName, String accountHolder) {
this.side = side;
this.accountNumber = accountNumber;
this.bankName = bankName;
this.accountHolder = accountHolder;
}

public static BankAccountDTO from(BankAccounts bankAccount) {
return BankAccountDTO.builder()
public static BankAccountDto from(BankAccounts bankAccount) {
return BankAccountDto.builder()
.side(bankAccount.getSide())
.accountNumber(bankAccount.getAccountNumber())
.bankName(bankAccount.getBankName())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import com.wedit.weditapp.domain.bankAccounts.domain.BankAccounts;
import com.wedit.weditapp.domain.bankAccounts.domain.repository.BankAccountRepository;
import com.wedit.weditapp.domain.bankAccounts.dto.BankAccountDTO;
import com.wedit.weditapp.domain.bankAccounts.dto.BankAccountDto;
import com.wedit.weditapp.domain.invitation.domain.Invitation;

import jakarta.transaction.Transactional;
Expand All @@ -20,8 +20,8 @@ public class BankAccountService {
private final BankAccountRepository bankAccountRepository;

// DTO 리스트를 엔티티 리스트로 변환하여 저장
public List<BankAccounts> createBankAccounts(List<BankAccountDTO> bankAccountDTOs, Invitation invitation) {
List<BankAccounts> bankAccounts = bankAccountDTOs.stream()
public List<BankAccounts> createBankAccounts(List<BankAccountDto> bankAccountDtos, Invitation invitation) {
List<BankAccounts> bankAccounts = bankAccountDtos.stream()
.map(dto -> BankAccounts.createBankAccount(
dto.getSide(),
dto.getAccountNumber(),
Expand All @@ -32,4 +32,13 @@ public List<BankAccounts> createBankAccounts(List<BankAccountDTO> bankAccountDTO

return bankAccountRepository.saveAll(bankAccounts);
}

// 특정 초대장 계좌 정보를 조회하여 DTO 리스트로 변환
public List<BankAccountDto> getBankAccounts(Invitation invitation) {
List<BankAccounts> bankAccounts = bankAccountRepository.findByInvitation(invitation);

return bankAccounts.stream() // 스트림 생성
.map(BankAccountDto::from) // entity -> DTO
.collect(Collectors.toList()); // 리스트로 수집
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.List;

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

import com.wedit.weditapp.domain.image.domain.Image;
import com.wedit.weditapp.domain.invitation.domain.Invitation;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.wedit.weditapp.domain.image.dto.response;

import com.wedit.weditapp.domain.image.domain.Image;

import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class ImageResponseDto {
private String url;

private int location;

@Builder
private ImageResponseDto(String url, int location) {
this.url = url;
this.location = location;
}

public static ImageResponseDto from(Image image){
return ImageResponseDto.builder()
.url(image.getUrl())
.location(image.getLocation())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.wedit.weditapp.domain.image.service;

import java.util.List;
import java.util.stream.Collectors;

import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.wedit.weditapp.domain.image.domain.Image;
import com.wedit.weditapp.domain.image.domain.repository.ImageRepository;
import com.wedit.weditapp.domain.image.dto.response.ImageResponseDto;
import com.wedit.weditapp.domain.invitation.domain.Invitation;
import com.wedit.weditapp.domain.shared.S3Service;

Expand All @@ -15,16 +17,12 @@

@Service
@RequiredArgsConstructor
@Transactional
public class ImageService {
private final S3Service s3Service;
private final ImageRepository imageRepository;
/**
* S3에 이미지를 업로드하고 URL을 반환하며, DB에 저장.
*
* @param images 업로드할 MultipartFile 리스트
* @param invitation 연관된 Invitation 엔티티
*/
@Transactional

// S3에 이미지를 업로드하고 URL을 반환하며, DB에 저장
public void saveImages(List<MultipartFile> images, Invitation invitation) {
if (images.size() != 4) {
throw new IllegalArgumentException("Exactly 4 images are required.");
Expand All @@ -44,6 +42,13 @@ public void saveImages(List<MultipartFile> images, Invitation invitation) {
imageRepository.save(imageEntity);
}
}
}

// 특정 청첩장 사진들을 조회하여 DTO 리스트로 변환
public List<ImageResponseDto> getImages(Invitation invitation) {
List<Image> image = imageRepository.findByInvitation(invitation);

return image.stream() // 스트림 생성
.map(ImageResponseDto::from) // entity -> DTO
.collect(Collectors.toList()); // 리스트로 수집
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.wedit.weditapp.domain.invitation.dto.request.InvitationCreateRequestDTO;
import com.wedit.weditapp.domain.invitation.dto.request.InvitationCreateRequestDto;

import com.wedit.weditapp.domain.invitation.dto.response.InvitationResponseDto;
import com.wedit.weditapp.domain.invitation.service.InvitationService;
import com.wedit.weditapp.global.response.GlobalResponseDto;

Expand All @@ -30,14 +30,22 @@ public class InvitationController {
private final InvitationService invitationService;

@PostMapping(path="/{memberId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@Operation(summary = "필수 정보 등록", description = "")
@Operation(summary = "필수 정보 등록", description = "청첩장 등록 및 이미지 업로드")
public ResponseEntity<GlobalResponseDto<Void>> createInvitation(
@RequestPart("images") List<MultipartFile> images,
@Valid @RequestPart("content") InvitationCreateRequestDTO request,
@Valid @RequestPart("content") InvitationCreateRequestDto request,
@PathVariable Long memberId) {
//@AuthenticationPrincipal UserDetails userDetail

return ResponseEntity.status(HttpStatus.CREATED)
.body(GlobalResponseDto.success(invitationService.createInvitation(memberId, request, images)));
}

@GetMapping("/{invitationId}")
@Operation(summary = "청첩장 조회", description = "특정 청첩장 상세 정보 조회")
public ResponseEntity<GlobalResponseDto<InvitationResponseDto>> getInvitation(
@PathVariable Long invitationId){
return ResponseEntity.status(HttpStatus.OK)
.body(GlobalResponseDto.success(invitationService.getInvitation(invitationId)));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

추후 비회원의 조회도 및 URL 생성 api까지 잘 부탁드리겠습니다! 그리고 본인 청첩장 조회의 역할이라면 Member 객체까지 활용하여 멤버와 청첩장 id 가 일치하는 것을 레포지토리에서 조회하는 것이 데이터의 무결성을 보장하기에 좋다고 생각하는데 이 부분에 대해 어떻게 생각하시나요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋은 생각인 것 같습니다! 추후 member 객체 활용하는 부분 추가하며 한꺼번에 추가하도록 하겠습니다!

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.wedit.weditapp.domain.invitation.domain;

import com.wedit.weditapp.domain.image.domain.Image;
import com.wedit.weditapp.domain.member.domain.Member;
import com.wedit.weditapp.domain.shared.BaseTimeEntity;
import com.wedit.weditapp.domain.shared.Theme;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
import java.time.LocalDate;
import java.util.List;

import com.wedit.weditapp.domain.bankAccounts.dto.BankAccountDTO;
import com.wedit.weditapp.domain.bankAccounts.dto.BankAccountDto;
import com.wedit.weditapp.domain.shared.Theme;

@Getter
@NoArgsConstructor
public class InvitationCreateRequestDTO {
public class InvitationCreateRequestDto {
@NotBlank(message = "groom cannot be blank")
private String groom; // 신랑 이름

Expand All @@ -34,7 +34,6 @@ public class InvitationCreateRequestDTO {

private LocalDate date; // 결혼식 날짜

@NotBlank(message = "theme cannot be blank")
private Theme theme; // 테마

private String distribution; // 청첩장 URL
Expand All @@ -45,5 +44,5 @@ public class InvitationCreateRequestDTO {

private boolean accountOption; // 계좌 공개 옵션

private List<BankAccountDTO> bankAccounts; // 계좌 정보 리스트
private List<BankAccountDto> bankAccounts; // 계좌 정보 리스트
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
import java.time.LocalDate;
import java.util.List;

import com.wedit.weditapp.domain.bankAccounts.dto.BankAccountDTO;
import com.wedit.weditapp.domain.bankAccounts.dto.BankAccountDto;
import com.wedit.weditapp.domain.shared.Theme;

@Getter
@NoArgsConstructor
public class InvitationUpdateRequestDTO {
public class InvitationUpdateRequestDto {
@NotBlank(message = "groom cannot be blank")
private String groom; // 신랑 이름

Expand All @@ -35,7 +35,6 @@ public class InvitationUpdateRequestDTO {
@NotBlank(message = "date cannot be blank")
private LocalDate date; // 결혼식 날짜

@NotBlank(message = "theme cannot be blank")
private Theme theme; // 테마

private String distribution; // 청첩장 URL
Expand All @@ -46,5 +45,5 @@ public class InvitationUpdateRequestDTO {

private boolean accountOption; // 계좌 공개 옵션

private List<BankAccountDTO> bankAccounts; // 계좌 정보 리스트
private List<BankAccountDto> bankAccounts; // 계좌 정보 리스트
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.wedit.weditapp.domain.invitation.dto.response;

import com.wedit.weditapp.domain.bankAccounts.dto.BankAccountDTO;
import com.wedit.weditapp.domain.bankAccounts.dto.BankAccountDto;
import com.wedit.weditapp.domain.image.dto.response.ImageResponseDto;
import com.wedit.weditapp.domain.invitation.domain.Invitation;
import com.wedit.weditapp.domain.shared.Theme;

Expand All @@ -14,7 +15,7 @@

@Getter
@NoArgsConstructor
public class InvitationResponseDTO {
public class InvitationResponseDto {
@NotBlank(message = "groom cannot be blank")
private String groom; // 신랑 이름

Expand Down Expand Up @@ -48,13 +49,15 @@ public class InvitationResponseDTO {

private boolean accountOption; // 계좌 공개 옵션

private List<BankAccountDTO> bankAccounts; // 계좌 정보 리스트
private List<BankAccountDto> bankAccounts; // 계좌 정보 리스트

private List<ImageResponseDto> image;

// DTO 생성 후 활성화
//private List<GuestbookResponseDTO> guestbooks; // 방명록 리스트

@Builder
private InvitationResponseDTO(String groom, String bride, String groomF, String groomM, String brideF, String brideM, String address, String extraAddress, LocalDate date, Theme theme, String distribution, boolean guestBookOption, boolean decisionOption, boolean accountOption, List<BankAccountDTO> bankAccounts
private InvitationResponseDto(String groom, String bride, String groomF, String groomM, String brideF, String brideM, String address, String extraAddress, LocalDate date, Theme theme, String distribution, boolean guestBookOption, boolean decisionOption, boolean accountOption, List<BankAccountDto> bankAccounts, List<ImageResponseDto> image
//, List<GuestbookResponseDTO> guestbooks
) {
this.groom = groom;
Expand All @@ -72,30 +75,31 @@ private InvitationResponseDTO(String groom, String bride, String groomF, String
this.decisionOption = decisionOption;
this.accountOption = accountOption;
this.bankAccounts = bankAccounts;
this.image = image;
//this.guestbooks = guestbooks;
}

public static InvitationResponseDTO from(Invitation invitation, List<BankAccountDTO> bankAccounts
public static InvitationResponseDto from(Invitation invitation, List<BankAccountDto> bankAccounts, List<ImageResponseDto> image
//, List<GuestbookResponseDTO> guestbooks
) {
return InvitationResponseDTO.builder()
.groom(invitation.getGroom())
.bride(invitation.getBride())
.groomF(invitation.getGroomF())
.groomM(invitation.getGroomM())
.brideF(invitation.getBrideF())
.brideM(invitation.getBrideM())
.address(invitation.getAddress())
.extraAddress(invitation.getExtraAddress())
.date(invitation.getDate())
.theme(invitation.getTheme())
.distribution(invitation.getDistribution())
.guestBookOption(invitation.isGuestBookOption())
.decisionOption(invitation.isDecisionOption())
.accountOption(invitation.isAccountOption())
.bankAccounts(bankAccounts)
//.guestbooks(guestbooks)
.build();
return InvitationResponseDto.builder()
.groom(invitation.getGroom())
.bride(invitation.getBride())
.groomF(invitation.getGroomF())
.groomM(invitation.getGroomM())
.brideF(invitation.getBrideF())
.brideM(invitation.getBrideM())
.address(invitation.getAddress())
.extraAddress(invitation.getExtraAddress())
.date(invitation.getDate())
.theme(invitation.getTheme())
.distribution(invitation.getDistribution())
.guestBookOption(invitation.isGuestBookOption())
.decisionOption(invitation.isDecisionOption())
.accountOption(invitation.isAccountOption())
.bankAccounts(bankAccounts)
.image(image)
//.guestbooks(guestbooks)
.build();
}
}

Loading
Loading