Skip to content

Commit

Permalink
[Feature] 관심사 목록 조회와 생성을 구현한다 (#77)
Browse files Browse the repository at this point in the history
* feature: 관심사 목록 조회 구현

* style: 개행 제거

* feature: 관심사 생성 구현
  • Loading branch information
vectorch9 authored Nov 2, 2023
1 parent c1af430 commit 8b6a589
Show file tree
Hide file tree
Showing 12 changed files with 204 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
@Service
public class SaveBadgeService {


private static final String CATEGORY = "BADGE";

private final Badges badges;
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/daybyquest/global/error/ExceptionCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ public enum ExceptionCode {
EXCEED_BADGE("BDE-02", BAD_REQUEST, "뱃지는 최대 15개만 지정가능합니다"),

// Interest
NOT_EXIST_INTEREST("INT-00", BAD_REQUEST, "존재하지 않는 관심사 입니다"),
NOT_EXIST_INTEREST("INT-00", BAD_REQUEST, "존재하지 않는 관심사입니다"),
ALREADY_EXIST_INTEREST("INT-01", BAD_REQUEST, "이미 존재하는 관심사 이름입니다"),

// Relationship
NOT_FOLLOWING_USER("REL-00", BAD_REQUEST, "팔로우하지 않은 사용자입니다"),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package daybyquest.interest.application;

import daybyquest.interest.domain.Interests;
import daybyquest.interest.dto.response.InterestResponse;
import daybyquest.interest.dto.response.MultiInterestResponse;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class GetInterestsService {

private final Interests interests;

public GetInterestsService(final Interests interests) {
this.interests = interests;
}

@Transactional(readOnly = true)
public MultiInterestResponse invoke() {
return new MultiInterestResponse(interests.findAll().stream().map(InterestResponse::of).toList());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package daybyquest.interest.application;

import daybyquest.global.utils.MultipartFileUtils;
import daybyquest.image.vo.Image;
import daybyquest.image.vo.ImageIdentifierGenerator;
import daybyquest.image.vo.Images;
import daybyquest.interest.domain.Interest;
import daybyquest.interest.domain.Interests;
import daybyquest.interest.dto.request.SaveInterestRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

@Service
public class SaveInterestService {

private static final String CATEGORY = "INTEREST";

private final Interests interests;

private final Images images;

private final ImageIdentifierGenerator generator;

public SaveInterestService(final Interests interests, final Images images,
final ImageIdentifierGenerator generator) {
this.interests = interests;
this.images = images;
this.generator = generator;
}

@Transactional
public void invoke(final SaveInterestRequest request, final MultipartFile file) {
final String identifier = generator.generateIdentifier(CATEGORY, file.getOriginalFilename());
images.upload(identifier, MultipartFileUtils.getInputStream(file));
final Interest interest = new Interest(request.getName(), new Image(identifier));
interests.save(interest);
}
}
16 changes: 15 additions & 1 deletion src/main/java/daybyquest/interest/domain/Interest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package daybyquest.interest.domain;

import daybyquest.global.error.exception.InvalidDomainException;
import daybyquest.image.vo.Image;
import jakarta.persistence.Column;
import jakarta.persistence.Embedded;
Expand All @@ -14,8 +15,10 @@
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Interest {

private static final int MAX_NAME_LENGTH = 20;

@Id
@Column(length = 10)
@Column(length = MAX_NAME_LENGTH)
private String name;

@Embedded
Expand All @@ -24,5 +27,16 @@ public class Interest {
public Interest(final String name, final Image image) {
this.name = name;
this.image = image;
validateName();
}

public String getImageIdentifier() {
return image.getImageIdentifier();
}

private void validateName() {
if (name.isEmpty() || name.length() > MAX_NAME_LENGTH) {
throw new InvalidDomainException();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,7 @@ interface InterestRepository extends Repository<Interest, String> {

List<Interest> findAllByNameIn(final Collection<String> names);

List<Interest> findAll();

boolean existsByName(final String name);
}
18 changes: 18 additions & 0 deletions src/main/java/daybyquest/interest/domain/Interests.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package daybyquest.interest.domain;

import static daybyquest.global.error.ExceptionCode.ALREADY_EXIST_INTEREST;

import daybyquest.global.error.exception.InvalidDomainException;
import daybyquest.global.error.exception.NotExistInterestException;
import java.util.Collection;
import java.util.List;
Expand All @@ -14,6 +17,17 @@ public class Interests {
this.interestRepository = interestRepository;
}

public void save(final Interest interest) {
validateNotExistentByName(interest.getName());
interestRepository.save(interest);
}

public void validateNotExistentByName(final String interestName) {
if (interestRepository.existsByName(interestName)) {
throw new InvalidDomainException(ALREADY_EXIST_INTEREST);
}
}

public void validateInterest(final String interestName) {
if (!interestRepository.existsByName(interestName)) {
throw new NotExistInterestException();
Expand All @@ -35,4 +49,8 @@ private void validateContainsInterest(final Collection<String> interestStrings,
throw new NotExistInterestException();
}
}

public List<Interest> findAll() {
return interestRepository.findAll();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package daybyquest.interest.dto.request;

import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class SaveInterestRequest {

@NotBlank
private String name;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package daybyquest.interest.dto.response;

import daybyquest.interest.domain.Interest;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class InterestResponse {

private String name;

private String imageIdentifier;

private InterestResponse(final String name, final String imageIdentifier) {
this.name = name;
this.imageIdentifier = imageIdentifier;
}

public static InterestResponse of(final Interest interest) {
return new InterestResponse(interest.getName(), interest.getImageIdentifier());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package daybyquest.interest.dto.response;

import java.util.List;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class MultiInterestResponse {

private List<InterestResponse> interests;

public MultiInterestResponse(final List<InterestResponse> interests) {
this.interests = interests;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package daybyquest.interest.presentation;

import daybyquest.auth.Authorization;
import daybyquest.auth.domain.AccessUser;
import daybyquest.interest.application.SaveInterestService;
import daybyquest.interest.dto.request.SaveInterestRequest;
import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RestController
public class InterestCommandApi {

private final SaveInterestService saveInterestService;

public InterestCommandApi(final SaveInterestService saveInterestService) {
this.saveInterestService = saveInterestService;
}

@PostMapping("/interest")
@Authorization(admin = true)
public ResponseEntity<Void> saveInterest(final AccessUser user,
@RequestPart("image") final MultipartFile file,
@RequestPart("request") @Valid final SaveInterestRequest request) {
saveInterestService.invoke(request, file);
return ResponseEntity.ok().build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package daybyquest.interest.presentation;

import daybyquest.interest.application.GetInterestsService;
import daybyquest.interest.dto.response.MultiInterestResponse;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class InterestQueryApi {

private final GetInterestsService getInterestsService;

public InterestQueryApi(final GetInterestsService getInterestsService) {
this.getInterestsService = getInterestsService;
}

@GetMapping("/interest")
public ResponseEntity<MultiInterestResponse> getInterests() {
final MultiInterestResponse response = getInterestsService.invoke();
return ResponseEntity.ok(response);
}
}

0 comments on commit 8b6a589

Please sign in to comment.