Conversation
상태 업데이트
이벤트 전달 시 주문 아이디 전 달 생성 로직 단건 주문에 맞춰 변경 컨수머들 너무 시끄러워서 일단 주석 .. 통합 테스트 때 살리겠습니다
WalkthroughInventoryService의 ROP 검사 로직을 개별 발주 생성에서 Map 기반 배치 생성으로 변경하고, PO 관련 엔티티/DTO/서비스/컨트롤러를 추가·수정했으며 Kafka PO 이벤트 소비자(주석 처리됨)와 페이로드 매핑을 도입했습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Inventory as InventoryService
participant POS as PurchaseOrderService
participant Repo as PurchaseOrderRepository
participant Event as EventPublisher
Inventory->>POS: checkRop: build Map<Inventory,Integer> orderMap
POS->>POS: createPurchaseOrders(orderMap) --- batch construct
POS->>Repo: saveAll(purchaseOrders)
Repo-->>POS: persisted entities (ids)
POS-->>Inventory: Map<Inventory, Long> savedOrderMap
loop for each savedOrderMap entry
Inventory->>Event: emit OrderToFactoryDto(partOrderId, warehouse, items)
Event->>(외부): publish to part-order-events
end
sequenceDiagram
participant Kafka as Kafka Topic
participant Consumer as PurchaseEventConsumer
participant POS as PurchaseOrderService
participant Repo as PurchaseOrderRepository
Kafka->>Consumer: 메시지 수신 (part-order-events)
Consumer->>Consumer: parse JSON -> eventType, payload
alt PartOrderStatusChanged
Consumer->>POS: updatePOStatus(POEventPayload)
POS->>Repo: findById(partOrderId) -> update status/scheduledDate/priority 등
Repo-->>POS: save(updated)
else PartOrderCompleted
Consumer->>POS: completePOStatus(POEventPayload)
POS->>Repo: findById(partOrderId) -> update status/progressRate/deleted
Repo-->>POS: save(updated)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
🔇 Additional comments (1)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 9
🧹 Nitpick comments (6)
src/main/java/com/sampoom/backend/api/order/entity/POStatus.java (1)
1-17: LGTM!발주 주문 상태를 관리하기 위한 열거형이 적절하게 정의되었습니다. 각 상태에 대한 한글 레이블도 명확합니다.
선택적 개선 사항:
korean필드명을label또는koreanLabel로 변경하면 의도가 더 명확해집니다.- private String korean; - POStatus(String korean) { - this.korean = korean; + private String koreanLabel; + POStatus(String koreanLabel) { + this.koreanLabel = koreanLabel; }src/main/java/com/sampoom/backend/api/order/controller/PurchaseOrderController.java (1)
3-3: 사용하지 않는 import를 제거하세요.Line 27에서
POStatus로 변경되었으므로OrderStatusimport는 더 이상 사용되지 않습니다.-import com.sampoom.backend.api.order.entity.OrderStatus;src/main/java/com/sampoom/backend/api/order/service/PurchaseOrderService.java (1)
48-60: Stream API 사용을 고려하세요.전통적인 for 루프 대신 Stream API를 사용하면 코드가 더 간결하고 읽기 쉬워집니다.
public Map<Inventory, Long> createPurchaseOrders(Map<Inventory, Integer> invMap) { - Map<Inventory, Long> purchaseOrderMap = new HashMap<>(); - List<PurchaseOrder> orderList = new ArrayList<>(); - - for (Map.Entry<Inventory, Integer> entry : invMap.entrySet()) - orderList.add(makePurchaseOrder(entry.getKey(), entry.getValue())); + List<PurchaseOrder> orderList = invMap.entrySet().stream() + .map(entry -> makePurchaseOrder(entry.getKey(), entry.getValue())) + .toList(); + List<PurchaseOrder> savedOrderList = purchaseOrderRepository.saveAll(orderList); - for (PurchaseOrder order : savedOrderList) - purchaseOrderMap.put(order.getInventory(), order.getId()); - - return purchaseOrderMap; + return savedOrderList.stream() + .collect(Collectors.toMap(PurchaseOrder::getInventory, PurchaseOrder::getId)); }src/main/java/com/sampoom/backend/api/order/entity/PurchaseOrder.java (1)
38-40: primitive double 사용을 고려하세요.
progressRate가 항상 0.0 기본값을 가지므로 null이 유효한 값인지 확인이 필요합니다. null이 필요하지 않다면 primitivedouble을 사용하여 NullPointerException 위험을 제거하세요.@Column(name = "progress_rate") @Builder.Default - private Double progressRate = 0.0; + private double progressRate = 0.0;src/main/java/com/sampoom/backend/api/inventory/service/InventoryService.java (1)
228-238: OrderToFactoryDto 구조를 재검토하세요.각 발주에 대해 개별 이벤트를 발행하면서
items리스트에 단일 항목만 포함시키고 있습니다.OrderToFactoryDto가 여러 항목을 지원하도록 설계되었다면, 이 구조가 비효율적일 수 있습니다.만약 각 발주가 정말 단일 항목만 포함한다면,
OrderToFactoryDto를 단순화하는 것을 고려하세요. 그렇지 않다면, 발주 항목 그룹화 로직을 검토하세요.src/main/java/com/sampoom/backend/api/order/event/PurchaseEventConsumer.java (1)
39-39: POEventPayload 캐스팅 안전성을 검증하세요.Line 39의 무조건적인 캐스팅
(POEventPayload) event.getPayload()는EventPayloadMapper가 올바른 클래스를 반환하지 않으면ClassCastException을 발생시킬 수 있습니다. Line 30의 null 체크로 어느 정도 보호되지만, 타입 안전성을 위해instanceof체크를 추가하는 것을 고려하세요.if (!(event.getPayload() instanceof POEventPayload)) { log.error("⚠️ Unexpected payload type for eventType: {}", eventType); return; } POEventPayload payload = (POEventPayload) event.getPayload();
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
src/main/java/com/sampoom/backend/api/inventory/service/InventoryService.java(3 hunks)src/main/java/com/sampoom/backend/api/order/controller/PurchaseOrderController.java(2 hunks)src/main/java/com/sampoom/backend/api/order/dto/POEventPayload.java(1 hunks)src/main/java/com/sampoom/backend/api/order/dto/POFilterDto.java(2 hunks)src/main/java/com/sampoom/backend/api/order/dto/POItemDto.java(1 hunks)src/main/java/com/sampoom/backend/api/order/dto/POResDto.java(3 hunks)src/main/java/com/sampoom/backend/api/order/entity/POStatus.java(1 hunks)src/main/java/com/sampoom/backend/api/order/entity/PurchaseOrder.java(2 hunks)src/main/java/com/sampoom/backend/api/order/event/PurchaseEventConsumer.java(1 hunks)src/main/java/com/sampoom/backend/api/order/service/OrderService.java(2 hunks)src/main/java/com/sampoom/backend/api/order/service/PurchaseOrderService.java(4 hunks)src/main/java/com/sampoom/backend/api/part/event/EventPayloadMapper.java(2 hunks)src/main/java/com/sampoom/backend/api/rop/dto/OrderToFactoryDto.java(1 hunks)src/main/java/com/sampoom/backend/common/response/ErrorStatus.java(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
src/main/java/com/sampoom/backend/api/order/dto/POItemDto.java (1)
src/main/java/com/sampoom/backend/api/order/dto/POEventPayload.java (1)
Getter(8-27)
src/main/java/com/sampoom/backend/api/order/entity/PurchaseOrder.java (4)
src/main/java/com/sampoom/backend/api/order/dto/POEventPayload.java (1)
Getter(8-27)src/main/java/com/sampoom/backend/api/order/dto/POFilterDto.java (1)
Getter(10-20)src/main/java/com/sampoom/backend/api/order/dto/POResDto.java (1)
Getter(10-64)src/main/java/com/sampoom/backend/api/order/dto/OrderStatusEvent.java (1)
Builder(8-14)
src/main/java/com/sampoom/backend/api/order/entity/POStatus.java (3)
src/main/java/com/sampoom/backend/api/order/dto/POEventPayload.java (1)
Getter(8-27)src/main/java/com/sampoom/backend/api/order/dto/POFilterDto.java (1)
Getter(10-20)src/main/java/com/sampoom/backend/api/order/dto/POResDto.java (1)
Getter(10-64)
src/main/java/com/sampoom/backend/api/order/dto/POEventPayload.java (2)
src/main/java/com/sampoom/backend/api/rop/dto/OrderToFactoryDto.java (1)
Getter(12-21)src/main/java/com/sampoom/backend/api/order/dto/POItemDto.java (1)
Getter(7-15)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (java-kotlin)
🔇 Additional comments (13)
src/main/java/com/sampoom/backend/api/rop/dto/OrderToFactoryDto.java (1)
17-17: LGTM!발주 주문 ID를 이벤트 페이로드에 포함시키기 위한 필드 추가가 적절합니다.
src/main/java/com/sampoom/backend/api/part/event/EventPayloadMapper.java (1)
27-29: LGTM!발주 주문 상태 변경 및 완료 이벤트에 대한 페이로드 매핑이 올바르게 추가되었습니다.
src/main/java/com/sampoom/backend/common/response/ErrorStatus.java (1)
48-48: LGTM!발주 주문서를 찾을 수 없는 경우에 대한 에러 상태가 적절하게 추가되었습니다.
src/main/java/com/sampoom/backend/api/order/dto/POFilterDto.java (1)
19-19: LGTM!
POStatus열거형으로의 타입 변경이 적절합니다.src/main/java/com/sampoom/backend/api/order/dto/POItemDto.java (1)
1-15: LGTM!발주 항목 정보를 담는 DTO가 적절하게 정의되었습니다. 필드 타입과 구조가 올바릅니다.
src/main/java/com/sampoom/backend/api/order/dto/POResDto.java (2)
29-29: LGTM!
POStatus열거형으로의 타입 변경이 필드와 생성자 모두에서 일관되게 적용되었습니다.Also applies to: 43-43
59-63: LGTM!
POStatus의getKorean()메서드를 올바르게 호출하여 한글 레이블을 반환하고 있습니다.src/main/java/com/sampoom/backend/api/order/controller/PurchaseOrderController.java (1)
6-6: LGTM!
OrderStatus에서POStatus로의 마이그레이션이 올바르게 적용되었습니다.Also applies to: 27-27
src/main/java/com/sampoom/backend/api/order/service/PurchaseOrderService.java (1)
39-46: LGTM!메서드가
PurchaseOrder객체를 반환하도록 변경되어 배치 생성 패턴에 적합해졌습니다.src/main/java/com/sampoom/backend/api/order/dto/POEventPayload.java (1)
26-26: Boolean 래퍼 타입 사용을 재검토하세요.
Boolean래퍼 타입은 null을 허용하지만, deleted 필드에 null 값이 의미가 있는지 확인이 필요합니다. 명확한 true/false 값만 필요하다면 primitiveboolean을 사용하는 것이 더 안전합니다.src/main/java/com/sampoom/backend/api/order/entity/PurchaseOrder.java (1)
33-33: LGTM!
POStatus로의 마이그레이션과 기본값 설정이 적절합니다.src/main/java/com/sampoom/backend/api/inventory/service/InventoryService.java (2)
209-242: PR 설명과 구현 불일치를 확인하세요.PR 설명에는 "발주 생성 시 단건(single-item) 처리로 변경"이라고 되어 있지만, 실제 구현은 배치 처리로 변경되었습니다:
- Line 221:
createPurchaseOrders(orderMap)- 여러 PO를 한 번에 생성- Lines 223-241: 생성된 각 PO에 대해 개별 이벤트를 발행
구현 로직 자체는 올바르게 보이지만, PR 설명과 상반됩니다. PR 설명을 업데이트하거나 의도를 명확히 해야 합니다.
221-221: LGTM!배치 PO 생성 방식으로 변경하여 데이터베이스 왕복을 줄였습니다.
src/main/java/com/sampoom/backend/api/order/dto/POEventPayload.java
Outdated
Show resolved
Hide resolved
src/main/java/com/sampoom/backend/api/order/dto/POFilterDto.java
Outdated
Show resolved
Hide resolved
src/main/java/com/sampoom/backend/api/order/entity/PurchaseOrder.java
Outdated
Show resolved
Hide resolved
src/main/java/com/sampoom/backend/api/order/entity/PurchaseOrder.java
Outdated
Show resolved
Hide resolved
src/main/java/com/sampoom/backend/api/order/event/PurchaseEventConsumer.java
Show resolved
Hide resolved
src/main/java/com/sampoom/backend/api/order/service/OrderService.java
Outdated
Show resolved
Hide resolved
src/main/java/com/sampoom/backend/api/order/service/PurchaseOrderService.java
Show resolved
Hide resolved
미사용 임포트, 변수명 등 컨벤션 맞춤
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/main/java/com/sampoom/backend/api/order/dto/POEventPayload.java (1)
20-21: 날짜 필드에 날짜 타입 사용을 검토해주세요.
requiredDate와scheduledDate를 문자열로 유지하면 포맷/파싱 책임이 소비자에게 남아 오류 여지가 큽니다.LocalDate또는LocalDateTime으로 선언해 직렬화 규약을 고정하는 편이 안전합니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/main/java/com/sampoom/backend/api/order/dto/POEventPayload.java(1 hunks)src/main/java/com/sampoom/backend/api/order/dto/POFilterDto.java(2 hunks)src/main/java/com/sampoom/backend/api/order/dto/POResDto.java(3 hunks)src/main/java/com/sampoom/backend/api/order/entity/PurchaseOrder.java(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/main/java/com/sampoom/backend/api/order/dto/POFilterDto.java
- src/main/java/com/sampoom/backend/api/order/entity/PurchaseOrder.java
🧰 Additional context used
🧬 Code graph analysis (1)
src/main/java/com/sampoom/backend/api/order/dto/POEventPayload.java (1)
src/main/java/com/sampoom/backend/api/order/dto/POItemDto.java (1)
Getter(7-15)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (java-kotlin)
🔇 Additional comments (1)
src/main/java/com/sampoom/backend/api/order/dto/POResDto.java (1)
28-56: POStatus 전환 반영을 확인했습니다.필드와 생성자 모두 새 enum으로 정리되어 기존 QueryProjection 흐름과 충돌 우려가 없습니다.
로컬데이트타임으로 파싱
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
src/main/java/com/sampoom/backend/api/order/service/PurchaseOrderService.java (1)
123-142: 중복 조회 로직을 추출하세요.
updatePOStatus와completePOStatus메서드가 동일한findById().orElseThrow()로직을 반복합니다.공통 조회 로직을 private 메서드로 추출하세요:
+private PurchaseOrder findPurchaseOrder(Long partOrderId) { + return purchaseOrderRepository.findById(partOrderId) + .orElseThrow(() -> new NotFoundException(ErrorStatus.PO_NOT_FOUND.getMessage())); +} + public void updatePOStatus(POEventPayload poEventPayload) { - PurchaseOrder purchaseOrder = purchaseOrderRepository.findById(poEventPayload.getPartOrderId()) - .orElseThrow(() -> new NotFoundException(ErrorStatus.PO_NOT_FOUND.getMessage())); + PurchaseOrder purchaseOrder = findPurchaseOrder(poEventPayload.getPartOrderId()); purchaseOrder.setStatus(poEventPayload.getStatus()); purchaseOrder.setScheduledDate( - LocalDateTime.parse(poEventPayload.getScheduledDate(), DateTimeFormatter.ISO_DATE)); + LocalDate.parse(poEventPayload.getScheduledDate(), DateTimeFormatter.ISO_DATE).atStartOfDay()); purchaseOrder.setDeleted(poEventPayload.getDeleted()); purchaseOrder.setProgressRate(poEventPayload.getProgressRate()); purchaseOrderRepository.save(purchaseOrder); } public void completePOStatus(POEventPayload poEventPayload) { - PurchaseOrder purchaseOrder = purchaseOrderRepository.findById(poEventPayload.getPartOrderId()) - .orElseThrow(() -> new NotFoundException(ErrorStatus.PO_NOT_FOUND.getMessage())); + PurchaseOrder purchaseOrder = findPurchaseOrder(poEventPayload.getPartOrderId()); purchaseOrder.setStatus(poEventPayload.getStatus()); purchaseOrder.setProgressRate(poEventPayload.getProgressRate()); purchaseOrderRepository.save(purchaseOrder); }src/main/java/com/sampoom/backend/api/order/entity/PurchaseOrder.java (1)
12-12: 엔티티에 클래스 레벨 @Setter 사용을 재고하세요.JPA 엔티티에 클래스 레벨
@Setter를 사용하면id나createdAt같은 필드를 포함한 모든 필드가 외부에서 변경 가능해져 캡슐화가 깨집니다. 비즈니스 메서드(예:updateStatus(),updateProgress())를 사용하거나 필요한 필드에만 선택적으로 setter를 추가하는 것을 권장합니다.예시:
public void updateStatus(POStatus newStatus) { this.status = newStatus; } public void updateProgress(Double rate, LocalDateTime scheduledDate) { this.progressRate = rate; this.scheduledDate = scheduledDate; } public void markAsDeleted() { this.deleted = true; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/main/java/com/sampoom/backend/api/order/entity/PurchaseOrder.java(2 hunks)src/main/java/com/sampoom/backend/api/order/service/PurchaseOrderService.java(4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/main/java/com/sampoom/backend/api/order/entity/PurchaseOrder.java (3)
src/main/java/com/sampoom/backend/api/order/dto/POFilterDto.java (1)
Getter(9-19)src/main/java/com/sampoom/backend/api/order/dto/POResDto.java (1)
Getter(9-63)src/main/java/com/sampoom/backend/api/order/dto/POEventPayload.java (1)
Getter(8-27)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (java-kotlin)
🔇 Additional comments (3)
src/main/java/com/sampoom/backend/api/order/service/PurchaseOrderService.java (2)
40-47: 메서드 시그니처 변경이 적절합니다.
makePurchaseOrder가 이제PurchaseOrder를 반환하여 배치 생성 패턴을 지원합니다. 변경사항이 합리적입니다.
49-61: 배치 생성 로직이 정상적으로 작동합니다.여러 발주를 생성하고 매핑을 반환하는 로직이 올바릅니다.
saveAll을 사용한 배치 저장도 적절합니다.src/main/java/com/sampoom/backend/api/order/entity/PurchaseOrder.java (1)
35-46: 새로운 필드 추가가 적절합니다.
POStatus로의 타입 변경과 기본값 설정이 합리적입니다.scheduledDate를LocalDateTime으로 선언한 것이 타입 안전성 측면에서 올바릅니다.deleted필드명이 JavaBean 컨벤션을 따르며, Lombok이 올바른setDeleted()와isDeleted()메서드를 생성합니다.
📝 Summary
발주 상태 업데이트 이벤트 수신
발주 생성 시 단건으로 로직 변경, 주문 아이디 페이로드에 포함.
🙏 Question & PR point
📬 Reference
Summary by CodeRabbit
새로운 기능
개선 사항
버그 수정