import { Injectable } from '@nestjs/common'; import { EntityManager, EntityRepository } from '@mikro-orm/postgresql'; import { FilterQuery } from '@mikro-orm/core'; import { Invoice } from '../entities/invoice.entity'; import { PaginatedResult } from 'src/common/interfaces/pagination.interface'; import { FindInvoicesDto } from '../dto/find-invoices.dto'; interface FindInvoicesOpts extends FindInvoicesDto { userId?: string; } @Injectable() export class InvoiceRepository extends EntityRepository { constructor(readonly em: EntityManager) { super(em, Invoice); } async findAllPaginated(opts: FindInvoicesOpts): Promise> { const { page = 1, limit = 10, search, orderBy = 'createdAt', order = 'desc', userId, from, to, enableTax, requestId, confirmStatus, } = opts; const offset = (page - 1) * limit; const where: FilterQuery = {}; if (userId) { where.user = { id: userId }; } if (requestId) { where.request = { id: requestId }; } if (typeof enableTax === 'boolean') { where.enableTax = enableTax; } if (confirmStatus) { where.confirmStatus = confirmStatus; } if (from || to) { where.createdAt = {}; if (from) { where.createdAt.$gte = new Date(from); } if (to) { where.createdAt.$lte = new Date(to); } } if (search) { const searchPattern = `%${search}%`; const searchConditions: FilterQuery[] = [ { user: { firstName: { $ilike: searchPattern } } } as FilterQuery, { user: { lastName: { $ilike: searchPattern } } } as FilterQuery, { user: { phone: { $ilike: searchPattern } } } as FilterQuery, ]; const numericSearch = Number(search); if (!isNaN(numericSearch) && isFinite(numericSearch)) { searchConditions.push({ invoiceNumber: numericSearch } as FilterQuery); } where.$or = searchConditions; } const [data, total] = await this.findAndCount(where, { limit, offset, orderBy: { [orderBy]: order.toLowerCase() as 'asc' | 'desc' }, populate: ['user', 'request', 'items', 'items.product'], }); const totalPages = Math.ceil(total / limit); return { data, meta: { total, page, limit, totalPages, }, }; } }