mirror of
https://github.com/HamzaSha1/zod-backend.git
synced 2026-03-10 18:41:46 +00:00
- Added MoneyRequestNotificationListener to handle notifications for money request events (created, approved, declined). - Introduced new notification event constants for money requests. - Updated notification interfaces to include money request event payloads. - Enhanced existing notification system to support money request notifications, notifying parents and children appropriately. - Updated device service to support finding devices by ID for improved functionality.
134 lines
5.1 KiB
TypeScript
134 lines
5.1 KiB
TypeScript
import { BadRequestException, Injectable, Logger } from '@nestjs/common';
|
|
import { EventEmitter2 } from '@nestjs/event-emitter';
|
|
import { Transactional } from 'typeorm-transactional';
|
|
import { Roles } from '~/auth/enums';
|
|
import { NOTIFICATION_EVENTS } from '~/common/modules/notification/constants/event-names.constant';
|
|
import {
|
|
IMoneyRequestApprovedEvent,
|
|
IMoneyRequestCreatedEvent,
|
|
IMoneyRequestDeclinedEvent,
|
|
} from '~/common/modules/notification/interfaces/notification-events.interface';
|
|
import { OciService } from '~/document/services';
|
|
import { Junior } from '~/junior/entities/junior.entity';
|
|
import { JuniorService } from '~/junior/services';
|
|
import { CreateMoneyRequestDto, MoneyRequestsFiltersRequestDto, RejectionMoneyRequestDto } from '../dtos/request';
|
|
import { MoneyRequest } from '../entities/money-request.entity';
|
|
import { MoneyRequestStatus } from '../enums';
|
|
import { MoneyRequestsRepository } from '../repositories';
|
|
|
|
@Injectable()
|
|
export class MoneyRequestsService {
|
|
private readonly logger = new Logger(MoneyRequestsService.name);
|
|
constructor(
|
|
private readonly moneyRequestsRepository: MoneyRequestsRepository,
|
|
private readonly juniorService: JuniorService,
|
|
private readonly ociService: OciService,
|
|
private readonly eventEmitter: EventEmitter2,
|
|
) {}
|
|
async createMoneyRequest(juniorId: string, body: CreateMoneyRequestDto) {
|
|
const junior = await this.juniorService.findJuniorById(juniorId);
|
|
const moneyRequest = await this.moneyRequestsRepository.createMoneyRequest(junior.id, junior.guardianId, body);
|
|
const moneyRequestWithRelations = await this.moneyRequestsRepository.findByIdWithAllRelations(moneyRequest.id);
|
|
|
|
const event: IMoneyRequestCreatedEvent = {
|
|
moneyRequest: moneyRequestWithRelations!,
|
|
timestamp: new Date(),
|
|
};
|
|
this.eventEmitter.emit(NOTIFICATION_EVENTS.MONEY_REQUEST_CREATED, event);
|
|
|
|
return this.findById(moneyRequest.id);
|
|
}
|
|
|
|
async findById(id: string, userId?: string, role?: Roles): Promise<MoneyRequest> {
|
|
const moneyRequest = await this.moneyRequestsRepository.findById(id, userId, role);
|
|
if (!moneyRequest) {
|
|
throw new BadRequestException('MONEY_REQUEST.NOT_FOUND');
|
|
}
|
|
await this.prepareJuniorImages([moneyRequest.junior]);
|
|
return moneyRequest;
|
|
}
|
|
|
|
async findMoneyRequests(
|
|
userId: string,
|
|
role: Roles,
|
|
filters: MoneyRequestsFiltersRequestDto,
|
|
): Promise<[MoneyRequest[], number]> {
|
|
const [moneyRequests, count] = await this.moneyRequestsRepository.findAll(userId, role, filters);
|
|
const juniors = moneyRequests.map((moneyRequest) => moneyRequest.junior);
|
|
await this.prepareJuniorImages(juniors);
|
|
return [moneyRequests, count];
|
|
}
|
|
|
|
@Transactional()
|
|
async approveMoneyRequest(id: string, guardianId: string): Promise<void> {
|
|
const moneyRequest = await this.moneyRequestsRepository.findById(id, guardianId, Roles.GUARDIAN);
|
|
|
|
if (!moneyRequest) {
|
|
throw new BadRequestException('MONEY_REQUEST.NOT_FOUND');
|
|
}
|
|
|
|
if (moneyRequest.status == MoneyRequestStatus.APPROVED) {
|
|
throw new BadRequestException('MONEY_REQUEST.ALREADY_APPROVED');
|
|
}
|
|
|
|
await Promise.all([
|
|
this.moneyRequestsRepository.approveMoneyRequest(id),
|
|
this.juniorService.transferToJunior(
|
|
moneyRequest.juniorId,
|
|
{ amount: moneyRequest.amount },
|
|
moneyRequest.guardianId,
|
|
),
|
|
]);
|
|
|
|
const updatedMoneyRequest = await this.moneyRequestsRepository.findByIdWithAllRelations(id, guardianId, Roles.GUARDIAN);
|
|
const event: IMoneyRequestApprovedEvent = {
|
|
moneyRequest: updatedMoneyRequest!,
|
|
timestamp: new Date(),
|
|
};
|
|
this.eventEmitter.emit(NOTIFICATION_EVENTS.MONEY_REQUEST_APPROVED, event);
|
|
}
|
|
|
|
async rejectMoneyRequest(
|
|
id: string,
|
|
guardianId: string,
|
|
rejectionReasondto: RejectionMoneyRequestDto,
|
|
): Promise<void> {
|
|
const moneyRequest = await this.moneyRequestsRepository.findById(id, guardianId, Roles.GUARDIAN);
|
|
|
|
if (!moneyRequest) {
|
|
throw new BadRequestException('MONEY_REQUEST.NOT_FOUND');
|
|
}
|
|
|
|
if (moneyRequest.status == MoneyRequestStatus.APPROVED) {
|
|
throw new BadRequestException('MONEY_REQUEST.ALREADY_APPROVED');
|
|
}
|
|
|
|
if (moneyRequest.status == MoneyRequestStatus.REJECTED) {
|
|
throw new BadRequestException('MONEY_REQUEST.ALREADY_REJECTED');
|
|
}
|
|
|
|
await this.moneyRequestsRepository.rejectMoneyRequest(id, rejectionReasondto?.rejectionReason);
|
|
|
|
const updatedMoneyRequest = await this.moneyRequestsRepository.findByIdWithAllRelations(id, guardianId, Roles.GUARDIAN);
|
|
const event: IMoneyRequestDeclinedEvent = {
|
|
moneyRequest: updatedMoneyRequest!,
|
|
rejectionReason: rejectionReasondto?.rejectionReason,
|
|
timestamp: new Date(),
|
|
};
|
|
this.eventEmitter.emit(NOTIFICATION_EVENTS.MONEY_REQUEST_DECLINED, event);
|
|
}
|
|
|
|
private async prepareJuniorImages(juniors: Junior[]) {
|
|
this.logger.log(`Preparing junior images`);
|
|
await Promise.all(
|
|
juniors.map(async (junior) => {
|
|
const profilePicture = junior.customer.user.profilePicture;
|
|
|
|
if (profilePicture) {
|
|
profilePicture.url = await this.ociService.generatePreSignedUrl(profilePicture);
|
|
}
|
|
}),
|
|
);
|
|
}
|
|
}
|