Como operador de sala de armas / pañol, quiero registrar la entrega de un equipo a un agente validando su aptitud en tiempo real, para garantizar que solo se entreguen recursos habilitados y mantener la cadena de custodia intacta.
Recorrido paso a paso de cómo transformo un problema operativo real en un software funcionando: desde el análisis inicial y la organización de tareas, hasta la base de datos y la demo en vivo.
Planillas en papel y Excel desactualizadas, demoras de 45 min por turno y falta de control sobre equipos prestados.
Sistema web centralizado que registra entregas y devoluciones en segundos, evitando préstamos duplicados.
Node.js, PostgreSQL, interfaz web rápida y pruebas automatizadas de calidad (QA).
Trabajo ordenado por etapas (Kanban), entregas parciales revisables y comunicación constante.
Antes de escribir una sola línea de código, se realizó una auditoría minuciosa del flujo de trabajo existente para identificar cuellos de botella operativos, riesgos de duplicidad y requisitos de negocio prioritarios.
Estructuración del backlog en sprints cortos con límites de trabajo en curso (WIP Limits). Prueba arrastrar las tarjetas entre columnas o filtrarlas por disciplina técnica para observar la distribución del esfuerzo.
Diseño relacional en Tercera Forma Normal (3FN). Haz clic o pasa el cursor sobre las entidades para inspeccionar sus claves foráneas, índices de integridad y relaciones 1:N.
Se utiliza SELECT ... FOR UPDATE durante la creación del préstamo. Esto garantiza a nivel de motor SQL que ninguna otra transacción concurrentemente intente operar sobre el mismo equipo, eliminando condiciones de carrera.
Se implementó una restricción física: CREATE UNIQUE INDEX idx_equipo_activo ON prestamos (equipo_id) WHERE estado = 'ACTIVO';. Aunque la capa de aplicación fallara, la base de datos rechaza cualquier duplicidad por constraint.
La tabla prestamos opera bajo principio de solo adición (append-only) para auditorías forenses. Los datos de fecha, custodio y recepción se sellan de manera inalterable para peritajes legales.
Código tipado, separación estricta de responsabilidades (Service / Repository pattern) y pruebas automatizadas que verifican los casos de borde críticos antes de llegar a producción.
import { PoolClient } from 'pg';
import { EquipmentAlreadyLoanedException, UserBlockedException } from '../exceptions';
export class LoanService {
constructor(private readonly dbPool: any) {}
/**
* Registra un préstamo asegurando atomicidad y prevención de race conditions.
*/
async registrarPrestamo(equipoId: string, usuarioId: string, operadorId: string): Promise<PrestamoResult> {
const client: PoolClient = await this.dbPool.connect();
try {
await client.query('BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED');
// 1. Bloqueo pesimista sobre la fila del equipo: previene carreras concurrentes
const equipRes = await client.query(
'SELECT id, estado, modelo FROM equipos WHERE id = $1 FOR UPDATE',
[equipoId]
);
if (equipRes.rows.length === 0) {
throw new Error('El equipo especificado no existe en inventario');
}
const equipo = equipRes.rows[0];
if (equipo.estado !== 'DISPONIBLE') {
throw new EquipmentAlreadyLoanedException(
`El equipo ${equipo.modelo} no está disponible (Estado actual: ${equipo.estado})`
);
}
// 2. Validar que el usuario solicitante esté activo
const userRes = await client.query(
'SELECT id, activo FROM usuarios WHERE id = $1',
[usuarioId]
);
if (!userRes.rows[0]?.activo) {
throw new UserBlockedException('El agente solicitante se encuentra inhabilitado');
}
// 3. Insertar el préstamo y mutar el estado del equipo de forma atómica
const insertLoanQuery = `
INSERT INTO prestamos (equipo_id, usuario_id, operador_id, estado, fecha_prestamo)
VALUES ($1, $2, $3, 'ACTIVO', NOW())
RETURNING id, fecha_prestamo;
`;
const loanRes = await client.query(insertLoanQuery, [equipoId, usuarioId, operadorId]);
await client.query(
'UPDATE equipos SET estado = \'PRESTADO\' WHERE id = $1',
[equipoId]
);
await client.query('COMMIT');
return {
prestamoId: loanRes.rows[0].id,
fechaPrestamo: loanRes.rows[0].fecha_prestamo,
exitoso: true
};
} catch (error) {
await client.query('ROLLBACK');
throw error;
} finally {
client.release();
}
}
}
Simulador interactivo del panel de guardia. Puedes buscar equipos, filtrar por estado y accionar préstamos o devoluciones en tiempo real para verificar la reactividad del estado y la bitácora de eventos.
| Código | Modelo & Categoría | Estado Actual | Custodio Asignado | Acción Operativa |
|---|
Combino metodologías ágiles rigurosas, diseño de bases de datos resilientes y desarrollo de software limpio para transformar procesos críticos en ventajas competitivas estables.