Skip to content

Commit

Permalink
Merge branch 'dev-be' into feat/47-write-checklist-api
Browse files Browse the repository at this point in the history
  • Loading branch information
shin-jisong authored Jul 23, 2024
2 parents 8ce6fb9 + 2f1c2e4 commit acd7d06
Show file tree
Hide file tree
Showing 18 changed files with 407 additions and 14 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/backend-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ jobs:
- name: Grant execute permission for gradlew
run: chmod +x backend/bang-ggood/gradlew

- name: Write application.yml
env:
APPLICATION_YML: ${{ secrets.APPLICATION_YML }}
APPLICATION_TEST_YML: ${{ secrets.APPLICATION_TEST_YML }}
run: |
echo "${APPLICATION_YML}" > src/main/resources/application.yml
echo "${APPLICATION_TEST_YML}" > src/test/resources/application-test.yml
- name: Build with Gradle
run: ./gradlew clean build
working-directory: backend/bang-ggood
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/backend-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ jobs:

- name: Grant execute permission for gradlew
run: chmod +x gradlew

- name: Write application.yml
env:
APPLICATION_YML: ${{ secrets.APPLICATION_YML }}
APPLICATION_TEST_YML: ${{ secrets.APPLICATION_TEST_YML }}
run: |
echo "${APPLICATION_YML}" > src/main/resources/application.yml
echo "${APPLICATION_TEST_YML}" > src/test/resources/application-test.yml
- name: Build with Gradle
run: ./gradlew clean build
Expand Down
1 change: 1 addition & 0 deletions backend/bang-ggood/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ bin/

### IntelliJ IDEA ###
src/main/resources/application.yml
src/test/resources/application-test.yml
.idea
*.iws
*.iml
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.bang_ggood.category.controller;

import com.bang_ggood.category.dto.CategoriesReadResponse;
import com.bang_ggood.category.dto.CategoryPriorityCreateRequest;
import com.bang_ggood.category.service.CategoryService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CategoryController {

private final CategoryService categoryService;

public CategoryController(CategoryService categoryService) {
this.categoryService = categoryService;
}

@PostMapping("/categories/priority")
public ResponseEntity<Void> createCategoriesPriority(@RequestBody CategoryPriorityCreateRequest request) {
// TODO: List 요소 null check 필요
categoryService.createCategoriesPriority(request);
return ResponseEntity.noContent().build();
}

@GetMapping("/categories")
public ResponseEntity<CategoriesReadResponse> readCategories() {
return ResponseEntity.ok(categoryService.readCategories());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.bang_ggood.category.domain;

import java.util.Arrays;

public enum Category {

CLEAN(1, "청결"),
ROOM_CONDITION(2, "방 컨디션"),
AMENITY(3, "편의시설"),
OPTION(4, "옵션"),
ENVIRONMENT(5, "주거환경"),
SECURITY(6, "보안"),
ECONOMIC(7, "경제적");

private final int id;
private final String description;

Category(int id, String description) {
this.id = id;
this.description = description;
}

public static boolean contains(int id) {
return Arrays.stream(values())
.anyMatch(category -> category.id == id);
}

public int getId() {
return id;
}

public String getDescription() {
return description;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.bang_ggood.category.domain;

import com.bang_ggood.BaseEntity;
import com.bang_ggood.user.domain.User;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import java.util.Objects;

@Entity
public class CategoryPriority extends BaseEntity {

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

@Column(nullable = false)
private Integer categoryId;

@ManyToOne(fetch = FetchType.LAZY)
private User user;

protected CategoryPriority() {
}

public CategoryPriority(Integer categoryId, User user) {
this.categoryId = categoryId;
this.user = user;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
CategoryPriority that = (CategoryPriority) o;
return Objects.equals(id, that.id);
}

@Override
public int hashCode() {
return Objects.hash(id);
}

@Override
public String toString() {
return "CategoryPriority{" +
"id=" + id +
", categoryId=" + categoryId +
", user=" + user +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.bang_ggood.category.dto;

import java.util.List;

public record CategoriesReadResponse(List<CategoryReadResponse> categories) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.bang_ggood.category.dto;

import java.util.List;

public record CategoryPriorityCreateRequest(List<Integer> categoryIds) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.bang_ggood.category.dto;

import com.bang_ggood.category.domain.Category;

public record CategoryReadResponse(Integer categoryId, String categoryName) {

public static CategoryReadResponse from(Category category) {
return new CategoryReadResponse(category.getId(), category.getDescription());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.bang_ggood.category.repository;

import com.bang_ggood.category.domain.CategoryPriority;
import org.springframework.data.jpa.repository.JpaRepository;

public interface CategoryPriorityRepository extends JpaRepository<CategoryPriority, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.bang_ggood.category.service;

import com.bang_ggood.category.domain.Category;
import com.bang_ggood.category.domain.CategoryPriority;
import com.bang_ggood.category.dto.CategoriesReadResponse;
import com.bang_ggood.category.dto.CategoryPriorityCreateRequest;
import com.bang_ggood.category.dto.CategoryReadResponse;
import com.bang_ggood.category.repository.CategoryPriorityRepository;
import com.bang_ggood.exception.BangggoodException;
import com.bang_ggood.user.domain.User;
import com.bang_ggood.user.repository.UserRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

import static com.bang_ggood.exception.ExceptionCode.CATEGORY_DUPLICATED;
import static com.bang_ggood.exception.ExceptionCode.CATEGORY_NOT_FOUND;
import static com.bang_ggood.exception.ExceptionCode.CATEGORY_PRIORITY_INVALID_COUNT;

@Service
public class CategoryService {

private static final int MAX_CATEGORY_PRIORITY_COUNT = 3;

private final CategoryPriorityRepository categoryPriorityRepository;
private final UserRepository userRepository;

public CategoryService(CategoryPriorityRepository categoryPriorityRepository, UserRepository userRepository) {
this.categoryPriorityRepository = categoryPriorityRepository;
this.userRepository = userRepository;
}

@Transactional
public void createCategoriesPriority(CategoryPriorityCreateRequest request) {
validateDuplication(request);
validateCategoryCount(request);
validateCategoryId(request);

User user = userRepository.getUserById(1L);
List<CategoryPriority> categoryPriorities = request.categoryIds().stream()
.map(id -> new CategoryPriority(id, user))
.toList();

categoryPriorityRepository.saveAll(categoryPriorities);
}

private void validateDuplication(CategoryPriorityCreateRequest request) {
if (request.categoryIds().size() != Set.copyOf(request.categoryIds()).size()) {
throw new BangggoodException(CATEGORY_DUPLICATED);
}
}

private void validateCategoryCount(CategoryPriorityCreateRequest request) {
if (request.categoryIds().size() > MAX_CATEGORY_PRIORITY_COUNT) {
throw new BangggoodException(CATEGORY_PRIORITY_INVALID_COUNT);
}
}

private void validateCategoryId(CategoryPriorityCreateRequest request) {
for (Integer id : request.categoryIds()) {
if (!Category.contains(id)) {
throw new BangggoodException(CATEGORY_NOT_FOUND);
}
}
}

public CategoriesReadResponse readCategories() {
List<CategoryReadResponse> categoryReadResponses = Arrays.stream(Category.values())
.map(CategoryReadResponse::from)
.toList();
return new CategoriesReadResponse(categoryReadResponses);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ public enum ExceptionCode {
INVALID_PARAMETER(HttpStatus.BAD_REQUEST, "잘못된 인자입니다."),
INVALID_OPTION_ID(HttpStatus.BAD_REQUEST, "잘못된 옵션 ID입니다."),
INVALID_QUESTION_ID(HttpStatus.BAD_REQUEST, "잘못된 질문 ID입니다.");
USER_NOT_FOUND(HttpStatus.BAD_REQUEST, "유저 존재하지 않습니다."),
CATEGORY_PRIORITY_INVALID_COUNT(HttpStatus.BAD_REQUEST, "카테고리 개수가 유효하지 않습니다."),
CATEGORY_NOT_FOUND(HttpStatus.BAD_REQUEST, "카테코리가 존재하지 않습니다."),
CATEGORY_DUPLICATED(HttpStatus.BAD_REQUEST, "중복된 카테고리가 존재합니다."),
;

private final HttpStatus httpStatus;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ public User(Long id, String name) {
this.name = name;
}

public User(String name) {
this.name = name;
}

protected User() {
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.bang_ggood.user.repository;

import com.bang_ggood.exception.BangggoodException;
import com.bang_ggood.exception.ExceptionCode;
import com.bang_ggood.user.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {

default User getUserById(Long id) {
return findById(id).orElseThrow(() -> new BangggoodException(ExceptionCode.USER_NOT_FOUND));
}
}
11 changes: 11 additions & 0 deletions backend/bang-ggood/src/main/resources/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,14 @@ CREATE TABLE checklist_question
FOREIGN KEY (checklist_id) REFERENCES checklist (id)
);


CREATE TABLE category_priority
(
id bigint generated by default as identity,
category_id tinyint not null,
user_id bigint not null,
created_at TIMESTAMP not null,
modified_at TIMESTAMP not null,
primary key (id),
foreign key (user_id) references users
);
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,15 @@
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import java.time.LocalDateTime;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;

@ActiveProfiles("test")
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
class JpaAuditingTest {
import java.time.LocalDateTime;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertAll;

class JpaAuditingTest extends IntegrationTestSupport{

@Autowired
private TestRepository testRepository;
Expand Down
Loading

0 comments on commit acd7d06

Please sign in to comment.