Agentic Trading Lab
에이전트와 대화하고, 거래 아이디어를 테스트하며, 코드 없이 실제 시장 데이터에 AI 트레이딩 에이전트를 적용
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Web app Next.js 16 + Supabase para que operadores de sucursal carguen comprobantes (facturas de compra, recibos de cobranza) que luego se importan en ContaSystem desktop.
Diseño: "Modern Ledger" — ver
design/DESIGN_SYSTEM.mdpara tokens, tipografía y componentes.
@theme en app/globals.css@supabase/ssr (server) + @supabase/supabase-js (browser)next/fontProyecto Supabase con los schemas aplicados:
01_schema.sql (sync de socios — define user_grupos, user_empresas)05_comprobantes_online.sql (esta feature — tablas *_remoto + RPCs + RLS)../contasystem-desktop/docs/supabase/.Al menos una empresa con permite_comprobantes_online = 1 en SQLite local.
El usuario Supabase (operador o contador) tiene que estar asignado en public.user_empresas (o public.user_grupos) para las empresas que va a ver.
Catálogos subidos desde ContaSystem desktop:
cd contasystem-web-carga
npm install
# Copiá las credenciales del proyecto Supabase (Project Settings → API)
cp .env.local.example .env.local
# Editá .env.local con NEXT_PUBLIC_SUPABASE_URL y NEXT_PUBLIC_SUPABASE_ANON_KEY
npm run dev
Abrir http://localhost:3000 — redirige a /login.
/login — email/password (Supabase Auth)./empresa — selector de empresas habilitadas:
/carga.localStorage (cs-carga-empresa-id) y en sesiones siguientes salta directo./carga — pantalla principal:
pendiente / importado / rechazado.upsert_comprobante_web → fila nueva con numeración WEB-{empresa}-{YYYY}-{seq}.Reemplaza el pasaje de lista a mano en la puerta. El desktop emite un token opaco por inscripción, arma el QR y lo manda en el recibo de cobro o en la confirmación de inscripción; la web lo escanea.
Requisitos SQL (Supabase → SQL Editor), en este orden:
34_asistencia_qr.sql — vive en ../contasystem-desktop/docs/supabase/.
Crea entradas_remoto y los RPCs buscar_entrada /
marcar_asistencia_entrada.supabase/desmarcar_asistencia.sql —
agrega desmarcar_asistencia_entrada y la traza de la desmarca. Sin esto
todo funciona salvo el botón de desmarcar, que responde 501 diciendo qué
falta correr. En el desktop este archivo va como 35_desmarcar_asistencia.sql.También hace falta SUPABASE_SERVICE_ROLE_KEY: los RPCs son SECURITY DEFINER
y la tabla no está expuesta a anon.
| Ruta | Sesión | Qué hace |
|---|---|---|
/a/{token} | no | Muestra la entrada (evento, nombre, estado) y re-dibuja el QR. No marca nada. |
/checkin | sí | Escáner del staff: cámara → marca asistencia → resultado a pantalla completa. Pestaña Manual para pasar lista sin cámara. |
Abrir la URL del QR NO marca asistencia. La marca la hace personal del
evento desde /checkin, autenticado. Si bastara con abrir el link, cualquiera
se autoregistraría desde su casa — y un preview de link de WhatsApp o Gmail lo
dispararía solo. Por eso /a/{token} usa buscar_entrada, que es de sólo
lectura, y nunca marcar_asistencia_entrada.
| Resultado | Pantalla | Cuándo |
|---|---|---|
ok | Verde | Primer ingreso. |
ya_presente | Ámbar, "ya ingresó a las HH:MM" | Reescaneo, o check-in ya hecho a mano en el desktop. Suele ser alguien intentando entrar dos veces. |
anulada | Rojo | La inscripción se dio de baja. |
no_encontrada | Rojo | Token inexistente, de otra empresa, o QR ajeno. |
otro_evento | Rojo | Entrada válida pero de otro evento de la misma empresa (agregado de la web, no del SQL). |
El marcado es idempotente: reescanear no pisa la hora del primer ingreso.
asistio_por guarda el email de la sesión del operador, nunca un valor que
venga del navegador.
El respaldo sin cámara, y también la forma de pasar lista a mano. Marca por el
mismo endpoint que el escáner, así el resultado y la traza en asistio_por son
idénticos.
roles_evento:
arranca con Asistente / Expositor / Organización). "Todos" saca el filtro.
Una entrada sin rol asignado cuenta como asistente, igual que en el
desktop; si no, la mayoría no aparecería en la vista por defecto.Al desmarcar quedan desmarcada_at / desmarcada_por con la traza, y la
corrección es firme: upsert_entrada fue modificado para que un push posterior
del desktop no vuelva a marcar a la persona (antes, COALESCE(existente, entrante) la resucitaba en el próximo reenvío de recibo). Una marca
genuinamente nueva —un reescaneo después de la desmarca— sí entra.
Lado desktop: resuelto.
pullAsistenciasQRbaja también las desmarcas (segunda consulta sobredesmarcada_at) y resuelve por última escritura; y desde el 30/08/2026 una desmarca hecha EN el desktop viaja a la nube por la misma RPC (autoPushDesmarcaAsistencia). Verdocs/eventos-performance-propuesta.mden el repo del desktop.
entradas_remoto guarda un único nombre_completo armado como
"NOMBRE APELLIDO", así que para ordenar por apellido hay que deshacer esa unión.
No se parte con heurística: "MARÍA ELISA DE LEÓN" y "ANA GONZÁLEZ ROSSI"
tienen la misma forma y el corte va en lugares distintos. Se resuelve contra la
ficha del socio (socios_datos, que sí tiene los campos separados) usando el
documento de la entrada como clave. Quien no tenga ficha se muestra con el
nombre completo tal cual y se ordena por él.
localhost). En http:// no hay visor —
el control manual sigue funcionando.No crea, no borra ni reconcilia entradas: el desktop es dueño del alta y del
estado. Lo único que la web escribe es la asistencia — asistio_at /
asistio_por / asistio_origen y la traza desmarcada_* — y siempre vía
marcar_asistencia_entrada o desmarcar_asistencia_entrada.
contasystem-web-carga/
├── app/
│ ├── layout.tsx # fuentes + Toaster
│ ├── globals.css # tokens Tailwind v4 + utilidades (.field, .btn-primary, .badge…)
│ ├── page.tsx # redirect → /login o /empresa según sesión
│ ├── login/page.tsx # signIn Supabase
│ ├── empresa/page.tsx # selector + localStorage
│ ├── (app)/carga/page.tsx # form + lista últimos 20
│ ├── a/[token]/page.tsx # vista PÚBLICA de una entrada (destino del QR)
│ ├── (app)/checkin/ # escáner del staff (cámara + control manual)
│ └── api/checkin/ # eventos · marcar · desmarcar · entradas
├── components/
│ ├── Header.tsx # header persistente con dropdown user
│ ├── Highlight.tsx # subrayado ámbar (una palabra por pantalla)
│ └── Stamp.tsx # sello decorativo (solo login)
├── lib/
│ ├── format.ts # formato uruguayo de números/fechas + hora Montevideo
│ ├── types.ts # tipos TS de tablas Supabase
│ ├── entradas.ts # RPCs de asistencia (server-only)
│ ├── entradas-types.ts # tipos de entradas/check-in (client-safe)
│ ├── checkin-token.ts # URL del QR o token pelado → token
│ ├── checkin-auth.ts # scope por empresa de /api/checkin/*
│ ├── qr.ts # QR en SVG (server-only)
│ └── supabase/
│ ├── client.ts # createBrowserClient
│ ├── server.ts # createServerClient (Server Components)
│ └── middleware.ts # updateSession para middleware.ts
├── proxy.ts # gate de auth (middleware de Next 16; excluye las rutas públicas)
├── design/ # ← mockup HTML, design system doc, primitivos JSX
└── .env.local.example
NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY (formulario público de eventos, tracking, elecciones) y CRON_SECRET (cron de cumpleaños). Ver .env.local.example.| Problema | Causa probable |
|---|---|
"No tenés empresas asignadas" en /empresa | Falta entrada en public.user_empresas para tu UUID + empresa_id |
Plantillas vacías en /carga | El contador no subió catálogos todavía (ContaSystem → Sync → "Subir catálogos a la web") |
new row violates row-level security policy al guardar | El user no tiene acceso a la empresa que viene en el payload (RLS) |
| Error 500 en RPC | La empresa o la plantilla referenciada no existe en remoto |
/checkin no abre la cámara y avisa de HTTPS | La página está servida por http://. getUserMedia sólo corre en contexto seguro: usar la URL de Vercel o localhost |
/checkin muestra "todavía no hay entradas con QR emitidas" | El desktop no subió ninguna entrada para esa empresa, o el evento es más viejo que la ventana del selector (?dias=, default 60) |
Could not find the function public.buscar_entrada | Falta correr 34_asistencia_qr.sql |
| "Falta correr supabase/desmarcar_asistencia.sql" al desmarcar | Justamente eso: correr ese archivo en el SQL Editor |
| Se desmarcó en la web pero el desktop la sigue viendo presente | Esperado por ahora: el pull del desktop todavía no baja las desmarcas (ver el pie de supabase/desmarcar_asistencia.sql) |
Todo escaneo da no_encontrada | La empresa activa de la web no es la dueña de esas entradas (el marcado está scopeado por empresa) |
| Falta gente en la lista Manual | El filtro está en un rol. Por defecto muestra sólo Asistente: tocar Todos |
| Alguien aparece sin "APELLIDO, Nombre" al ordenar por apellido | Su documento no resuelve contra socios_datos (sin ficha, o documento distinto). Se muestra el nombre completo tal cual |
Si los problemas persisten, revisar el SQL Editor de Supabase y verificar:
-- Tenants asignados al user logueado
SELECT 'empresa' AS tipo, empresa_id AS id FROM public.user_empresas WHERE user_id = (SELECT id FROM auth.users WHERE email = '[email protected]')
UNION ALL
SELECT 'grupo' AS tipo, grupo_id AS id FROM public.user_grupos WHERE user_id = (SELECT id FROM auth.users WHERE email = '[email protected]');
-- Catálogos visibles
SELECT * FROM public.empresas_online_remoto;
SELECT id, nombre_razon_social, tipo FROM public.contactos_remoto;
SELECT id, nombre, iva_porcentaje, activo FROM public.plantillas_remoto;