Skip to content
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
2 changes: 1 addition & 1 deletion spring/src/main/generated/umc/spring/domain/QMission.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class QMission extends EntityPathBase<Mission> {
//inherited
public final DateTimePath<java.time.LocalDateTime> createdAt = _super.createdAt;

public final DatePath<java.time.LocalDate> dueAt = createDate("dueAt", java.time.LocalDate.class);
public final DateTimePath<java.time.LocalDateTime> dueAt = createDateTime("dueAt", java.time.LocalDateTime.class);

public final NumberPath<Long> id = createNumber("id", Long.class);

Expand Down
19 changes: 16 additions & 3 deletions spring/src/main/generated/umc/spring/domain/QReview.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public class QReview extends EntityPathBase<Review> {

private static final long serialVersionUID = 1510377220L;

private static final PathInits INITS = PathInits.DIRECT2;

public static final QReview review = new QReview("review");

public final umc.spring.domain.common.QBase _super = new umc.spring.domain.common.QBase(this);
Expand All @@ -33,19 +35,30 @@ public class QReview extends EntityPathBase<Review> {

public final NumberPath<Integer> star = createNumber("star", Integer.class);

public final QStore store;

//inherited
public final DateTimePath<java.time.LocalDateTime> updatedAt = _super.updatedAt;

public QReview(String variable) {
super(Review.class, forVariable(variable));
this(Review.class, forVariable(variable), INITS);
}

public QReview(Path<? extends Review> path) {
super(path.getType(), path.getMetadata());
this(path.getType(), path.getMetadata(), PathInits.getFor(path.getMetadata(), INITS));
}

public QReview(PathMetadata metadata) {
super(Review.class, metadata);
this(metadata, PathInits.getFor(metadata, INITS));
}

public QReview(PathMetadata metadata, PathInits inits) {
this(Review.class, metadata, inits);
}

public QReview(Class<? extends Review> type, PathMetadata metadata, PathInits inits) {
super(type, metadata, inits);
this.store = inits.isInitialized("store") ? new QStore(forProperty("store"), inits.get("store")) : null;
}

}
Expand Down
2 changes: 2 additions & 0 deletions spring/src/main/generated/umc/spring/domain/QStore.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ public class QStore extends EntityPathBase<Store> {

public final QRegion region;

public final NumberPath<Float> score = createNumber("score", Float.class);

//inherited
public final DateTimePath<java.time.LocalDateTime> updatedAt = _super.updatedAt;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ public class ErrorResponse {
private final String code;
private final String message;
}


Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ public ErrorResponse getErrorResponseDto() {
public ErrorResponse getErrorResponseDtoWithHttpStatus() {
return this.code.buildErrorDtoWithHttpStatus();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,13 @@ public enum ErrorResponse implements BaseErrorResponse {
TEMP_EXCEPTION(HttpStatus.BAD_REQUEST, "TEMP4001", "이거는 테스트"),
ARTICLE_NOT_FOUND(HttpStatus.NOT_FOUND, "ARTICLE4001", "게시글이 없습니다."),

// 요청 파라미터 관련 에러
INVALID_PAGE_INDEX(HttpStatus.BAD_REQUEST, "COMMON4002", "page는 1 이상의 값이어야 합니다."),

// 가게 없음 에러
STORE_NOT_FOUND(HttpStatus.BAD_REQUEST, "STORE4001", "해당 스토어가 존재하지 않습니다.");

//
private final HttpStatus httpStatus;
private final String code;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package umc.spring.apipayload.validation;

import jakarta.validation.Constraint;
import jakarta.validation.Payload;
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;

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ExistingUserValidator.class)
@Documented
public @interface ExistingUser {
String message() default "USER_NOT_FOUND";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package umc.spring.apipayload.validation;

import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import umc.spring.repository.user.UserRepository;

@Component
@RequiredArgsConstructor
public class ExistingUserValidator implements ConstraintValidator<ExistingUser, Long> {

private final UserRepository userRepository;

@Override
public boolean isValid(Long userId, ConstraintValidatorContext context) {
if (userId == null) return true; // @NotNull 로 별도 처리

boolean exists = userRepository.existsById(userId);
if (!exists) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("MEMBER_NOT_FOUND")
.addConstraintViolation();
}
return exists;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package umc.spring.apipayload.validation;

import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.*;

@Documented
@Constraint(validatedBy = umc.spring.apipayload.validation.PageValidator.class)
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface PageVaild {
String message() default "유효하지 않은 페이지 번호입니다.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package umc.spring.apipayload.validation;

import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import umc.spring.apipayload.exception.GeneralException;
import umc.spring.apipayload.status.ErrorResponse;


public class PageValidator implements ConstraintValidator<PageVaild, Integer> {
@Override
public boolean isValid(Integer value, ConstraintValidatorContext context) {
if (value == null || value < 1) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("INVALID_PAGE_INDEX").addConstraintViolation();
return false;
}
return true;
}
}

11 changes: 11 additions & 0 deletions spring/src/main/java/umc/spring/converter/MissionConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,21 @@
import org.springframework.stereotype.Component;
import umc.spring.domain.Mission;
import umc.spring.web.dto.mission.AddMissionResponse;
import umc.spring.web.dto.mission.MissionListResponse;

@Component
public class MissionConverter {
public AddMissionResponse toResponse(Mission mission) {
return new AddMissionResponse(mission.getId());
}

public MissionListResponse toMissionListResponse(Mission mission) {
return MissionListResponse.builder()
.missionId(mission.getId())
.storeName(mission.getStore().getName())
.points(mission.getPoints())
.requirements(mission.getRequirements())
.dueAt(mission.getDueAt())
.build();
}
}
11 changes: 11 additions & 0 deletions spring/src/main/java/umc/spring/converter/ReviewConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,21 @@
import org.springframework.stereotype.Component;
import umc.spring.domain.Review;
import umc.spring.web.dto.review.AddReviewResponse;
import umc.spring.web.dto.review.ReviewListResponse;

@Component
public class ReviewConverter {
public AddReviewResponse toResponse(Review r) {
return new AddReviewResponse(r.getId());
}

public ReviewListResponse toReviewListResponse(Review review) {
return ReviewListResponse.builder()
.reviewId(review.getId())
.content(review.getContent())
.star(review.getStar())
.createdAt(review.getCreatedAt())
.build();
}

}
4 changes: 4 additions & 0 deletions spring/src/main/java/umc/spring/domain/Review.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ public class Review extends Base {
private String content;
private int star;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "store_id")
private Store store;

@Builder.Default
@OneToMany(
cascade = CascadeType.ALL,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package umc.spring.repository.mission;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import umc.spring.domain.Mission;

@Repository
public interface MissionRepository extends JpaRepository<Mission, Long> {

Page<Mission> findAllByStoreId(Long storeId, Pageable pageable);
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package umc.spring.repository.review;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import umc.spring.domain.Review;
import umc.spring.domain.Store;

@Repository
public interface ReviewRepository extends JpaRepository<Review, Long> {
Page<Review> findAllByStore(Store store, Pageable pageable);
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
package umc.spring.repository.usermission;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import umc.spring.domain.User;
import umc.spring.domain.enums.MissionStatus;
import umc.spring.domain.mapping.UserMission;

public interface UserMissionRepository extends JpaRepository<UserMission, Long> {
// 유저가 해당 미션에 참여 중인지 여부 확인
boolean existsByUser_IdAndMission_Id(Long userId, Long missionId);

// 진행 중인 미션 조회 (페이징)
Page<UserMission> findAllByUserAndMissionStatus(User user, MissionStatus missionStatus, Pageable pageable);
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,35 @@
package umc.spring.service.mission;

import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import umc.spring.apipayload.exception.GeneralException;
import umc.spring.apipayload.status.ErrorResponse;
import umc.spring.converter.MissionConverter;
import umc.spring.domain.Mission;
import umc.spring.domain.Store;
import umc.spring.domain.User;
import umc.spring.domain.enums.MissionStatus;
import umc.spring.domain.mapping.UserMission;
import umc.spring.repository.mission.MissionRepository;
import umc.spring.repository.store.StoreRepository;
import umc.spring.repository.user.UserRepository;
import umc.spring.repository.usermission.UserMissionRepository;
import umc.spring.service.usermission.UserMissionService;
import umc.spring.web.dto.mission.AddMissionRequest;
import umc.spring.web.dto.mission.MissionListResponse;

@Service
@RequiredArgsConstructor
public class MissionService {

private final StoreRepository storeRepo;
private final UserRepository userRepo;
private final MissionRepository missionRepo;
private final UserMissionRepository userMissionRepo;
private final MissionConverter converter;

@Transactional
public Mission addMission(AddMissionRequest req) {
Expand All @@ -32,4 +45,11 @@ public Mission addMission(AddMissionRequest req) {

return missionRepo.save(mission);
}

@Transactional(readOnly = true)
public Page<MissionListResponse> getMissionsByStore(Long storeId, Pageable pageable) {
return missionRepo.findAllByStoreId(storeId, pageable)
.map(converter::toMissionListResponse);
}

}
Loading