14.1 Del enunciado a los datos
Antes de programar una fórmula conviene transformar el enunciado en una estructura explícita. Si guardamos importes, períodos y conceptos en variables sueltas, resulta fácil perder la relación entre ellos.
Los objetos agrupan propiedades de una misma entidad; los arreglos mantienen colecciones ordenadas. Juntos permiten representar una operación completa.
14.2 Un objeto para la operación
Las propiedades generales pueden reunirse en un objeto:
const operacion = {
id: "op-001",
nombre: "Proyecto de ejemplo",
perspectiva: "inversor",
unidadTiempo: "meses",
flujos: []
};
console.log("Operación:", operacion.nombre);
console.log("Perspectiva:", operacion.perspectiva);
console.log("Unidad:", operacion.unidadTiempo);
console.log("Cantidad de flujos:", operacion.flujos.length);Los nombres indican qué representa cada valor. Esto es más claro que depender de la posición de datos sin etiqueta.
14.3 Un arreglo para los movimientos
Una operación puede contener una cantidad variable de flujos. Los almacenamos dentro de un arreglo:
const operacion = { nombre: "Proyecto de ejemplo", flujos: [] };
operacion.flujos = [
{ periodo: 0, importe: -100000, concepto: "aporte inicial" },
{ periodo: 1, importe: 30000, concepto: "cobro" },
{ periodo: 2, importe: 80000, concepto: "cobro final" }
];
console.log("Cantidad de flujos:", operacion.flujos.length);
operacion.flujos.forEach(flujo => {
console.log(`t=${flujo.periodo}: ${flujo.concepto}, importe=${flujo.importe}`);
});Cada elemento tiene la misma forma, por lo que puede validarse y procesarse de manera uniforme.
14.4 Elegir propiedades y tipos
| Propiedad | Tipo | Regla |
|---|---|---|
id | texto | Identificador estable y no vacío |
nombre | texto | Descripción legible |
perspectiva | texto | Punto de vista declarado |
unidadTiempo | texto | Una unidad admitida |
flujos | arreglo | Contiene objetos de movimiento |
periodo | número entero | Mayor o igual que cero |
importe | número | Positivo, negativo o cero |
concepto | texto | No vacío |
14.5 Identidad y posición son diferentes
El índice de un elemento puede cambiar al ordenar o eliminar movimientos. Por eso no conviene utilizarlo como identidad permanente.
El índice dice dónde está ahora; el identificador dice qué registro es.
Un identificador estable permite actualizar el movimiento correcto incluso después de reorganizar el arreglo.
14.6 Mantener la perspectiva y la unidad
La perspectiva y la unidad temporal pertenecen a la operación completa cuando todos los flujos comparten esos criterios. Guardarlas una sola vez evita repetir texto y reduce contradicciones.
Si algunos movimientos usan fechas y otros períodos, conviene normalizarlos antes de aplicar algoritmos. Mezclar unidades sin una regla explícita debilita el modelo.
14.7 Los signos se conservan en los importes
El objeto no necesita una propiedad separada que diga “ingreso” o “egreso” si esa clasificación puede derivarse del signo:
function tipoDeFlujo(importe) {
if (importe > 0) return "ingreso";
if (importe < 0) return "egreso";
return "sin movimiento";
}
console.log("5000:", tipoDeFlujo(5000));
console.log("-5000:", tipoDeFlujo(-5000));
console.log("0:", tipoDeFlujo(0));Evitar datos duplicados impide situaciones inconsistentes como { importe: -5000, tipo: "ingreso" }.
14.8 Validar antes de calcular
Una validación básica comprueba estructura, tipos y límites:
function flujoValido(flujo) {
return Number.isInteger(flujo.periodo) &&
flujo.periodo >= 0 &&
Number.isFinite(flujo.importe) &&
typeof flujo.concepto === "string" &&
flujo.concepto.trim() !== "";
}
const flujoCorrecto = { periodo: 2, importe: 75000, concepto: "cobro" };
const flujoIncorrecto = { periodo: -1, importe: Infinity, concepto: "" };
console.log("Flujo correcto:", flujoValido(flujoCorrecto));
console.log("Flujo incorrecto:", flujoValido(flujoIncorrecto));Number.isFinite rechaza valores como NaN e Infinity, que no deben ingresar a un cálculo monetario.
14.9 Transformar sin perder los datos originales
Métodos como map y filter producen nuevos arreglos. Esto permite preparar vistas sin modificar la fuente:
const operacion = {
flujos: [
{ periodo: 0, importe: -100000, concepto: "aporte inicial" },
{ periodo: 1, importe: 30000, concepto: "cobro" },
{ periodo: 2, importe: 80000, concepto: "cobro final" }
]
};
const ingresos = operacion.flujos
.filter(flujo => flujo.importe > 0);
const etiquetas = operacion.flujos
.map(flujo => `t=${flujo.periodo}: ${flujo.concepto}`);
console.log("Cantidad de ingresos:", ingresos.length);
etiquetas.forEach(etiqueta => console.log(etiqueta));Mantener separadas la información original y sus presentaciones facilita comprobar resultados.
14.10 Ordenar por período
sort modifica el arreglo sobre el que actúa. Para conservar el orden recibido, primero creamos una copia:
const operacion = {
flujos: [
{ periodo: 5, importe: 150000, concepto: "cobro final" },
{ periodo: 0, importe: -200000, concepto: "compra" },
{ periodo: 2, importe: 75000, concepto: "cobro parcial" }
]
};
const ordenados = [...operacion.flujos]
.sort((a, b) => a.periodo - b.periodo);
console.log("Orden original:", operacion.flujos.map(f => f.periodo).join(", "));
console.log("Copia ordenada:", ordenados.map(f => f.periodo).join(", "));Dos movimientos pueden compartir período. Si el orden entre ellos importa, necesitamos además un criterio secundario estable.
14.11 Agrupar movimientos del mismo período
Puede haber varios cobros y pagos en un mismo momento. Antes de combinarlos debemos decidir si necesitamos conservar el detalle.
Mantiene cada concepto como registro independiente.
Suma importes del mismo período para obtener un flujo neto.
Conserva el origen y genera una agrupación derivada.
La tercera opción suele ser la más segura: no destruye información y permite mostrar resúmenes.
14.12 Convertir a JSON
JSON es un formato textual útil para guardar o intercambiar datos compatibles. JSON.stringify convierte el objeto en texto:
const operacion = {
id: "op-001",
nombre: "Proyecto de ejemplo",
unidadTiempo: "meses",
flujos: [{ periodo: 0, importe: -100000, concepto: "aporte" }]
};
const texto = JSON.stringify(operacion, null, 2);
const copia = JSON.parse(texto);
console.log(texto);
console.log("Nombre recuperado:", copia.nombre);
console.log("Es una copia diferente:", copia !== operacion);JSON no conserva funciones, comentarios ni objetos Date como fechas especiales. Una fecha se guarda normalmente como texto y debe validarse al recuperarla.
JSON válido no significa operación válida: el formato puede ser correcto aunque falten propiedades o existan importes incoherentes.
14.13 Constructor de operaciones
Editá los datos generales y los movimientos. La herramienta valida, ordena por período y genera el objeto JSON resultante. Podés agregar hasta ocho flujos.
Objeto financiero estructurado
Modelo de datos sin fórmulas de interés.
Movimientos
| Período | Importe con signo | Concepto | Acción |
|---|
JSON generado
La estructura es válida y está ordenada por período.
14.14 Ejercicio propuesto
Modelá una operación llamada “Plan de equipamiento”, vista desde la perspectiva de una empresa y medida en meses. Contiene estos movimientos: −$200.000 en t = 0, +$75.000 en t = 2 y +$150.000 en t = 5.
- Creá el objeto con sus propiedades generales.
- Agregá un identificador a cada flujo.
- Validá período, importe y concepto.
- Obtené una copia ordenada por período.
- Convertí el resultado a JSON.
Ver solución y código
function flujoValido(flujo) {
return Number.isInteger(flujo.periodo) &&
flujo.periodo >= 0 &&
Number.isFinite(flujo.importe) &&
typeof flujo.concepto === "string" &&
flujo.concepto.trim() !== "";
}
const operacion = {
id: "op-equipamiento",
nombre: "Plan de equipamiento",
perspectiva: "empresa",
unidadTiempo: "meses",
flujos: [
{ id: "f-1", periodo: 0, importe: -200000, concepto: "compra" },
{ id: "f-2", periodo: 2, importe: 75000, concepto: "cobro parcial" },
{ id: "f-3", periodo: 5, importe: 150000, concepto: "cobro final" }
]
};
const esValida = operacion.flujos.every(flujoValido);
const json = JSON.stringify(operacion, null, 2);
console.log("Operación válida:", esValida);
console.log(json);La suma nominal es $25.000, pero no se interpreta como rentabilidad porque los movimientos están ubicados en fechas diferentes.
14.15 Ideas para recordar
- Un objeto agrupa propiedades de una operación.
- Un arreglo representa una colección variable y ordenable de movimientos.
- Los nombres de propiedades deben expresar su significado y unidad.
- Los identificadores no deben depender de la posición del arreglo.
- La validación ocurre antes del cálculo.
- Ordenar una copia evita modificar accidentalmente los datos originales.
- JSON conserva datos, pero no garantiza que sean correctos.
En el próximo tema comenzaremos el módulo de modelos estudiando el interés como precio por usar dinero.