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

[DEV-18] Completed Credit #247

Merged
merged 37 commits into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
f840bf0
refactor: 전공 필드명 변경에 따른 코드 수정
Hoya324 Mar 19, 2024
7587022
feat: 복수전공에 따른 전공이수 학점 Type
Hoya324 Mar 19, 2024
4b384ba
refactor: 복수전공 로직 추가에 따른 매개변수 변경
Hoya324 Mar 19, 2024
5764f45
refactor: 복수전공에 따른 졸업 요건 학점수 변경
Hoya324 Mar 19, 2024
4d4e2b4
refactor: 복수전공에 따른 parsing 로직 수정
Hoya324 Mar 19, 2024
4743ab7
refactor: 부전공 졸업 학점 변경 로직 시점 변경
Hoya324 Mar 19, 2024
fff2144
refactor: 유저 정보 수정시 복수전공 수정 추가
Hoya324 Mar 19, 2024
4c4fc66
refactor: user domain에 복수전공 필드 추 및 주전공 변수명 변경
Hoya324 Mar 19, 2024
b467e20
test: 부전공 졸업학점 조정 test로 수정
Hoya324 Mar 19, 2024
a02d3c6
test: 복수전공 parsing test
Hoya324 Mar 19, 2024
88a4df1
refactor: 졸업요건 계산 로직에 복수전공 추가
Hoya324 Mar 19, 2024
3b63e7d
refactor: 필요없는 import 제거
Hoya324 Mar 19, 2024
bde3cc9
refactor: GraduationCategory 타입 추가 및 수정
5uhwann Mar 27, 2024
4e2bcf4
feat: CompletedCredit 도메인 모델 작성
5uhwann Mar 28, 2024
b987a8d
feat: CompletedCredit jpa entity 작성
5uhwann Mar 28, 2024
ddbb9c8
feat: CompletedCredit jpa entity 작성
5uhwann Mar 28, 2024
caa99f7
feat: CompletedCreditPersistenceMapper 구현
5uhwann Mar 28, 2024
e185d3a
feat: CompletedCreditRepository - 이수 학점 조회 구현
5uhwann Mar 28, 2024
7488916
feat: FindCompletedCreditPort 구현
5uhwann Mar 28, 2024
368446f
feat: FindCompletedCreditUseCase 구현
5uhwann Mar 31, 2024
eeb2861
refactor: 불필요 컨트롤러 삭제
5uhwann Mar 31, 2024
6759d61
refactor: CalculateGraduationUseCase 리턴 타입 변경
5uhwann Mar 31, 2024
8318277
feat: GenerateOrModifyCompletedCreditPort 구현
5uhwann Apr 2, 2024
3d825db
feat: GenerateOrModifyCompletedCreditUseCase 구현
5uhwann Apr 3, 2024
cf49e79
refactor: 성적표 업로드로 인한 이수 학점 업데이트 구현
5uhwann Apr 3, 2024
a55741d
feat: CompletedCreditController 구현
5uhwann Apr 3, 2024
6aad94e
test: 테스트 오류 수정
5uhwann Apr 5, 2024
b8183ae
build: 테스트 코드 롬복 의존성 추가
5uhwann Apr 5, 2024
dadbcfd
refactor: 불필요 의존성 제거
5uhwann Apr 5, 2024
6ff3660
refactor: 부정확 로직 제거
5uhwann Apr 5, 2024
82d7a00
refactor: swagger 코드 추가
5uhwann Apr 5, 2024
f3b6a6f
refactor: endpoint 수정
5uhwann Apr 5, 2024
9a0e40d
refactor: 불필요 코드 삭제
5uhwann Apr 5, 2024
37a8bfe
refactor: 채플 이수 학점 오류 수정
5uhwann Apr 5, 2024
a2f9a86
refactor: GenerateOrModifyCompletedCreditUseCase 사용 위치 수정
5uhwann Apr 7, 2024
2749bd1
refactor: 채플 기이수 학점 산정 방식 수정
5uhwann Apr 7, 2024
a866f9a
refactor: GenerateOrModifyCompletedCredit 모델 생성 위치 수정
5uhwann Apr 7, 2024
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
4 changes: 3 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ dependencies {
implementation "com.google.guava:guava:32.1.3-jre"
implementation "com.querydsl:querydsl-jpa:${queryDslVersion}"
implementation "com.querydsl:querydsl-apt:${queryDslVersion}"
//implementation 'org.flywaydb:flyway-core:6.4.2'
// implementation 'org.flywaydb:flyway-core:6.4.2'
implementation 'org.springdoc:springdoc-openapi-ui:1.6.9'
implementation 'io.sentry:sentry-logback:1.7.30'

Expand All @@ -56,6 +56,8 @@ dependencies {
testImplementation 'org.testcontainers:testcontainers:1.19.0'
testImplementation 'org.testcontainers:mysql:1.19.0'
testImplementation 'org.testcontainers:junit-jupiter:1.13.0'
testCompileOnly 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'


}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.plzgraduate.myongjigraduatebe.completedcredit.api;

import java.util.List;

import com.plzgraduate.myongjigraduatebe.completedcredit.api.dto.CompletedCreditResponse;
import com.plzgraduate.myongjigraduatebe.core.meta.LoginUser;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;

@Tag(name = "CompletdCredit")
public interface FindCompletedCreditApiPresentation {

@Operation(summary = "기이수 학점 조회", description = "유저의 기이수 학점 조회 API")
@Parameter(name = "userId", description = "로그인한 유저의 PK값 - 자동 적용")
List<CompletedCreditResponse> getCompletedCredits(@LoginUser Long userId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.plzgraduate.myongjigraduatebe.completedcredit.api;

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

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import com.plzgraduate.myongjigraduatebe.completedcredit.api.dto.CompletedCreditResponse;
import com.plzgraduate.myongjigraduatebe.completedcredit.application.usecase.FindCompletedCreditUseCase;
import com.plzgraduate.myongjigraduatebe.core.meta.LoginUser;
import com.plzgraduate.myongjigraduatebe.core.meta.WebAdapter;

import lombok.RequiredArgsConstructor;

@WebAdapter
@RequestMapping(value = "/api/v1/graduations/credits")
@RequiredArgsConstructor
public class FindCompletedCreditsController implements FindCompletedCreditApiPresentation{

private final FindCompletedCreditUseCase findCompletedCreditUseCase;

@GetMapping()
public List<CompletedCreditResponse> getCompletedCredits(@LoginUser Long userId) {
return findCompletedCreditUseCase.findCompletedCredits(userId).stream()
.map(CompletedCreditResponse::from)
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.plzgraduate.myongjigraduatebe.completedcredit.api.dto;

import com.plzgraduate.myongjigraduatebe.completedcredit.domain.model.CompletedCredit;

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

@Getter
@NoArgsConstructor
public class CompletedCreditResponse {

private String category;
private int totalCredit;
private double takenCredit;
private boolean completed;

@Builder
private CompletedCreditResponse(String category, int totalCredit, double takenCredit, boolean completed) {
this.category = category;
this.totalCredit = totalCredit;
this.takenCredit = takenCredit;
this.completed = completed;
}

public static CompletedCreditResponse from(CompletedCredit completedCredit) {
return CompletedCreditResponse.builder()
.category(completedCredit.getGraduationCategory().name())
.totalCredit(completedCredit.getTotalCredit())
.takenCredit(completedCredit.getTakenCredit())
.completed(completedCredit.getTakenCredit() >= completedCredit.getTotalCredit())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.plzgraduate.myongjigraduatebe.completedcredit.application.port;

import java.util.List;

import com.plzgraduate.myongjigraduatebe.completedcredit.domain.model.CompletedCredit;
import com.plzgraduate.myongjigraduatebe.user.domain.model.User;

public interface FindCompletedCreditPort {

List<CompletedCredit> findCompletedCredit(User user);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.plzgraduate.myongjigraduatebe.completedcredit.application.port;

import java.util.List;

import com.plzgraduate.myongjigraduatebe.completedcredit.domain.model.CompletedCredit;
import com.plzgraduate.myongjigraduatebe.user.domain.model.User;

public interface GenerateOrModifyCompletedCreditPort {

void generateOrModifyCompletedCredits(User user, List<CompletedCredit> completedCredits);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분만 분리되면 될거 같습니다! 수고하셨어요!

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.plzgraduate.myongjigraduatebe.completedcredit.application.service;

import java.util.List;

import org.springframework.transaction.annotation.Transactional;

import com.plzgraduate.myongjigraduatebe.completedcredit.application.port.FindCompletedCreditPort;
import com.plzgraduate.myongjigraduatebe.completedcredit.application.usecase.FindCompletedCreditUseCase;
import com.plzgraduate.myongjigraduatebe.completedcredit.domain.model.CompletedCredit;
import com.plzgraduate.myongjigraduatebe.core.meta.UseCase;
import com.plzgraduate.myongjigraduatebe.user.application.usecase.find.FindUserUseCase;
import com.plzgraduate.myongjigraduatebe.user.domain.model.User;

import lombok.RequiredArgsConstructor;

@UseCase
@RequiredArgsConstructor
@Transactional(readOnly = true)
class FindCompletedCreditService implements FindCompletedCreditUseCase {

private final FindUserUseCase findUserUseCase;
private final FindCompletedCreditPort findCompletedCreditPort;

@Override
public List<CompletedCredit> findCompletedCredits(Long userId) {
User user = findUserUseCase.findUserById(userId);
return findCompletedCreditPort.findCompletedCredit(user);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package com.plzgraduate.myongjigraduatebe.completedcredit.application.service;

import static com.plzgraduate.myongjigraduatebe.graduation.domain.model.ChapelResult.GRADUATION_COUNT;
import static com.plzgraduate.myongjigraduatebe.graduation.domain.model.GraduationCategory.CHAPEL;
import static com.plzgraduate.myongjigraduatebe.graduation.domain.model.GraduationCategory.FREE_ELECTIVE;
import static com.plzgraduate.myongjigraduatebe.graduation.domain.model.GraduationCategory.NORMAL_CULTURE;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.springframework.transaction.annotation.Transactional;

import com.plzgraduate.myongjigraduatebe.completedcredit.application.port.FindCompletedCreditPort;
import com.plzgraduate.myongjigraduatebe.completedcredit.application.port.GenerateOrModifyCompletedCreditPort;
import com.plzgraduate.myongjigraduatebe.completedcredit.application.usecase.GenerateOrModifyCompletedCreditUseCase;
import com.plzgraduate.myongjigraduatebe.completedcredit.domain.model.CompletedCredit;
import com.plzgraduate.myongjigraduatebe.core.meta.UseCase;
import com.plzgraduate.myongjigraduatebe.graduation.application.usecase.CalculateGraduationUseCase;
import com.plzgraduate.myongjigraduatebe.graduation.domain.model.DetailGraduationResult;
import com.plzgraduate.myongjigraduatebe.graduation.domain.model.GraduationCategory;
import com.plzgraduate.myongjigraduatebe.graduation.domain.model.GraduationResult;
import com.plzgraduate.myongjigraduatebe.user.domain.model.User;

import lombok.RequiredArgsConstructor;

@UseCase
@Transactional
@RequiredArgsConstructor
class GenerateOrModifyCompletedCreditService implements GenerateOrModifyCompletedCreditUseCase {

private final FindCompletedCreditPort findCompletedCreditPort;
private final GenerateOrModifyCompletedCreditPort generateOrModifyCompletedCreditPort;

private final CalculateGraduationUseCase calculateGraduationUseCase;

@Override
public void generateOrModifyCompletedCredit(User user) {
List<CompletedCredit> completedCredits = findCompletedCreditPort.findCompletedCredit(user);
GraduationResult graduationResult = calculateGraduationUseCase.calculateGraduation(user);
List<DetailGraduationResult> detailGraduationResults = graduationResult.getDetailGraduationResults();

List<CompletedCredit> updatedCompletedCredits = createGeneralCompletedCreditModel(completedCredits,
detailGraduationResults);
CompletedCredit chapelCompletedCreditModel = createOrUpdateChapelCompletedCreditModel(completedCredits,
graduationResult);
CompletedCredit normalCultureCompletedCreditModel = createOrUpdateNormalCultureCompletedCreditModel(
completedCredits, graduationResult);
CompletedCredit freeElectiveCompletedCreditModel = createOrUpdateFreeElectiveCompletedCreditModel(
completedCredits, graduationResult);

ArrayList<CompletedCredit> allCompletedCreditModels = new ArrayList<>(updatedCompletedCredits);
allCompletedCreditModels.addAll(
List.of(chapelCompletedCreditModel, normalCultureCompletedCreditModel, freeElectiveCompletedCreditModel));
generateOrModifyCompletedCreditPort.generateOrModifyCompletedCredits(user, allCompletedCreditModels);
}

private List<CompletedCredit> createGeneralCompletedCreditModel(
List<CompletedCredit> completedCredits, List<DetailGraduationResult> detailGraduationResults) {
Map<DetailGraduationResult, Optional<CompletedCredit>> resultMap = detailGraduationResults.stream()
.collect(Collectors.toMap(
Function.identity(),
detailGraduationResult -> completedCredits.stream()
.filter(completedCredit -> completedCredit.getGraduationCategory()
.equals(detailGraduationResult.getGraduationCategory()))
.findFirst()
));
return resultMap.keySet().stream()
.map(detailGraduationResult -> createCompletedCreditModel(detailGraduationResult,
resultMap.get(detailGraduationResult)))
.collect(Collectors.toList());
}

private CompletedCredit createCompletedCreditModel(DetailGraduationResult detailGraduationResult,
Optional<CompletedCredit> completedCredit) {
return CompletedCredit.builder()
.id(completedCredit.map(CompletedCredit::getId).orElse(null))
.totalCredit(detailGraduationResult.getTotalCredit())
.takenCredit(detailGraduationResult.getTakenCredit())
.graduationCategory(detailGraduationResult.getGraduationCategory())
.build();
}

private CompletedCredit createOrUpdateChapelCompletedCreditModel(List<CompletedCredit> completedCredits,
GraduationResult graduationResult) {
Optional<CompletedCredit> chapelCompletedCredit = findCompletedCreditByCategory(completedCredits, CHAPEL);
return chapelCompletedCredit.map(
completedCredit -> updateCompletedCredit(completedCredit, GRADUATION_COUNT / 2,
graduationResult.getChapelResult().getTakenChapelCredit()))
.orElseGet(() -> CompletedCredit.createChapelCompletedCreditModel(graduationResult.getChapelResult()));
}

private CompletedCredit createOrUpdateNormalCultureCompletedCreditModel(List<CompletedCredit> completedCredits,
GraduationResult graduationResult) {
Optional<CompletedCredit> normalCultureCompletedCredit = findCompletedCreditByCategory(completedCredits,
NORMAL_CULTURE);
return normalCultureCompletedCredit.map(completedCredit -> updateCompletedCredit(completedCredit,
graduationResult.getNormalCultureGraduationResult().getTotalCredit(),
graduationResult.getNormalCultureGraduationResult().getTakenCredit()))
.orElseGet(() -> CompletedCredit.createNormalCultureCompletedCreditModel(
graduationResult.getNormalCultureGraduationResult()));
}

private CompletedCredit createOrUpdateFreeElectiveCompletedCreditModel(List<CompletedCredit> completedCredits,
GraduationResult graduationResult) {
Optional<CompletedCredit> freeElectiveCompletedCredit = findCompletedCreditByCategory(completedCredits,
FREE_ELECTIVE);
return freeElectiveCompletedCredit.map(completedCredit -> updateCompletedCredit(completedCredit,
graduationResult.getFreeElectiveGraduationResult().getTotalCredit(),
graduationResult.getFreeElectiveGraduationResult().getTakenCredit()))
.orElseGet(() -> CompletedCredit.createFreeElectiveCompletedCreditModel(
graduationResult.getFreeElectiveGraduationResult()));
}

private Optional<CompletedCredit> findCompletedCreditByCategory(List<CompletedCredit> completedCredits,
GraduationCategory category) {
return completedCredits.stream()
.filter(completedCredit -> completedCredit.getGraduationCategory() == category)
.findFirst();
}

private CompletedCredit updateCompletedCredit(CompletedCredit completedCredit,
int totalCredit, double takenCredit) {
completedCredit.updateCredit(totalCredit, takenCredit);
return completedCredit;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.plzgraduate.myongjigraduatebe.completedcredit.application.usecase;

import java.util.List;

import com.plzgraduate.myongjigraduatebe.completedcredit.domain.model.CompletedCredit;

public interface FindCompletedCreditUseCase {

List<CompletedCredit> findCompletedCredits(Long userId);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.plzgraduate.myongjigraduatebe.completedcredit.application.usecase;

import com.plzgraduate.myongjigraduatebe.user.domain.model.User;

public interface GenerateOrModifyCompletedCreditUseCase {

void generateOrModifyCompletedCredit(User user);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.plzgraduate.myongjigraduatebe.completedcredit.domain.model;

import static com.plzgraduate.myongjigraduatebe.graduation.domain.model.GraduationCategory.*;

import com.plzgraduate.myongjigraduatebe.graduation.domain.model.ChapelResult;
import com.plzgraduate.myongjigraduatebe.graduation.domain.model.DetailGraduationResult;
import com.plzgraduate.myongjigraduatebe.graduation.domain.model.FreeElectiveGraduationResult;
import com.plzgraduate.myongjigraduatebe.graduation.domain.model.GraduationCategory;
import com.plzgraduate.myongjigraduatebe.graduation.domain.model.NormalCultureGraduationResult;

import lombok.Builder;
import lombok.Getter;

@Getter
public class CompletedCredit {

private final Long id;
private final GraduationCategory graduationCategory;
private int totalCredit;
private double takenCredit;

@Builder
private CompletedCredit(Long id, GraduationCategory graduationCategory, int totalCredit,
double takenCredit) {
this.id = id;
this.graduationCategory = graduationCategory;
this.totalCredit = totalCredit;
this.takenCredit = takenCredit;
}

public static CompletedCredit from(DetailGraduationResult detailGraduationResults) {
return CompletedCredit.builder()
.graduationCategory(detailGraduationResults.getGraduationCategory())
.totalCredit(detailGraduationResults.getTotalCredit())
.takenCredit(detailGraduationResults.getTakenCredit()).build();
}

public static CompletedCredit createChapelCompletedCreditModel(ChapelResult chapelResult) {
return CompletedCredit.builder()
.graduationCategory(CHAPEL)
.totalCredit(ChapelResult.GRADUATION_COUNT / 2)
.takenCredit(chapelResult.getTakenChapelCredit()).build();
}

public static CompletedCredit createNormalCultureCompletedCreditModel(
NormalCultureGraduationResult normalCultureGraduationResult) {
return CompletedCredit.builder()
.graduationCategory(NORMAL_CULTURE)
.totalCredit(normalCultureGraduationResult.getTotalCredit())
.takenCredit(normalCultureGraduationResult.getTakenCredit()).build();
}

public static CompletedCredit createFreeElectiveCompletedCreditModel(
FreeElectiveGraduationResult freeElectiveGraduationResult) {
return CompletedCredit.builder()
.graduationCategory(FREE_ELECTIVE)
.totalCredit(freeElectiveGraduationResult.getTotalCredit())
.takenCredit(freeElectiveGraduationResult.getTakenCredit()).build();
}

public void updateCredit(int totalCredit, double takenCredit) {
this.totalCredit = totalCredit;
this.takenCredit = takenCredit;
}
}
Loading
Loading