Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { IsDateString, IsOptional } from 'class-validator';

export class TransactionListQuery {
@IsOptional()
@IsDateString()
createdFrom?: string;

@IsOptional()
@IsDateString()
createdTo?: string;

@IsOptional()
@IsDateString()
outputFrom?: string;

@IsOptional()
@IsDateString()
outputTo?: string;
}
14 changes: 14 additions & 0 deletions src/subdomains/generic/support/dto/user-data-support.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,20 @@ export class SellSupportInfo {
volume: number;
}

export class TransactionListEntry {
id: number;
type?: string;
accountId?: number;
name?: string;
domicile?: string;
created?: Date;
eventDate?: Date;
outputDate?: Date;
assets?: string;
amountInChf?: number;
highRisk?: boolean;
}

export class KycFileListEntry {
kycFileId: number;
id: number;
Expand Down
10 changes: 10 additions & 0 deletions src/subdomains/generic/support/support.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ import { UserActiveGuard } from 'src/shared/auth/user-active.guard';
import { UserRole } from 'src/shared/auth/user-role.enum';
import { RefundDataDto } from 'src/subdomains/core/history/dto/refund-data.dto';
import { BankRefundDto } from 'src/subdomains/core/history/dto/transaction-refund.dto';
import { TransactionListQuery } from './dto/transaction-list-query.dto';
import {
KycFileListEntry,
KycFileYearlyStats,
TransactionListEntry,
UserDataSupportInfoDetails,
UserDataSupportInfoResult,
UserDataSupportQuery,
Expand Down Expand Up @@ -53,6 +55,14 @@ export class SupportController {
return this.supportService.getKycFileStats();
}

@Get('transactionList')
@ApiBearerAuth()
@ApiExcludeEndpoint()
@UseGuards(AuthGuard(), RoleGuard(UserRole.COMPLIANCE), UserActiveGuard())
async getTransactionList(@Query() query: TransactionListQuery): Promise<TransactionListEntry[]> {
return this.supportService.getTransactionList(query);
}

@Get(':id')
@ApiBearerAuth()
@ApiExcludeEndpoint()
Expand Down
31 changes: 31 additions & 0 deletions src/subdomains/generic/support/support.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { UserData } from '../user/models/user-data/user-data.entity';
import { UserDataService } from '../user/models/user-data/user-data.service';
import { User } from '../user/models/user/user.entity';
import { UserService } from '../user/models/user/user.service';
import { TransactionListQuery } from './dto/transaction-list-query.dto';
import {
BankDataSupportInfo,
BankTxSupportInfo,
Expand All @@ -44,6 +45,7 @@ import {
KycFileYearlyStats,
KycStepSupportInfo,
SellSupportInfo,
TransactionListEntry,
TransactionSupportInfo,
UserDataSupportInfo,
UserDataSupportInfoDetails,
Expand Down Expand Up @@ -152,8 +154,37 @@ export class SupportService {
return result;
}

async getTransactionList(query: TransactionListQuery): Promise<TransactionListEntry[]> {
const dateFrom = new Date(query.createdFrom ?? new Date(Date.now() - 3 * 24 * 60 * 60 * 1000).toISOString());
const dateTo = new Date(query.createdTo ?? new Date().toISOString());
dateTo.setHours(23, 59, 59, 999);

const outputFrom = query.outputFrom ? new Date(query.outputFrom) : undefined;
const outputTo = query.outputTo ? new Date(query.outputTo) : undefined;
if (outputTo) outputTo.setHours(23, 59, 59, 999);

const transactions = await this.transactionService.getTransactionList(dateFrom, dateTo, outputFrom, outputTo);
return transactions.map((t) => this.toTransactionListEntry(t));
}

// --- MAPPING METHODS --- //

private toTransactionListEntry(tx: Transaction): TransactionListEntry {
return {
id: tx.id,
type: tx.type,
accountId: tx.userData?.id,
name: tx.userData?.verifiedName,
domicile: tx.userData?.country?.name,
created: tx.created,
eventDate: tx.eventDate,
outputDate: tx.outputDate,
assets: tx.assets,
amountInChf: tx.amountInChf,
highRisk: tx.highRisk,
};
}

private toKycFileListEntry(userData: UserData, auditStartDate?: Date): KycFileListEntry {
return {
kycFileId: userData.kycFileId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,46 @@ export class TransactionService {
});
}

async getTransactionList(dateFrom?: Date, dateTo?: Date, outputFrom?: Date, outputTo?: Date): Promise<Transaction[]> {
const query = this.repo
.createQueryBuilder('transaction')
.select('transaction')
.leftJoinAndSelect('transaction.userData', 'userData')
.leftJoinAndSelect('userData.country', 'country')
.where('transaction.type IS NOT NULL');

if (dateFrom || dateTo || outputFrom || outputTo) {
query.andWhere(
new Brackets((qb) => {
if (dateFrom && dateTo) {
qb.where('transaction.created BETWEEN :dateFrom AND :dateTo', { dateFrom, dateTo });
} else if (dateFrom) {
qb.where('transaction.created >= :dateFrom', { dateFrom });
} else if (dateTo) {
qb.where('transaction.created <= :dateTo', { dateTo });
}

if (outputFrom || outputTo) {
const outputCondition =
outputFrom && outputTo
? 'transaction.outputDate BETWEEN :outputFrom AND :outputTo'
: outputFrom
? 'transaction.outputDate >= :outputFrom'
: 'transaction.outputDate <= :outputTo';

if (dateFrom || dateTo) {
qb.andWhere(outputCondition, { outputFrom, outputTo });
} else {
qb.where(outputCondition, { outputFrom, outputTo });
}
}
}),
);
}

return query.orderBy('transaction.id', 'DESC').getMany();
}

async getTransactionsForAccount(userDataId: number, from = new Date(0), to = new Date()): Promise<Transaction[]> {
return this.repo.find({
where: { userData: { id: userDataId }, type: Not(IsNull()), created: Between(from, to) },
Expand Down
Loading