codigo0/backend/src/infrastructure/mappers/DrugMapper.ts

107 lines
3.4 KiB
TypeScript

/**
* DrugMapper - Infrastructure Layer
* Convierte entre Domain (Drug) y Persistence (DB rows).
*/
import type { Drug, AdministrationRoute, DrugCategory } from '../../domain/entities/Drug.js';
import { ContentStatus } from '../../domain/value-objects/ContentStatus.js';
export interface DrugRow {
id: string;
slug: string;
generic_name: string;
trade_name?: string | null;
category: string;
line: string;
frequency: string;
presentation: string;
adult_dose: string;
pediatric_dose?: string | null;
routes?: string[] | null;
dilution?: string | null;
indications?: string[] | null;
contraindications?: string[] | null;
side_effects?: string | null;
antidote?: string | null;
notes?: string[] | null;
critical_points?: string[] | null;
source?: string | null;
status: string;
version: string;
latest_version: string;
created_at: Date | string;
updated_at: Date | string;
created_by: string;
updated_by?: string | null;
}
/**
* Convierte una fila de BD a entidad de dominio.
*/
export function toDomain(row: DrugRow): Drug {
const status = typeof row.status === 'string' ? ContentStatus.fromString(row.status) : ContentStatus.DRAFT;
const createdAt = row.created_at instanceof Date ? row.created_at : new Date(String(row.created_at));
const updatedAt = row.updated_at instanceof Date ? row.updated_at : new Date(String(row.updated_at));
return {
id: row.id,
slug: row.slug,
genericName: row.generic_name,
tradeName: row.trade_name ?? undefined,
category: row.category as DrugCategory,
line: row.line === 'first' || row.line === 'second' ? row.line : 'first',
frequency: row.frequency === 'high' || row.frequency === 'medium' || row.frequency === 'low' ? row.frequency : 'medium',
presentation: row.presentation,
adultDose: row.adult_dose,
pediatricDose: row.pediatric_dose ?? undefined,
routes: (row.routes ?? []) as AdministrationRoute[],
dilution: row.dilution ?? undefined,
indications: row.indications ?? [],
contraindications: row.contraindications ?? [],
sideEffects: row.side_effects ?? undefined,
antidote: row.antidote ?? undefined,
notes: row.notes ?? [],
criticalPoints: row.critical_points ?? [],
source: row.source ?? undefined,
status,
version: row.version ?? '1.0.0',
latestVersion: row.latest_version ?? row.version ?? '1.0.0',
createdAt,
updatedAt,
createdBy: row.created_by,
updatedBy: row.updated_by ?? undefined,
};
}
/**
* Convierte entidad de dominio a objeto para persistencia (snake_case).
*/
export function toPersistence(drug: Drug): Record<string, unknown> {
return {
id: drug.id,
slug: drug.slug,
generic_name: drug.genericName,
trade_name: drug.tradeName ?? null,
category: drug.category,
line: drug.line,
frequency: drug.frequency,
presentation: drug.presentation,
adult_dose: drug.adultDose,
pediatric_dose: drug.pediatricDose ?? null,
routes: [...drug.routes],
dilution: drug.dilution ?? null,
indications: [...drug.indications],
contraindications: [...drug.contraindications],
side_effects: drug.sideEffects ?? null,
antidote: drug.antidote ?? null,
notes: [...drug.notes],
critical_points: [...drug.criticalPoints],
source: drug.source ?? null,
status: drug.status.toString(),
version: drug.version,
latest_version: drug.latestVersion,
created_by: drug.createdBy,
updated_by: drug.updatedBy ?? drug.createdBy,
};
}