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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
application.yml

### STS ###
.apt_generated
Expand Down
33 changes: 33 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,41 @@ dependencies {
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

// QueryDSL : OpenFeign
implementation "io.github.openfeign.querydsl:querydsl-jpa:7.0"
implementation "io.github.openfeign.querydsl:querydsl-core:7.0"
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') {
useJUnitPlatform()
}

// QueryDSL 관련 설정
// generated/querydsl 폴더 생성 & 삽입
def querydslDir = layout.buildDirectory.dir("generated/querydsl").get().asFile

// 소스 세트에 생성 경로 추가 (구체적인 경로 지정)
sourceSets {
main.java.srcDirs += [ querydslDir ]
}

// 컴파일 시 생성 경로 지정
tasks.withType(JavaCompile).configureEach {
options.generatedSourceOutputDirectory.set(querydslDir)
}

// clean 태스크에 생성 폴더 삭제 로직 추가
clean.doLast {
file(querydslDir).deleteDir()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.example.umc9th.domain.mission.controller;

import com.example.umc9th.domain.mission.converter.MissionConverter;
import com.example.umc9th.domain.mission.dto.MissionRequestDTO;
import com.example.umc9th.domain.mission.dto.MissionResponseDTO;
import com.example.umc9th.domain.mission.entity.Mission;
import com.example.umc9th.domain.mission.service.MissionService;
import com.example.umc9th.domain.user.entity.UserMission;
import com.example.umc9th.global.apiPayload.ApiResponse;
import com.example.umc9th.global.apiPayload.code.GeneralSuccessCode;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
public class MissionController {

private final MissionService missionService;

@PostMapping("/restaurants/{restaurantId}/missions")
public ApiResponse<MissionResponseDTO.AddResultDTO> addMission(@PathVariable Long restaurantId,
@RequestBody @Valid MissionRequestDTO.AddMissionDTO request) {
Mission mission = missionService.addMission(restaurantId, request);
return ApiResponse.onSuccess(GeneralSuccessCode.SUCCESS, MissionConverter.toAddResultDTO(mission));
}

@PostMapping("/missions/{missionId}/challenge")
public ApiResponse<MissionResponseDTO.ChallengeResultDTO> challengeMission(@PathVariable Long missionId,
@RequestBody @Valid MissionRequestDTO.ChallengeMissionDTO request) {
UserMission userMission = missionService.challengeMission(missionId, request);
return ApiResponse.onSuccess(GeneralSuccessCode.SUCCESS, MissionConverter.toChallengeResultDTO(userMission));
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.example.umc9th.domain.mission.converter;

import com.example.umc9th.domain.mission.dto.MissionRequestDTO;
import com.example.umc9th.domain.mission.dto.MissionResponseDTO;
import com.example.umc9th.domain.mission.entity.Mission;
import com.example.umc9th.domain.restaurant.entity.Restaurant;
import com.example.umc9th.domain.user.entity.User;
import com.example.umc9th.domain.user.entity.UserMission;
import com.example.umc9th.domain.user.enums.MissionStatus;

import java.time.LocalDateTime;

public class MissionConverter {

public static MissionResponseDTO.AddResultDTO toAddResultDTO(Mission mission) {
return MissionResponseDTO.AddResultDTO.builder()
.missionId(mission.getId())
.createdAt(LocalDateTime.now())
.build();
}

public static MissionResponseDTO.ChallengeResultDTO toChallengeResultDTO(UserMission userMission) {
return MissionResponseDTO.ChallengeResultDTO.builder()
.userMissionId(userMission.getId())
.createdAt(LocalDateTime.now())
.build();
}

public static Mission toMission(MissionRequestDTO.AddMissionDTO request, Restaurant restaurant) {
return Mission.builder()
.restaurant(restaurant)
.reward(request.getReward())
.deadline(request.getDeadline())
.goal(request.getGoal())
.build();
}

public static UserMission toUserMission(Mission mission, User user) {
return UserMission.builder()
.mission(mission)
.user(user)
.status(MissionStatus.CHALLENGING)
.build();
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.example.umc9th.domain.mission.dto;

import jakarta.validation.constraints.Future;
import jakarta.validation.constraints.NotNull;
import lombok.Getter;

import java.time.LocalDateTime;

public class MissionRequestDTO {

@Getter
public static class AddMissionDTO {
@NotNull
private Integer reward;
@NotNull
private Integer goal;
@NotNull
@Future
private LocalDateTime deadline;
}

@Getter
public static class ChallengeMissionDTO {
@NotNull
private Long userId;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
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 MissionResponseDTO {

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class AddResultDTO {
private Long missionId;
private LocalDateTime createdAt;
}

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class ChallengeResultDTO {
private Long userMissionId;
private LocalDateTime createdAt;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.example.umc9th.domain.mission.service;

import com.example.umc9th.domain.mission.dto.MissionRequestDTO;
import com.example.umc9th.domain.mission.entity.Mission;
import com.example.umc9th.domain.user.entity.UserMission;

public interface MissionService {
Mission addMission(Long restaurantId, MissionRequestDTO.AddMissionDTO request);
UserMission challengeMission(Long missionId, MissionRequestDTO.ChallengeMissionDTO request);
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.example.umc9th.domain.mission.service;

import com.example.umc9th.domain.mission.converter.MissionConverter;
import com.example.umc9th.domain.mission.dto.MissionRequestDTO;
import com.example.umc9th.domain.mission.entity.Mission;
import com.example.umc9th.domain.mission.repository.MissionRepository;
import com.example.umc9th.domain.restaurant.entity.Restaurant;
import com.example.umc9th.domain.restaurant.repository.RestaurantRepository;
import com.example.umc9th.domain.user.entity.User;
import com.example.umc9th.domain.user.entity.UserMission;
import com.example.umc9th.domain.user.repository.UserMissionRepository;
import com.example.umc9th.domain.user.repository.UserRepository;
import com.example.umc9th.global.apiPayload.code.GeneralErrorCode;
import com.example.umc9th.global.apiPayload.exception.GeneralException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class MissionServiceImpl implements MissionService {

private final MissionRepository missionRepository;
private final RestaurantRepository restaurantRepository;
private final UserRepository userRepository;
private final UserMissionRepository userMissionRepository;

@Override
@Transactional
public Mission addMission(Long restaurantId, MissionRequestDTO.AddMissionDTO request) {
Restaurant restaurant = restaurantRepository.findById(restaurantId)
.orElseThrow(() -> new GeneralException(GeneralErrorCode.RESTAURANT_NOT_FOUND));

Mission mission = MissionConverter.toMission(request, restaurant);

return missionRepository.save(mission);
}

@Override
@Transactional
public UserMission challengeMission(Long missionId, MissionRequestDTO.ChallengeMissionDTO request) {
Mission mission = missionRepository.findById(missionId)
.orElseThrow(() -> new GeneralException(GeneralErrorCode.MISSION_NOT_FOUND));

User user = userRepository.findById(request.getUserId())
.orElseThrow(() -> new GeneralException(GeneralErrorCode.USER_NOT_FOUND));

// 이미 도전 중인지 체크하는 로직이 있으면 좋겠지만 생략

UserMission userMission = MissionConverter.toUserMission(mission, user);

return userMissionRepository.save(userMission);
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.example.umc9th.domain.restaurant.controller;

import com.example.umc9th.domain.restaurant.converter.RestaurantConverter;
import com.example.umc9th.domain.restaurant.dto.RestaurantRequestDTO;
import com.example.umc9th.domain.restaurant.dto.RestaurantResponseDTO;
import com.example.umc9th.domain.restaurant.entity.Restaurant;
import com.example.umc9th.domain.restaurant.service.RestaurantService;
import com.example.umc9th.global.apiPayload.ApiResponse;
import com.example.umc9th.global.apiPayload.code.GeneralSuccessCode;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
@RequestMapping("/regions")
public class RestaurantController {

private final RestaurantService restaurantService;

@PostMapping("/{regionId}/restaurants")
public ApiResponse<RestaurantResponseDTO.AddResultDTO> addRestaurant(@PathVariable Long regionId,
@RequestBody @Valid RestaurantRequestDTO.AddRestaurantDTO request) {
Restaurant restaurant = restaurantService.addRestaurant(regionId, request);
return ApiResponse.onSuccess(GeneralSuccessCode.SUCCESS, RestaurantConverter.toAddResultDTO(restaurant));
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.example.umc9th.domain.restaurant.converter;

import com.example.umc9th.domain.restaurant.dto.RestaurantRequestDTO;
import com.example.umc9th.domain.restaurant.dto.RestaurantResponseDTO;
import com.example.umc9th.domain.restaurant.entity.Region;
import com.example.umc9th.domain.restaurant.entity.Restaurant;
import com.example.umc9th.domain.restaurant.entity.RestaurantType;

import java.time.LocalDateTime;

public class RestaurantConverter {

public static RestaurantResponseDTO.AddResultDTO toAddResultDTO(Restaurant restaurant) {
return RestaurantResponseDTO.AddResultDTO.builder()
.restaurantId(restaurant.getId())
.createdAt(LocalDateTime.now())
.build();
}

public static Restaurant toRestaurant(RestaurantRequestDTO.AddRestaurantDTO request, Region region, RestaurantType restaurantType) {
return Restaurant.builder()
.name(request.getName())
.location(request.getAddress())
.region(region)
.restaurantType(restaurantType)
.build();
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.example.umc9th.domain.restaurant.dto;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Getter;

public class RestaurantRequestDTO {

@Getter
public static class AddRestaurantDTO {
@NotBlank
private String name;
@NotBlank
private String address;
@NotNull
private Long categoryId; // RestaurantType ID
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.example.umc9th.domain.restaurant.dto;

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

import java.time.LocalDateTime;

public class RestaurantResponseDTO {

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class AddResultDTO {
private Long restaurantId;
private LocalDateTime createdAt;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.example.umc9th.domain.restaurant.service;

import com.example.umc9th.domain.restaurant.dto.RestaurantRequestDTO;
import com.example.umc9th.domain.restaurant.entity.Restaurant;

public interface RestaurantService {
Restaurant addRestaurant(Long regionId, RestaurantRequestDTO.AddRestaurantDTO request);
}

Loading