import { Injectable, NotFoundException } from '@nestjs/common'; import { scopedDirections } from '../user-trade-access/trade-scope.util'; import { ReportQueryDto } from './dto/report-query.dto'; import { REPORT_QUERIES, ReportFilters, ReportResult } from './report-queries'; import { ReportsRepository } from './reports.repository'; import type { Freight } from '@edr/types'; const DAY_MS = 24 * 60 * 60 * 1000; const list = (csv?: string): string[] | null => { const items = csv?.split(',').map((s) => s.trim()).filter(Boolean) ?? []; return items.length ? items : null; }; @Injectable() export class ReportsService { constructor(private readonly repository: ReportsRepository) {} run( key: string, dto: ReportQueryDto, allowedDirections: Freight.ScheduleTradeDirection[] | null, ): Promise { if (!(key in REPORT_QUERIES)) { throw new NotFoundException(`Unknown report: ${key}`); } // No default range: absent dates mean all time, so exports cover everything. const to = dto.dateTo ? new Date(dto.dateTo) : null; const from = dto.dateFrom ? new Date(dto.dateFrom) : null; const filters: ReportFilters = { dateFrom: from ? from.toISOString() : null, // dateTo is inclusive in the API; queries treat the bound as exclusive. dateTo: to ? new Date(to.getTime() + DAY_MS).toISOString() : null, granularity: dto.granularity ?? 'day', companyIds: list(dto.companyIds), routeIds: list(dto.routeIds), yardIds: list(dto.yardIds), cargoTypeIds: list(dto.cargoTypeIds), statuses: list(dto.statuses), directions: scopedDirections(allowedDirections, dto.direction), freightType: dto.freightType ?? null, }; return this.repository.run(key, filters); } }