[Fix] 점수 행 없는 회원 활동점수 부여 시 silent no-op → 명시적 실패로 수정 - #350
Open
GOOHAESEUNG wants to merge 1 commit into
Open
Conversation
활동점수 부여(V1·V2, 개인·팀)가 기존 PersonalActivityScore 행만 조회해 루프를 돌기 때문에, 행이 없는 대상은 조회 결과에서 빠져 기록 생성 없이 201 성공을 반환했다. 관리자는 점수를 부여했다고 믿지만 실제로는 아무것도 반영되지 않는 무결성 문제다. 갱신용 행 잠금 조회(getPersonalScoreListByIdsForUpdate, getTeamScoreListByIdsForUpdate)에서 조회 결과 수가 요청 대상 수와 다르면 PersonalScoreNotFoundException으로 명확히 실패시킨다. 재현 회귀 테스트 4건 추가.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
배경
POST /v1/manager/activity-records(또는/v1/admin/...)로 활동점수를 부여할 때, 대상 회원의PersonalActivityScore행이 존재하지 않으면 아무 기록도 생성하지 않고 201 성공을 반환하는 silent no-op 버그가 있었습니다.ActivityRecordUsecase가getPersonalScoreListByIdsForUpdate(memberIdList)로 기존 점수 행만 조회해 루프를 돌기 때문에, 행이 없는 회원은 조회 결과에서 빠져 조용히 건너뛰어짐createActivityRecordList에도 동일하게 존재변경 사항
수정 —
PersonalScoreGetService갱신용 행 잠금 조회 2개(
getPersonalScoreListByIdsForUpdate,getTeamScoreListByIdsForUpdate)에서 조회 결과 수가 요청 대상 수(중복 제거 기준)와 다르면PersonalScoreNotFoundException(400) 을 던집니다.findScoreByRecord의 팀 점수get(0)이 행 부재 시IndexOutOfBoundsException(500)을 내던 것도 같은 예외(400)로 정리됨수정 방향 선택 근거 (옵션 1: 명시적 실패)
대안이었던 자가 치유(없는 행을
PersonalActivityScore.from(Member)로 생성 후 진행)는 배제했습니다 — 기본 점수 부여(YB 100/OB 50)는 회원 승인 플로우의 책임이고, 점수 행 부재라는 정합성 이상 신호를 조용히 덮게 되기 때문입니다. 자가 치유가 낫다고 판단되면 리뷰에서 논의 후 전환 가능합니다.재현 회귀 테스트 —
ActivityRecordMissingScoreRegressionTest(4건)수정 전 코드에서 4건 모두 실패(예외 없이 통과)함을 확인 후 수정했습니다.
mock 리포지토리 + 실제
PersonalScoreGetService조합으로 검증 (H2의ActivityRecordDDL 한계로 기존 회귀 테스트와 동일한 방식).검증
RefreshTokenService는 로컬 Docker 미기동으로 인한 Testcontainers 환경 문제 — 본 변경과 무관)🤖 Generated with Claude Code