From 04ee115cf49acaecf86276653f3995f47b5273b9 Mon Sep 17 00:00:00 2001 From: ChoiWheatley Date: Tue, 4 Feb 2025 15:25:14 +0900 Subject: [PATCH] feat(handleMatchedDepositDeleteRequested): Add reset provdon --- src/event-handlers/deposit-delete.saga.ts | 27 ++++++++++++++++++++++- src/features/deposit/deposit.e2e.spec.ts | 11 +++++++-- src/tests/mock-factory.ts | 19 ++++++++-------- 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/event-handlers/deposit-delete.saga.ts b/src/event-handlers/deposit-delete.saga.ts index 56e1db7..ff822bc 100644 --- a/src/event-handlers/deposit-delete.saga.ts +++ b/src/event-handlers/deposit-delete.saga.ts @@ -30,7 +30,9 @@ export class DepositDeleteSaga { ) {} /** - * 후원이 정상적으로 처리되어 연관된 후원을 먼저 제거해야 합니다. 이 프로세스는 후원 삭제 성공 여부에 따라 실패할 수 있는 프로세스로, 예외 발생시 적절한 보상조치를 수행합니다. + * 후원이 정상적으로 처리되어 연관된 후원을 먼저 제거해야 합니다. 그리고 예비후원의 상태를 초기화한 뒤 이체내역을 삭제합니다. + * + * 이 프로세스는 후원 삭제 성공 여부에 따라 실패할 수 있는 프로세스로, 예외 발생시 적절한 보상조치를 수행합니다. */ @OnEvent(MatchedDepositDeleteRequestedEvent.name, { async: true }) async handleMatchedDepositDeleteRequested( @@ -70,6 +72,29 @@ export class DepositDeleteSaga { throw error; } } + + // 예비후원 매치 취소 + try { + await this.cancelMatchProvDon.execute( + deposit.senderSig, + depositId, + adminId, + ); + } catch (error) { + if (error instanceof InvalidStatus) { + // 예비후원 매치 취소 실패! 보상 절차를 진행합니다 + // send notification to admin + const notiDto = new CreateNotificationDto({ + recvId: adminId, + sendId: undefined, + notiType: NotiType.ProvisionalDonationMatchCancelFailed, + subId: deposit.senderSig, + }); + await this.notiService.createNoti(notiDto); + } else { + throw error; + } + } } /** diff --git a/src/features/deposit/deposit.e2e.spec.ts b/src/features/deposit/deposit.e2e.spec.ts index cfd944a..ec815eb 100644 --- a/src/features/deposit/deposit.e2e.spec.ts +++ b/src/features/deposit/deposit.e2e.spec.ts @@ -488,7 +488,7 @@ describe('Deposit API E2E Test', () => { expect(foundDeposit).toBeNull(); }); - it('should delete donation and decrease fundSum if matched', async () => { + it('should delete donation and decrease fundSum and reset to pending on provdon if matched', async () => { // Scenario: Create matched deposit, donation, and funding const funding = await createMockFundingWithRelations( { @@ -496,11 +496,12 @@ describe('Deposit API E2E Test', () => { fundingRepo, depositRepo, donationRepo, + provDonRepo, }, { fundUser: mockFundingOwner, }, - { deposit: 1, donation: 1 }, + { deposit: 1, donation: 1, provDonation: 1 }, ); const donation = funding.donations[0]; @@ -524,6 +525,12 @@ describe('Deposit API E2E Test', () => { where: { donId: donation.donId }, }); expect(foundDonation).toBeNull(); + + // Provisional Donation의 상태가 Pending이어야 합니다. + const foundProvDon = await provDonRepo.findOne({ + where: { senderSig: deposit.senderSig }, + }); + expect(foundProvDon.status).toBe(ProvisionalDonationStatus.Pending); }); }); diff --git a/src/tests/mock-factory.ts b/src/tests/mock-factory.ts index 4d76c2d..2508faf 100644 --- a/src/tests/mock-factory.ts +++ b/src/tests/mock-factory.ts @@ -234,22 +234,21 @@ export const createMockFundingWithRelations = async ( mockFunding.donations = donations; await delegate.fundingRepo.save(mockFunding); } - } - // Handle optional provisional donations - if (delegate.provDonRepo) { - await Promise.all( - Array(amount?.provDonation ?? 1) - .fill(null) - .map(() => - delegate.provDonRepo.save( + // Handle optional provisional donations + if (delegate.provDonRepo) { + await delegate.provDonRepo.save( + Array(amount?.provDonation ?? 1) + .fill(null) + .map((_, index) => createMockProvisionalDonation({ funding: mockFunding, senderUser: mockUser, + senderSig: deposits[index].senderSig, }), ), - ), - ); + ); + } } return mockFunding;