Suite 101 · arquitectura

La raya: lo que se le paga a la gente

Un taller le paga a su gente cada semana y lo apunta en una libreta. Esto es esa libreta, con tres cosas que una libreta no puede: que el dinero salga de una cuenta de verdad, que el estado de cuenta diga a quién se le pagó, y que lo que gana cada quien no lo vea cualquiera. Lo que NO hace —calcular IMSS e ISR— es la decisión más importante del diseño.

Al 20 de septiembre de 2026Contrato de la API 0.27.0Migración del OrgDB 0014

Lo que a propósito no hace

No calcula retenciones. No genera CFDI de nómina. No sabe de IMSS, de INFONAVIT ni de subsidio al empleo.

Esto no es una versión incompleta a la que le faltan cosas: es el alcance que se escogió al analizarlo, y conviene decir por qué. Una retención mal calculada no falla el día que se calcula. Falla meses después, en una revisión, con recargos y multa, y para entonces ya se repitió cincuenta veces. Un sistema que se equivoca en voz baja y con autoridad es peor que no tener sistema: quien lleva eso hoy lo lleva con su contador, y lo revisa una persona que sabe.

Lo que sí hacía falta, y hoy se hace en papel, es apuntar qué se le pagó a cada quien, de dónde salió, y que quede un recibo. Eso es lo que hay aquí, completo.

Un movimiento por persona

Al pagar un corte de raya se crea un egreso por cada persona, con su nombre, y no un solo egreso por el total.

Cuesta más filas y es lo correcto. Con un egreso global, conciliar contra el banco se vuelve adivinar: el estado de cuenta dice «RAYA 6,400» y no dice a quién. Y corregirle el monto a una persona obligaría a tocar el pago de todas, que es exactamente el tipo de operación donde se pierde dinero sin que nadie lo note.

Con un renglón por persona, el movimiento de cada quien se corrige solo, en la misma pantalla de movimientos donde se corrige cualquier otro.

Lo que la pantalla NO calcula

El neto de cada renglón —sueldo más extras menos descuentos— y el total del corte los calcula el servidor. La pantalla enseña una suma mientras se teclea, y lo dice con esas palabras: «la cuenta buena la hace el servidor al guardar; esto es para leerlo».

Es la misma regla que precio_venta en los proyectos, y por el mismo motivo: si el total viniera de la pantalla, dos personas capturando a la vez mandarían dos totales distintos y los dos se creerían. Una cifra de dinero tiene un solo lugar donde se calcula.

El nombre se congela

Cada renglón guarda el nombre de la persona copiado, no apuntado por llave a personal.

Parece un descuido de principiante y es lo contrario. Un recibo dice a quién se le pagó ese día. Si el nombre saliera de la tabla de gente, corregir un apellido mal escrito el año que entra reescribiría todos los recibos viejos, incluidos los que ya tienen una firma encima. Un documento firmado no cambia porque cambie el directorio.

Pagada es pagada

Un corte nace en borrador: se corrige cuantas veces haga falta y no mueve un peso. Al pagarlo cambia a pagada, y desde ahí no se reescribe ni se cancela.

La razón es de contabilidad y no de permisos: ese dinero ya salió de la cuenta, y borrar el corte no lo regresa. Lo único honesto que se puede hacer es corregir el movimiento de la persona a la que se le pagó de más o de menos, y eso es lo que dice la pantalla cuando se intenta.

Lo mismo del lado de la base: un corte sólo puede tener a cada persona una vez, y lo impide un índice único, no una validación. Si se colara dos veces, se le pagaría dos veces y el total cuadraría igual: nadie lo nota hasta que falta dinero en la caja.

El permiso, y por qué es otro

Ver la raya pide personal.es_nominas, una etiqueta que sólo el dueño reparte. Ya existía una parecida, es_contador, para quién puede pagar las órdenes de compra — y no se reusó.

Pagarle a un proveedor y saber cuánto gana cada quien son dos permisos distintos. En una oficina chica, el segundo es el que causa problemas si anda suelto, y es justo el que se repartiría de más si viniera pegado al primero.

El permiso se revisa en el servidor, en cada llamada, no al pintar el menú: quitarle la marca a alguien surte efecto al momento aunque tenga la pantalla abierta. Y quien reparte la marca queda apuntado en orden_eventos, la misma bitácora donde ya vivía quién pudo pagar y desde cuándo — porque es la misma clase de hecho y separarlo obligaría a leer dos tablas para reconstruir un mes.

La gente, sin duplicar la lista

La raya se le paga a quien está en personal, que es la misma tabla que llena roster101 con los expedientes. No se inventó otra lista de gente: si hubiera dos, un día no cuadrarían y nadie sabría cuál manda.

Pero una empresa que sólo usa dash101 tendría esa tabla vacía, sin raya y sin dónde arreglarlo. Para eso hay una puerta chica, POST /nomina/gente, que pide el permiso de nóminas y sólo deja poner nombre y puesto. dash101 sigue sin poder escribir personal por el CRUD genérico: el permiso de campo no se abrió.

Cómo quedó medido

387 pruebas de la API en verde, 18 de ellas nuevas para la raya, y 139 en dash101. Las que valen son las que cuidan el dinero cruzando la frontera: la pantalla captura en pesos y la API guarda en centavos, así que hay una prueba que paga un corte y comprueba los importes del otro lado. Si esa conversión se cayera de un lado, un sueldo de $3,500 se pagaría en $35 o en $350,000 y el total seguiría cuadrando consigo mismo.

La migración 0014 se mide aparte con sqlite3 en memoria, porque rehace orden_eventos —SQLite no deja cambiar un CHECK con un ALTER— y una copia es donde se pierden cosas sin que nada truene. Se comprueba que la bitácora quede idéntica con sus fechas, que la llave foránea sobreviva, y que es_nominas nazca apagado en todos los que ya estaban: una columna de permiso que naciera encendida le abriría los sueldos a la empresa entera el día del despliegue, en silencio.