Commit Graph

70 Commits

Author SHA1 Message Date
2523635716 reporte concentrado estilo legacy: tabla detalle ventas x metodo x moneda + legacy_id en cita/venta + metodo saldo_favor + fix moneda USD en pagos del POS 2026-10-10 09:24:57 +00:00
85df17545f instancia 2: dominio clinica.consultoria-as.com (antes clinica2.consultoria-as.com) 2026-10-08 01:17:52 +00:00
582c267ec0 segunda instancia white-label (clinica2) + fix de orden de menus en instalacion limpia
Infra (todo convive en la misma VPS, mismo addons_path read-only):
- infra/clinica2/: odoo.conf (puerto 8070, db clinica2_odoo, data_dir
  propio), odoo-clinica2.service (sin env vars de WACRM/Supabase/Hermes),
  nginx-vhost (80 con server_name clinica2.consultoria-as.com + 8880 LAN,
  /api/odoo -> 8070, /wacrm/ cortado con 403), postinstall.py (brand neutro,
  menu WACRM vacio, admin con password propio y must_change_password)
- docs/segunda-instancia.md: mapa completo de la instalacion, pasos para
  reproducir (instancia 3+), pendiente del hostname en dashboard del tunel
  (remotamente administrado), aislamiento de datos escenario B
- frontend/public/brand/: logos SVG neutros + favicon para la instancia 2

Fix de menus (aplica a todas las instalaciones limpias, una sola pasada):
- menu_skeen_root se mueve a skeen_pacientes (modulo raiz de la jerarquia);
  en bases existentes se transfirio el ownership del xmlid (ir_model_data)
  asi actualizar no duplica el menu
- menu_skeen_citas (padre) se declara en skeen_citas/views/menus.xml que
  carga antes que bloqueo/lista_espera; menu_views.xml conserva las entradas
  con action (cargan despues de cita_views, donde se define la accion)
- referencias actualizadas: pacientes(catalogos/recetas), monedero, ventas,
  inventario, visitas -> skeen_pacientes.menu_skeen_root

Verificacion: produccion (skeen_odoo) actualizada sin duplicar menus y API
intacta; instalacion limpia clinica2_odoo 9 modulos OK; 15/15 tests
end-to-end (brand neutro, login admin, WACRM oculto+403, datos vacios)
2026-10-08 00:44:30 +00:00
2f7cbe237e white-label: brand de la clinica por configuracion (fase 1 de instancia sin branding SKEEN)
- backend: GET/PUT /skeen/frontend/v1/brand leyendo ir.config_parameter
  skeen.clinic.brand (JSON: nombre, logo_claro, logo_oscuro, pie) con
  defaults SKEEN; GET publico (el login lo necesita sin sesion), PUT admin
  con auditoria. frontend_users.xml: 'Administrador SKEEN' -> 'Administrador'
- frontend: ClinicBrand + BRAND_DEFAULT en odoo.ts; brand y setBrand en el
  contexto de auth (fetch al boot + cache localStorage + document.title)
- Login/layouts/mensajes/exports leen el brand en vez de strings SKEEN:
  Login.tsx, SkeenLayout, HomeNestLayout, Cumpleanos (wa + export),
  Pacientes/Ventas/Cortes/Reportes/Kpis/Alertas/AgendaPrint (titulos),
  useClinicaPrint (fallback nombre), Login hace GET publico al montar
- Configuracion > Clinica: tarjeta 'Identidad de la clinica' (solo admin)
  para editar nombre/pie/logos con preview
- no renombrado (invisible al usuario): rutas API /skeen/*, claves
  localStorage, nombres de modulos, parametros skeen.*

Verificacion API: 11/11 tests OK (defaults, PUT merge, campo invalido
ignorado, restore, admin neutral). Deploy: build + rsync + Odoo reiniciado
2026-10-08 00:09:00 +00:00
2573562218 lista de espera: salas consultoria/cabina (toggle + etiqueta) y scroll de WhatsApp
- skeen_citas: campo sala en skeen.lista.espera (consultoria/cabina, indexado)
- frontend.py: sala en _lista_espera_to_dict, create y update (toggle desde
  la etiqueta; valor invalido vuelve a sin sala; cambio queda en historial)
- ListaEspera.tsx: toggle Todas/Consultoria/Cabina con conteo, etiqueta
  clicable en cada tarjeta que alterna de sala, selector en el modal de alta
- Agenda.tsx: cambiarSala() conectado al panel
- WacrmMessages.tsx: el auto-refresco ya no empuja el scroll abajo si el
  usuario esta leyendo mensajes anteriores (solo baja al cambiar de
  conversacion, por deep-link o al enviar respuesta propia)

Verificacion API: 7/7 tests OK (alta con sala, toggle, valor invalido, GET)
2026-09-30 10:33:52 +00:00
169864958d permisos de agenda: selector de acciones por usuario (ver, agendar, editar, eliminar, visitas)
- roles.py: AGENDA_PERMS, AGENDA_PERM_KEYS, WRITE_RANK_MIN, agenda_defaults_for,
  resolve_agenda_perms, AGENDA_STATUS_PERM, AGENDA_STATE_PERM, _agenda_status_perm
- frontend_user.py: campo agenda_perms, _agenda_perms_list(), to_public_dict()
  expone agenda_perms y agenda_perms_custom
- auth.py: require_agenda(perm) decorador + agenda_perm_error()
- frontend.py: @require_agenda aplicado a 22 endpoints + branch en
  update_appointment_status por accion
- auth_users_update: whitelist acepta agenda_perms
- Odoo upgrade: columna skeen_frontend_user.agenda_perms
- Frontend: types AgendaPerm, AGENDA_PERM_ITEMS, canAgenda() en auth.tsx
- UsuariosPanel: checkboxes de permisos de agenda en modal de permisos
- Agenda.tsx: gates por permiso en crear/editar/eliminar/visitas/dragdrop/bloqueos
- EstadoChecklist/BloqueosModal/ListaEspera: hide actions without permission

Verificacion API: 18/18 tests OK (admin hereda, recorte=403, lect=403, restore=null)
2026-09-30 09:46:51 +00:00
85a281add1 Permisos por pestana de reportes y ruido de serializacion en presencia
Auditoria de 260 visitas (26 rutas x 10 roles) sobre el build actual: 0 hallazgos.
Dos defectos reales que salieron del barrido anterior se corrigen aqui.

1) Reportes: la matriz guarda claves '/reportes?tab=x' y puede conceder una
   pestana suelta (Horas agenda al medico, Exportar a cosmetologia) sin dar el
   modulo. Nadie la respetaba:
   - App.tsx: nuevo ReportesRoute que evalua la pestana del URL; si el rol no
     tiene '/reportes' pero si alguna pestana, aterriza en la primera permitida.
   - Reportes.tsx: familias, favoritos y el boton "Exportar datos" se filtran
     por canSee('/reportes?tab=x'). 'exportar' no pertenece a ninguna familia,
     por eso se lista en TABS_FUERA_DE_FAMILIA (si no, el guard lo reescribia a
     'general' y admin perdia la vista). El query se sincroniza con lo renderizado.
   - SkeenLayout/HomeNestLayout: "Horas agenda" y "Exportar datos" aparecen en
     Analitica para que el permiso sea alcanzable desde el menu, no solo a
     mano. Clasico ya los traia.
   - auth.py: _medico_reporte_permitido consulta la matriz antes de vetar
     /reports/ al medico. Sin ese puente el menu ofrecia la opcion y la API
     respondia 403. Las demas rutas vetadas (sales, payments, wallets, pos)
     siguen cerradas: verificado comisiones=403, horas-agenda=200.

2) skeen_chat/_touch: 211 "could not serialize access due to concurrent update"
   en un barrido. Bandeja, badge y heartbeat salen en paralelo y cada uno
   emitia el UPDATE de last_seen aunque no aplicara cambios, abortando la
   transaccion de otra peticion. Se corta antes de tocar la fila cuando el
   registro es reciente; el savepoint queda para el caso de empate exacto.
   Ráfaga de 128 peticiones concurrentes: todas 200, presencia sigue
   actualizando (online=true, last_seen avanza) y el ruido bajo de 211 a 5.
2026-09-30 01:26:37 +00:00
5a16f694de Inventario: campo de precio de venta editable (faltaba en la UI)
El modelo tenia el campo price y el POS lo usa para cobrar, pero ni el
formulario de alta lo capturaba ni existia modal de edicion: los 170
articulos tenian precio en 0 y recepcion tecleaba el precio a mano en
cada venta.

- Backend: inventory_create acepta price; inventory_update lo permite
  entre los campos editables (con conversion float).
- Frontend: columna 'Precio venta' en la tabla, campo en el alta y
  modal nuevo 'Editar articulo' (nombre, precio, costo, SKU, categoria,
  unidad, niveles y notas). La existencia sigue cambiando solo via
  Ajustar para dejar registro del movimiento.
2026-09-29 23:33:12 +00:00
7b54e40104 Agenda: colores de estado mas fuertes y boton de En curso
- Badge y bloques de la cuadricula: cada estado con su color propio y
  fuerte (pendiente=ambar, confirmada=esmeralda, llego/en cabina=cielo,
  en curso=violeta, completada=gris, cancelo/no show=rosa). Antes varios
  compartian tonos pastel casi iguales. La leyenda del grid usa los
  mismos colores.
- badgeForAppointmentState: llego e en_curso tenian variant de pendiente
  (se veian igual); ahora arrived y progress, y no_show/waitlist tienen
  las suyas.
- Boton 'Marcar en curso' (accion start del backend) en las acciones
  rapidas de la vista de lista y tarjetas moviles, entre Llegada y
  Completar.
- Mini-checklist del flujo en el tooltip de la cuadricula (solo lectura;
  click abre el detalle con el checklist completo interactivo).
2026-09-29 23:11:58 +00:00
5385fc3a53 Auditoria de plataforma: rutas rotas y errores por rol
Recorrido dinamico de las 26 rutas con los 10 roles (260 visitas con
navegador real) mas revision estatica de endpoints FE vs BE. Hallazgos
y correcciones:

- frontend.py: expedientes_recientes no tenia @http.route (el endpoint
  /expedientes-recientes respondia 404). Se expone con GET + lectura.
- auth.py: MEDICO_BLOCKED_PREFIXES hacia match por startswith, asi que
  /sales_goal quedaba bloqueado para medicos (403 en consola en todas
  las pantallas por el widget de meta del mes). Ahora el match exige
  frontera de path (/sales bloquea /sales/x pero no /sales_goal).
- Reportes: getCommissions (endpoint admin-only) iba dentro de un
  Promise.all; el 403 tumbaba todo el tab General para recepcion,
  gerencia, enfermeria, psicologa, farmacia y lectura. Ahora va en
  peticion aislada y solo se llama para admin; la seccion de comisiones
  del tab General solo se renderiza para admin.
- Matriz de menus guardada: medico habia quedado fuera de /pacientes
  y /visitas (los defaults del codigo lo incluyen y los medicos lo
  necesitan para ver clientes e historial). Restaurado via PUT
  /roles/permissions (queda en skeen_config_audit).

Verificado con navegador: medico entra a /pacientes y /visitas sin
403; recepcion y gerencia cargan /reportes sin error; admin sigue
viendo la seccion de comisiones. Usuarios temporales de auditoria
eliminados.
2026-09-28 21:13:38 +00:00
a4358ada15 Fix: crash (React #310) al abrir informacion de un paciente
useClinicaPrint() quedaba despues de un return condicional en
EstadoCuentaPrint, ReciboPrint, CortePrint y ConteoPrint (migracion de
clinicSettings del punto 11). Al pasar de paciente null a uno real el
numero de hooks cambiaba entre renders y React tumaba la pantalla con
'Minified React error #310'. El hook ahora va antes de cualquier return
condicional en los 4 componentes.
2026-09-28 20:18:58 +00:00
89429aee9b Login: evitar pantalla en blanco al arrancar
- ErrorBoundary global: si un modulo falla al renderizar se muestra un
  mensaje amable con recargar en lugar de pantalla en blanco.
- El bootstrap de auth ya no se queda cargando para siempre: si /auth/me
  no responde en 20 s (red lenta o tunel caido) se muestra una pantalla
  de reintento. Si la red fallo se conserva la sesion; solo se descarta
  el token cuando el servidor contesta (401).
2026-09-28 19:52:23 +00:00
72f12946c3 Punto 11: editor de diseno de tickets en Configuracion > Tickets
- Nuevo modelo skeen.ticket.config (AbstractModel) con layout, datos de clinica
  y logo en ir.config_parameter; _mezclar() hace que layouts viejos hereden las
  secciones nuevas; _validar() rechaza valores imposibles y textos largos.
- Endpoints GET/PUT /ticket_config, PUT /ticket_config/clinica,
  POST /ticket_config/reset (reset solo admin) con auditoria en skeen_config_audit.
- Los datos de la clinica pasan de localStorage (cada caja imprimia distinto)
  a configuracion compartida en el servidor.
- TicketDoc.tsx renderiza segun el diseno: ancho 58/80mm, fuente, tamano de letra,
  separador, mayusculas, orden de bloques y 29 secciones activables.
- TicketDesigner.tsx: editor completo con vista previa en vivo, reorden de bloques,
  textos personalizables y carga de logo.
- TicketPrint.tsx ahora es un wrapper de TicketDoc; ReciboPrint, EstadoCuentaPrint,
  RecetaPrint, CortePrint y ConteoPrint usan useClinicaPrint().
- _sale_to_dict expone telefono del paciente, medico que atendio y datos de paquete;
  pos_checkout devuelve recibido/cambio en MXN y USD para imprimirlos.
2026-09-24 18:19:51 +00:00
e89bcdca3a Punto 7: gerencia puede corregir tickets sin cancelarlos (lineas, precios, descuento y notas) con ajuste automatico de monedero e inventario 2026-09-24 17:53:22 +00:00
dcf2c367f1 Puntos 16 y 10: modulo de paquetes de sesiones (catalogo, saldo por paciente, descuento en agenda, venta en POS) + fix de auditoria silenciosa 2026-09-24 17:17:29 +00:00
Kimi
09b4f25bb8 Punto 13: alta/baja de médicos desde el módulo Médicos
- Columna 'Estado' con switch Activo/Baja (confirmación previa) y checkbox
  'Mostrar dados de baja' para poder reactivar.
- GET /doctors solo devuelve activos; include_inactive=1 para la pantalla de
  Médicos. Cada médico expone su campo 'active'.
- Reglas en modelo: un empleado dado de baja no admite citas nuevas
  (skeen.cita), ni asignación de pacientes (res.partner.primary_doctor_id),
  ni líneas de venta (skeen.venta.line.prescribed_by_id). El historial
  existente no se toca: los constraints solo corren cuando cambia la
  asignación.
- ValidationError se responde 400 con mensaje legible en pacientes y ventas.
- fix: badges de estado de cita en agenda y dashboard usan la etiqueta de la
  clínica en lugar del valor técnico.
2026-09-24 16:03:02 +00:00
Kimi
d0eac00a40 Agenda: cierre rápido de agendas por médico, lista de espera, duraciones 30/45/60, checklist de estados con bitácora y auto-refresh 30s
- BloqueosModal: alta multi-médico, rango repetible por día de la semana,
  motivos predefinidos, edición/borrado y cierre rápido desde la cabecera
  de cada columna (todo el día / resto del día / rango).
- skeen.lista.espera + panel y modal en la agenda: prioridad, franja, rango
  de fechas, agendar precargado, avisar por WhatsApp y aviso cuando se
  libera un hueco compatible.
- duration en skeen.cita (0 = la del servicio): la cita ocupa sus bloques de
  15 min reales en las 4 vistas, con celdas de continuación.
- Checklist de estados (Agendada → Confirmada → En cabina → En consulta →
  Completada) con avance/retroceso, cancelación y no-show con confirmación,
  y bitácora de quién/cuándo en skeen.cita.state.log.
- Etiquetas del sistema legacy alineadas (Canceló / Lista de espera / En
  cabina) en badges de agenda y dashboard.
- Auto refresco silencioso cada 30 s (pausable, se pospone con modales,
  escritura o drag) en citas + bloqueos + lista de espera en un solo request.
2026-09-24 15:46:38 +00:00
e32a79084a Fix IA (max_tokens del modelo de razonamiento + fallback al gateway), sidebar con toggle arriba, busqueda de un solo campo (paciente/global), editar expediente, marketing en visitas, responsive de agenda; doc de diagnostico WhatsApp 2026-09-24 10:01:55 +00:00
d75411f0d9 POS vista lista, modulo Tickets para gerencia con cancelacion auditada, y saldo a favor (recargas de anticipo desde expediente y agenda, canje en POS) 2026-09-18 04:25:33 +00:00
cebf8d663d Permisos: marketing (export completo, agenda/citas, cumpleanos, visitas, WACRM), gerencia gestiona usuarios y roles, recepcion edita expedientes, cosmetologas ven agenda, fix del sidebar que no dejaba seleccionar Leads 2026-09-18 03:23:44 +00:00
c38783eb31 Oleada UX 7: Chat (presencia, busqueda en historial) y WACRM (metricas para gerencia, notas internas y etiquetas que sobreviven al sync) + fixes de concurrencia 2026-09-17 23:46:40 +00:00
31c92ac419 Oleada UX 6: Reportes agrupados en familias con rango global persistente y favoritos; Configuracion con auditoria de cambios y simulador de comisiones 2026-09-17 22:06:11 +00:00
cd945df6a5 Oleada UX 5: Servicios (duplicar, favoritos y orden para POS, mas vendidos) y Medicos (semana tipo con validacion en agenda, meta mensual con progreso) 2026-09-17 21:28:43 +00:00
9ee3343e22 Oleada UX 4: Pagos/Adeudos (cobro en 1 click con recibo, plan de pagos), Monedero (movimientos narrados, ajustes auditados, MXN+USD), Inventario (alta rapida, conteo fisico con ajuste e historial, alertas accionables) + fix de folios de pago y cantidades de movimientos 2026-09-17 20:31:52 +00:00
ac5896b1fc Oleada UX 3: POS (repetir ultima venta, aviso de paquetes, atajos, caja desde POS), Ventas (cancelacion auditada con reversion de monedero y stock, detalle inline, presets de fecha), Cortes (historial comparativo y export) 2026-09-17 19:26:02 +00:00
b4f91527f1 Oleada UX 2: Agenda (mensajes de conflicto humanos, imprimir agenda del dia, confirmacion en lote, prefs persistentes) y Pacientes (acciones en ficha, timeline unificada, aviso de telefono duplicado) + fixes de precarga e impresion 2026-09-17 18:47:35 +00:00
afc208a7b7 UX Dashboard: fila Hoy en la clinica, KPIs clickeables, deltas; Cumpleanos wa.me E.164; Mis ventas con grafica diaria 2026-09-17 07:25:16 +00:00
8ba3d2582b WACRM: historial completo con paginacion desde el origen, sync refleja eliminaciones y trae todo el historial 2026-09-11 10:58:57 +00:00
4f49188deb Oleada B: fusion Expedientes en Pacientes (+chip sin visita 6m), sidebar colapsable SKEEN, edicion completa de citas, autocompletado de paciente, bloqueos excluidos de slots 2026-09-11 10:38:08 +00:00
0b45abc197 Gerencia rango operativo (crear citas), permisos por prefijo para rutas de detalle, matriz alineada (inventario para recepcion) 2026-09-11 09:48:37 +00:00
212f51cf9e Login: mensaje amigable y ojo de password; agenda: click en celda libre para agendar (estilo Google Calendar) 2026-09-09 10:37:15 +00:00
c7dcd171ee Fix pantalla en blanco al entrar: landing por rol cuando el Dashboard no es visible + matrices de menus coherentes 2026-09-08 22:17:21 +00:00
b101468c7a Login: busqueda de usuario insensible a mayusculas/minisculas 2026-09-08 21:55:02 +00:00
4f9a16103f Corte de caja asistido (esperado vs contado, diferencias, PDF) y fotos antes/despues con comparacion en expediente 2026-09-08 07:27:57 +00:00
e8690dd74e Monitoreo de salud del sistema cada 15 min con alertas por WhatsApp (doc tecnica) 2026-09-08 06:11:01 +00:00
b71b730a73 Guia WACRM: capturas corregidas (modal asignar abierto, anotaciones reposicionadas) 2026-09-08 01:35:16 +00:00
6baa8756f2 Guia WACRM ilustrada para usuarios finales: capturas anotadas, letra grande, lenguaje llano 2026-09-08 01:27:17 +00:00
6434c4f86a Guia WACRM version usuario final (sin detalle tecnico, URLs del tunel) + PDF 2026-09-08 01:02:25 +00:00
b825764ed7 Guia WACRM en PDF 2026-09-07 19:48:27 +00:00
1c438c24c5 Guia completa de uso del WACRM (revisado en vivo: webhook, envios, Sofia/Hermes, integracion SKEEN, limitaciones) 2026-09-06 09:06:01 +00:00
42536e9d2a Roles: administracion renombrado a gerencia 2026-09-03 04:16:59 +00:00
bf659bf652 Roles: entrenador renombrado a administracion (administracion de clinica, sin Configuracion) 2026-09-03 00:32:40 +00:00
3f6f1c5f8f delta_import: desactivar _check_bloqueos y dedup de servicios HIST por codigo (reimport robusto) 2026-09-02 23:45:43 +00:00
cfacb23f45 UX: notificaciones de chat con toast y sonido (WebAudio) + skeletons de carga en Agenda y Chat 2026-09-01 22:51:01 +00:00
f0d7ac4c01 POS: boton Cobrar desde cita (precarga paciente/servicio/doctor) y ticket termico imprimible con reimpresion en Ventas 2026-09-01 22:39:26 +00:00
2710d9d92d UX Pacientes: drawer de ficha clicable global, cumpleanos en dashboard/agenda, badges VIP/alergias/adeudo en ficha y POS 2026-09-01 22:26:09 +00:00
7261da3ab1 Agenda UX: nav de fecha con Hoy, linea de hora actual, colores por categoria, tooltips, vista Semana y Reagendar 2026-09-01 21:59:48 +00:00
bf36fb5586 POS: selector Doctor que atendio para asignar la venta completa a un doctor (comisiones) 2026-08-31 06:00:04 +00:00
fea4918494 Staff: campo tipo Doctor/Cosmetologa, filtro por tipo en agenda y selector editable en modulo Medicos 2026-08-31 05:19:13 +00:00
339ba235b1 Configuracion: seccion Comisiones con % global default y % editable por doctor 2026-08-31 04:45:45 +00:00