Lalabase
Tickets, Doku, Zeiterfassung und Kundengespräche an einem Ort, durchsuchbar per KI. Für Softwarefirmen mit Kundenprojekten. Open Source: auf deinem eigenen Server oder in unserer Cloud in Deutschland.
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
Aplicación web para la gestión de rutas, flotas, cotizaciones, finanzas y equipo de una operación logística. Incluye dashboards por rol (administrador, transportista, colaborador, vendedor, desarrollador), autenticación con Better Auth, permisos granulares por módulo y base de datos PostgreSQL. Dominio: www.jtplogistics.com (el dominio sin www redirige aquí)檢視完整 README ↗
Aplicación web para la gestión de rutas, flotas, cotizaciones, finanzas y equipo de una operación logística. Incluye dashboards por rol (administrador, transportista, colaborador, vendedor, desarrollador), autenticación con Better Auth, permisos granulares por módulo y base de datos PostgreSQL.
Dominio: www.jtplogistics.com (el dominio sin www redirige aquí)
Calendar de shadcnLos roles se guardan en inglés en la BD: admin, carrier, collaborator, vendor, developer.
El administrador tiene acceso total. El colaborador no ve nada por defecto: el admin le enciende permisos módulo por módulo desde Colaboradores → editar, con cuatro niveles por módulo (leer, crear, editar, eliminar). Esos permisos viven como columnas booleanas en users (can_view_*, can_create_*, can_update_*, can_delete_*) y se aplican en dos capas:
requireCollaboratorPermission() en el layout.tsx del módulo (redirige si no tiene permiso).gateTasks, gateMural) que responde 403.El admin siempre pasa ambas capas sin necesidad de tener los flags encendidos.
Los mismos módulos que el admin, pero limitados a los permisos que el admin le encienda: rutas, cotizador, cotización marítima, tipos de unidad, mensajes, embarques, finanzas, clientes, proveedores, vendedores, colaboradores, laptops, celulares, correos, ideas, tareas, historial y mural.
Las contraseñas de laptops, celulares, cuentas de correo y las notas de contraseña de colaboradores no son credenciales de acceso a la plataforma: son datos que el administrador necesita poder consultar. Por eso se cifran de forma reversible (AES-256-GCM) en vez de guardarse con hash.
CREDENTIALS_ENCRYPTION_KEY, fuera de la base de datos: un volcado de la BD por sí solo no revela nada.hasPassword. El valor se pide de uno en uno a /api/credentials/<tipo>/<id> al pulsar el ojo.revealed.v1:<iv>:<tag>:<datos>. Los valores sin ese prefijo se tratan como texto plano heredado y se devuelven tal cual, para que la app funcione durante una migración.pnpm db:encrypt-credentials (simulación) y --apply para escribir. Es idempotente.Tablero interno visible solo para el personal de JTP (admin y colaboradores con canViewMural). Transportistas y vendedores quedan fuera.
users.birth_date y employee_profiles.hire_date. Si esas fechas están vacías, la persona no aparece.vercel.json) dispara /api/cron/mural-greetings todos los días a las 14:00 UTC (8:00 en Guadalajara). Felicita a quien cumple años o aniversario y avisa al equipo ese mismo día. No hay resumen diario ni semanal: cada entrada avisa sola al crearse, editarse o cancelarse. Protegido con CRON_SECRET.Para que RH administre el mural, el admin le enciende los cuatro permisos de Mural; al resto del equipo le basta con leer.
jtplogistics/
├── prisma/
│ ├── schema.prisma # Modelos (users, routes, shipments, mural_*, etc.)
│ ├── seed.ts # Datos de prueba (usuarios, rutas, activos)
│ └── migrations/ # SQL versionado (se escribe a mano, ver más abajo)
├── src/
│ ├── app/
│ │ ├── (auth)/ # login, register, forgot-password, reset-password
│ │ ├── admin/dashboard/
│ │ ├── carrier/dashboard/
│ │ ├── collaborator/dashboard/
│ │ ├── vendor/dashboard/
│ │ ├── developer/dashboard/
│ │ └── api/ # auth, admin, collaborator, carrier, vendor, mural, cron
│ ├── components/
│ │ ├── ui/ # shadcn + componentes base (DataTable, DatePicker, Lexical)
│ │ └── dashboard/ # componentes por módulo
│ ├── hooks/
│ ├── lib/ # auth, db, validators, utils, config, data, correos
│ └── types/
├── public/
├── docs/
│ ├── conventions.md # Convenciones de BD y datos
│ └── reporte-ciberseguridad.html # Controles de seguridad (imprimible a PDF)
├── instrumentation.ts # Normalización de BETTER_AUTH_URL al arranque
├── vercel.json # Cron del resumen diario del mural
└── next.config.ts
La interfaz y los textos visibles están en español; el código (rutas, variables, comentarios) en inglés.
Crear .env en la raíz (no se commitea). Ejemplo:
# Base de datos
DATABASE_URL="postgresql://..."
# Better Auth (en producción usar el dominio final CON www)
BETTER_AUTH_SECRET="..." # mínimo 32 caracteres (openssl rand -base64 32)
BETTER_AUTH_URL="http://localhost:3000"
# Opcional: orígenes adicionales (CSRF)
# BETTER_AUTH_TRUSTED_ORIGINS=https://www.jtplogistics.com
# Cloudinary
CLOUDINARY_CLOUD_NAME="..."
CLOUDINARY_API_KEY="..."
CLOUDINARY_API_SECRET="..."
# Resend. Sin RESEND_API_KEY los correos solo se imprimen en consola (útil en dev).
RESEND_API_KEY="..."
EMAIL_FROM="JTP Logistics <[email protected]>"
# URL pública usada en los enlaces y el logo de los correos.
# Sin ella los correos salen sin logo ni botón (no se rompen, usan un respaldo).
NEXT_PUBLIC_APP_URL="http://localhost:3000"
# Secreto del cron del resumen diario del mural. Vercel lo manda como
# "Authorization: Bearer <valor>". Si está vacío, el endpoint no exige credencial
# (cómodo en local, nunca en producción).
CRON_SECRET=""
# Llave del almacén de credenciales de activos (contraseñas de laptops,
# celulares, cuentas de correo y notas de colaborador). Generar con:
# openssl rand -base64 32
CREDENTIALS_ENCRYPTION_KEY=""
Notas:
VERCEL_URL se rellena automáticamente y se usa para trustedOrigins si hace falta.NEXT_PUBLIC_APP_URL se incrusta en el bundle durante el build: al cambiarla hay que redesplegar para que surta efecto.CREDENTIALS_ENCRYPTION_KEY no se puede perder. Sin ella, las contraseñas de activos guardadas quedan irrecuperables. Debe existir una copia fuera de Vercel (gestor de contraseñas o resguardo físico).# Instalar dependencias (también corre prisma generate)
pnpm install
# Aplicar migraciones
pnpm db:migrate:deploy
# (Opcional) Poblar datos de prueba
pnpm db:seed
# (Opcional) Sembrar configuración de portada/branding
pnpm db:seed-settings
# (Opcional) Crear cuenta demo transportista
pnpm db:create-demo-carrier
# Desarrollo
pnpm dev
Abrir http://localhost:3000. Para entrar con datos de prueba, ver el mensaje al final de pnpm db:seed (correos y contraseñas por rol).
pnpm db:migrate(prisma migrate dev) está roto en este proyecto: falla al crear la shadow database en Neon.
El flujo que sí funciona:
prisma/schema.prisma.prisma/migrations/<AAAAMMDDHHMMSS>_<nombre>/migration.sql con el SQL correspondiente.pnpm db:migrate:deploy.pnpm db:generate.Ojo: db:migrate:deploy aplica contra la base de datos de DATABASE_URL, que es la BD real compartida. Revisar el SQL antes de correrlo.
| Comando | Descripción |
|---|---|
pnpm dev | Servidor de desarrollo |
pnpm build | Build de producción |
pnpm start | Servidor de producción |
pnpm lint | ESLint |
pnpm test | Pruebas con Vitest |
pnpm test:watch | Pruebas en modo watch |
pnpm db:generate | Generar Prisma Client |
pnpm db:migrate | Migraciones en desarrollo (roto, ver arriba) |
pnpm db:migrate:deploy | Aplicar migraciones |
pnpm db:seed | Ejecutar seed |
pnpm db:seed-settings | Seed de ajustes/configuración |
pnpm db:create-demo-carrier | Crear cuenta demo transportista |
pnpm db:encrypt-credentials | Cifrar credenciales de activos que sigan en claro |
pnpm db:assign-route-creator | Asignar creador a rutas existentes |
pnpm db:sync-route-destination-states | Sincronizar estados destino de rutas |
pnpm db:studio | Abrir Prisma Studio |
pnpm test corre Vitest sobre la lógica pura (sin BD ni red): coincidencia de embarques y finanzas, búsqueda, fechas de cumpleaños y aniversarios, y armado de los correos de felicitación.
Los módulos con lógica que valga la pena probar se separan de los que tocan Prisma —por ejemplo mural-celebrations.ts (puro) frente a mural-celebrations-query.ts (BD)— porque importar @/lib/db en una prueba falla si no hay DATABASE_URL.
CI (.github/workflows/ci.yml) corre en cada push y PR: typecheck, lint, test y build.
skipDuplicates), pero reinicia otras entidades de prueba.EMAIL_FROM.DATABASE_URL, BETTER_AUTH_SECRET, BETTER_AUTH_URL, NEXT_PUBLIC_APP_URL (con la URL final, https://www.jtplogistics.com) y CRON_SECRET.pnpm build; si BETTER_AUTH_URL no trae protocolo, se normaliza a https:// al arrancar.vercel.json queda registrado solo, sin configuración extra en el panel.Reglas de base de datos, nombres y validaciones: docs/conventions.md.
En resumen: tablas y columnas en snake_case, código en camelCase, correos y slugs normalizados a minúsculas, y los roles guardados en inglés.
Proyecto privado.