From 26c09de7c9c2e03665de9398ffa10f12a8cc9aab Mon Sep 17 00:00:00 2001 From: Klaus Date: Mon, 10 Nov 2025 15:15:10 +0900 Subject: [PATCH] =?UTF-8?q?feat(admin-can):=20=EA=B4=80=EB=A6=AC=EC=9E=90?= =?UTF-8?q?=20=EC=BA=94=20=EC=B6=A9=EC=A0=84=20API=EB=A5=BC=20=EB=8B=A4?= =?UTF-8?q?=EC=A4=91=20=ED=9A=8C=EC=9B=90=20=EC=9D=BC=EA=B4=84=20=EC=B6=A9?= =?UTF-8?q?=EC=A0=84=EC=9C=BC=EB=A1=9C=20=ED=99=95=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - AdminCanChargeRequest: memberId → memberIds(List)로 변경 - AdminCanService.charge: memberIds 선조회 후 다건 충전 로직 추가 - 잘못된/비어있는 회원번호 검증 및 트랜잭션 롤백으로 정합성 보장 배경: 관리자 일괄 충전 요구사항 반영으로 여러 회원에게 동일 수량의 캔을 한 번에 충전할 수 있도록 개선. 중복 ID는 제거하여 중복 충전을 방지하고, 하나라도 유효하지 않으면 전체 롤백되도록 처리하여 데이터 정합성 확보. --- .../admin/can/AdminCanChargeRequest.kt | 2 +- .../sodalive/admin/can/AdminCanService.kt | 27 +++++++++++-------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/can/AdminCanChargeRequest.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/can/AdminCanChargeRequest.kt index bbb8fd0..22cfb98 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/can/AdminCanChargeRequest.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/can/AdminCanChargeRequest.kt @@ -1,7 +1,7 @@ package kr.co.vividnext.sodalive.admin.can data class AdminCanChargeRequest( - val memberId: Long, + val memberIds: List, val method: String, val can: Int ) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/can/AdminCanService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/can/AdminCanService.kt index 612e414..9e780dc 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/can/AdminCanService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/can/AdminCanService.kt @@ -40,22 +40,27 @@ class AdminCanService( @Transactional fun charge(request: AdminCanChargeRequest) { - val member = memberRepository.findByIdOrNull(request.memberId) - ?: throw SodaException("잘못된 회원번호 입니다.") - if (request.can <= 0) throw SodaException("1 캔 이상 입력하세요.") if (request.method.isBlank()) throw SodaException("기록내용을 입력하세요.") - val charge = Charge(0, request.can, status = ChargeStatus.ADMIN) - charge.title = "${request.can.moneyFormat()} 캔" - charge.member = member + val ids = request.memberIds.distinct() + if (ids.isEmpty()) throw SodaException("회원번호를 입력하세요.") - val payment = Payment(status = PaymentStatus.COMPLETE, paymentGateway = PaymentGateway.PG) - payment.method = request.method - charge.payment = payment + val members = memberRepository.findAllById(ids).toList() + if (members.size != ids.size) throw SodaException("잘못된 회원번호 입니다.") - chargeRepository.save(charge) + members.forEach { member -> + val charge = Charge(0, request.can, status = ChargeStatus.ADMIN) + charge.title = "${request.can.moneyFormat()} 캔" + charge.member = member - member.pgRewardCan += charge.rewardCan + val payment = Payment(status = PaymentStatus.COMPLETE, paymentGateway = PaymentGateway.PG) + payment.method = request.method + charge.payment = payment + + chargeRepository.save(charge) + + member.pgRewardCan += charge.rewardCan + } } }