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

전남대 BE_서영우 4주차 과제 (1단계) #229

Open
wants to merge 8 commits into
base: westzeroright
Choose a base branch
from
48 changes: 47 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,47 @@
# spring-gift-enhancement
# spring-gift-enhancement

## 구현할 기능 목록

### 1단계

### 상품 카테고리

TO DO
- [ ] 카테코리 엔티티 클래스 정의
- [ ] 상품 정보에 카테고리 추가


- [ ] 카테고리 기본 CRUD
- [ ] 카테고리에 속한 상품 조회 - 테스트 코드
- [ ] 상품을 등록할 떼 카테고리 설정
- [ ] 상품의 카테고리 수정 ex) A 상품의 카테고리를 '교환권' 카테고리에서 '과제면회권' 카테고리로 변경한다

고려해야할 사항
- 상품에는 항상 하나의 카테고리가 있어야 한다.
- 상품 카테고리는 수정할 수 있다.
- 관리자 화면에서 상품을 추가할 때 카테고리를 지정할 수 있다.
- 카테고리는 1차 카테고리만 있으며 2차 카테고리는 고려하지 않는다.
- 카테고리의 예시는 아래와 같다.
- 교환권, 상품권, 뷰티, 패션, 식품, 리빙/도서, 레저/스포츠, 아티스트/캐릭터, 유아동/반려, 디지털/가전, 카카오프렌즈, 트렌드 선물, 백화점, ...

**Request**
```http request
GET /api/categories HTTP/1.1
```

**Response**
```http request
HTTP/1.1 200
Content-Type: application/json

[
{
"id": 91,
"name": "교환권",
"color": "#6c95d1",
"imageUrl": "https://gift-s.kakaocdn.net/dn/gift/images/m640/dimm_theme.png",
"description": ""
}
]

```
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ dependencies {
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.6'
implementation 'org.projectlombok:lombok'
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
testImplementation 'org.mockito:mockito-junit-jupiter:5.2.0'
}

tasks.named('test') {
Expand Down
54 changes: 54 additions & 0 deletions src/main/java/gift/category/CategoryController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package gift.category;

import java.util.List;
import org.springframework.http.HttpEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
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.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/categories")
public class CategoryController {

private final CategoryService categoryService;

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

@GetMapping
public List<CategoryResponseDto> getAllCategory() {
return categoryService.getAllCategory();
}

@PostMapping
public CategoryResponseDto addCateogory(@RequestBody CategoryRequestDto categoryRequestDto) {
return categoryService.postCategory(categoryRequestDto);
}

@PutMapping("/{id}")
public CategoryResponseDto updateCategory(@PathVariable Long id, @RequestBody CategoryRequestDto categoryRequestDto) {
return categoryService.putCategory(id, categoryRequestDto);
}

@DeleteMapping("/{id}")
public HttpEntity<String> deleteCategory(@PathVariable Long id) {
return categoryService.deleteCategoryById(id);
}

@GetMapping("/{id}")
public CategoryResponseDto getCategoryById(@PathVariable Long id) {
return categoryService.getCategoryById(id);
}

@GetMapping("/products/{id}")
public List<Long> getProducts(@PathVariable Long id) {
return categoryService.getProductsInCategory(id);
}

}
12 changes: 12 additions & 0 deletions src/main/java/gift/category/CategoryRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package gift.category;

import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface CategoryRepository extends JpaRepository<Cateogory,Long> {

Optional<Cateogory> findByName(String name);

}
5 changes: 5 additions & 0 deletions src/main/java/gift/category/CategoryRequestDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package gift.category;

public record CategoryRequestDto(String name, String color, String imageUrl, String description) {

}
5 changes: 5 additions & 0 deletions src/main/java/gift/category/CategoryResponseDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package gift.category;

public record CategoryResponseDto(Long id, String name, String color, String imageUrl, String description) {

}
103 changes: 103 additions & 0 deletions src/main/java/gift/category/CategoryService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package gift.category;

import gift.exception.AlreadyExistCategory;
import gift.exception.InvalidCategory;
import gift.product.Product;
import gift.product.ProductRepository;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.http.HttpEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

@Service
public class CategoryService {

private final CategoryRepository categoryRepository;
private final ProductRepository productRepository;

public CategoryService(CategoryRepository categoryRepository, ProductRepository productRepository) {
this.categoryRepository = categoryRepository;
this.productRepository = productRepository;
}

public List<CategoryResponseDto> getAllCategory() {
return categoryRepository.findAll().stream()
.map(category -> new CategoryResponseDto(
category.getId(),
category.getName(),
category.getColor(),
category.getImageUrl(),
category.getDescription()))
.collect(Collectors.toList());
}

public CategoryResponseDto postCategory(CategoryRequestDto categoryRequestDto) {
Cateogory cateogory = new Cateogory(
categoryRequestDto.name(),
categoryRequestDto.color(),
categoryRequestDto.imageUrl(),
categoryRequestDto.description()
);
if (categoryRepository.findByName(cateogory.getName()).isPresent()) {
throw new AlreadyExistCategory("동일한 카테고리가 이미 존재합니다.");
}

categoryRepository.saveAndFlush(cateogory);

return new CategoryResponseDto(
cateogory.getId(),
cateogory.getName(),
cateogory.getColor(),
cateogory.getImageUrl(),
cateogory.getDescription()
);
}

public CategoryResponseDto putCategory(Long id, CategoryRequestDto categoryRequestDto) {
Cateogory cateogory = categoryRepository.findById(id)
.orElseThrow(() -> new InvalidCategory("유효하지 않은 카테고리입니다."));

cateogory.update(categoryRequestDto.name(), categoryRequestDto.color(), categoryRequestDto.imageUrl(), categoryRequestDto.description());
categoryRepository.saveAndFlush(cateogory);

return new CategoryResponseDto(
cateogory.getId(),
cateogory.getName(),
cateogory.getColor(),
cateogory.getImageUrl(),
cateogory.getDescription()
);
}

public HttpEntity<String> deleteCategoryById(Long id) {
Cateogory cateogory = categoryRepository.findById(id)
.orElseThrow(() -> new InvalidCategory("유효하지 않은 카테고리입니다."));

categoryRepository.delete(cateogory);

return ResponseEntity.ok("성공적으로 삭제되었습니다");
}

public CategoryResponseDto getCategoryById(Long id) {
Cateogory cateogory = categoryRepository.findById(id)
.orElseThrow(() -> new InvalidCategory("유효하지 않은 카테고리입니다."));

return new CategoryResponseDto(
cateogory.getId(),
cateogory.getName(),
cateogory.getColor(),
cateogory.getImageUrl(),
cateogory.getDescription()
);
}

public List<Long> getProductsInCategory(Long id) {
List<Product> products = productRepository.findAllByCateogory_Id(id);

return products.stream()
.map(Product::getId)
.collect(Collectors.toList());
}

}
75 changes: 75 additions & 0 deletions src/main/java/gift/category/Cateogory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package gift.category;

import gift.product.Product;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "category")
public class Cateogory {

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

@Column(name = "name", nullable = false, unique = true)
private String name;

@Column(name = "color", nullable = false)
private String color;

@Column(name = "image_url", nullable = false)
private String imageUrl;

@Column(name = "description", nullable = false)
private String description;

@OneToMany
@JoinColumn
private List<Product> products = new ArrayList<>();

protected Cateogory() {
}

public Cateogory(String name, String color, String imageUrl, String description) {
this.name = name;
this.color = color;
this.imageUrl = imageUrl;
this.description = description;
}

public Long getId() {
return id;
}

public String getName() {
return name;
}

public String getColor() {
return color;
}

public String getImageUrl() {
return imageUrl;
}

public String getDescription() {
return description;
}

public void update(String name, String color, String imageUrl, String description) {
this.name = name;
this.color = color;
this.imageUrl = imageUrl;
this.description = description;
}
}
8 changes: 8 additions & 0 deletions src/main/java/gift/exception/AlreadyExistCategory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package gift.exception;

public class AlreadyExistCategory extends RuntimeException{

public AlreadyExistCategory(String message) {
super(message);
}
}
8 changes: 8 additions & 0 deletions src/main/java/gift/exception/InvalidCategory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package gift.exception;

import java.util.NoSuchElementException;

public class InvalidCategory extends NoSuchElementException {

public InvalidCategory(String message) {super(message);}
}
18 changes: 17 additions & 1 deletion src/main/java/gift/product/Product.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package gift.product;

import gift.category.Cateogory;
import jakarta.persistence.Column;
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 jakarta.persistence.Table;

@Entity
Expand All @@ -24,13 +27,18 @@ public class Product {
@Column(name = "image_url", nullable = false)
private String imageUrl;

@ManyToOne
@JoinColumn(name = "category_id")
private Cateogory cateogory;

protected Product() {
}

public Product(String name, int price, String imageUrl) {
public Product(String name, int price, String imageUrl, Cateogory cateogory) {
this.name = name;
this.price = price;
this.imageUrl = imageUrl;
this.cateogory = cateogory;
}

public void update(String name, int price, String imageUrl) {
Expand All @@ -39,6 +47,10 @@ public void update(String name, int price, String imageUrl) {
this.imageUrl = imageUrl;
}

public void changeCategory(Cateogory cateogory) {
this.cateogory = cateogory;
}

public Long getId() {
return id;
}
Expand All @@ -54,5 +66,9 @@ public int getPrice() {
public String getImageUrl() {
return imageUrl;
}

public Cateogory getCateogory() {
return cateogory;
}
}

Loading