import { Injectable } from '@nestjs/common'; import { CsvRateResultDto, CsvRateSearchResponseDto, PriceBreakdownDto, FobBreakdownDto, } from '../dto/csv-rate-search.dto'; import { CsvRateSearchOutput, CsvRateSearchResult, RateSearchFilters, } from '@domain/ports/in/search-csv-rates.port'; import { RateSearchFiltersDto } from '../dto/rate-search-filters.dto'; import { CsvRateConfigDto } from '../dto/csv-rate-upload.dto'; import { CsvRateConfigOrmEntity } from '@infrastructure/persistence/typeorm/entities/csv-rate-config.orm-entity'; @Injectable() export class CsvRateMapper { mapFiltersDtoToDomain(dto?: RateSearchFiltersDto): RateSearchFilters | undefined { if (!dto) return undefined; return { companies: dto.companies, onlyDirect: dto.onlyDirect, excludeNonDgRoutes: dto.excludeNonDgRoutes, minPrice: dto.minPrice, maxPrice: dto.maxPrice, currency: dto.currency, minTransitDays: dto.minTransitDays, maxTransitDays: dto.maxTransitDays, containerTypes: dto.containerTypes, departureDate: dto.departureDate ? new Date(dto.departureDate) : undefined, }; } mapSearchResultToDto(result: CsvRateSearchResult): CsvRateResultDto { const rate = result.rate; const bd = result.priceBreakdown; const fobBreakdown: FobBreakdownDto = { documentation: bd.fobBreakdown.documentation, isps: bd.fobBreakdown.isps, handling: bd.fobBreakdown.handling, solas: bd.fobBreakdown.solas, customs: bd.fobBreakdown.customs, ams_aci: bd.fobBreakdown.ams_aci, isf5: bd.fobBreakdown.isf5, dgAdmin: bd.fobBreakdown.dgAdmin, }; const priceBreakdown: PriceBreakdownDto = { freightCharge: bd.freightCharge, freightCurrency: bd.freightCurrency, fobFixed: bd.fobFixed, fobHandling: bd.fobHandling, fobDG: bd.fobDG, fobCurrency: bd.fobCurrency, fobBreakdown, dgSurchargeAmount: bd.dgSurchargeAmount, dgSurchargeCurrency: bd.dgSurchargeCurrency, dgSurchargeStatus: bd.dgSurchargeStatus, totalFreight: bd.totalFreight, totalFob: bd.totalFob, totalPriceForSorting: bd.totalPriceForSorting, primaryCurrency: bd.primaryCurrency, }; return { companyName: rate.companyName, companyEmail: rate.companyEmail, originCFS: rate.originCFS, origin: rate.originCode.getValue(), portOfLoading: rate.portOfLoading, routing: rate.routing, destinationCFS: rate.destinationCFS, destination: rate.destinationCode.getValue(), destinationCountry: rate.destinationCountry, containerType: rate.containerType.getValue(), priceBreakdown, frequency: rate.frequency, transitDays: result.adjustedTransitDays ?? rate.transitDays, validUntil: rate.validity.getEndDate().toISOString().split('T')[0], dgAccepted: rate.isDgAccepted(), dgSurchargeStatus: bd.dgSurchargeStatus, remarks: rate.remarks, source: result.source, matchScore: result.matchScore, serviceLevel: result.serviceLevel, priceMultiplier: result.priceMultiplier, originalTransitDays: result.originalTransitDays, }; } mapSearchOutputToResponseDto(output: CsvRateSearchOutput): CsvRateSearchResponseDto { return { results: output.results.map(r => this.mapSearchResultToDto(r)), totalResults: output.totalResults, searchedFiles: output.searchedFiles, searchedAt: output.searchedAt, appliedFilters: output.appliedFilters as any, }; } mapConfigEntityToDto(entity: CsvRateConfigOrmEntity): CsvRateConfigDto { return { id: entity.id, companyName: entity.companyName, csvFilePath: entity.csvFilePath, type: entity.type, hasApi: entity.hasApi, apiConnector: entity.apiConnector, isActive: entity.isActive, uploadedAt: entity.uploadedAt, rowCount: entity.rowCount, metadata: entity.metadata, }; } mapConfigEntitiesToDtos(entities: CsvRateConfigOrmEntity[]): CsvRateConfigDto[] { return entities.map(e => this.mapConfigEntityToDto(e)); } }