invoice event

This commit is contained in:
2026-02-22 14:44:04 +03:30
parent eee5de8d00
commit cc8f96a99b
6 changed files with 104 additions and 6 deletions
@@ -0,0 +1,19 @@
export class InvoiceCreatedEvent {
constructor(
public readonly invoiceId: string,
public readonly invoiceNumber: string,
public readonly total: number,
public readonly userId: string,
) {}
}
// export class OrderStatusChangedEvent {
// constructor(
// public readonly orderId: string,
// public readonly userId: string,
// public readonly orderNumber: string,
// public readonly: string,
// public readonly previousStatus: OrderStatusEnum,
// public readonly newStatus: OrderStatusEnum,
// ) { }
// }
+6 -3
View File
@@ -6,9 +6,11 @@ import { Invoice } from './entities/invoice.entity';
import { InvoiceItem } from './entities/invoice-item.entity';
import { ProductModule } from '../product/product.module';
import { InvoiceRepository } from './repositories/invoice.repository';
import { InvoiceListeners } from './listeners/invoice.listeners';
import { JwtModule } from '@nestjs/jwt';
import { RolesModule } from '../roles/roles.module';
import { AuthModule } from '../auth/auth.module';
import { NotificationsModule } from '../notification/notifications.module';
@Module({
imports: [
@@ -16,10 +18,11 @@ import { AuthModule } from '../auth/auth.module';
ProductModule,
RolesModule,
JwtModule,
AuthModule
AuthModule,
NotificationsModule,
],
controllers: [InvoiceController],
providers: [InvoiceService, InvoiceRepository],
providers: [InvoiceService, InvoiceRepository, InvoiceListeners],
exports: [InvoiceService, InvoiceRepository],
})
export class InvoiceModule { }
export class InvoiceModule {}
+17 -2
View File
@@ -1,5 +1,6 @@
import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common';
import { EntityManager } from '@mikro-orm/postgresql';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { CreateInvoiceDto } from './dto/create-invoice.dto';
import { UpdateInvoiceDto } from './dto/update-invoice.dto';
import { FindInvoicesDto } from './dto/find-invoices.dto';
@@ -9,6 +10,7 @@ import { Request } from '../request/entities/request.entity';
import { User } from '../user/entities/user.entity';
import { ProductService } from '../product/providers/product.service';
import { InvoiceRepository } from './repositories/invoice.repository';
import { InvoiceCreatedEvent } from './events/invoice.events';
const TAX_RATE = 0.1;
@@ -18,7 +20,8 @@ export class InvoiceService {
private readonly em: EntityManager,
private readonly productService: ProductService,
private readonly invoiceRepository: InvoiceRepository,
) { }
private readonly eventEmitter: EventEmitter2,
) {}
async create(dto: CreateInvoiceDto) {
@@ -49,7 +52,7 @@ export class InvoiceService {
const discount = dto.items.reduce((acc, item) => acc + (item.discount ?? 0), 0);
return this.em.transactional(async (em) => {
const invoice = await this.em.transactional(async (em) => {
const invoice = em.create(Invoice, {
user,
...(request && { request }),
@@ -98,6 +101,18 @@ export class InvoiceService {
await em.flush();
return invoice;
});
this.eventEmitter.emit(
InvoiceCreatedEvent.name,
new InvoiceCreatedEvent(
invoice.id,
String(invoice.invoiceNumber),
invoice.total!,
user.id,
),
);
return invoice;
}
findAll(userId: string, dto: FindInvoicesDto) {
@@ -0,0 +1,44 @@
import { Injectable, Logger } from '@nestjs/common';
import { OnEvent } from '@nestjs/event-emitter';
import { ConfigService } from '@nestjs/config';
import { NotificationQueueService } from 'src/modules/notification/services/notification-queue.service';
import { InvoiceCreatedEvent } from '../events/invoice.events';
@Injectable()
export class InvoiceListeners {
private readonly logger = new Logger(InvoiceListeners.name);
private invoiceCreatedSmsTemplateId: string;
constructor(
private readonly notificationQueueService: NotificationQueueService,
private readonly configService: ConfigService,
) {
this.invoiceCreatedSmsTemplateId =
this.configService.get<string>('SMS_PATTERN_INVOICE_CREATED') ?? 'invoice-created';
}
@OnEvent(InvoiceCreatedEvent.name)
async handleInvoiceCreated(event: InvoiceCreatedEvent) {
try {
this.logger.log(
`Invoice created event received: ${event.invoiceId} for user: ${event.userId}, invoice number: ${event.invoiceNumber}`,
);
await this.notificationQueueService.addSmsNotification({
recipient: { userId: event.userId },
templateId: this.invoiceCreatedSmsTemplateId,
parameters: {
invoiceNumber: event.invoiceNumber,
total: event.total.toString(),
},
});
this.logger.log(`Invoice created notification queued for user ${event.userId}`);
} catch (error) {
this.logger.error(
`Failed to send notification for invoice created event: ${event.invoiceId}`,
error instanceof Error ? error.stack : String(error),
);
}
}
}
@@ -64,6 +64,15 @@ export class LearningController {
// ----------------- Admin routes -----------------
@Get('admin/learnings')
@UseGuards(AdminAuthGuard)
@Permissions(PermissionEnum.MANAGE_LEARNINGS)
@ApiOperation({ summary: 'Find all learnings videos as admin' })
findAllLearningsAsAdmin() {
return this.learningService.findLearningsVideos();
}
@Post('admin/learnings')
@UseGuards(AdminAuthGuard)
@Permissions(PermissionEnum.MANAGE_LEARNINGS)
@@ -96,6 +105,14 @@ export class LearningController {
return this.learningService.createLearningCategory(createDto);
}
@Get('admin/learnings/category')
@UseGuards(AdminAuthGuard)
@Permissions(PermissionEnum.MANAGE_LEARNINGS)
@ApiOperation({ summary: 'Get all learning categories' })
getCategories() {
return this.learningService.findCategories()
}
@Patch('admin/learnings/category/:id')
@UseGuards(AdminAuthGuard)
@Permissions(PermissionEnum.MANAGE_LEARNINGS)
@@ -60,7 +60,7 @@ export class LearningService {
}
async findLearningsVideos() {
const learnings = await this.learningRepository.findAll();
const learnings = await this.learningRepository.findAll({populate: ['category']});
return { learnings };
}