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 구현 #10

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions 라이/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ dependencies {
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springdoc:springdoc-openapi-ui:1.6.15'
implementation 'io.springfox:springfox-swagger2:2.9.2'
implementation 'io.springfox:springfox-swagger-ui:2.9.2'
implementation 'org.springframework.boot:spring-boot-starter-validation'
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ public enum ErrorStatus implements BaseErrorCode {
_UNAUTHORIZED(HttpStatus.UNAUTHORIZED,"COMMON401","인증이 필요합니다."),
_FORBIDDEN(HttpStatus.FORBIDDEN, "COMMON403", "금지된 요청입니다."),

// 멤버 관려 에러
// Member
MEMBER_NOT_FOUND(HttpStatus.BAD_REQUEST, "MEMBER4001", "사용자가 없습니다."),
NICKNAME_NOT_EXIST(HttpStatus.BAD_REQUEST, "MEMBER4002", "닉네임은 필수 입니다."),

// 예시,,,
ARTICLE_NOT_FOUND(HttpStatus.NOT_FOUND, "ARTICLE4001", "게시글이 없습니다."),
// Food Category
FOOD_CATEGORY_NOT_FOUND(HttpStatus.NOT_FOUND, "FOODCATEGORY4001", "음식 카테고리가 없습니다."),

// For test
TEMP_EXCEPTION(HttpStatus.BAD_REQUEST, "TEMP4001", "이거는 테스트");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.umc.demo.apiPayload.exception.handler;

import com.umc.demo.apiPayload.code.BaseErrorCode;
import com.umc.demo.apiPayload.exception.GeneralException;

public class FoodCategoryHandler extends GeneralException {

public FoodCategoryHandler(BaseErrorCode errorCode) {
super(errorCode);
}
}
39 changes: 39 additions & 0 deletions 라이/src/main/java/com/umc/demo/config/SwaggerConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.umc.demo.config;

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.servers.Server;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SwaggerConfig {

@Bean
public OpenAPI UMCstudyAPI() {
Info info = new Info()
.title("UMC Server WorkBook API")
.description("UMC Server WorkBook API 명세서")
.version("1.0.0");

String jwtSchemeName = "JWT TOKEN";
// API 요청헤더에 인증정보 포함
SecurityRequirement securityRequirement = new SecurityRequirement().addList(jwtSchemeName);
// SecuritySchemes 등록
Components components = new Components()
.addSecuritySchemes(jwtSchemeName, new SecurityScheme()
.name(jwtSchemeName)
.type(SecurityScheme.Type.HTTP) // HTTP 방식
.scheme("bearer")
.bearerFormat("JWT"));

return new OpenAPI()
.addServersItem(new Server().url("/"))
.info(info)
.addSecurityItem(securityRequirement)
.components(components);
}
}
43 changes: 43 additions & 0 deletions 라이/src/main/java/com/umc/demo/converter/MemberConverter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.umc.demo.converter;

import com.umc.demo.domain.Member;
import com.umc.demo.domain.enums.Gender;
import com.umc.demo.web.dto.MemberRequestDTO;
import com.umc.demo.web.dto.MemberResponseDTO;
import java.time.LocalDateTime;
import java.util.ArrayList;

public class MemberConverter {

public static MemberResponseDTO.JoinResultDTO toJoinResultDTO(Member member){
return MemberResponseDTO.JoinResultDTO.builder()
.memberId(member.getId())
.createdAt(LocalDateTime.now())
.build();
}

public static Member toMember(MemberRequestDTO.JoinDto request){

Gender gender = null;

switch (request.getGender()){
case 1:
gender = Gender.MALE;
break;
case 2:
gender = Gender.FEMALE;
break;
case 3:
gender = Gender.NONE;
break;
}

return Member.builder()
.address(request.getAddress())
.specAddress(request.getSpecAddress())
.gender(gender)
.name(request.getName())
.memberPreferList(new ArrayList<>())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.umc.demo.converter;

import com.umc.demo.domain.FoodCategory;
import com.umc.demo.domain.mapping.MemberPrefer;
import java.util.List;
import java.util.stream.Collectors;

public class MemberPreferConverter {

public static List<MemberPrefer> toMemberPreferList(List<FoodCategory> foodCategoryList){

return foodCategoryList.stream()
.map(foodCategory ->
MemberPrefer.builder()
.foodCategory(foodCategory)
.build()
).collect(Collectors.toList());
}
}
8 changes: 7 additions & 1 deletion 라이/src/main/java/com/umc/demo/domain/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,14 @@
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;

@Entity
@Getter
@DynamicUpdate
@DynamicInsert
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
Expand Down Expand Up @@ -58,9 +63,10 @@ public class Member extends BaseEntity {

private LocalDate inactiveDate;

@Column(nullable = false, length = 50)
// @Column(nullable = false, length = 50)
private String email;

@ColumnDefault("0")
private Integer point;

@OneToMany(mappedBy = "member", cascade = CascadeType.ALL)
Expand Down
2 changes: 1 addition & 1 deletion 라이/src/main/java/com/umc/demo/domain/enums/Gender.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package com.umc.demo.domain.enums;

public enum Gender {
MALE, FEMALE
MALE, FEMALE, NONE,
}
11 changes: 11 additions & 0 deletions 라이/src/main/java/com/umc/demo/domain/mapping/MemberPrefer.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,15 @@ public class MemberPrefer extends BaseEntity {
@JoinColumn(name = "category_id")
private FoodCategory foodCategory;

public void setMember(Member member){
if(this.member != null)
member.getMemberPreferList().remove(this);
this.member = member;
member.getMemberPreferList().add(this);
}

public void setFoodCategory(FoodCategory foodCategory){
this.foodCategory = foodCategory;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.umc.demo.repository;

import com.umc.demo.domain.FoodCategory;
import org.springframework.data.jpa.repository.JpaRepository;

public interface FoodCategoryRepository extends JpaRepository<FoodCategory, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.umc.demo.repository;

import com.umc.demo.domain.Member;
import org.springframework.data.jpa.repository.JpaRepository;

public interface MemberRepository extends JpaRepository<Member, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.umc.demo.service.MemberService;

import com.umc.demo.domain.Member;
import com.umc.demo.web.dto.MemberRequestDTO;

public interface MemberCommandService {

Member joinMember(MemberRequestDTO.JoinDto request);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.umc.demo.service.MemberService;

import com.umc.demo.apiPayload.code.status.ErrorStatus;
import com.umc.demo.apiPayload.exception.handler.FoodCategoryHandler;
import com.umc.demo.converter.MemberConverter;
import com.umc.demo.converter.MemberPreferConverter;
import com.umc.demo.domain.FoodCategory;
import com.umc.demo.domain.Member;
import com.umc.demo.domain.mapping.MemberPrefer;
import com.umc.demo.repository.FoodCategoryRepository;
import com.umc.demo.repository.MemberRepository;
import com.umc.demo.web.dto.MemberRequestDTO;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class MemberCommandServiceImpl implements MemberCommandService {

private final MemberRepository memberRepository;

private final FoodCategoryRepository foodCategoryRepository;

@Override
@Transactional
public Member joinMember(MemberRequestDTO.JoinDto request) {

Member newMember = MemberConverter.toMember(request);
List<FoodCategory> foodCategoryList = request.getPreferCategory().stream()
.map(category -> {
return foodCategoryRepository.findById(category).orElseThrow(() -> new FoodCategoryHandler(
ErrorStatus.FOOD_CATEGORY_NOT_FOUND));
}).collect(Collectors.toList());

List<MemberPrefer> memberPreferList = MemberPreferConverter.toMemberPreferList(foodCategoryList);

memberPreferList.forEach(memberPrefer -> {memberPrefer.setMember(newMember);});

return memberRepository.save(newMember);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.umc.demo.service.MemberService;

public interface MemberQueryService {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.umc.demo.service.MemberService;

public class MemberQueryServiceImpl {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.umc.demo.validation.annotation;

import com.umc.demo.validation.validator.CategoriesExistValidator;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;

@Documented
@Constraint(validatedBy = CategoriesExistValidator.class)
@Target( { ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface ExistCategories {

String message() default "해당하는 카테고리가 존재하지 않습니다.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.umc.demo.validation.validator;

import com.umc.demo.apiPayload.code.status.ErrorStatus;
import com.umc.demo.repository.FoodCategoryRepository;
import com.umc.demo.validation.annotation.ExistCategories;
import java.util.List;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class CategoriesExistValidator implements ConstraintValidator<ExistCategories, List<Long>> {

private final FoodCategoryRepository foodCategoryRepository;

@Override
public void initialize(ExistCategories constraintAnnotation) {
ConstraintValidator.super.initialize(constraintAnnotation);
}

@Override
public boolean isValid(List<Long> values, ConstraintValidatorContext context) {
boolean isValid = values.stream()
.allMatch(value -> foodCategoryRepository.existsById(value));

if (!isValid) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(ErrorStatus.FOOD_CATEGORY_NOT_FOUND.toString()).addConstraintViolation();
}

return isValid;

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.umc.demo.web.controller;

import com.umc.demo.apiPayload.ApiResponse;
import com.umc.demo.converter.MemberConverter;
import com.umc.demo.domain.Member;
import com.umc.demo.service.MemberService.MemberCommandService;
import com.umc.demo.web.dto.MemberRequestDTO;
import com.umc.demo.web.dto.MemberResponseDTO;
import javax.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
@RequestMapping("/members")
public class MemberRestController {

private final MemberCommandService memberCommandService;

@PostMapping("/")
public ApiResponse<MemberResponseDTO.JoinResultDTO> join(@RequestBody @Valid MemberRequestDTO.JoinDto request){
Member member = memberCommandService.joinMember(request);
return ApiResponse.onSuccess(MemberConverter.toJoinResultDTO(member));
}
}
31 changes: 31 additions & 0 deletions 라이/src/main/java/com/umc/demo/web/dto/MemberRequestDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.umc.demo.web.dto;

import com.umc.demo.validation.annotation.ExistCategories;
import java.util.List;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import lombok.Getter;

public class MemberRequestDTO {

@Getter
public static class JoinDto{
@NotBlank
String name;
@NotNull
Integer gender;
@NotNull
Integer birthYear;
@NotNull
Integer birthMonth;
@NotNull
Integer birthDay;
@Size(min = 5, max = 12)
String address;
@Size(min = 5, max = 12)
String specAddress;
@ExistCategories
List<Long> preferCategory;
}
}
Loading