Skip to content

refactor: 입고 삭제 기능 수정#182

Merged
JoonKyoLee merged 4 commits intomainfrom
refactor/delete-receipt
Dec 13, 2025
Merged

refactor: 입고 삭제 기능 수정#182
JoonKyoLee merged 4 commits intomainfrom
refactor/delete-receipt

Conversation

@JoonKyoLee
Copy link
Contributor

@JoonKyoLee JoonKyoLee commented Dec 13, 2025

✨ 작업 내용

  • 입고 삭제 기능 수정

📝 적용 범위

  • /receipt

📌 참고 사항

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 영수증 삭제 기능이 추가되었습니다.
    • 삭제된 영수증은 시스템에서 자동으로 필터링되어 표시되지 않습니다.
  • 개선사항

    • 영수증 삭제 API가 작업 결과에 대한 명확한 응답을 반환합니다.

✏️ Tip: You can customize this high-level summary in your review settings.

@JoonKyoLee JoonKyoLee self-assigned this Dec 13, 2025
@coderabbitai
Copy link

coderabbitai bot commented Dec 13, 2025

Walkthrough

입고(Receipt) 엔티티의 삭제 방식을 변경합니다. 기존 활성화 상태 플래그 기반에서 deletedAt 타임스탬프 기반의 소프트 삭제로 전환하며, 도메인 메서드명을 deactivate()에서 delete()로 개선하고, 서비스 레이어의 접근 제어를 강화하여 삭제된 레코드 자동 필터링을 구현합니다.

Changes

Cohort / File(s) 변경 요약
도메인 모델 소프트 삭제 구현
src/main/java/com/almang/inventory/receipt/domain/Receipt.java
LocalDateTime deletedAt 필드 추가 및 @SQLDelete, @Where 애너테이션으로 Hibernate 레벨 소프트 삭제 구성; deactivate()delete() 메서드 이름 변경 및 삭제 시 deletedAt을 현재 시간으로 설정
서비스 레이어 삭제 흐름 동기화
src/main/java/com/almang/inventory/receipt/service/ReceiptService.java
도메인 메서드 호출 업데이트 (receipt.delete()) 및 findReceiptByIdAndValidateAccess()에서 삭제된 레코드 필터링 로직 추가 (deletedAt != null 체크로 RECEIPT_NOT_FOUND 예외 발생)
테스트 업데이트
src/test/java/com/almang/inventory/receipt/service/ReceiptServiceTest.java
deleteReceipt() 반환 타입 변경 (voidDeleteReceiptResponse) 및 테스트 어설션 로직 변경으로 응답 객체 기반 검증 구현

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20-25 minutes

  • 추가 검토 대상:
    • @SQLDelete 쿼리 문자열 검증: 실제 UPDATE 쿼리가 의도대로 deleted_at 값을 설정하는지 확인
    • @Where 절이 기존 activated 필드 기반 쿼리와 충돌하지 않는지 검증 (특히 기존 데이터 마이그레이션 전략)
    • findReceiptByIdAndValidateAccess()의 deletedAt 체크 로직이 다른 조회 메서드에서도 일관되게 적용되는지 확인
    • 테스트 케이스 커버리지: 정상 삭제 경로 외에 이미 삭제된 레코드 재조회 시나리오가 충분히 테스트되는지 검증

Possibly related PRs

  • feat: 입고 삭제 기능 구현 #90: 입고 삭제 엔드포인트와 deleteReceipt() 서비스 메서드 초기 구현 추가—해당 PR에서는 receipt.deactivate() 호출했으며, 이 PR이 소프트 삭제로 재구성하므로 직접 연관
  • feat: 입고 조회 기능 구현 #84: findReceiptByIdAndValidateAccess() 메서드 도입—이 PR의 접근 제어 강화(삭제 레코드 필터링) 로직이 해당 메서드를 기반으로 함
  • feat: 입고 목록 조회 기능 구현 #85: 입고 목록 조회 및 레포지토리 쿼리 메서드 추가—소프트 삭제 도입 시 기존 쿼리가 삭제된 레코드를 자동 필터링하는지 확인 필요

Poem

활성화 플래그 대신 시간의 흔적을 남기니 ⏰
소프트 삭제의 우아함, 데이터는 영원히 🗂️
deactivate의 옛 길을 delete로 갈아입고,
WHERE 절이 조용히 삭제된 것들을 가려내네 🎭

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 soft-delete 기능 도입과 delete 메서드 리팩토링 등 주요 변경사항을 모두 아우르는 핵심 의도를 명확하게 전달합니다.
Description check ✅ Passed PR 설명이 정해진 템플릿을 따르고 있으며, 작업 내용, 적용 범위, 참고 사항을 모두 포함하고 있습니다.
Linked Issues check ✅ Passed Issue #154의 요구사항인 'deletedAt으로 판단하도록 수정'이 완전히 구현되었습니다: Receipt 엔티티에 deletedAt 필드 추가, soft-delete 로직 적용, 서비스에서 deletedAt 검증 추가
Out of Scope Changes check ✅ Passed 모든 변경사항이 Issue #154의 deletedAt 기반 리팩토링 목표와 일치하며, 범위 밖의 변경은 발견되지 않습니다.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/delete-receipt

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/main/java/com/almang/inventory/receipt/service/ReceiptService.java (2)

251-251: deletedAt(null) 명시적 설정은 선택적입니다.

LocalDateTime 필드의 기본값은 null이므로 생략 가능하지만, 코드 가독성 측면에서 명시적으로 작성한 것은 괜찮습니다. 취향의 영역입니다. 🤷


287-298: deletedAt 수동 체크가 @Where 어노테이션과 중복됩니다.

Receipt 엔티티에 @Where(clause = "deleted_at IS NULL")가 적용되어 있으므로, findById() 호출 시 삭제된 레코드는 자동으로 필터링되어 Optional.empty()가 반환됩니다. 따라서 Lines 291-293의 수동 체크는 일반적으로 도달하지 않습니다.

권장 사항:

  • @Where를 신뢰한다면 수동 체크 제거 고려
  • 또는 Native Query 등 @Where가 적용되지 않는 케이스에 대한 방어 코드로 유지

현재 구조에서는 방어적 코딩으로 볼 수 있으나, Receipt.java의 @SQLDelete 어노테이션 문제와 함께 soft-delete 전략을 통일하는 것이 좋겠습니다.

#!/bin/bash
# Description: Check if there are native queries or other methods that might bypass @Where clause
# Search for native queries or custom repository methods related to Receipt

echo "=== Checking for native queries or custom repository methods ==="
rg -n "@Query.*nativeQuery.*true" --type=java

echo ""
echo "=== Checking ReceiptRepository methods ==="
ast-grep --pattern 'interface ReceiptRepository {
  $$$
}'
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 329528e and fe4d069.

📒 Files selected for processing (3)
  • src/main/java/com/almang/inventory/receipt/domain/Receipt.java (3 hunks)
  • src/main/java/com/almang/inventory/receipt/service/ReceiptService.java (3 hunks)
  • src/test/java/com/almang/inventory/receipt/service/ReceiptServiceTest.java (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-22T18:12:13.172Z
Learnt from: JoonKyoLee
Repo: almang2/inventory-server PR: 66
File: src/main/java/com/almang/inventory/order/domain/OrderItem.java:41-53
Timestamp: 2025-11-22T18:12:13.172Z
Learning: In the almang2/inventory-server repository, OrderItem entity update methods (updateQuantity, updatePrice in src/main/java/com/almang/inventory/order/domain/OrderItem.java) do not require null checks because OrderService will validate parameters before calling these update methods, following the same pattern as Product entity updates.
<!--

Applied to files:

  • src/test/java/com/almang/inventory/receipt/service/ReceiptServiceTest.java
🔇 Additional comments (3)
src/main/java/com/almang/inventory/receipt/domain/Receipt.java (1)

73-83: delete() 메서드 로직이 잘 구현되었습니다.

상태 검증 후 deletedAt, activated, status를 함께 설정하여 기존 로직과의 하위 호환성을 유지합니다. 마이그레이션 기간 동안 안전한 접근 방식입니다. 👍

src/test/java/com/almang/inventory/receipt/service/ReceiptServiceTest.java (1)

882-889: 테스트 로직이 새로운 soft-delete 흐름에 맞게 잘 수정되었습니다.

DeleteReceiptResponse를 통한 성공 여부 확인과 삭제된 입고 조회 시 예외 발생 검증이 적절합니다. @Where 어노테이션으로 인해 삭제된 레코드는 자동 필터링되어 RECEIPT_NOT_FOUND 예외가 발생합니다. 깔끔! ✨

src/main/java/com/almang/inventory/receipt/service/ReceiptService.java (1)

145-145: receipt.delete() 호출이 올바르게 적용되었습니다.

deactivate()에서 delete()로의 메서드명 변경이 의도를 더 명확하게 표현합니다.

Comment on lines +23 to +24
@SQLDelete(sql = "UPDATE receipts SET deleted_at = NOW() WHERE receipt_id = ?")
@Where(clause = "deleted_at IS NULL")
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

@SQLDelete 어노테이션이 실제로 사용되지 않습니다.

@SQLDelete는 JPA의 EntityManager.remove() 또는 CrudRepository.delete(entity) 호출 시에만 트리거됩니다. 현재 ReceiptService.deleteReceipt()receipt.delete() 도메인 메서드를 호출하여 필드만 설정하므로, @SQLDelete가 실행되지 않습니다.

두 가지 접근 방식 중 하나를 선택하세요:

  1. 도메인 메서드 방식 유지: @SQLDelete 어노테이션 제거 (현재 로직에서 불필요)
  2. JPA 방식 사용: receiptRepository.delete(receipt) 호출로 변경하고, 도메인 delete() 메서드에서 deletedAt 설정 제거

@Where 어노테이션은 조회 시 삭제된 레코드를 자동 필터링하므로 유지하면 좋습니다.

참고: Hibernate Soft Delete 공식 문서

🤖 Prompt for AI Agents
In src/main/java/com/almang/inventory/receipt/domain/Receipt.java around lines
23-24, the @SQLDelete annotation is unused because delete logic calls the domain
method receipt.delete() instead of EntityManager/Repository.delete(), so remove
the @SQLDelete line, keep the @Where(clause = "deleted_at IS NULL") to continue
filtering soft-deleted rows, and ensure any imports related only to @SQLDelete
are removed; alternatively, if you prefer the JPA approach, change
ReceiptService.deleteReceipt() to call receiptRepository.delete(receipt) and
remove the domain delete() setter, but do not keep both patterns.

@JoonKyoLee JoonKyoLee merged commit c7360fa into main Dec 13, 2025
1 check passed
@JoonKyoLee JoonKyoLee deleted the refactor/delete-receipt branch December 19, 2025 13:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[REFACTOR] 입고 삭제 기능 수정

1 participant