Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

src/withdrawal: Allow deletion of withdrawal records #582

Merged
merged 7 commits into from
Dec 12, 2023
Merged
1 change: 0 additions & 1 deletion apps/api/src/campaign/campaign.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ import {
NotificationService,
donationNotificationSelect,
} from '../sockets/notifications/notification.service'
import { DonationMetadata } from '../donations/dontation-metadata.interface'
import { Expense } from '@prisma/client'
import { SendGridParams } from '../notifications/providers/notifications.sendgrid.types'
import * as NotificationData from '../notifications/notification-data.json'
Expand Down
99 changes: 94 additions & 5 deletions apps/api/src/withdrawal/withdrawal.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { NotFoundException, ForbiddenException } from '@nestjs/common'
import { NotFoundException, BadRequestException } from '@nestjs/common'
import { Test, TestingModule } from '@nestjs/testing'
import { WithdrawStatus, Currency } from '@prisma/client'
import { WithdrawStatus, Currency, Withdrawal } from '@prisma/client'
import { mockReset } from 'jest-mock-extended'
import { MockPrismaService, prismaMock } from '../prisma/prisma-client.mock'
import { CreateWithdrawalDto } from './dto/create-withdrawal.dto'
Expand All @@ -9,7 +9,7 @@ import { WithdrawalController } from './withdrawal.controller'
import { WithdrawalService } from './withdrawal.service'
import { MarketingNotificationsModule } from '../notifications/notifications.module'

const mockData = [
const mockData: Withdrawal[] = [
{
id: '00000000-0000-0000-0000-000000000001',
status: WithdrawStatus.initial,
Expand Down Expand Up @@ -362,9 +362,98 @@ describe('WithdrawalController', () => {
})

describe('removeData', () => {
it('should not remove withdrawals', async () => {
it("should decrement vault's blockedAmount on initial withdrawn deletion", async () => {
const withdrawal = mockData[0]
await expect(controller.remove(withdrawal.id)).rejects.toThrow(new ForbiddenException())
prismaMock.withdrawal.delete.mockResolvedValue(withdrawal)
await expect(controller.remove(withdrawal.id)).toResolve()
expect(prismaMock.withdrawal.delete).toHaveBeenCalledWith({
where: { id: withdrawal.id },
})
expect(prismaMock.vault.update).toHaveBeenCalledWith({
where: { id: withdrawal.sourceVaultId },
data: {
amount: {
increment: 0,
},
blockedAmount: {
decrement: withdrawal.amount,
},
},
})
})

it("should increment vault's amount on succeeded withdrawn deletion ", async () => {
const withdrawal = { ...mockData[0], status: WithdrawStatus.succeeded }
prismaMock.withdrawal.delete.mockResolvedValue(withdrawal)
await expect(controller.remove(withdrawal.id)).toResolve()
expect(prismaMock.withdrawal.delete).toHaveBeenCalledWith({
where: { id: withdrawal.id },
})
expect(prismaMock.vault.update).toHaveBeenCalledWith({
where: { id: withdrawal.sourceVaultId },
data: {
amount: {
increment: withdrawal.amount,
},
blockedAmount: {
decrement: 0,
},
},
})
})

it("shouldn't update vault's amount and blockedAmount on cancelled withdrawn deletion", async () => {
const withdrawal = { ...mockData[0], status: WithdrawStatus.cancelled }
prismaMock.withdrawal.delete.mockResolvedValue(withdrawal)
await expect(controller.remove(withdrawal.id)).toResolve()
expect(prismaMock.withdrawal.delete).toHaveBeenCalledWith({
where: { id: withdrawal.id },
})
expect(prismaMock.vault.update).toHaveBeenCalledWith({
where: { id: withdrawal.sourceVaultId },
data: {
amount: {
increment: 0,
},
blockedAmount: {
decrement: 0,
},
},
})
})

it("shouldn't update vault's amount and blockedAmount on declined withdrawn deletion", async () => {
const withdrawal = { ...mockData[0], status: WithdrawStatus.declined }
prismaMock.withdrawal.delete.mockResolvedValue(withdrawal)
await expect(controller.remove(withdrawal.id)).toResolve()
expect(prismaMock.withdrawal.delete).toHaveBeenCalledWith({
where: { id: withdrawal.id },
})
expect(prismaMock.vault.update).toHaveBeenCalledWith({
where: { id: withdrawal.sourceVaultId },
data: {
amount: {
increment: 0,
},
blockedAmount: {
decrement: 0,
},
},
})
})

it('Should throw an error if delete query rejects', async () => {
const withdrawal = mockData[1]
prismaMock.withdrawal.delete.mockRejectedValue(withdrawal)
await expect(controller.remove(withdrawal.id)).rejects.toThrow(
new BadRequestException("Withdrawal record couldn't be deleted"),
)

expect(prismaMock.withdrawal.delete).toHaveBeenCalledWith({
where: { id: withdrawal.id },
})

expect(prismaMock.vault.update).not.toHaveBeenCalled()
})
})
})
34 changes: 23 additions & 11 deletions apps/api/src/withdrawal/withdrawal.service.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import {
Injectable,
Logger,
NotFoundException,
BadRequestException,
ForbiddenException,
} from '@nestjs/common'
import { Injectable, Logger, NotFoundException, BadRequestException } from '@nestjs/common'
import { Withdrawal, WithdrawStatus } from '@prisma/client'
import { PrismaService } from '../prisma/prisma.service'
import { CreateWithdrawalDto } from './dto/create-withdrawal.dto'
Expand Down Expand Up @@ -124,11 +118,29 @@ export class WithdrawalService {
return result
}

// Functionality will be reworked soon
async remove(id: string): Promise<Withdrawal | null> {
throw new ForbiddenException()
const result = await this.prisma.withdrawal.delete({ where: { id: id } })
if (!result) throw new NotFoundException('Not found')
const result = await this.prisma.withdrawal
.delete({
where: { id: id },
})
.catch(() => {
throw new BadRequestException("Withdrawal record couldn't be deleted")
})

const isSucceeded = result.status === WithdrawStatus.succeeded
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it is better to check the status before updating, instead of incrementing with 0...

const isCancelled =
result.status === WithdrawStatus.cancelled || result.status === WithdrawStatus.declined

await this.prisma.vault.update({
where: { id: result.sourceVaultId },
data: {
amount: { increment: isSucceeded ? result.amount : 0 },
blockedAmount: {
decrement: isCancelled || isSucceeded ? 0 : result.amount,
},
},
})

return result
}
}
Loading