diff --git a/backend/src/modules/dashboard/dashboard.controller.ts b/backend/src/modules/dashboard/dashboard.controller.ts new file mode 100644 index 0000000..ede0d5f --- /dev/null +++ b/backend/src/modules/dashboard/dashboard.controller.ts @@ -0,0 +1,15 @@ +import { Controller, Get, UseGuards } from '@nestjs/common'; +import { DashboardService } from './dashboard.service'; +import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard'; +import { CurrentUser } from '../../common/decorators/current-user.decorator'; + +@Controller('dashboard') +@UseGuards(JwtAuthGuard) +export class DashboardController { + constructor(private dashboardService: DashboardService) {} + + @Get('stats') + async getStats(@CurrentUser() user: any) { + return this.dashboardService.getStats(user.tenantId); + } +} diff --git a/backend/src/modules/dashboard/dashboard.service.ts b/backend/src/modules/dashboard/dashboard.service.ts new file mode 100644 index 0000000..76c1a6a --- /dev/null +++ b/backend/src/modules/dashboard/dashboard.service.ts @@ -0,0 +1,69 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository, Between } from 'typeorm'; +import { Invoice, InvoiceStatus } from '../invoices/entities/invoice.entity'; +import { Company } from '../companies/entities/company.entity'; + +@Injectable() +export class DashboardService { + constructor( + @InjectRepository(Invoice) + private invoiceRepository: Repository, + @InjectRepository(Company) + private companyRepository: Repository, + ) {} + + async getStats(tenantId: string) { + const totalInvoices = await this.invoiceRepository.count({ + where: { tenant_id: tenantId }, + }); + + const approvedInvoices = await this.invoiceRepository.count({ + where: { tenant_id: tenantId, status: InvoiceStatus.APPROVED }, + }); + + const pendingInvoices = await this.invoiceRepository.count({ + where: { + tenant_id: tenantId, + status: InvoiceStatus.EXTRACTING // or any non-final state + }, + }); + + const companiesCount = await this.companyRepository.count({ + where: { tenant_id: tenantId }, + }); + + // Calculate total tax (mock logic for now, should sum up tax fields) + const invoices = await this.invoiceRepository.find({ + where: { tenant_id: tenantId, status: InvoiceStatus.APPROVED }, + select: ['total_tax'], + }); + + const totalTax = invoices.reduce((sum, inv) => sum + Number(inv.total_tax || 0), 0); + + // Get recent activities (last 5 invoices) + const recentInvoices = await this.invoiceRepository.find({ + where: { tenant_id: tenantId }, + order: { created_at: 'DESC' }, + take: 5, + relations: ['company'], + }); + + return { + stats: { + totalInvoices, + approvedInvoices, + pendingInvoices, + companiesCount, + totalTax, + }, + recentActivities: recentInvoices.map(inv => ({ + id: inv.id, + number: inv.invoice_number || 'قيد الاستخراج...', + company: inv.company?.name, + status: inv.status, + date: inv.created_at, + })), + }; + } +}