Skip to content

Commit d1f3830

Browse files
authored
Merge pull request #455 from ndii-dev/chore/payments-limits-boundaries-cache
refactor: introduce payment limits boundary and cache stub
2 parents ac52f89 + ad96406 commit d1f3830

5 files changed

Lines changed: 36 additions & 10 deletions

File tree

src/limits/limits.service.spec.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ describe('LimitsService', () => {
3232
incrementLimitChecks: jest.fn(),
3333
};
3434

35+
cacheService = { get: jest.fn(), set: jest.fn(), delete: jest.fn() };
36+
3537
const module: TestingModule = await Test.createTestingModule({
3638
providers: [
3739
LimitsService,
@@ -68,6 +70,17 @@ describe('LimitsService', () => {
6870
const result = await service.getLimits(walletId);
6971
expect(result).toEqual(limit);
7072
});
73+
74+
it('should use the cache layer for wallet limits', async () => {
75+
const limit = { walletId, dailyLimit: 100, perTransactionLimit: 10 };
76+
cacheService.get.mockReturnValue(limit);
77+
78+
const result = await service.getLimits(walletId);
79+
80+
expect(result).toEqual(limit);
81+
expect(cacheService.get).toHaveBeenCalledWith(`limits:${walletId}`);
82+
expect(prisma.walletLimit.findUnique).not.toHaveBeenCalled();
83+
});
7184
});
7285

7386
describe('checkLimits', () => {

src/payments/payments-limits.integration.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ describe('Payments and Limits Integration', () => {
4343
PaymentsService,
4444
LimitsService,
4545
{ provide: PrismaService, useValue: mockPrisma },
46+
{ provide: PAYMENT_LIMITS_PORT, useExisting: LimitsService },
4647
{ provide: WalletsService, useValue: mockWalletsService },
4748
{ provide: RequestContextService, useValue: mockRequestContext },
4849
],

src/payments/payments.service.spec.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { BadRequestException, NotFoundException } from '@nestjs/common';
33
import { EventEmitter2 } from '@nestjs/event-emitter';
44
import { PaymentsService } from './payments.service';
55
import { PrismaService } from '../prisma/prisma.service';
6-
import { LimitsService } from '../limits/limits.service';
76
import { WalletsService } from '../wallets/wallets.service';
87
import { MetricsService } from '../metrics/metrics.service';
98
import { WalletStatus } from '../wallets/domain/wallet.model';
@@ -31,7 +30,7 @@ const BASE_DTO = {
3130
describe('PaymentsService', () => {
3231
let service: PaymentsService;
3332
let prisma: any;
34-
let limitsService: any;
33+
let paymentLimitsPort: any;
3534
let walletsService: any;
3635
let eventEmitter: any;
3736
let metrics: any;
@@ -46,7 +45,7 @@ describe('PaymentsService', () => {
4645
count: jest.fn(),
4746
},
4847
};
49-
limitsService = { checkLimits: jest.fn() };
48+
paymentLimitsPort = { checkLimits: jest.fn() };
5049
walletsService = { findWalletById: jest.fn() };
5150
eventEmitter = { emit: jest.fn() };
5251
metrics = {
@@ -59,7 +58,7 @@ describe('PaymentsService', () => {
5958
providers: [
6059
PaymentsService,
6160
{ provide: PrismaService, useValue: prisma },
62-
{ provide: LimitsService, useValue: limitsService },
61+
{ provide: PAYMENT_LIMITS_PORT, useValue: paymentLimitsPort },
6362
{ provide: WalletsService, useValue: walletsService },
6463
{ provide: EventEmitter2, useValue: eventEmitter },
6564
{ provide: MetricsService, useValue: metrics },
@@ -78,7 +77,7 @@ describe('PaymentsService', () => {
7877
walletsService.findWalletById
7978
.mockResolvedValueOnce(ACTIVE_WALLET)
8079
.mockResolvedValueOnce(RECEIVER_WALLET);
81-
limitsService.checkLimits.mockResolvedValue(undefined);
80+
paymentLimitsPort.checkLimits.mockResolvedValue(undefined);
8281
prisma.payment.create.mockResolvedValue({
8382
id: 1,
8483
...BASE_DTO,
@@ -93,7 +92,7 @@ describe('PaymentsService', () => {
9392
expect(walletsService.findWalletById).toHaveBeenCalledWith(
9493
BASE_DTO.receiverWalletId,
9594
);
96-
expect(limitsService.checkLimits).toHaveBeenCalledWith(
95+
expect(paymentLimitsPort.checkLimits).toHaveBeenCalledWith(
9796
BASE_DTO.walletId,
9897
BASE_DTO.amount,
9998
);
@@ -166,7 +165,7 @@ describe('PaymentsService', () => {
166165
walletsService.findWalletById
167166
.mockResolvedValueOnce(ACTIVE_WALLET)
168167
.mockResolvedValueOnce(RECEIVER_WALLET);
169-
limitsService.checkLimits.mockResolvedValue(undefined);
168+
paymentLimitsPort.checkLimits.mockResolvedValue(undefined);
170169
prisma.payment.create.mockResolvedValue({
171170
id: 1,
172171
...BASE_DTO,
@@ -175,7 +174,7 @@ describe('PaymentsService', () => {
175174

176175
await service.create(BASE_DTO);
177176

178-
expect(limitsService.checkLimits).toHaveBeenCalledWith(
177+
expect(paymentLimitsPort.checkLimits).toHaveBeenCalledWith(
179178
BASE_DTO.walletId,
180179
BASE_DTO.amount,
181180
);

src/payments/payments.service.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
Inject,
23
Injectable,
34
NotFoundException,
45
BadRequestException,
@@ -8,8 +9,11 @@ import { EventEmitter2 } from '@nestjs/event-emitter';
89
import { CreatePaymentDto } from './dto/create-payment.dto';
910
import { UpdatePaymentDto } from './dto/update-payment.dto';
1011
import { PrismaService } from '../prisma/prisma.service';
11-
import { LimitsService } from '../limits/limits.service';
1212
import { WalletsService } from '../wallets/wallets.service';
13+
import {
14+
PAYMENT_LIMITS_PORT,
15+
PaymentLimitsPort,
16+
} from './ports/payment-limits.port';
1317
import { WalletStatus } from '../wallets/domain/wallet.model';
1418
import { PaymentStatus } from './entities/payment.entity';
1519
import { PaginationDto, PaginatedResponse } from '../common/dto/pagination.dto';
@@ -33,7 +37,8 @@ export class PaymentsService {
3337

3438
constructor(
3539
private readonly prisma: PrismaService,
36-
private readonly limitsService: LimitsService,
40+
@Inject(PAYMENT_LIMITS_PORT)
41+
private readonly paymentLimitsPort: PaymentLimitsPort,
3742
private readonly walletsService: WalletsService,
3843
private readonly eventEmitter: EventEmitter2,
3944
private readonly metrics: MetricsService,
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { Injectable, InjectionToken } from '@nestjs/common';
2+
3+
export const PAYMENT_LIMITS_PORT = Symbol('PAYMENT_LIMITS_PORT') as InjectionToken;
4+
5+
@Injectable()
6+
export abstract class PaymentLimitsPort {
7+
abstract checkLimits(walletId: string, amount: number): Promise<void> | void;
8+
}

0 commit comments

Comments
 (0)