Depósitos CPS

El stock de toda la empresa en un solo lugar: qué hay, dónde está y a qué obra se fue.

RolDesarrollador full-stack único: modelo de datos, núcleo SQL, backend, frontend y deployClienteGrupo CPS, construcción y aberturas de aluminioAño2026
Hablemos del proyectoEl código es privado por tratarse de una herramienta interna de la empresa.
Next.jsTypeScriptTailwind 4shadcn/uiSupabasePostgreSQLRLSCoolify
100% trazable

El stock nunca se corrige "a dedo": cada cambio nace de un comprobante numerado, con usuario y fecha. El número que ves es la suma de su historia. Y el stock negativo es imposible por diseño, incluso con operaciones simultáneas.

Sistema interno de Grupo CPS para gestionar materiales y herramientas entre depósitos y obras: pedidos y órdenes de compra, transferencias, vales de consumo con rendición, reparaciones y ajustes. Cada operación queda asentada en un kardex inmutable con costeo por precio promedio ponderado, y el equipo ve stock valorizado, alertas y reportes en vivo.

Grupo CPS mueve materiales y herramientas entre varios depósitos y obras en simultáneo. Ese movimiento se seguía con planillas, mensajes y memoria: saber cuánto había de un artículo y dónde estaba implicaba llamar, contar y confiar.

Las consecuencias eran siempre las mismas: faltantes que aparecían con la obra arrancada, material "en viaje" que no figuraba en ningún lado, compras de apuro sin registro, y ningún número confiable de cuánto capital había inmovilizado en stock ni cuánto había consumido cada obra.

Y había un problema más fino: las herramientas. Una amoladora no es "3 amoladoras": es esta amoladora, con su número de serie, que está en tal obra, volvió rota o se perdió. Y alguien tiene que responder por ella.

El stock no se edita: se registra. Todo lo demás se deriva de ahí.

La decisión que ordena todo el sistema: nadie escribe "quedan 40 bolsas". Se registra el movimiento que lo explica (una compra recibida, una transferencia, un vale de consumo, un ajuste) como asiento de un kardex inmutable: los movimientos solo se insertan, y corregir es generar el contra-asiento, nunca borrar.

El saldo por depósito lo mantiene la propia base de datos, con una restricción que hace imposible el stock negativo incluso con operaciones concurrentes. Y lo que está viajando o en el service también es stock: los depósitos virtuales "En tránsito" y "Reparación" garantizan que la suma de todos los saldos siempre iguale el stock real de la empresa.

Sobre esa base, el costeo usa precio promedio ponderado congelado en cada movimiento: las transferencias no alteran el promedio y las devoluciones reingresan al costo del vale original. Por eso el "stock valorizado" del dashboard es un número defendible, no una estimación.

Todo el circuito del material, del pedido a la obra.

  1. 01

    Pedidos y órdenes de compra

    Cualquier usuario, también los jefes de obra, pide lo que necesita con destino y fecha límite. Logística arma las órdenes, que pueden mezclar proveedores por renglón y alimentan un histórico de precios por artículo y proveedor.

  2. 02

    Recepciones parciales

    Las compras y transferencias se reciben de a tandas. Cerrar con faltantes es una decisión explícita, con motivo: recién ahí se da de baja lo que no llegó.

  3. 03

    Transferencias "en viaje"

    El material que va de un depósito a otro pasa por un estado intermedio real: mientras viaja no está en ninguno de los dos, está en tránsito, con camión y personas asignadas al traslado.

  4. 04

    Vales de consumo con rendición

    Lo que sale a obra se rinde: lo usado se imputa al gasto de la obra y lo que vuelve reingresa al stock al costo congelado del vale.

  5. 05

    Herramientas por número de serie

    Cada unidad física tiene su ciclo de vida: disponible → en obra → en reparación → rota o perdida. Se rinden por unidad, y las rotas o perdidas se imputan a la obra que las tenía.

  6. 06

    Dashboard y alertas por usuario

    Cada usuario arma su inicio con los widgets que le sirven, y las notificaciones avisan solas: pedidos vencidos o por vencer, transferencias demoradas y stock bajo mínimo.

El sistema también resuelve lo aburrido pero crítico: kardex por depósito u obra en cualquier período, consulta de un artículo en todos los depósitos a la vez, compras en pesos o dólares con su moneda registrada, y órdenes de compra en PDF con lugar para firmas, porque el circuito físico con el proveedor también es parte del sistema.

La lógica de negocio vive en la base de datos, no en la interfaz.

UI

Next.js + shadcn/ui

Pantallas de operación y consulta: dashboard personalizable, movimientos, kardex y catálogos.

API

Supabase self-hosted

PostgreSQL + Auth + API corriendo en el propio servidor de la empresa, no en una nube de terceros.

RPC

RPCs transaccionales

Cada operación es una función que valida rol y reglas de negocio dentro de la base, en una transacción.

LED

Kardex inmutable

Los movimientos solo se insertan; corregir es contra-asentar. Un trigger mantiene los saldos por depósito.

SEC

RLS en todas las tablas

Las tablas de movimientos no tienen políticas de escritura: la única puerta de entrada son las RPCs.

OPS

VPS + Coolify

Deploy automático en cada push, migraciones aplicadas por CI y backups diarios del servidor y de la base.

Ocultar botones en la interfaz es ergonomía; la barrera real está en PostgreSQL. Aunque alguien hablara directo con la API, no puede saltarse las reglas: cada escritura pasa por una función que valida todo del lado de la base.

Un sistema de stock es un sistema de confianza: cada número tiene que poder defenderse.

Roles con lo mínimo necesario

El rol admin opera y administra; el rol consulta (jefes de obra, dirección) lee todo pero solo escribe sus propios pedidos de compra y su dashboard. Y nadie puede auto-promoverse de rol.

Usuarios cerrados por defecto

El registro público está deshabilitado y los perfiles nacen inactivos, sin acceso a datos, hasta que un admin los activa desde la app.

Quién hizo qué, siempre

Emitir, recibir, cancelar, rendir: cada acción queda registrada con usuario y fecha, visible en todas las pantallas para todos los usuarios.

Anular no es borrar

Las anulaciones generan el asiento inverso y la historia queda completa. No existe la corrección silenciosa.

El núcleo se prueba donde vive: en SQL.

Suite de tests del núcleo SQL
1.500+ líneas · ~160 aserciones
Qué cubre
Numeración, costeo PPP, recepciones parciales, rendiciones, herramientas por serie, RLS y roles
Stock negativo
Imposible por diseño, incluso en concurrencia
Esquema versionado
19 migraciones, aplicadas automáticamente por CI

La suite corre dentro de una transacción que se revierte al final: prueba el núcleo real contra la base real, sin ensuciarla. Si la regla vive en PostgreSQL, el test también.

El sistema por dentro.

Dashboard de inicio del sistema de depósitos de Grupo CPS
El dashboard de inicio: stock valorizado, movimientos de los últimos 30 días, stock por depósito, gasto por obra y alertas de pedidos vencidos, transferencias demoradas y stock bajo mínimo.
Kardex por depósito con saldos y movimientos del período
El kardex por depósito u obra: saldos del período, cada movimiento con su comprobante y su usuario, y anulaciones como contra-asiento. Nada se borra.
Orden de compra generada en PDF lista para firmar
Orden de compra en PDF, lista para imprimir y firmar con el proveedor: el circuito físico también sale del sistema.
  • Un sistema de stock es un sistema de confianza: si la gente no le cree al número, vuelve a la planilla. La trazabilidad total es lo que sostiene esa confianza.
  • Modelar movimientos en vez de cantidades simplificó todo lo demás: kardex, auditoría, anulaciones y valorización salieron del mismo diseño.
  • Poner las reglas de negocio en la base de datos, y testearlas ahí, hace que la seguridad no dependa de qué botones muestra la interfaz.
  • El circuito físico también es software: la orden de compra en PDF con lugar para firmas importa tanto como la tabla que la genera.

¿Tu operación también vive en planillas y mensajes?

Este es el tipo de sistema que más disfruto construir. El código es interno de la empresa, pero podemos hablar del problema.