Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import com.whylog.server.domain.decision.dto.ApplicationResponse;
import com.whylog.server.domain.decision.dto.DecisionRequest;
import com.whylog.server.domain.decision.exception.DecisionErrorCode;
import com.whylog.server.domain.decision.service.ApplicationCommandService;
import com.whylog.server.domain.decision.service.ApplicationQueryService;
import com.whylog.server.domain.git.exception.GitErrorCode;
import com.whylog.server.global.apiPayload.ApiResponse;
import com.whylog.server.global.apiPayload.annotation.ApiErrorCodeExample;
import com.whylog.server.global.apiPayload.annotation.ApiErrorCodeExamples;
Expand All @@ -27,6 +29,7 @@
@Tag(name = "Application", description = "적용사항 관련 API")
public class ApplicationController {

private final ApplicationCommandService applicationCommandService;
private final ApplicationQueryService applicationQueryService;


Expand All @@ -42,34 +45,71 @@ public ApiResponse<ApplicationResponse.ApplicationDetailDTO> getApplication(
}

@GetMapping("/{applicationId}/recommended-commits")
@Operation(summary = "추천 커밋 조회 API", description = "특정 적용사항의 추천 커밋 목록을 조회하는 API입니다.")
@Operation(summary = "추천 커밋 조회 API", description = "특정 적용사항의 추천 커밋 목록을 조회하는 API입니다.최신순으로 조회, 페이징 없습니다.")
@ApiErrorCodeExamples({
@ApiErrorCodeExample(value = ErrorStatus.class, name = "_BAD_REQUEST"),
@ApiErrorCodeExample(value = DecisionErrorCode.class, name = "APPLICATION_NOT_FOUND"),
@ApiErrorCodeExample(value = GitErrorCode.class, name = "COMMIT_NOT_FOUND")
})
public ApiResponse<List<ApplicationResponse.RecommendedCommitDTO>> getRecommendedCommits(
@PathVariable Long applicationId) {
return ApiResponse.onSuccess(null);
return ApiResponse.onSuccess(applicationQueryService.getRecommendedCommits(applicationId));
}

@GetMapping("/{applicationId}/connected-commits")
@Operation(summary = "연결된 커밋 조회 API", description = "특정 적용사항에 연결된 커밋 목록을 조회하는 API입니다.")
public ApiResponse<List<ApplicationResponse.ConnectedCommitDTO>> getConnectedCommits(
@Operation(summary = "연결된 커밋 조회 API", description = "특정 적용사항에 연결된 커밋 목록을 조회하는 API입니다.최신순으로 조회, 페이징 없습니다.")
@ApiErrorCodeExamples({
@ApiErrorCodeExample(value = ErrorStatus.class, name = "_BAD_REQUEST"),
@ApiErrorCodeExample(value = DecisionErrorCode.class, name = "APPLICATION_NOT_FOUND"),
})
public ApiResponse<ApplicationResponse.ConnectedCommitListDTO> getConnectedCommits(
@PathVariable Long applicationId) {
return ApiResponse.onSuccess(null);
return ApiResponse.onSuccess(applicationQueryService.getConnectedCommits(applicationId));
}

@GetMapping("/{applicationId}/status")
@Operation(summary = "적용현황 조회 API", description = "특정 적용사항에 연결된 커밋 해시, 커밋 메시지, 연결된 커밋 개수를 조회하는 API입니다.")
@ApiErrorCodeExamples({
@ApiErrorCodeExample(value = ErrorStatus.class, name = "_BAD_REQUEST"),
@ApiErrorCodeExample(value = DecisionErrorCode.class, name = "APPLICATION_NOT_FOUND")
})
public ApiResponse<ApplicationResponse.ApplicationStatusDTO> getApplicationStatus(
@PathVariable Long applicationId) {
return ApiResponse.onSuccess(applicationQueryService.getApplicationStatus(applicationId));
}

@PostMapping("/{applicationId}/commits")
@Operation(summary = "커밋 연결 API", description = "적용사항에 커밋을 연결하는 API입니다.")
@Operation(summary = "커밋 연결 API", description = """
적용사항에 커밋을 연결하는 API입니다.

단일 연결과 다중 연결 모두 `commit_ids` 배열로 전달합니다.
단건 연결 예시: `{ "commit_ids": [1] }`
다건 연결 예시: `{ "commit_ids": [1, 2, 3] }`
요청한 커밋 중 하나라도 이미 연결되어 있으면 전체 요청이 실패합니다.
""")
@ApiErrorCodeExamples({
@ApiErrorCodeExample(value = ErrorStatus.class, name = "_BAD_REQUEST"),
@ApiErrorCodeExample(value = DecisionErrorCode.class, name = "APPLICATION_NOT_FOUND"),
@ApiErrorCodeExample(value = GitErrorCode.class, name = "COMMIT_NOT_FOUND"),
@ApiErrorCodeExample(value = DecisionErrorCode.class, name = "APPLICATION_COMMIT_ALREADY_CONNECTED")
})
public ApiResponse<ApplicationResponse.CommitConnectionResponseDTO> connectCommit(
@PathVariable Long applicationId,
@Valid @RequestBody DecisionRequest.CommitConnectionDTO request) {
return ApiResponse.onSuccess(null);
return ApiResponse.onSuccess(applicationCommandService.connectCommit(applicationId, request));
}

@PostMapping("/{decisionId}/recommendations")
@Operation(summary = "추천 결과 저장 API", description = "적용사항의 추천 결과를 저장하는 API입니다.")
@ApiErrorCodeExamples({
@ApiErrorCodeExample(value = ErrorStatus.class, name = "_BAD_REQUEST"),
@ApiErrorCodeExample(value = DecisionErrorCode.class, name = "DECISION_NOT_FOUND"),
@ApiErrorCodeExample(value = GitErrorCode.class, name = "COMMIT_NOT_FOUND")
})
public ApiResponse<ApplicationResponse.RecommendedCommitDTO> saveRecommendation(
@PathVariable Long decisionId,
@Valid @RequestBody DecisionRequest.RecommendationDTO request) {
return ApiResponse.onSuccess(null);
}

// TODO: 적용현황 조회 api 추가
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package com.whylog.server.domain.decision.controller;

import com.whylog.server.domain.decision.dto.ApplicationResponse;
import com.whylog.server.domain.decision.dto.DecisionResponse;
import com.whylog.server.domain.decision.exception.DecisionErrorCode;
import com.whylog.server.domain.decision.service.DecisionQueryService;
import com.whylog.server.global.apiPayload.ApiResponse;
import com.whylog.server.global.apiPayload.annotation.ApiErrorCodeExample;
import com.whylog.server.global.apiPayload.annotation.ApiErrorCodeExamples;
import com.whylog.server.global.apiPayload.code.status.ErrorStatus;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
Expand All @@ -11,31 +15,22 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/api/decisions")
@RequiredArgsConstructor
@Tag(name = "Decision", description = "결정사항 관련 API")
public class DecisionController {

private final DecisionQueryService decisionQueryService;

@GetMapping("/{decisionId}/reliability")
@Operation(summary = "신뢰도 조회 API", description = "특정 결정사항의 신뢰도 정보를 조회하는 API입니다.")
@ApiErrorCodeExamples({
@ApiErrorCodeExample(value = ErrorStatus.class, name = "_BAD_REQUEST"),
@ApiErrorCodeExample(value = DecisionErrorCode.class, name = "DECISION_NOT_FOUND")
})
public ApiResponse<DecisionResponse.ReliabilityDTO> getReliability(
@PathVariable Long decisionId) {
return ApiResponse.onSuccess(null);
}

@Operation(summary = "추천 커밋 조회 API", description = "특정 적용사항의 추천 커밋 목록을 조회하는 API입니다.")
public ApiResponse<List<ApplicationResponse.RecommendedCommitDTO>> getRecommendedCommits(
@PathVariable Long applicationId) {
return ApiResponse.onSuccess(null);
}

@GetMapping("/{applicationId}/connected-commits")
@Operation(summary = "연결된 커밋 조회 API", description = "특정 적용사항에 연결된 커밋 목록을 조회하는 API입니다.")
public ApiResponse<List<ApplicationResponse.ConnectedCommitDTO>> getConnectedCommits(
@PathVariable Long applicationId) {
return ApiResponse.onSuccess(null);
return ApiResponse.onSuccess(decisionQueryService.getReliability(decisionId));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -113,17 +113,28 @@ public static class DecisionReasonItemDTO {
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Schema(description = "적용현황 항목")
@Schema(description = "적용현황 조회 응답")
public static class ApplicationStatusDTO {

@Schema(description = "연결된 커밋 개수", example = "3")
private Integer commitCount;

@Schema(description = "적용현황 커밋 목록")
private List<ApplicationBaseItemDTO> commits;
}

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Schema(description = "적용현황 커밋 항목")
public static class ApplicationBaseItemDTO {

@Schema(description = "커밋 해시", example = "b8fd9ad")
private String commitHash;

@Schema(description = "커밋 메시지", example = "feat: API 구현")
private String commitMessage;

@Schema(description = "세부 사항 목록", example = "SessionRepository 추상화 도입")
private List<String> details; //ai 분석 응답
}

@Getter
Expand All @@ -133,9 +144,6 @@ public static class ApplicationBaseItemDTO {
@Schema(description = "추천 커밋 응답")
public static class RecommendedCommitDTO {

@Schema(description = "적용사항 ID", example = "1")
private Long applicationId;

@Schema(description = "저장소 이름", example = "whyLog-Backend")
private String repositoryName;

Expand All @@ -152,6 +160,20 @@ public static class RecommendedCommitDTO {
private String reason;
}

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Schema(description = "연결된 커밋 목록 조회 응답")
public static class ConnectedCommitListDTO {

@Schema(description = "연결된 커밋 개수", example = "3")
private Integer commitCount;

@Schema(description = "연결된 커밋 목록")
private List<ConnectedCommitDTO> commits;
}

@Getter
@NoArgsConstructor
@AllArgsConstructor
Expand Down Expand Up @@ -182,9 +204,8 @@ public static class CommitConnectionResponseDTO {
@Schema(description = "적용사항 ID", example = "1")
private Long applicationId;

@Schema(description = "커밋 ID", example = "abc123def456")
private String commitId;

@Schema(description = "연결된 커밋 ID 목록", example = "[1, 2, 3]")
private List<Long> commitIds;
}

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.whylog.server.domain.decision.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.util.List;
import lombok.*;

public class DecisionRequest {
Expand All @@ -13,9 +15,9 @@ public class DecisionRequest {
@Schema(description = "커밋 연결 요청")
public static class CommitConnectionDTO {

@Schema(description = "커밋 ID", example = "1")
@NotBlank
private Long commitId;
@Schema(description = "연결할 커밋 ID 목록. 단건 연결도 배열로 전달합니다.", example = "[1, 2, 3]")
@NotEmpty
private List<@NotNull Long> commitIds;
}

@Getter
Expand All @@ -26,7 +28,7 @@ public static class CommitConnectionDTO {
public static class RecommendationDTO {

@Schema(description = "추천 커밋 ID", example = "1")
@NotBlank
@NotNull
private Long commitId;

@Schema(description = "추천 이유", example = "이 커밋은 관련된 이슈를 해결하는 커밋입니다.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ public class Decision extends BaseEntity {
@Column(name = "is_created")
private Boolean isCreated;

@Column(name = "reliability_score")
private Integer reliabilityScore;

@OneToMany(mappedBy = "decision", cascade = CascadeType.ALL, orphanRemoval = true)
private final List<Application> applications = new ArrayList<>();
//
Expand All @@ -45,20 +48,15 @@ public class Decision extends BaseEntity {
//
// @OneToMany(mappedBy = "decision", cascade = CascadeType.ALL, orphanRemoval = true)
// private final List<DecisionBase> decisionBases = new ArrayList<>();
//
// @OneToMany(mappedBy = "decision", cascade = CascadeType.ALL, orphanRemoval = true)
// private final List<DecisionCommits> decisionCommits = new ArrayList<>();
//
// @OneToMany(mappedBy = "decision", cascade = CascadeType.ALL, orphanRemoval = true)
// private final List<com.whylog.server.domain.git.entity.CommitConnection> commitConnections = new ArrayList<>();
//
// @OneToMany(mappedBy = "decision", cascade = CascadeType.ALL, orphanRemoval = true)
// private final List<EffectRatio> effectRatios = new ArrayList<>();

public static Decision create(Meeting meeting, boolean isCreated) {
Decision decision = new Decision();
decision.meeting = meeting;
decision.isCreated = isCreated;
return decision;
}

public void updateReliabilityScore(Integer reliabilityScore) {
this.reliabilityScore = reliabilityScore;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.whylog.server.domain.decision.entity;

import com.whylog.server.domain.git.entity.Commit;
import com.whylog.server.global.entity.BaseEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
Expand All @@ -11,13 +10,20 @@
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@Table(name = "Decision_Commits")
@Table(
name = "Decision_Commits",
uniqueConstraints = @UniqueConstraint(
name = "uk_decision_commits_decision_commit",
columnNames = {"decision_id", "commit_id"}
)
)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class DecisionCommits extends BaseEntity {

Expand All @@ -32,4 +38,20 @@ public class DecisionCommits extends BaseEntity {

@Column(name = "commit_id", nullable = false)
private Long commitId; // 매핑 X,

@Column(name = "reason", columnDefinition = "TEXT")
private String reason;

public static DecisionCommits create(Decision decision, Long commitId, String reason) {
DecisionCommits decisionCommits = new DecisionCommits();
decisionCommits.decision = decision;
decisionCommits.commitId = commitId;
decisionCommits.reason = reason;
return decisionCommits;
}

// 저장시
public void updateReason(String reason) {
this.reason = reason;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public enum DecisionErrorCode implements BaseErrorCode {

DECISION_NOT_FOUND(HttpStatus.NOT_FOUND, "DECISION_404", "존재하지 않는 결정사항입니다."),
APPLICATION_NOT_FOUND(HttpStatus.NOT_FOUND, "APPLICATION_404", "존재하지 않는 적용사항입니다."),
APPLICATION_COMMIT_ALREADY_CONNECTED(HttpStatus.CONFLICT, "APPLICATION_COMMIT_409", "이미 연결된 커밋입니다."),
;

private final HttpStatus httpStatus;
Expand Down
Loading
Loading