mirror of
https://github.com/HamzaSha1/zod-backend.git
synced 2025-11-26 00:24:54 +00:00
Compare commits
2 Commits
44124b9964
...
918b15c315
| Author | SHA1 | Date | |
|---|---|---|---|
| 918b15c315 | |||
| 1830d92cbd |
@ -58,7 +58,9 @@ export class CardResponseDto {
|
|||||||
this.status = card.status;
|
this.status = card.status;
|
||||||
this.statusDescription = CardStatusDescriptionMapper[card.statusDescription][UserLocale.ENGLISH].description;
|
this.statusDescription = CardStatusDescriptionMapper[card.statusDescription][UserLocale.ENGLISH].description;
|
||||||
this.balance =
|
this.balance =
|
||||||
card.customerType === CustomerType.CHILD ? Math.min(card.limit, card.account.balance) : card.account.balance;
|
card.customerType === CustomerType.CHILD
|
||||||
|
? Math.min(card.limit, card.account.balance)
|
||||||
|
: card.account.balance - card.account.reservedBalance;
|
||||||
this.reservedBalance = card.customerType === CustomerType.PARENT ? card.account.reservedBalance : null;
|
this.reservedBalance = card.customerType === CustomerType.PARENT ? card.account.reservedBalance : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,7 +32,16 @@ export class Transaction {
|
|||||||
@Column({ name: 'rrn', nullable: true, type: 'varchar' })
|
@Column({ name: 'rrn', nullable: true, type: 'varchar' })
|
||||||
rrn!: string;
|
rrn!: string;
|
||||||
|
|
||||||
@Column({ type: 'decimal', precision: 12, scale: 2, name: 'transaction_amount' })
|
@Column({
|
||||||
|
type: 'decimal',
|
||||||
|
precision: 12,
|
||||||
|
scale: 2,
|
||||||
|
name: 'transaction_amount',
|
||||||
|
transformer: {
|
||||||
|
to: (value: number) => value,
|
||||||
|
from: (value: string) => parseFloat(value),
|
||||||
|
},
|
||||||
|
})
|
||||||
transactionAmount!: number;
|
transactionAmount!: number;
|
||||||
|
|
||||||
@Column({ type: 'varchar', name: 'transaction_currency' })
|
@Column({ type: 'varchar', name: 'transaction_currency' })
|
||||||
|
|||||||
@ -84,4 +84,16 @@ export class TransactionRepository {
|
|||||||
where: { transactionId, accountReference },
|
where: { transactionId, accountReference },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getTransactionsForCardWithinDateRange(juniorId: string, startDate: Date, endDate: Date): Promise<Transaction[]> {
|
||||||
|
return this.transactionRepository
|
||||||
|
.createQueryBuilder('transaction')
|
||||||
|
.innerJoinAndSelect('transaction.card', 'card')
|
||||||
|
.where('card.customerId = :juniorId', { juniorId })
|
||||||
|
.andWhere('transaction.transactionScope = :scope', { scope: TransactionScope.CARD })
|
||||||
|
.andWhere('transaction.transactionType = :type', { type: TransactionType.EXTERNAL })
|
||||||
|
.andWhere('transaction.transactionDate BETWEEN :startDate AND :endDate', { startDate, endDate })
|
||||||
|
.orderBy('transaction.transactionDate', 'DESC')
|
||||||
|
.getMany();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -163,6 +163,10 @@ export class CardService {
|
|||||||
return finalAmount.toNumber();
|
return finalAmount.toNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getWeeklySummary(juniorId: string) {
|
||||||
|
return this.transactionService.getWeeklySummary(juniorId);
|
||||||
|
}
|
||||||
|
|
||||||
fundIban(iban: string, amount: number) {
|
fundIban(iban: string, amount: number) {
|
||||||
return this.accountService.fundIban(iban, amount);
|
return this.accountService.fundIban(iban, amount);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { forwardRef, Inject, Injectable, UnprocessableEntityException } from '@nestjs/common';
|
import { forwardRef, Inject, Injectable, UnprocessableEntityException } from '@nestjs/common';
|
||||||
import Decimal from 'decimal.js';
|
import Decimal from 'decimal.js';
|
||||||
|
import moment from 'moment';
|
||||||
import { Transactional } from 'typeorm-transactional';
|
import { Transactional } from 'typeorm-transactional';
|
||||||
import {
|
import {
|
||||||
AccountTransactionWebhookRequest,
|
AccountTransactionWebhookRequest,
|
||||||
@ -73,4 +74,43 @@ export class TransactionService {
|
|||||||
|
|
||||||
return existingTransaction;
|
return existingTransaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getWeeklySummary(juniorId: string) {
|
||||||
|
const startOfWeek = moment().startOf('week').toDate();
|
||||||
|
const endOfWeek = moment().endOf('week').toDate();
|
||||||
|
|
||||||
|
const transactions = await this.transactionRepository.getTransactionsForCardWithinDateRange(
|
||||||
|
juniorId,
|
||||||
|
startOfWeek,
|
||||||
|
endOfWeek,
|
||||||
|
);
|
||||||
|
const summary = {
|
||||||
|
startOfWeek: startOfWeek,
|
||||||
|
endOfWeek: endOfWeek,
|
||||||
|
total: 0,
|
||||||
|
monday: 0,
|
||||||
|
tuesday: 0,
|
||||||
|
wednesday: 0,
|
||||||
|
thursday: 0,
|
||||||
|
friday: 0,
|
||||||
|
saturday: 0,
|
||||||
|
sunday: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
transactions.forEach((transaction) => {
|
||||||
|
const day = moment(transaction.transactionDate).format('dddd').toLowerCase() as
|
||||||
|
| 'monday'
|
||||||
|
| 'tuesday'
|
||||||
|
| 'wednesday'
|
||||||
|
| 'thursday'
|
||||||
|
| 'friday'
|
||||||
|
| 'saturday'
|
||||||
|
| 'sunday';
|
||||||
|
summary[day] += transaction.transactionAmount;
|
||||||
|
});
|
||||||
|
|
||||||
|
summary.total = transactions.reduce((acc, curr) => acc + curr.transactionAmount, 0);
|
||||||
|
|
||||||
|
return summary;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,6 +32,7 @@ import {
|
|||||||
ThemeResponseDto,
|
ThemeResponseDto,
|
||||||
TransferToJuniorResponseDto,
|
TransferToJuniorResponseDto,
|
||||||
} from '../dtos/response';
|
} from '../dtos/response';
|
||||||
|
import { WeeklySummaryResponseDto } from '../dtos/response/weekly-summary.response.dto';
|
||||||
import { JuniorService } from '../services';
|
import { JuniorService } from '../services';
|
||||||
|
|
||||||
@Controller('juniors')
|
@Controller('juniors')
|
||||||
@ -144,4 +145,16 @@ export class JuniorController {
|
|||||||
|
|
||||||
return ResponseFactory.data(new TransferToJuniorResponseDto(newAmount));
|
return ResponseFactory.data(new TransferToJuniorResponseDto(newAmount));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Get(':juniorId/weekly-summary')
|
||||||
|
@UseGuards(RolesGuard)
|
||||||
|
@AllowedRoles(Roles.GUARDIAN)
|
||||||
|
@ApiDataResponse(WeeklySummaryResponseDto)
|
||||||
|
async getWeeklySummary(
|
||||||
|
@Param('juniorId', CustomParseUUIDPipe) juniorId: string,
|
||||||
|
@AuthenticatedUser() user: IJwtPayload,
|
||||||
|
) {
|
||||||
|
const summary = await this.juniorService.getWeeklySummary(juniorId, user.sub);
|
||||||
|
return ResponseFactory.data(summary);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
31
src/junior/dtos/response/weekly-summary.response.dto.ts
Normal file
31
src/junior/dtos/response/weekly-summary.response.dto.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
|
||||||
|
export class WeeklySummaryResponseDto {
|
||||||
|
@ApiProperty({ description: 'Start date of the week', example: '2023-10-01' })
|
||||||
|
startOfWeek!: Date;
|
||||||
|
@ApiProperty({ description: 'End date of the week', example: '2023-10-07' })
|
||||||
|
endOfWeek!: Date;
|
||||||
|
@ApiProperty({ description: 'Total amount spent in the week', example: 350 })
|
||||||
|
total!: number;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Amount spent on Sunday', example: 50 })
|
||||||
|
sunday!: number;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Amount spent on Monday', example: 30 })
|
||||||
|
monday!: number;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Amount spent on Tuesday', example: 20 })
|
||||||
|
tuesday!: number;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Amount spent on Wednesday', example: 40 })
|
||||||
|
wednesday!: number;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Amount spent on Thursday', example: 60 })
|
||||||
|
thursday!: number;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Amount spent on Friday', example: 70 })
|
||||||
|
friday!: number;
|
||||||
|
|
||||||
|
@ApiProperty({ description: 'Amount spent on Saturday', example: 80 })
|
||||||
|
saturday!: number;
|
||||||
|
}
|
||||||
@ -209,6 +209,18 @@ export class JuniorService {
|
|||||||
this.logger.log(`Junior ${juniorId} deleted successfully`);
|
this.logger.log(`Junior ${juniorId} deleted successfully`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getWeeklySummary(juniorId: string, guardianId: string) {
|
||||||
|
const doesBelong = this.doesJuniorBelongToGuardian(guardianId, juniorId);
|
||||||
|
|
||||||
|
if (!doesBelong) {
|
||||||
|
this.logger.error(`Junior ${juniorId} does not belong to guardian ${guardianId}`);
|
||||||
|
throw new BadRequestException('JUNIOR.NOT_BELONG_TO_GUARDIAN');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.log(`Getting weekly summary for junior ${juniorId}`);
|
||||||
|
return this.cardService.getWeeklySummary(juniorId);
|
||||||
|
}
|
||||||
|
|
||||||
private async prepareJuniorImages(juniors: Junior[]) {
|
private async prepareJuniorImages(juniors: Junior[]) {
|
||||||
this.logger.log(`Preparing junior images`);
|
this.logger.log(`Preparing junior images`);
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
|
|||||||
Reference in New Issue
Block a user