Skip to content

About

Registra gastos con monto, foto de la boleta y quién aprueba. Ejemplo abierto de una app en sube.sh

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Control de gastos

Registra gastos con monto, foto de la boleta y quién aprueba.

Dos pantallas: la tuya, donde registras lo que gastaste y ves en qué va, y la de quien aprueba, que es la misma app filtrada por su correo.

Corre en sube, que le pone la base de datos, el dominio, el TLS y el inicio de sesión. La app no trae código de autenticación.

Por qué existe este ejemplo

Aquí no hay escritura anónima como en el registro de visitas: todo el mundo tiene sesión. Lo interesante es otra cosa, y es quién puede aprobar.

La plataforma sabe quién eres. No sabe quién es tu jefatura, y no debería — eso cambia por empresa, por proyecto y a veces por monto. Así que la app no inventa roles: quien gasta escribe el correo de quien firma, y la cola de aprobación es literalmente eso.

// app/aprobaciones/page.tsx — la regla de acceso es el filtro
where(and(eq(expenses.approverEmail, user.email), eq(expenses.status, 'pending')))

Es cómo funcionaba el formulario en papel, y tiene una propiedad que un flag de is_admin no tiene: no existe un estado donde alguien vea gastos que nadie le mandó. La acción que aprueba vuelve a comprobar lo mismo, así que mandar el id de un gasto ajeno a mano no calza con ninguna fila.

Lo que sí falta, y vale decirlo: nada impide que escribas tu propio correo como aprobador. Si eso importa en tu empresa, es una línea en la acción — pero es una regla tuya, no de la plataforma.

Plata

Los montos se guardan como enteros de pesos:

amount: integer('amount').notNull()

El peso chileno no tiene centavos, así que el peso ya es la unidad mínima y la plata nunca pasa por un redondeo. Una app en otra moneda debería guardar centavos igual — un entero de la unidad más chica — y no un número flotante.

Boletas

Las fotos van al almacenamiento de la app y se muestran con un link firmado que expira:

await storage.put(`boletas/${id}`, bytes, file.type)
const url = await storage.temporaryUrl(key)

La app no tiene credenciales del almacenamiento. Pide el link a la plataforma, que decide a qué archivos puede llegar esta app: una llave que nombre el archivo de otra app no se firma, diga lo que diga este código.

Correrlo

npm install
npm run build

Construye sin base de datos. Para verlo con datos hay que desplegarlo:

npm i -g @sube.sh/cli   # o usa npx
sube new "Control de gastos"
sube deploy

Estructura

app/page.tsx                 mis gastos y el formulario
app/aprobaciones/page.tsx    la cola de quien aprueba
src/db/schema.ts             una tabla: expenses

middleware.ts y next.config.ts los pone la plataforma. AGENTS.md explica las reglas que un asistente de IA debe respetar al modificar esta app.

Licencia

MIT.

About

Registra gastos con monto, foto de la boleta y quién aprueba. Ejemplo abierto de una app en sube.sh

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages