Skip to content

Commit

Permalink
Merge pull request #10 from Lightieey/feature/#9-회원가입-API-구현
Browse files Browse the repository at this point in the history
[Feat(라이/김민지)] 회원가입 API 구현
  • Loading branch information
Lightieey authored Nov 27, 2023
2 parents 8cfbf2c + 91ff9ee commit 44f8d18
Show file tree
Hide file tree
Showing 20 changed files with 348 additions and 5 deletions.
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

0 comments on commit 44f8d18

Please sign in to comment.