diff --git a/src/main/java/com/koliving/api/GlobalExceptionHandler.java b/src/main/java/com/koliving/api/GlobalExceptionHandler.java index cb9857b3..c50d789b 100644 --- a/src/main/java/com/koliving/api/GlobalExceptionHandler.java +++ b/src/main/java/com/koliving/api/GlobalExceptionHandler.java @@ -5,7 +5,6 @@ import static com.koliving.api.token.confirmation.ConfirmationTokenType.SIGN_UP; import com.koliving.api.base.ErrorResponse; -import com.koliving.api.base.ServiceError; import com.koliving.api.base.exception.KolivingServiceException; import com.koliving.api.dto.ConfirmationTokenErrorDto; import com.koliving.api.dto.ResponseDto; @@ -18,8 +17,8 @@ import com.koliving.api.token.confirmation.ConfirmationToken; import com.koliving.api.token.confirmation.ConfirmationTokenService; import com.koliving.api.token.confirmation.ConfirmationTokenType; -import com.koliving.api.user.SignUpStatus; -import com.koliving.api.user.User; +import com.koliving.api.user.domain.SignUpStatus; +import com.koliving.api.user.domain.User; import com.koliving.api.user.application.UserService; import com.koliving.api.utils.HttpUtils; import java.util.Locale; diff --git a/src/main/java/com/koliving/api/KolivingApplication.java b/src/main/java/com/koliving/api/KolivingApplication.java index 06a52a90..9896fcd3 100644 --- a/src/main/java/com/koliving/api/KolivingApplication.java +++ b/src/main/java/com/koliving/api/KolivingApplication.java @@ -4,6 +4,8 @@ import static com.koliving.api.location.domain.LocationType.GU; import com.google.common.collect.Sets; +import com.koliving.api.email.IEmailService; +import com.koliving.api.email.MailType; import com.koliving.api.file.domain.ImageFile; import com.koliving.api.file.infra.ImageFileRepository; import com.koliving.api.i18n.Language; @@ -21,9 +23,11 @@ import com.koliving.api.room.infra.FurnishingRepository; import com.koliving.api.room.infra.LikeRepository; import com.koliving.api.room.infra.RoomRepository; -import com.koliving.api.user.User; -import com.koliving.api.user.UserRepository; -import com.koliving.api.user.UserRole; +import com.koliving.api.user.domain.Notification; +import com.koliving.api.user.domain.User; +import com.koliving.api.user.infra.NotificationRepository; +import com.koliving.api.user.infra.UserRepository; +import com.koliving.api.user.domain.UserRole; import jakarta.annotation.PostConstruct; import java.time.LocalDate; import java.util.Arrays; @@ -38,9 +42,6 @@ import org.springframework.context.annotation.Profile; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; @EnableJpaAuditing @SpringBootApplication @@ -69,25 +70,33 @@ CommandLineRunner commandLineRunner( ImageFileRepository imageFileRepository, LikeRepository likeRepository, UserRepository userRepository, - PasswordEncoder encoder + PasswordEncoder encoder, + NotificationRepository notificationRepository ) { return args -> { initImageFiles(imageFileRepository); initFurnishings(furnishingRepository); initLocations(locationRepository); initLanguages(languageRepository); - User user = initUser(userRepository, encoder); + User user = initUser(userRepository, encoder, notificationRepository); initRooms(roomRepository, locationRepository, furnishingRepository, imageFileRepository, likeRepository, user); }; } - private User initUser(UserRepository userRepository, PasswordEncoder encoder) { + private User initUser(UserRepository userRepository, PasswordEncoder encoder, NotificationRepository notificationRepository) { final User user = User.valueOf("koliving@koliving.com", encoder.encode("test1234!@"), UserRole.USER); final User user2 = User.valueOf("koliving2@koliving.com", encoder.encode("test1234!@"), UserRole.USER); final User manager = User.valueOf("manager@koliving.com", encoder.encode("test1234!@"), UserRole.ADMIN); - userRepository.saveAll(List.of(user2, manager)); - return userRepository.save(user); + userRepository.saveAll(List.of(user, manager)); + userRepository.save(user2); + + // 알림 + notificationRepository.save(Notification.of(user, user2)); + notificationRepository.save(Notification.of(manager, user)); + notificationRepository.save(Notification.of(user2, user)); + + return user2; } private void initImageFiles(ImageFileRepository imageFileRepository) { @@ -171,8 +180,12 @@ private void initLanguages(LanguageRepository languageRepository) { Language.valueOf("ko", "email_duplication", "이미 존재하는 이메일입니다 : {0}"), Language.valueOf("en", "auth_email_subject", "Confirm your email"), Language.valueOf("ko", "auth_email_subject", "이메일 인증을 완료하세요"), + Language.valueOf("en", "contact_email_subject", "Someone is interested in your posts."), + Language.valueOf("ko", "contact_email_subject", "누군가 당신의 게시글에 관심이 있어요."), Language.valueOf("en", "auth_email_subtitle", "Click the link below to proceed with authentication"), Language.valueOf("ko", "auth_email_subtitle", "아래 링크를 클릭하셔서 인증을 진행하세요"), + Language.valueOf("en", "contact_email_subtitle", "Possible roommate has shown interest in your room!"), + Language.valueOf("ko", "contact_email_subtitle", "룸메이트가 당신의 방에 관심을 보였습니다!"), Language.valueOf("en", "auth_email_link_guidance", "If the button doesn't work, copy and paste the link below into url"), Language.valueOf("ko", "auth_email_link_guidance", "버튼이 동작하지 않다면, 아래 링크를 url에 붙여 인증을 시도하세요"), diff --git a/src/main/java/com/koliving/api/auth/AuthController.java b/src/main/java/com/koliving/api/auth/AuthController.java index a9c5ab38..ffc459e7 100644 --- a/src/main/java/com/koliving/api/auth/AuthController.java +++ b/src/main/java/com/koliving/api/auth/AuthController.java @@ -12,9 +12,9 @@ import com.koliving.api.exception.DuplicateResourceException; import com.koliving.api.exception.NonExistentResourceException; import com.koliving.api.token.confirmation.ConfirmationTokenType; -import com.koliving.api.user.SignUpStatus; -import com.koliving.api.user.User; -import com.koliving.api.user.UserPropertyEditor; +import com.koliving.api.user.domain.SignUpStatus; +import com.koliving.api.user.domain.User; +import com.koliving.api.user.infra.UserPropertyEditor; import com.koliving.api.user.application.UserService; import com.koliving.api.utils.HttpUtils; import com.koliving.api.validation.EmailDuplicationValidator; diff --git a/src/main/java/com/koliving/api/auth/AuthFacade.java b/src/main/java/com/koliving/api/auth/AuthFacade.java index a1077f16..3e4b3969 100644 --- a/src/main/java/com/koliving/api/auth/AuthFacade.java +++ b/src/main/java/com/koliving/api/auth/AuthFacade.java @@ -16,9 +16,8 @@ import com.koliving.api.token.confirmation.ConfirmationToken; import com.koliving.api.token.confirmation.ConfirmationTokenType; import com.koliving.api.token.confirmation.IConfirmationTokenService; -import com.koliving.api.user.User; -import com.koliving.api.user.UserRepository; -import com.koliving.api.user.application.UserService; +import com.koliving.api.user.domain.User; +import com.koliving.api.user.infra.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.context.ApplicationEventPublisher; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; diff --git a/src/main/java/com/koliving/api/base/KLDescription.java b/src/main/java/com/koliving/api/base/KLDescription.java new file mode 100644 index 00000000..5d22e46f --- /dev/null +++ b/src/main/java/com/koliving/api/base/KLDescription.java @@ -0,0 +1,18 @@ +package com.koliving.api.base; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.springframework.core.annotation.AliasFor; + +/** + * author : haedoang date : 2023/11/05 description : + */ +@Retention(RetentionPolicy.SOURCE) +@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) +public @interface KLDescription { + String value() default ""; + + String example() default ""; +} diff --git a/src/main/java/com/koliving/api/config/ModelMapperConfig.java b/src/main/java/com/koliving/api/config/ModelMapperConfig.java index 006fa1d0..42d16101 100644 --- a/src/main/java/com/koliving/api/config/ModelMapperConfig.java +++ b/src/main/java/com/koliving/api/config/ModelMapperConfig.java @@ -1,7 +1,7 @@ package com.koliving.api.config; import com.koliving.api.dto.ProfileDto; -import com.koliving.api.user.User; +import com.koliving.api.user.domain.User; import org.modelmapper.ModelMapper; import org.modelmapper.convention.MatchingStrategies; import org.springframework.context.annotation.Bean; diff --git a/src/main/java/com/koliving/api/dto/ProfileDto.java b/src/main/java/com/koliving/api/dto/ProfileDto.java index 105cd616..9c951571 100644 --- a/src/main/java/com/koliving/api/dto/ProfileDto.java +++ b/src/main/java/com/koliving/api/dto/ProfileDto.java @@ -1,6 +1,6 @@ package com.koliving.api.dto; -import com.koliving.api.user.Gender; +import com.koliving.api.user.domain.Gender; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; diff --git a/src/main/java/com/koliving/api/email/EmailService.java b/src/main/java/com/koliving/api/email/EmailService.java index dceb9c0e..995c4a59 100644 --- a/src/main/java/com/koliving/api/email/EmailService.java +++ b/src/main/java/com/koliving/api/email/EmailService.java @@ -1,12 +1,16 @@ package com.koliving.api.email; import com.koliving.api.properties.EmailProperties; +import com.koliving.api.properties.FrontProperties; +import com.koliving.api.room.infra.RoomContactEvent; +import com.koliving.api.user.domain.User; import com.koliving.api.utils.HttpUtils; import jakarta.mail.MessagingException; import jakarta.mail.internet.MimeMessage; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.context.MessageSource; +import org.springframework.context.event.EventListener; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.core.io.ClassPathResource; import org.springframework.mail.MailException; @@ -33,6 +37,43 @@ public class EmailService implements IEmailService { private final EmailProperties emailProperties; private final HttpUtils httpUtils; + @Async("mailExecutor") + @Override + public void sendRoomContact(String to, String contact, String message, User sender, String link) { + try { + Locale currentLocale = httpUtils.getLocaleForLanguage(LocaleContextHolder.getLocale()); + + Map variables = new HashMap<>(); + variables.put("title", "KOLIVING"); + variables.put("subtitle", messageSource.getMessage("contact_email_subtitle", null, currentLocale)); + variables.put("contact", contact); + variables.put("message", message); + variables.put("roomLink", link); + variables.put("userName", sender.getFullName()); + variables.put("userAge", sender.getAge()); + variables.put("userImageProfile", sender.getImageProfile()); + variables.put("userGender", sender.getGender()); + variables.put("userDescription", sender.getDescription()); + + MimeMessage mimeMessage = mailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8"); + + helper.setSubject(messageSource.getMessage("contact_email_subject", null, currentLocale)); + helper.setTo(to); + helper.setText(emailTemplateUtil.generateEmail(MailType.CONTACT, variables), true); + helper.setFrom(emailProperties.getUsername()); + helper.addInline("logo", new ClassPathResource("static/image/logo-black.jpg")); + + mailSender.send(mimeMessage); + } catch (MessagingException e) { + log.error("failed to generate email", e); + throw new MailParseException("failed to generate email", e); + } catch (MailException e) { + log.error("failed to send email", e); + throw new MailSendException("Failed to send email", e); + } + } + @Async("mailExecutor") @Override public void send(MailType type, String to, String link) { diff --git a/src/main/java/com/koliving/api/email/IEmailService.java b/src/main/java/com/koliving/api/email/IEmailService.java index 45c1f5f3..ee77a9d0 100644 --- a/src/main/java/com/koliving/api/email/IEmailService.java +++ b/src/main/java/com/koliving/api/email/IEmailService.java @@ -1,6 +1,10 @@ package com.koliving.api.email; +import com.koliving.api.user.domain.User; + public interface IEmailService { void send(MailType type, String to, String url); + + void sendRoomContact(String to, String contactInfo, String message, User sender, String link); } diff --git a/src/main/java/com/koliving/api/email/MailType.java b/src/main/java/com/koliving/api/email/MailType.java index 0d24cec5..b31a253f 100644 --- a/src/main/java/com/koliving/api/email/MailType.java +++ b/src/main/java/com/koliving/api/email/MailType.java @@ -1,7 +1,8 @@ package com.koliving.api.email; public enum MailType { - AUTH("auth-email-template"); + AUTH("auth-email-template"), + CONTACT("contact-email-template"); private final String template; diff --git a/src/main/java/com/koliving/api/my/application/dto/UserProfileUpdateRequest.java b/src/main/java/com/koliving/api/my/application/dto/UserProfileUpdateRequest.java index af7de61c..fdc501af 100644 --- a/src/main/java/com/koliving/api/my/application/dto/UserProfileUpdateRequest.java +++ b/src/main/java/com/koliving/api/my/application/dto/UserProfileUpdateRequest.java @@ -1,8 +1,8 @@ package com.koliving.api.my.application.dto; import com.koliving.api.file.domain.ImageFile; -import com.koliving.api.user.Gender; -import com.koliving.api.user.User; +import com.koliving.api.user.domain.Gender; +import com.koliving.api.user.domain.User; import io.swagger.v3.oas.annotations.media.Schema; import org.springframework.lang.Nullable; diff --git a/src/main/java/com/koliving/api/my/ui/MyController.java b/src/main/java/com/koliving/api/my/ui/MyController.java index ca2826d7..8d2b12fd 100644 --- a/src/main/java/com/koliving/api/my/ui/MyController.java +++ b/src/main/java/com/koliving/api/my/ui/MyController.java @@ -4,7 +4,8 @@ import com.koliving.api.my.application.dto.UserProfileUpdateRequest; import com.koliving.api.room.application.RoomService; import com.koliving.api.room.application.dto.RoomResponse; -import com.koliving.api.user.User; +import com.koliving.api.user.application.dto.NotificationResponse; +import com.koliving.api.user.domain.User; import com.koliving.api.user.application.UserService; import com.koliving.api.user.application.dto.UserResponse; import io.swagger.v3.oas.annotations.Operation; @@ -12,6 +13,7 @@ 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 java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -99,4 +101,25 @@ public ResponseEntity> getLikedRooms(Pageable pageable, @Auth return ResponseEntity.ok() .body(responses); } + + @Operation( + summary = "알림 조회", + description = "알림 리스트 조회합니다", + responses = { + @ApiResponse( + responseCode = "200", + description = "알림 리스트 조회 성공" + ), + @ApiResponse( + responseCode = "400", + description = "알림 리스트 조회 실패", + content = @Content(schema = @Schema(implementation = ErrorResponse.class)) + ), + }) + @GetMapping("/notification") + public ResponseEntity> getNotifications(@AuthenticationPrincipal User user) { + List responses = userService.getNotifications(user); + return ResponseEntity.ok() + .body(responses); + } } diff --git a/src/main/java/com/koliving/api/room/application/RoomService.java b/src/main/java/com/koliving/api/room/application/RoomService.java index 229fbf6e..62f477c5 100644 --- a/src/main/java/com/koliving/api/room/application/RoomService.java +++ b/src/main/java/com/koliving/api/room/application/RoomService.java @@ -2,30 +2,37 @@ import static com.koliving.api.base.ServiceError.FORBIDDEN; import static com.koliving.api.base.ServiceError.RECORD_NOT_EXIST; +import static com.koliving.api.base.ServiceError.UNAUTHORIZED; import com.google.common.collect.Sets; import com.koliving.api.base.ServiceError; import com.koliving.api.base.exception.KolivingServiceException; +import com.koliving.api.email.IEmailService; import com.koliving.api.file.domain.ImageFile; import com.koliving.api.file.infra.ImageFileRepository; import com.koliving.api.location.domain.Location; import com.koliving.api.location.infra.LocationRepository; +import com.koliving.api.properties.FrontProperties; +import com.koliving.api.room.application.dto.RoomContactRequest; import com.koliving.api.room.application.dto.RoomResponse; import com.koliving.api.room.application.dto.RoomSaveRequest; import com.koliving.api.room.application.dto.RoomSearchCondition; import com.koliving.api.room.domain.Furnishing; import com.koliving.api.room.domain.Like; import com.koliving.api.room.domain.Room; +import com.koliving.api.room.infra.RoomContactEvent; import com.koliving.api.room.infra.FurnishingRepository; import com.koliving.api.room.infra.LikeRepository; import com.koliving.api.room.infra.RoomRepository; -import com.koliving.api.user.User; +import com.koliving.api.user.domain.Notification; +import com.koliving.api.user.domain.User; +import com.koliving.api.user.infra.UserRepository; import java.util.Collections; import java.util.List; -import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; @@ -45,6 +52,8 @@ public class RoomService { private final RoomRepository roomRepository; private final ImageFileRepository imageFileRepository; private final LikeRepository likeRepository; + private final IEmailService emailService; + private final FrontProperties frontProperties; public List list() { return roomRepository.findAllWithUser() @@ -144,4 +153,17 @@ private Room getRoom(Long id) { return roomRepository.findByIdWithUser(id) .orElseThrow(() -> new KolivingServiceException(RECORD_NOT_EXIST)); } + + @Transactional + public void contact(RoomContactRequest request, User user) { + final Room room = getRoom(request.roomId()); + final Notification notification = Notification.of(user, room.getUser()); + room.getUser().addReceivedNotification(notification); + emailService.sendRoomContact("haedoang@naver.com", request.contactInfo(), request.message(), user, getRoomDetailUrl(room.getId())); + } + + + public String getRoomDetailUrl(Long roomId) { + return String.format("%s/room/%d", frontProperties.getOrigin(), roomId); + } } diff --git a/src/main/java/com/koliving/api/room/application/dto/FurnishingResponse.java b/src/main/java/com/koliving/api/room/application/dto/FurnishingResponse.java index 1d8e7359..adb3d3be 100644 --- a/src/main/java/com/koliving/api/room/application/dto/FurnishingResponse.java +++ b/src/main/java/com/koliving/api/room/application/dto/FurnishingResponse.java @@ -2,8 +2,16 @@ import com.koliving.api.room.domain.Furnishing; +import io.swagger.v3.oas.annotations.media.Schema; -public record FurnishingResponse(Long id, String desc) { +@Schema(description = "가구 정보 조회") +public record FurnishingResponse( + @Schema(description = "가구 고유 ID") + Long id, + + @Schema(description = "가구 설명") + String desc +) { public static FurnishingResponse valueOf(Furnishing entity) { return new FurnishingResponse( diff --git a/src/main/java/com/koliving/api/room/application/dto/RoomContactRequest.java b/src/main/java/com/koliving/api/room/application/dto/RoomContactRequest.java new file mode 100644 index 00000000..d4d7b13d --- /dev/null +++ b/src/main/java/com/koliving/api/room/application/dto/RoomContactRequest.java @@ -0,0 +1,20 @@ +package com.koliving.api.room.application.dto; + +import io.swagger.v3.oas.annotations.media.Schema; + +/** + * author : haedoang date : 2023/11/01 description : + */ +@Schema(description = "방 contact 정보") +public record RoomContactRequest( + @Schema(description = "방 ID") + Long roomId, + + @Schema(description = "연락처 정보") + String contactInfo, + + @Schema(description = "연락처 메시지") + String message +) { + +} diff --git a/src/main/java/com/koliving/api/room/application/dto/WriterResponse.java b/src/main/java/com/koliving/api/room/application/dto/WriterResponse.java index 39bd31b8..a109a074 100644 --- a/src/main/java/com/koliving/api/room/application/dto/WriterResponse.java +++ b/src/main/java/com/koliving/api/room/application/dto/WriterResponse.java @@ -1,8 +1,8 @@ package com.koliving.api.room.application.dto; import com.fasterxml.jackson.annotation.JsonIgnore; -import com.koliving.api.user.Gender; -import com.koliving.api.user.User; +import com.koliving.api.user.domain.Gender; +import com.koliving.api.user.domain.User; import io.swagger.v3.oas.annotations.media.Schema; import java.time.LocalDate; diff --git a/src/main/java/com/koliving/api/room/domain/Like.java b/src/main/java/com/koliving/api/room/domain/Like.java index 188a18c2..dd59566b 100644 --- a/src/main/java/com/koliving/api/room/domain/Like.java +++ b/src/main/java/com/koliving/api/room/domain/Like.java @@ -3,7 +3,7 @@ import static lombok.AccessLevel.PROTECTED; import com.koliving.api.base.domain.BaseEntity; -import com.koliving.api.user.User; +import com.koliving.api.user.domain.User; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; diff --git a/src/main/java/com/koliving/api/room/domain/Room.java b/src/main/java/com/koliving/api/room/domain/Room.java index 26e53894..c46f071c 100644 --- a/src/main/java/com/koliving/api/room/domain/Room.java +++ b/src/main/java/com/koliving/api/room/domain/Room.java @@ -5,7 +5,7 @@ import com.koliving.api.file.domain.ImageFile; import com.koliving.api.location.domain.Location; import com.koliving.api.room.domain.info.RoomInfo; -import com.koliving.api.user.User; +import com.koliving.api.user.domain.User; import jakarta.persistence.AttributeOverride; import jakarta.persistence.Column; import jakarta.persistence.Embedded; @@ -30,7 +30,6 @@ import java.util.Set; import static com.koliving.api.base.ServiceError.ILLEGAL_ROOM_INFO; -import static com.koliving.api.base.ServiceError.UNAUTHORIZED; import static jakarta.persistence.GenerationType.IDENTITY; import static lombok.AccessLevel.PROTECTED; diff --git a/src/main/java/com/koliving/api/room/infra/RoomContactEvent.java b/src/main/java/com/koliving/api/room/infra/RoomContactEvent.java new file mode 100644 index 00000000..77f22417 --- /dev/null +++ b/src/main/java/com/koliving/api/room/infra/RoomContactEvent.java @@ -0,0 +1,57 @@ +package com.koliving.api.room.infra; + +import com.koliving.api.base.KLDescription; +import com.koliving.api.room.domain.Room; +import com.koliving.api.user.domain.Gender; +import com.koliving.api.user.domain.User; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * author : haedoang date : 2023/11/05 description : + */ +@Getter +@AllArgsConstructor +public class RoomContactEvent { + + @KLDescription(value = "수신자 이메일 주소", example = "koliving@koliving.kr") + private String to; + + @KLDescription(value = "방 ID") + private Long roomId; + + @KLDescription(value = "연락방법", example = "01011112222") + private String contactInfo; + + @KLDescription(value = "메시지", example = "방에 관심이 있어요^_^") + private String message; + + @KLDescription(value = "발송자 이름", example = "David Beckham") + private String senderName; + + @KLDescription(value = "발송자 연령", example = "30") + private Integer senderAge; + + @KLDescription(value = "발송자 프로파일 이미지 주소") + private String senderImageProfile; + + @KLDescription(value = "발송자 성별", example = "FEMALE") + private Gender senderGender; + + @KLDescription(value = "발송자 자기소개") + private String senderDescription; + + public static RoomContactEvent of(Room room, String contactInfo, String message, User sender) { + return new RoomContactEvent( + room.getUser().getEmail(), + room.getId(), + contactInfo, + message, + sender.getFullName(), + sender.getAge(), + sender.getImageProfile(), + sender.getGender(), + sender.getDescription() + ); + } +} diff --git a/src/main/java/com/koliving/api/room/ui/RoomController.java b/src/main/java/com/koliving/api/room/ui/RoomController.java index 1b017afe..101b56ff 100644 --- a/src/main/java/com/koliving/api/room/ui/RoomController.java +++ b/src/main/java/com/koliving/api/room/ui/RoomController.java @@ -2,10 +2,11 @@ import com.koliving.api.base.ErrorResponse; import com.koliving.api.room.application.RoomService; +import com.koliving.api.room.application.dto.RoomContactRequest; import com.koliving.api.room.application.dto.RoomResponse; import com.koliving.api.room.application.dto.RoomSaveRequest; import com.koliving.api.room.application.dto.RoomSearchCondition; -import com.koliving.api.user.User; +import com.koliving.api.user.domain.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -17,6 +18,7 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.web.PageableDefault; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.DeleteMapping; @@ -140,4 +142,25 @@ public ResponseEntity likeRoom(@PathVariable Long id, @AuthenticationPrinc return ResponseEntity.noContent() .build(); } + + @Operation( + summary = "방 연락하기", + description = "방 소유자에게 연락을 한다", + responses = { + @ApiResponse( + responseCode = "201", + description = "방 연락 요청 성공" + ), + @ApiResponse( + responseCode = "400", + description = "방 연락 요청 실패", + content = @Content(schema = @Schema(implementation = ErrorResponse.class)) + ), + }) + @PostMapping("/{id}/contact") + public ResponseEntity contactRoom(@RequestBody RoomContactRequest request, @AuthenticationPrincipal User user) { + roomService.contact(request, user); + return ResponseEntity.status(HttpStatus.CREATED) + .build(); + } } diff --git a/src/main/java/com/koliving/api/room/ui/RoomManageController.java b/src/main/java/com/koliving/api/room/ui/RoomManageController.java index ba40413f..59fb3e87 100644 --- a/src/main/java/com/koliving/api/room/ui/RoomManageController.java +++ b/src/main/java/com/koliving/api/room/ui/RoomManageController.java @@ -3,7 +3,6 @@ import com.koliving.api.base.ErrorResponse; import com.koliving.api.room.application.RoomService; import com.koliving.api.room.application.dto.RoomResponse; -import com.koliving.api.user.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -12,15 +11,11 @@ import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import static java.lang.Boolean.*; - @Tag(name = "[관리자] 룸 관리 API", description = "관리자 룸 관리 API") @RestController @RequestMapping("api/v1/management/rooms") diff --git a/src/main/java/com/koliving/api/user/application/IUserService.java b/src/main/java/com/koliving/api/user/application/IUserService.java index 35af1340..876357d6 100644 --- a/src/main/java/com/koliving/api/user/application/IUserService.java +++ b/src/main/java/com/koliving/api/user/application/IUserService.java @@ -1,7 +1,7 @@ package com.koliving.api.user.application; -import com.koliving.api.user.User; +import com.koliving.api.user.domain.User; import com.koliving.api.user.application.dto.UserResponse; import java.util.List; diff --git a/src/main/java/com/koliving/api/user/application/UserService.java b/src/main/java/com/koliving/api/user/application/UserService.java index 94e4bb53..dd156c4f 100644 --- a/src/main/java/com/koliving/api/user/application/UserService.java +++ b/src/main/java/com/koliving/api/user/application/UserService.java @@ -5,9 +5,16 @@ import com.koliving.api.file.domain.ImageFile; import com.koliving.api.file.infra.ImageFileRepository; import com.koliving.api.my.application.dto.UserProfileUpdateRequest; -import com.koliving.api.user.User; -import com.koliving.api.user.UserRepository; +import com.koliving.api.user.application.dto.NotificationResponse; import com.koliving.api.user.application.dto.UserResponse; +import com.koliving.api.user.domain.Notification; +import com.koliving.api.user.domain.NotifyType; +import com.koliving.api.user.domain.User; +import com.koliving.api.user.infra.NotificationRepository; +import com.koliving.api.user.infra.UserRepository; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; import lombok.RequiredArgsConstructor; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; @@ -16,15 +23,13 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.List; -import java.util.stream.Collectors; - @Service @Transactional(readOnly = true) @RequiredArgsConstructor public class UserService implements IUserService, UserDetailsService { private final UserRepository userRepository; + private final NotificationRepository notificationRepository; private final ImageFileRepository imageFileRepository; private final PasswordEncoder passwordEncoder; @@ -64,7 +69,8 @@ public void updateProfile(UserProfileUpdateRequest request, Long userId) { ImageFile imageFile = getImageFile(request); User updatable = request.toUser(imageFile); - User user = userRepository.findById(userId).orElseThrow(() -> new KolivingServiceException(ServiceError.RECORD_NOT_EXIST)); + User user = userRepository.findById(userId) + .orElseThrow(() -> new KolivingServiceException(ServiceError.RECORD_NOT_EXIST)); user.update(updatable); } @@ -74,7 +80,15 @@ private ImageFile getImageFile(UserProfileUpdateRequest request) { } public UserResponse findById(Long id) { - User user = userRepository.findById(id).orElseThrow(() -> new KolivingServiceException(ServiceError.RECORD_NOT_EXIST)); + User user = userRepository.findById(id) + .orElseThrow(() -> new KolivingServiceException(ServiceError.RECORD_NOT_EXIST)); return UserResponse.valueOf(user); } + + public List getNotifications(User user) { + final List receives = notificationRepository.findAllByReceiverId(user.getId()); + final List sent = notificationRepository.findAllBySenderId(user.getId()); + + return NotificationResponse.ofList(receives, sent); + } } diff --git a/src/main/java/com/koliving/api/user/application/dto/NotificationResponse.java b/src/main/java/com/koliving/api/user/application/dto/NotificationResponse.java new file mode 100644 index 00000000..aa28491e --- /dev/null +++ b/src/main/java/com/koliving/api/user/application/dto/NotificationResponse.java @@ -0,0 +1,48 @@ +package com.koliving.api.user.application.dto; + +import static com.koliving.api.user.domain.NotifyType.RECEIVE; +import static com.koliving.api.user.domain.NotifyType.SEND; + +import com.koliving.api.user.domain.Notification; +import com.koliving.api.user.domain.NotifyType; +import io.swagger.v3.oas.annotations.media.Schema; +import java.time.LocalDateTime; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * author : haedoang date : 2023/11/05 description : + */ +public record NotificationResponse( + + @Schema(description = "알림 타입[SEND, RECEIVE]") + NotifyType type, + + @Schema(description = "알림 발/수신자") + String userName, + + @Schema(description = "알림 생성일자") + LocalDateTime createdAt +) { + + public static NotificationResponse of(NotifyType type, Notification entity) { + return new NotificationResponse( + type, + type.isSend() ? entity.getSender().getFullName() : entity.getReceiver().getFullName(), + entity.getCreatedAt() + ); + } + + public static List ofList(List receives, List sent) { + return Stream.concat( + receives.stream() + .map(notification -> of(RECEIVE, notification) + ), + sent.stream() + .map(notification -> of(SEND, notification)) + ).sorted(Comparator.comparing(NotificationResponse::createdAt).reversed()) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/com/koliving/api/user/application/dto/UserResponse.java b/src/main/java/com/koliving/api/user/application/dto/UserResponse.java index 36c62fba..754cfa65 100644 --- a/src/main/java/com/koliving/api/user/application/dto/UserResponse.java +++ b/src/main/java/com/koliving/api/user/application/dto/UserResponse.java @@ -2,15 +2,45 @@ import com.koliving.api.file.domain.ImageFile; -import com.koliving.api.user.Gender; -import com.koliving.api.user.SignUpStatus; -import com.koliving.api.user.User; -import com.koliving.api.user.UserRole; - +import com.koliving.api.user.domain.Gender; +import com.koliving.api.user.domain.SignUpStatus; +import com.koliving.api.user.domain.User; +import com.koliving.api.user.domain.UserRole; +import io.swagger.v3.oas.annotations.media.Schema; import java.time.LocalDate; -public record UserResponse(Long id, String email, String firstName, String lastName, Gender gender, LocalDate birthDate, - String description, ImageFile imageFile, UserRole userRole, SignUpStatus signUpStatus) { +@Schema(description = "회원 정보") +public record UserResponse( + @Schema(description = "회원 고유 ID") + Long id, + + @Schema(description = "회원 EMAIL") + String email, + + @Schema(description = "회원 이름") + String firstName, + + @Schema(description = "회원 성") + String lastName, + + @Schema(description = "회원 성별") + Gender gender, + + @Schema(description = "회원 생년월일") + LocalDate birthDate, + + @Schema(description = "회원 자기소개") + String description, + + @Schema(description = "회원 이미지파일 정보") + ImageFile imageFile, + + @Schema(description = "회원 권한") + UserRole userRole, + + @Schema(description = "회원 가입 상태") + SignUpStatus signUpStatus +) { public static UserResponse valueOf(User entity) { return new UserResponse( diff --git a/src/main/java/com/koliving/api/user/Gender.java b/src/main/java/com/koliving/api/user/domain/Gender.java similarity index 93% rename from src/main/java/com/koliving/api/user/Gender.java rename to src/main/java/com/koliving/api/user/domain/Gender.java index 19f5cde7..12a5827b 100644 --- a/src/main/java/com/koliving/api/user/Gender.java +++ b/src/main/java/com/koliving/api/user/domain/Gender.java @@ -1,4 +1,4 @@ -package com.koliving.api.user; +package com.koliving.api.user.domain; import lombok.Getter; diff --git a/src/main/java/com/koliving/api/user/domain/Notification.java b/src/main/java/com/koliving/api/user/domain/Notification.java new file mode 100644 index 00000000..fb71bcae --- /dev/null +++ b/src/main/java/com/koliving/api/user/domain/Notification.java @@ -0,0 +1,50 @@ +package com.koliving.api.user.domain; + +import com.koliving.api.base.domain.BaseEntity; +import jakarta.persistence.Entity; +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.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; + +/** + * author : haedoang date : 2023/11/05 description : + */ +@Entity(name = "TB_NOTIFICATION") +@DynamicInsert +@DynamicUpdate +@Getter +@ToString +@EqualsAndHashCode(of = "id", callSuper = false) +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Notification extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne + @JoinColumn(name = "SENDER_ID") + private User sender; + + @ManyToOne + @JoinColumn(name = "RECEIVER_ID") + private User receiver; + + private Notification(User sender, User receiver) { + this.sender = sender; + this.receiver = receiver; + } + + public static Notification of(User sender, User receiver) { + return new Notification(sender, receiver); + } +} diff --git a/src/main/java/com/koliving/api/user/domain/NotifyType.java b/src/main/java/com/koliving/api/user/domain/NotifyType.java new file mode 100644 index 00000000..508c59b2 --- /dev/null +++ b/src/main/java/com/koliving/api/user/domain/NotifyType.java @@ -0,0 +1,17 @@ +package com.koliving.api.user.domain; + +/** + * author : haedoang date : 2023/11/05 description : + */ +public enum NotifyType { + SEND, + RECEIVE; + + public boolean isSend() { + return this == SEND; + } + + public boolean isReceive() { + return this == RECEIVE; + } +} diff --git a/src/main/java/com/koliving/api/user/SignUpStatus.java b/src/main/java/com/koliving/api/user/domain/SignUpStatus.java similarity index 89% rename from src/main/java/com/koliving/api/user/SignUpStatus.java rename to src/main/java/com/koliving/api/user/domain/SignUpStatus.java index f26f8082..8b250664 100644 --- a/src/main/java/com/koliving/api/user/SignUpStatus.java +++ b/src/main/java/com/koliving/api/user/domain/SignUpStatus.java @@ -1,4 +1,4 @@ -package com.koliving.api.user; +package com.koliving.api.user.domain; import lombok.Getter; diff --git a/src/main/java/com/koliving/api/user/User.java b/src/main/java/com/koliving/api/user/domain/User.java similarity index 82% rename from src/main/java/com/koliving/api/user/User.java rename to src/main/java/com/koliving/api/user/domain/User.java index e1813675..7dc11c53 100644 --- a/src/main/java/com/koliving/api/user/User.java +++ b/src/main/java/com/koliving/api/user/domain/User.java @@ -1,9 +1,11 @@ -package com.koliving.api.user; +package com.koliving.api.user.domain; import static com.koliving.api.base.ServiceError.UNAUTHORIZED; +import com.koliving.api.base.domain.BaseEntity; import com.koliving.api.base.exception.KolivingServiceException; import com.koliving.api.file.domain.ImageFile; +import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; @@ -13,17 +15,20 @@ import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.Lob; +import jakarta.persistence.OneToMany; import jakarta.persistence.OneToOne; import jakarta.persistence.Temporal; import jakarta.persistence.TemporalType; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.Period; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.UUID; +import java.util.List; +import java.util.Objects; import lombok.AccessLevel; import lombok.Builder; -import lombok.Data; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; @@ -45,7 +50,7 @@ @ToString @EqualsAndHashCode(of = "id", callSuper = false) @NoArgsConstructor(access = AccessLevel.PROTECTED) -public class User implements UserDetails { +public class User extends BaseEntity implements UserDetails { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -95,6 +100,12 @@ public class User implements UserDetails { @Column(name = "LAST_MODIFIED_DATE") private LocalDateTime lastModifiedDate; + @OneToMany(mappedBy = "receiver", cascade = CascadeType.ALL) + private List receivedNotifications = new ArrayList<>(); + + @OneToMany(mappedBy = "sender", cascade = CascadeType.ALL) + private List sentNotifications = new ArrayList<>(); + @Builder public User(String email) { this.email = email; @@ -139,6 +150,14 @@ public void completeSignUp() { this.signUpStatus = SignUpStatus.COMPLETED; } + public void addReceivedNotification(Notification notification) { + this.receivedNotifications.add(notification); + } + + public void addSentNotification(Notification notification) { + this.sentNotifications.add(notification); + } + @Override public Collection getAuthorities() { String role = userRole.getSecurityName(); @@ -180,6 +199,18 @@ public void checkPassword(PasswordEncoder passwordEncoder, String rawPassword) { } } + public String getFullName() { + return String.format("%s %s", firstName, lastName); + } + + public int getAge() { + return Period.between(birthDate, LocalDate.now()).getYears(); + } + + public String getImageProfile() { + return Objects.isNull(this.getImageFile()) ? null : this.imageFile.getPath(); + } + public void update(User updatable) { this.imageFile = updatable.imageFile; this.firstName = updatable.firstName; diff --git a/src/main/java/com/koliving/api/user/UserRole.java b/src/main/java/com/koliving/api/user/domain/UserRole.java similarity index 85% rename from src/main/java/com/koliving/api/user/UserRole.java rename to src/main/java/com/koliving/api/user/domain/UserRole.java index ef103f38..34d8bd3b 100644 --- a/src/main/java/com/koliving/api/user/UserRole.java +++ b/src/main/java/com/koliving/api/user/domain/UserRole.java @@ -1,4 +1,4 @@ -package com.koliving.api.user; +package com.koliving.api.user.domain; import lombok.Getter; diff --git a/src/main/java/com/koliving/api/user/infra/NotificationRepository.java b/src/main/java/com/koliving/api/user/infra/NotificationRepository.java new file mode 100644 index 00000000..f7d056a5 --- /dev/null +++ b/src/main/java/com/koliving/api/user/infra/NotificationRepository.java @@ -0,0 +1,16 @@ +package com.koliving.api.user.infra; + +import com.koliving.api.user.domain.Notification; +import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; + +/** + * author : haedoang date : 2023/11/05 description : + */ +public interface NotificationRepository extends JpaRepository { + + List findAllBySenderId(Long senderId); + + List findAllByReceiverId(Long senderId); + +} diff --git a/src/main/java/com/koliving/api/user/UserPropertyEditor.java b/src/main/java/com/koliving/api/user/infra/UserPropertyEditor.java similarity index 91% rename from src/main/java/com/koliving/api/user/UserPropertyEditor.java rename to src/main/java/com/koliving/api/user/infra/UserPropertyEditor.java index d6ae4996..9227c263 100644 --- a/src/main/java/com/koliving/api/user/UserPropertyEditor.java +++ b/src/main/java/com/koliving/api/user/infra/UserPropertyEditor.java @@ -1,6 +1,7 @@ -package com.koliving.api.user; +package com.koliving.api.user.infra; import com.koliving.api.user.application.UserService; +import com.koliving.api.user.domain.User; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/koliving/api/user/UserRepository.java b/src/main/java/com/koliving/api/user/infra/UserRepository.java similarity index 77% rename from src/main/java/com/koliving/api/user/UserRepository.java rename to src/main/java/com/koliving/api/user/infra/UserRepository.java index 4cf54cbc..c0d31f2c 100644 --- a/src/main/java/com/koliving/api/user/UserRepository.java +++ b/src/main/java/com/koliving/api/user/infra/UserRepository.java @@ -1,5 +1,6 @@ -package com.koliving.api.user; +package com.koliving.api.user.infra; +import com.koliving.api.user.domain.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; diff --git a/src/main/java/com/koliving/api/validation/EmailDuplicationValidator.java b/src/main/java/com/koliving/api/validation/EmailDuplicationValidator.java index f4a4f603..8741cf2f 100644 --- a/src/main/java/com/koliving/api/validation/EmailDuplicationValidator.java +++ b/src/main/java/com/koliving/api/validation/EmailDuplicationValidator.java @@ -1,8 +1,8 @@ package com.koliving.api.validation; import com.koliving.api.dto.AuthEmailRequestDto; -import com.koliving.api.user.User; -import com.koliving.api.user.UserRepository; +import com.koliving.api.user.domain.User; +import com.koliving.api.user.infra.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import org.springframework.validation.Errors; diff --git a/src/main/java/com/koliving/api/validation/EmailPresenceValidator.java b/src/main/java/com/koliving/api/validation/EmailPresenceValidator.java index b185321a..66d6b03c 100644 --- a/src/main/java/com/koliving/api/validation/EmailPresenceValidator.java +++ b/src/main/java/com/koliving/api/validation/EmailPresenceValidator.java @@ -1,8 +1,8 @@ package com.koliving.api.validation; import com.koliving.api.dto.AuthEmailRequestDto; -import com.koliving.api.user.User; -import com.koliving.api.user.UserRepository; +import com.koliving.api.user.domain.User; +import com.koliving.api.user.infra.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import org.springframework.validation.Errors; diff --git a/src/main/resources/templates/contact-email-template.html b/src/main/resources/templates/contact-email-template.html new file mode 100644 index 00000000..226e20c8 --- /dev/null +++ b/src/main/resources/templates/contact-email-template.html @@ -0,0 +1,52 @@ + + + + + + + + + +
+
+

+
+
+ +
+
+ +
+
+
+ userProfile +
+
+
+ years old + | + +
+
+
+
+ + \ No newline at end of file diff --git a/src/test/java/com/koliving/api/auth/login/LoginProviderTest.java b/src/test/java/com/koliving/api/auth/login/LoginProviderTest.java index 93e3fd9a..f9ebdc25 100644 --- a/src/test/java/com/koliving/api/auth/login/LoginProviderTest.java +++ b/src/test/java/com/koliving/api/auth/login/LoginProviderTest.java @@ -1,6 +1,6 @@ package com.koliving.api.auth.login; -import com.koliving.api.user.User; +import com.koliving.api.user.domain.User; import com.koliving.api.user.application.UserService; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/koliving/api/auth/login/LoginSuccessHandlerTest.java b/src/test/java/com/koliving/api/auth/login/LoginSuccessHandlerTest.java index 44701b84..b725665e 100644 --- a/src/test/java/com/koliving/api/auth/login/LoginSuccessHandlerTest.java +++ b/src/test/java/com/koliving/api/auth/login/LoginSuccessHandlerTest.java @@ -3,7 +3,7 @@ import com.koliving.api.auth.AuthFacade; import com.koliving.api.dto.JwtTokenDto; import com.koliving.api.dto.ResponseDto; -import com.koliving.api.user.User; +import com.koliving.api.user.domain.User; import com.koliving.api.utils.HttpUtils; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletResponse; diff --git a/src/test/java/com/koliving/api/fixtures/UserFixture.java b/src/test/java/com/koliving/api/fixtures/UserFixture.java index 8070eecd..5713ab81 100644 --- a/src/test/java/com/koliving/api/fixtures/UserFixture.java +++ b/src/test/java/com/koliving/api/fixtures/UserFixture.java @@ -1,6 +1,6 @@ package com.koliving.api.fixtures; -import com.koliving.api.user.User; +import com.koliving.api.user.domain.User; import java.util.UUID; diff --git a/src/test/java/com/koliving/api/room/infra/RoomRepositoryTest.java b/src/test/java/com/koliving/api/room/infra/RoomRepositoryTest.java index 138006e0..b8d013ed 100644 --- a/src/test/java/com/koliving/api/room/infra/RoomRepositoryTest.java +++ b/src/test/java/com/koliving/api/room/infra/RoomRepositoryTest.java @@ -4,7 +4,6 @@ import static com.koliving.api.fixtures.MaintenanceFixture.관리비_없음; import static com.koliving.api.fixtures.RoomInfoFixture.스튜디오_방0_욕실1_룸메1; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.useRepresentation; import com.koliving.api.BaseDataJpaTest; import com.koliving.api.fixtures.UserFixture; @@ -22,8 +21,8 @@ import java.util.NoSuchElementException; import java.util.stream.Collectors; -import com.koliving.api.user.User; -import com.koliving.api.user.UserRepository; +import com.koliving.api.user.domain.User; +import com.koliving.api.user.infra.UserRepository; import org.assertj.core.util.Sets; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; diff --git a/src/test/java/com/koliving/api/user/UserServiceTest.java b/src/test/java/com/koliving/api/user/UserServiceTest.java index 11a355bd..393cdcd0 100644 --- a/src/test/java/com/koliving/api/user/UserServiceTest.java +++ b/src/test/java/com/koliving/api/user/UserServiceTest.java @@ -2,6 +2,8 @@ import com.koliving.api.user.application.UserService; import com.koliving.api.user.application.dto.UserResponse; +import com.koliving.api.user.domain.User; +import com.koliving.api.user.infra.UserRepository; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -15,7 +17,6 @@ import java.util.Arrays; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; import static com.koliving.api.user.UserUtils.createUser; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/src/test/java/com/koliving/api/user/UserUtils.java b/src/test/java/com/koliving/api/user/UserUtils.java index a2d688cd..c4931b09 100644 --- a/src/test/java/com/koliving/api/user/UserUtils.java +++ b/src/test/java/com/koliving/api/user/UserUtils.java @@ -1,5 +1,6 @@ package com.koliving.api.user; +import com.koliving.api.user.domain.User; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication;