Skip to content
Open
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
7 changes: 7 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ dependencies {
annotationProcessor "io.github.openfeign.querydsl:querydsl-apt:7.0:jpa"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"

// Swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.13'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.13'

// Validation
implementation 'org.springframework.boot:spring-boot-starter-validation'
}

tasks.named('test') {
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/example/umc9th/Umc9thApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@SpringBootApplication
@EnableJpaAuditing // Baseentity 사용를 위한 어노테이션
public class Umc9thApplication {

public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.example.umc9th.domain.member.controller;

import com.example.umc9th.domain.member.dto.MemberReqDTO;
import com.example.umc9th.domain.member.dto.MemberResDTO;
import com.example.umc9th.domain.member.exception.code.MemberSuccessCode;
import com.example.umc9th.domain.member.service.MemberCommandService;
import com.example.umc9th.global.apiPayload.ApiResponse;
import jakarta.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;

@RequestMapping("/member")
@RestController
@RequiredArgsConstructor
public class MemberController {

private final MemberCommandService memberCommandService;

// 회원가입
@PostMapping("/sign-up")
public ApiResponse<MemberResDTO.JoinDTO> signUp(
@RequestBody @Valid MemberReqDTO.JoinDTO dto
){
return ApiResponse.onSuccess(memberCommandService.signup(dto));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.example.umc9th.domain.member.converter;

import com.example.umc9th.domain.member.dto.MemberReqDTO;
import com.example.umc9th.domain.member.dto.MemberResDTO;
import com.example.umc9th.domain.member.entity.Member;

public class MemberConverter {

// Entity -> DTO
public static MemberResDTO.JoinDTO toJoinDTO(
Member member
){
return MemberResDTO.JoinDTO.builder()
.memberId(member.getId())
.createAt(member.getCreatedAt())
.build();
}

// DTO -> Entity
public static Member toMember(
MemberReqDTO.JoinDTO dto
){
return Member.builder()
.name(dto.name())
.birthday(dto.birth())
.address(dto.address())
.gender(dto.gender())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.example.umc9th.domain.member.dto;

import com.example.umc9th.domain.member.enums.Gender;
import com.example.umc9th.global.annotation.ExistFoods;
import org.springframework.boot.autoconfigure.amqp.RabbitConnectionDetails;

import java.time.LocalDate;
import java.util.List;

public class MemberReqDTO {
public record JoinDTO(
String name,
Gender gender,
LocalDate birth,
String address,
@ExistFoods
List<Long> favoriteFood
){}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.example.umc9th.domain.member.dto;

import lombok.Builder;

import java.time.LocalDateTime;

public class MemberResDTO {
@Builder
public record JoinDTO(
Long memberId,
LocalDateTime createAt
){}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ public class Member extends BaseEntity {
@Column(name = "inactive_date")
private LocalDateTime inactiveDate;

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

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

@Column(name = "point")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Getter
@Setter
@Table(name = "member_mission")
public class MemberMission extends BaseEntity {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.example.umc9th.domain.member.exception;

import com.example.umc9th.global.apiPayload.code.BaseErrorCode;
import com.example.umc9th.global.apiPayload.exception.GeneralException;

public class FoodException extends GeneralException {
public FoodException(BaseErrorCode code) {

super(code);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.example.umc9th.domain.member.exception;

import com.example.umc9th.global.apiPayload.code.BaseErrorCode;
import com.example.umc9th.global.apiPayload.exception.GeneralException;

public class MemberException extends GeneralException {
public MemberException(BaseErrorCode code) {
super(code);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.example.umc9th.domain.member.exception.code;

import com.example.umc9th.global.apiPayload.code.BaseErrorCode;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
@AllArgsConstructor
public enum FoodErrorCode implements BaseErrorCode {
FOOD_NOT_FOUND(HttpStatus.NOT_FOUND, "FOOD404", "해당하는 음식이 존재하지 않습니다.");

private final HttpStatus status;
private final String code;
private final String message;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.example.umc9th.domain.member.exception.code;

import com.example.umc9th.global.apiPayload.code.BaseErrorCode;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
@AllArgsConstructor
public enum MemberErrorCode implements BaseErrorCode {

NOT_FOUND(HttpStatus.NOT_FOUND,
"MEMBER404_1",
"해당 사용자를 찾지 못했습니다."),
;

private final HttpStatus status;
private final String code;
private final String message;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.example.umc9th.domain.member.exception.code;

import com.example.umc9th.global.apiPayload.code.BaseSuccessCode;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
@AllArgsConstructor
public enum MemberSuccessCode implements BaseSuccessCode {

FOUND(HttpStatus.OK,
"MEMBER200_1",
"성공적으로 사용자를 조회했습니다."),
;

private final HttpStatus status;
private final String code;
private final String message;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.example.umc9th.domain.member.repository;

import com.example.umc9th.domain.member.entity.Food;
import org.springframework.data.jpa.repository.JpaRepository;

public interface FoodRepository extends JpaRepository<Food, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.example.umc9th.domain.member.repository;

import com.example.umc9th.domain.member.entity.mapping.MemberFood;
import org.springframework.data.jpa.repository.JpaRepository;

public interface MemberFoodRepository extends JpaRepository<MemberFood, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.example.umc9th.domain.member.service;

import com.example.umc9th.domain.member.dto.MemberReqDTO;
import com.example.umc9th.domain.member.dto.MemberResDTO;

public interface MemberCommandService {
// 회원가입
MemberResDTO.JoinDTO signup(
MemberReqDTO.JoinDTO dto
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.example.umc9th.domain.member.service;

import com.example.umc9th.domain.member.converter.MemberConverter;
import com.example.umc9th.domain.member.dto.MemberReqDTO;
import com.example.umc9th.domain.member.dto.MemberResDTO;
import com.example.umc9th.domain.member.entity.Food;
import com.example.umc9th.domain.member.entity.Member;
import com.example.umc9th.domain.member.entity.mapping.MemberFood;
import com.example.umc9th.domain.member.exception.FoodException;
import com.example.umc9th.domain.member.exception.code.FoodErrorCode;
import com.example.umc9th.domain.member.repository.FoodRepository;
import com.example.umc9th.domain.member.repository.MemberFoodRepository;
import com.example.umc9th.domain.member.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class MemberCommandServiceImpl implements MemberCommandService{

private final MemberRepository memberRepository;
private final MemberFoodRepository memberFoodRepository;
private final FoodRepository foodRepository;

// 회원가입
@Override
@Transactional
public MemberResDTO.JoinDTO signup(
MemberReqDTO.JoinDTO dto
){
// 사용자 생성
Member member = MemberConverter.toMember(dto);
// DB 적용
memberRepository.save(member);

// 선호 음식 존재 여부 확인
if (dto.favoriteFood().size() > 1){
List<MemberFood> memberFood = dto.favoriteFood().stream()
.map(id -> MemberFood.builder()
.member(member)
.food(foodRepository.findById(id)
.orElseThrow(() -> new FoodException(FoodErrorCode.FOOD_NOT_FOUND)))
.build()
)
.collect(Collectors.toList());

memberFoodRepository.saveAll(memberFood);
}


// 응답 DTO 생성
return MemberConverter.toJoinDTO(member);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.example.umc9th.domain.mission.controller;

import com.example.umc9th.domain.member.entity.mapping.MemberMission;
import com.example.umc9th.domain.mission.converter.MemberMissionConverter;
import com.example.umc9th.domain.mission.dto.MemberMissionResDto;
import com.example.umc9th.domain.mission.service.MissionCommandService;
import com.example.umc9th.global.apiPayload.ApiResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
@RequestMapping("/missions")
public class MissionController {

private final MissionCommandService missionCommandService;

// API: 가게의 미션을 도전 중인 미션에 추가
// URL: POST /missions/{missionId}/challenge
@PostMapping("/{missionId}/challenge")
public ApiResponse<MemberMissionResDto.CreateMemberMissionResultDto> challengeMission(
@PathVariable Long missionId
) {

MemberMission memberMission = missionCommandService.challengeMission(missionId);
return ApiResponse.onSuccess(MemberMissionConverter.toCreateResultDto(memberMission));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.example.umc9th.domain.mission.converter;

import com.example.umc9th.domain.member.entity.mapping.MemberMission;
import com.example.umc9th.domain.mission.dto.MemberMissionResDto;
import java.time.LocalDateTime;

public class MemberMissionConverter {

// 도전 시작 (DTO -> Entity)
public static MemberMission toEntity() {
return MemberMission.builder()
.isComplete(false) // 초기 상태는 '진행 중'
.build();
}

// 도전 성공 응답 (Entity -> DTO)
public static MemberMissionResDto.CreateMemberMissionResultDto toCreateResultDto(MemberMission memberMission) {
return MemberMissionResDto.CreateMemberMissionResultDto.builder()
.memberMissionId(memberMission.getId())
.createdAt(LocalDateTime.now())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.example.umc9th.domain.mission.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

public class MemberMissionResDto {

// 미션 도전 성공 시 응답 DTO
@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class CreateMemberMissionResultDto {
private Long memberMissionId; // 생성된 도전 기록의 ID
private LocalDateTime createdAt; // 도전 시작 시간
}
}
Loading