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 추가 #114

Merged
merged 6 commits into from
Nov 23, 2024
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
15 changes: 7 additions & 8 deletions sql/init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ CREATE TABLE interest_job
CREATE TABLE resume
(
resume_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(50) NOT NULL,
title VARCHAR(50) NOT NULL,
category VARCHAR(10) NOT NULL,
content VARCHAR(50) NOT NULL,
start_date DATE,
Expand All @@ -68,10 +68,10 @@ CREATE TABLE goal

CREATE TABLE member_goal
(
member_id BIGINT NOT NULL,
goal_id BIGINT NOT NULL,
is_complete BOOLEAN NOT NULL DEFAULT FALSE,
PRIMARY KEY (member_id, goal_id),
member_goal_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
member_id BIGINT NOT NULL,
goal_id BIGINT NOT NULL,
is_complete BOOLEAN NOT NULL DEFAULT FALSE,
CONSTRAINT member_goal_member FOREIGN KEY (member_id) REFERENCES member (member_id),
CONSTRAINT member_goal_goal FOREIGN KEY (goal_id) REFERENCES goal (goal_id)
) ENGINE = InnoDB
Expand All @@ -85,9 +85,8 @@ CREATE TABLE quest
created_at DATETIME NOT NULL,
deadline DATE NOT NULL,
sequence INT NOT NULL,
member_id BIGINT NOT NULL,
goal_id BIGINT NOT NULL,
CONSTRAINT fk_quest_member_goal FOREIGN KEY (member_id, goal_id) REFERENCES member_goal (member_id, goal_id)
member_goal_id BIGINT NOT NULL,
CONSTRAINT fk_quest_member_goal FOREIGN KEY (member_goal_id) REFERENCES member_goal (member_goal_id)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public enum ErrorCode {
SEARCH_SHORT_LENGTH_ERROR(40007, HttpStatus.BAD_REQUEST, "검색어는 2글자 이상이어야 합니다."),
INVALID_ACCESS_URL(40008, HttpStatus.BAD_REQUEST, "잘못된 사용자 접근입니다."),
INVALID_FILE(40009, HttpStatus.BAD_REQUEST, "잘못된 파일입니다."),
ALREADY_EXISTS_GOAL(40010, HttpStatus.BAD_REQUEST, "이미 목표가 존재합니다."),

// Gone Error
GONE_SHARED_URL(41001, HttpStatus.GONE, "해당 공유 URL이 만료되었습니다."),
Expand Down
37 changes: 31 additions & 6 deletions src/main/java/com/groom/orbit/goal/app/MemberGoalService.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package com.groom.orbit.goal.app;

import java.util.List;
import java.util.Optional;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.groom.orbit.common.dto.CommonSuccessDto;
import com.groom.orbit.common.exception.CommonException;
import com.groom.orbit.common.exception.ErrorCode;
import com.groom.orbit.goal.app.dto.request.CreateMemberGoalRequestDto;
import com.groom.orbit.goal.app.command.GoalCommandService;
import com.groom.orbit.goal.app.dto.request.MemberGoalRequestDto;
import com.groom.orbit.goal.app.dto.response.GetCompletedGoalResponseDto;
import com.groom.orbit.goal.app.dto.response.GetOnGoingGoalResponseDto;
import com.groom.orbit.goal.app.query.GoalQueryService;
Expand All @@ -31,6 +33,7 @@ public class MemberGoalService {
private final QuestQueryService questQueryService;
private final MemberQueryService memberQueryService;
private final GoalQueryService goalQueryService;
private final GoalCommandService goalCommandService;

@Transactional(readOnly = true)
public MemberGoal findMemberGoal(Long memberId, Long goalId) {
Expand All @@ -46,12 +49,12 @@ public List<GetOnGoingGoalResponseDto> findOnGoingGoals(Long memberId) {
return memberGoals.stream()
.map(
memberGoal -> {
Long goalId = memberGoal.getGoalId();
Long goalId = memberGoal.getGoal().getGoalId();
long totalQuestCount = questQueryService.getTotalQuestCount(goalId);
long finishQuestCount = questQueryService.getFinishQuestCount(goalId);

return new GetOnGoingGoalResponseDto(
memberGoal.getGoalId(), memberGoal.getTitle(), totalQuestCount, finishQuestCount);
goalId, memberGoal.getTitle(), totalQuestCount, finishQuestCount);
})
.toList();
}
Expand All @@ -78,14 +81,36 @@ public CommonSuccessDto deleteGoal(Long memberId, Long goalId) {
return new CommonSuccessDto(true);
}

public CommonSuccessDto createGoal(Long memberId, Long goalId, CreateMemberGoalRequestDto dto) {
public CommonSuccessDto createGoal(Long memberId, MemberGoalRequestDto dto) {
Member member = memberQueryService.findMember(memberId);
Goal goal = goalQueryService.findGoal(goalId);

Goal goal = getGoal(dto.title(), dto.category());
MemberGoal memberGoal = MemberGoal.create(member, goal);
goal.increaseCount();

memberGoalRepository.save(memberGoal);

return new CommonSuccessDto(true);
}

public CommonSuccessDto updateGoal(Long memberId, Long goalId, MemberGoalRequestDto dto) {
MemberGoal memberGoal = findMemberGoal(memberId, goalId);
Goal goal = getGoal(dto.title(), dto.category());

validateMemberGoal(memberId, goal.getGoalId());
memberGoal.updateGoal(goal);

// memberGoalRepository.updateGoalId(goal.getGoalId());
return new CommonSuccessDto(true);
}

private void validateMemberGoal(Long memberId, Long goalId) {
if (memberGoalRepository.findByMemberIdAndGoalId(memberId, goalId).isPresent()) {
throw new CommonException(ErrorCode.ALREADY_EXISTS_GOAL);
}
}

private Goal getGoal(String title, String category) {
Optional<Goal> findGoal = goalQueryService.findGoalByTitleAndCategory(title, category);
return findGoal.orElseGet(() -> goalCommandService.createGoal(title, category));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.groom.orbit.goal.app.command;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.groom.orbit.goal.dao.GoalRepository;
import com.groom.orbit.goal.dao.entity.Goal;

import lombok.RequiredArgsConstructor;

@Service
@Transactional
@RequiredArgsConstructor
public class GoalCommandService {

private final GoalRepository goalRepository;

@Transactional(propagation = Propagation.REQUIRES_NEW)
public Goal createGoal(String title, String category) {
Goal goal = Goal.create(title, category);

return goalRepository.save(goal);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.groom.orbit.goal.app.dto.request;

public record MemberGoalRequestDto(String title, String category) {}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.groom.orbit.goal.app.query;

import java.util.Optional;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -25,6 +27,11 @@ public Goal findGoal(Long goalId) {
.orElseThrow(() -> new CommonException(ErrorCode.NOT_FOUND_GOAL));
}

public Optional<Goal> findGoalByTitleAndCategory(String title, String category) {

return goalRepository.findByTitleAndCategory(title, GoalCategory.from(category));
}

public GetGoalCategoryResponseDto getGoalCategory() {
return new GetGoalCategoryResponseDto(GoalCategory.getAll());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.groom.orbit.goal.controller.command;

import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
Expand All @@ -11,7 +12,7 @@
import com.groom.orbit.common.dto.CommonSuccessDto;
import com.groom.orbit.common.dto.ResponseDto;
import com.groom.orbit.goal.app.MemberGoalService;
import com.groom.orbit.goal.app.dto.request.CreateMemberGoalRequestDto;
import com.groom.orbit.goal.app.dto.request.MemberGoalRequestDto;

import lombok.RequiredArgsConstructor;

Expand All @@ -28,11 +29,17 @@ public ResponseDto<CommonSuccessDto> deleteMemberGoal(
return ResponseDto.ok(memberGoalService.deleteGoal(memberId, goalId));
}

@PutMapping("/{goal_id}")
@PutMapping
public ResponseDto<CommonSuccessDto> createMemberGoal(
@AuthMember Long memberId, @RequestBody MemberGoalRequestDto dto) {
return ResponseDto.created(memberGoalService.createGoal(memberId, dto));
}

@PatchMapping("/{goal_id}")
public ResponseDto<CommonSuccessDto> updateMemberGoal(
@AuthMember Long memberId,
@PathVariable("goal_id") Long goalId,
@RequestBody CreateMemberGoalRequestDto dto) {
return ResponseDto.created(memberGoalService.createGoal(memberId, goalId, dto));
@RequestBody MemberGoalRequestDto dto) {
return ResponseDto.ok(memberGoalService.updateGoal(memberId, goalId, dto));
}
}
8 changes: 7 additions & 1 deletion src/main/java/com/groom/orbit/goal/dao/GoalRepository.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package com.groom.orbit.goal.dao;

import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;

import com.groom.orbit.goal.dao.entity.Goal;
import com.groom.orbit.goal.dao.entity.GoalCategory;

public interface GoalRepository extends JpaRepository<Goal, Long> {

public interface GoalRepository extends JpaRepository<Goal, Long> {}
Optional<Goal> findByTitleAndCategory(String title, GoalCategory category);
}
24 changes: 20 additions & 4 deletions src/main/java/com/groom/orbit/goal/dao/MemberGoalRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,35 @@
import org.springframework.data.repository.query.Param;

import com.groom.orbit.goal.dao.entity.MemberGoal;
import com.groom.orbit.goal.dao.entity.MemberGoalId;

public interface MemberGoalRepository extends JpaRepository<MemberGoal, MemberGoalId> {
public interface MemberGoalRepository extends JpaRepository<MemberGoal, Long> {

@Query("select mg from MemberGoal mg" + " where mg.memberId=:member_id and mg.goalId=:goal_id")
@Query(
"select mg from MemberGoal mg"
+ " join fetch mg.member m"
+ " join fetch mg.goal g"
+ " where m.id=:member_id and g.goalId=:goal_id")
Optional<MemberGoal> findById(@Param("member_id") Long memberId, @Param("goal_id") Long goalId);

@Query(
"select mg from MemberGoal mg"
+ " join fetch mg.goal g"
+ " join fetch mg.member m"
+ " where mg.isComplete=:is_complete"
+ " and mg.memberId=:member_id")
+ " and m=:member_id")
List<MemberGoal> findByIsComplete(
@Param("member_id") Long memberId, @Param("is_complete") Boolean isComplete);

@Query(
"select mg from MemberGoal mg"
+ " join fetch mg.goal g"
+ " join fetch mg.member m"
+ " where mg.member.id=:member_id and mg.goal.goalId=:goal_id")
Optional<MemberGoal> findByMemberIdAndGoalId(
@Param("member_id") Long memberId, @Param("goal_id") Long goalId);

// @Modifying
// @Query("UPDATE MemberGoal mg SET mg.goal.goalId = :goalId WHERE mg.memberGoalId =
// :memberGoalId")
// void updateGoalId(Long goalId);
}
21 changes: 16 additions & 5 deletions src/main/java/com/groom/orbit/goal/dao/QuestRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,36 @@ public interface QuestRepository extends JpaRepository<Quest, Long> {
@Query(
"select q from Quest q"
+ " join fetch q.memberGoal mg"
+ " where mg.memberId=:member_id and mg.goalId=:goal_id")
+ " join fetch mg.goal g"
+ " join fetch mg.member m"
+ " where m.id=:member_id and g.goalId=:goal_id")
List<Quest> findByMemberIdAndGoalId(
@Param("member_id") Long memberId, @Param("goal_id") Long goalId);

@Query("select count(*) from Quest q" + " join q.memberGoal mg" + " where mg.goalId=:goal_id")
@Query(
"select count(*) from Quest q"
+ " join q.memberGoal mg"
+ " join mg.goal g"
+ " where g.goalId=:goal_id")
int getCountByGoalId(@Param("goal_id") Long goalId);

List<Quest> findByQuestIdIn(List<Long> ids);

@Query("select count(*) from Quest q" + " join q.memberGoal mg" + " where mg.goalId=:goal_id")
@Query(
"select count(*) from Quest q"
+ " join q.memberGoal mg"
+ " join mg.goal g"
+ " where g.goalId=:goal_id")
long countByMemberGoal_GoalId(@Param("goal_id") Long goalId);

@Query(
"select count(*) from Quest q"
+ " join q.memberGoal mg"
+ " where q.isComplete=true and mg.goalId=:goal_id")
+ " join mg.goal g"
+ " where q.isComplete=true and g.goalId=:goal_id")
long countCompletedByMemberGoal_GoalId(@Param("goal_id") Long goalId);

@Query(
"SELECT q FROM Quest q join fetch q.memberGoal mg WHERE MONTH(q.deadline) = :month AND mg.memberId = :memberId ORDER BY q.deadline ASC")
"SELECT q FROM Quest q join fetch q.memberGoal mg join fetch mg.member m WHERE MONTH(q.deadline) = :month AND m.id = :memberId ORDER BY q.deadline ASC")
List<Quest> findAllByMonthAndMemberId(Long memberId, Integer month);
}
2 changes: 1 addition & 1 deletion src/main/java/com/groom/orbit/goal/dao/entity/Goal.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public class Goal {

@ColumnDefault("0")
@Column(nullable = false)
private Integer count;
private Integer count = 0;

public static Goal create(String title, String category) {
Goal goal = new Goal();
Expand Down
23 changes: 13 additions & 10 deletions src/main/java/com/groom/orbit/goal/dao/entity/MemberGoal.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,44 +7,43 @@
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.IdClass;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;

import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.DynamicUpdate;

import com.groom.orbit.member.dao.jpa.entity.Member;

import lombok.Getter;

@Entity
@Getter
@DynamicUpdate
@Table(name = "member_goal")
@IdClass(MemberGoalId.class)
public class MemberGoal {

@Id
@Column(name = "member_id") // 필드 명시
private Long memberId; // 변경

@Id
@Column(name = "goal_id") // 필드 명시
private Long goalId; // 변경
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "member_goal_id")
private Long memberGoalId;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id", insertable = false, updatable = false)
private Member member;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "goal_id", insertable = false, updatable = false)
@JoinColumn(name = "goal_id")
private Goal goal;

@ColumnDefault("false")
@Column(nullable = false)
private Boolean isComplete;
private Boolean isComplete = false;

@OneToMany(mappedBy = "memberGoal", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Quest> quests = new ArrayList<>();
Expand All @@ -60,4 +59,8 @@ public static MemberGoal create(Member member, Goal goal) {
public String getTitle() {
return this.goal.getTitle();
}

public void updateGoal(Goal goal) {
this.goal = goal;
}
}
Loading
Loading