Saltar al contenido
Caso · 11 / 19← Todos los trabajos

Grow ERP

Un ERP para distribuidoras de alimento animal: punto de venta, factura electrónica, stock por sucursal, repartos y cuentas.

Rol
Desarrollo full-stack y mantenimiento, desde el esquema de la base hasta el servidor donde corre
Stack
Next.js 15 (App Router), React 19, TypeScript, Prisma + PostgreSQL, TanStack Table / Query, AFIP SDK, Docker Compose + Caddy, Vitest + Playwright
Punto de venta
Punto de ventaServer Actions como capa de negocio, con permiso en cada acción
(01) El problema

Una distribuidora de alimento para mascotas y animales manejaba el negocio entre planillas, cuadernos y programas sueltos. Vende en mostrador y al por mayor, desde más de una sucursal, y cada factura tiene que pasar por AFIP/ARCA. Los pedidos se aprueban, se arman en el depósito y salen en camión. El dueño no es programador, así que el sistema también tenía que poder correrlo y mantenerlo el propio negocio.

Mi rolConstruí el producto y lo mantuve andando en producción para el negocio, con cada cambio que fueron pidiendo.
(02) ResultadosContados en el código
1,535commits, con mantenimiento continuo
105modelos de datos en el esquema
93pantallas en la app
(03) Arquitectura

Tres decisiones que lo definieron.

  1. 01

    Server Actions como capa de negocio, con permiso en cada acción

    Por qué. El dominio vive en 76 archivos de acciones que las páginas llaman directo. Cada una arranca con protectAction y la lista de roles permitidos. Ocultar un ítem del menú es solo visual; escribir la URL a mano igual choca con el control. Nueve roles, del dueño al repartidor, comparten una sola app.

    El costo. No hay una API REST general. La tienda online y las subidas necesitan rutas propias con otra autenticación, y una acción nueva sin el control quedaría abierta.

  2. 02

    La deuda de cada cliente se guarda dos veces, a propósito

    Por qué. La cuenta corriente es la fuente de verdad del saldo total del cliente. Cada factura además guarda su saldo pendiente, para imputar pagos a facturas concretas y calcular la antigüedad de la deuda.

    El costo. Todo movimiento de plata tiene que escribir en los dos. Si uno se saltea, las pantallas no coinciden, así que hay un script de conciliación que los compara.

  3. 03

    Un servidor que controla el dueño, y una guía para correrlo

    Por qué. La app, Postgres y Caddy corren juntos con Docker Compose en un solo VPS. Una guía de nueve capítulos cubre la instalación, los backups, los certificados de AFIP y cómo hacer cambios con un asistente de IA. Un hook de pre-push corre tipos, lint, tests y build.

    El costo. Un solo servidor significa sin redundancia, y los backups dependen de un cron que alguien tiene que revisar.

(04) GaleríaSeguí scrolleando →
Punto de venta
Punto de venta · Venta de mostrador por código de barras o nombre, con los totales del día de la caja arriba.
Ventas y facturación
Ventas y facturación · Cada venta con su estado de pago y de factura, lista para pedir el CAE a AFIP.
Stock por sucursal
Stock por sucursal · Stock, valor y mínimos de la sucursal elegida, con ajustes y transferencias.
Plan de repartos
Plan de repartos · Las hojas de ruta del día por repartidor y vehículo. El mapa necesita una clave de Google Maps, que esta demo no tiene.
(05) Qué haría después
01Sumar foreign keys a la base. El esquema usa el relation mode de Prisma, así que borrar un registro puede dejar referencias colgadas que rompen el POS.
02Correr Playwright en CI contra una base con datos de prueba. Hoy los tests de punta a punta son smoke tests de solo lectura que necesitan una cuenta real.
03Pasar los controles del pre-push a un pipeline de CI, para que un hook salteado no pueda subir un build roto.
Próximo proyecto · 12 / 19
Tiendas →Un core de tienda y un CLI en Go que genera tiendas nuevas
Caso · 11 / 19

Grow ERP

Un ERP para distribuidoras de alimento animal: punto de venta, factura electrónica, stock por sucursal, repartos y cuentas.

Rol
Desarrollo full-stack y mantenimiento, desde el esquema de la base hasta el servidor donde corre
Stack
Next.js 15 (App Router), React 19, TypeScript, Prisma + PostgreSQL, TanStack Table / Query, AFIP SDK, Docker Compose + Caddy, Vitest + Playwright
Grow ERP
(01) El problema

Una distribuidora de alimento para mascotas y animales manejaba el negocio entre planillas, cuadernos y programas sueltos. Vende en mostrador y al por mayor, desde más de una sucursal, y cada factura tiene que pasar por AFIP/ARCA. Los pedidos se aprueban, se arman en el depósito y salen en camión. El dueño no es programador, así que el sistema también tenía que poder correrlo y mantenerlo el propio negocio.

Mi rolConstruí el producto y lo mantuve andando en producción para el negocio, con cada cambio que fueron pidiendo.
(02) Resultados
1,535commits, con mantenimiento continuo
105modelos de datos en el esquema
93pantallas en la app
(03) Arquitectura

Tres decisiones que lo definieron.

01

Server Actions como capa de negocio, con permiso en cada acción

Por qué. El dominio vive en 76 archivos de acciones que las páginas llaman directo. Cada una arranca con protectAction y la lista de roles permitidos. Ocultar un ítem del menú es solo visual; escribir la URL a mano igual choca con el control. Nueve roles, del dueño al repartidor, comparten una sola app.

El costo. No hay una API REST general. La tienda online y las subidas necesitan rutas propias con otra autenticación, y una acción nueva sin el control quedaría abierta.

02

La deuda de cada cliente se guarda dos veces, a propósito

Por qué. La cuenta corriente es la fuente de verdad del saldo total del cliente. Cada factura además guarda su saldo pendiente, para imputar pagos a facturas concretas y calcular la antigüedad de la deuda.

El costo. Todo movimiento de plata tiene que escribir en los dos. Si uno se saltea, las pantallas no coinciden, así que hay un script de conciliación que los compara.

03

Un servidor que controla el dueño, y una guía para correrlo

Por qué. La app, Postgres y Caddy corren juntos con Docker Compose en un solo VPS. Una guía de nueve capítulos cubre la instalación, los backups, los certificados de AFIP y cómo hacer cambios con un asistente de IA. Un hook de pre-push corre tipos, lint, tests y build.

El costo. Un solo servidor significa sin redundancia, y los backups dependen de un cron que alguien tiene que revisar.

(04) Galería
Punto de venta
Punto de venta · Venta de mostrador por código de barras o nombre, con los totales del día de la caja arriba.
Ventas y facturación
Ventas y facturación · Cada venta con su estado de pago y de factura, lista para pedir el CAE a AFIP.
Stock por sucursal
Stock por sucursal · Stock, valor y mínimos de la sucursal elegida, con ajustes y transferencias.
Plan de repartos
Plan de repartos · Las hojas de ruta del día por repartidor y vehículo. El mapa necesita una clave de Google Maps, que esta demo no tiene.
(05) Qué haría después
01Sumar foreign keys a la base. El esquema usa el relation mode de Prisma, así que borrar un registro puede dejar referencias colgadas que rompen el POS.
02Correr Playwright en CI contra una base con datos de prueba. Hoy los tests de punta a punta son smoke tests de solo lectura que necesitan una cuenta real.
03Pasar los controles del pre-push a un pipeline de CI, para que un hook salteado no pueda subir un build roto.
Próximo proyectoTiendas →
Nahuel SantillánES