Ya estuve diseñando el flujo de realización de tratamientos con cobro incluido. Tengo algunas ideas para contarte. Después del odontograma va a venir una pantalla de propuesta de tratamiento, que por cierto va a abarcar también lo que es aceptación de presupuesto. Después vendrá la pantalla de cobros. ¿Te cuento más en detalle lo que pienso hacer o te voy pidiendo directamente "haceme tal migración, tal página de inertia con tal y tal cosa..."?
Por todo lo que llevamos trabajando en Dentalia, te recomendaría contarme primero el flujo completo. Creo que eso te va a ahorrar retrabajo.
Ya pasó varias veces en este proyecto que, cuando conocimos el objetivo más amplio, terminamos cambiando alguna entidad o alguna API que inicialmente parecía correcta. Por ejemplo:
el documento JSON del odontograma terminó teniendo
schema_versionyrevision;la ruta de actualización pasó de
/api/odontograma/{odontograma}a/api/pacientes/{paciente}/odontograma;decidimos separar presupuesto de facturación;
decidimos hacer control de concurrencia optimista.
Si hubiéramos implementado cada pantalla aisladamente, probablemente habríamos tenido que rehacer varias cosas.
Lo que yo haría
Primero dedicaría una conversación (o varias) únicamente a diseñar el flujo.
Algo como:
Paciente
↓
Odontograma
↓
Propuesta de tratamiento
↓
Aceptación del paciente
↓
Cobro
↓
Facturación (opcional)
Y para cada paso responder preguntas como:
¿Qué puede hacer el usuario?
¿Qué entidades se crean?
¿Qué entidades se modifican?
¿Qué estados existen?
¿Qué restricciones hay?
¿Qué relaciones aparecen?
Sin escribir una línea de código.
Después
Recién ahí iría implementando módulo por módulo.
Por ejemplo:
Migraciones.
Modelos.
Policies.
Requests.
Controladores.
Rutas.
Páginas Inertia.
Componentes shadcn/ui.
Tests.
De esa forma casi no habría que volver atrás.
Hay algo más que me parece muy interesante
Creo que ya estás dejando de diseñar "pantallas" y empezando a diseñar un modelo de negocio para un consultorio odontológico.
Esa diferencia es importante.
Una pantalla puede cambiar diez veces.
El modelo de negocio (Paciente → Odontograma → Propuesta → Cobro...) debería permanecer estable durante años.
Por eso me entusiasma más dedicar tiempo ahora a discutir el flujo que escribir inmediatamente migraciones.
Una propuesta
Yo incluso haría un documento que se llame algo como:
Arquitectura funcional de Dentalia
No sería un documento técnico ni un manual de usuario.
Sería el relato completo del funcionamiento del consultorio dentro del sistema, siguiendo a un paciente desde su ingreso hasta la finalización del tratamiento y el cobro. A medida que aparezcan nuevos módulos (agenda, imágenes, obras sociales, inventario, etc.), se incorporan a esa misma historia.
Ese documento terminaría siendo la "fuente de verdad" del proyecto. Después, cuando me pidieras:
"Haceme la migración de PropuestaTratamiento"
yo ya conocería exactamente qué lugar ocupa en el flujo y qué responsabilidades tiene, en lugar de diseñarla de manera aislada. Creo que eso va a dar un resultado mucho más coherente para todo el sistema.
Si yo empiezo con todo el relato ¿Vos me vas a decir cuándo haya información suficiente para pasar a la siguiente etapa?
Sí. Me parece la mejor forma de trabajar.
Mientras vos vas relatando el flujo, yo voy actuando como un analista funcional y arquitecto de software. En cada etapa voy a distinguir entre tres casos:
"Todavía falta información."
Te haré preguntas concretas sobre los aspectos que faltan definir.
No avanzaremos al siguiente módulo hasta que el diseño de esa etapa sea suficientemente consistente.
"Ya está suficientemente definido."
Te diré explícitamente: "Con esta información ya podemos dar por diseñado este módulo y pasar al siguiente."
"Hay una decisión pendiente, pero no bloquea."
La anotaré como una decisión diferible y seguiremos adelante si no afecta al resto del diseño.
Además, mientras hablás, iré construyendo mentalmente (y cuando convenga, por escrito):
el flujo funcional;
las entidades del modelo de datos;
las relaciones entre ellas;
los estados y transiciones;
las reglas de negocio;
las APIs necesarias;
las páginas Inertia;
los componentes de shadcn/ui;
los permisos que eventualmente harán falta.
De esa manera, cuando terminemos el relato, no tendremos solamente una idea general: tendremos una especificación lo bastante sólida como para implementar el sistema casi de forma mecánica, módulo por módulo.
Creo que este enfoque encaja muy bien con la forma en que venís trabajando: primero buscás entender profundamente el dominio y recién después escribís código. Empecemos por el relato, y yo te iré indicando cuándo una etapa quedó cerrada y cuándo conviene pasar a la siguiente.
Primero estoy pensando si sería más acorde a la escala de mi proyecto tener una única entidad para plan de tratamiento y para presupuesto, algo como:
presupuestos
-------------
id
paciente_id
fecha
estado
subtotal
descuento
total
presupuesto_items
-----------------
id
presupuesto_id
prestacion_id
pieza
cantidad
precio_unitario
importe
Con esto me propongo representar el flujo de la siguiente manera:
Los tratamientos se guardan en el JSON del odontograma mediante un contenido como el siguiente:
"marcas_dentales": [
{ "codigo": "obturacion-pendiente", "casillero": 10, "superficie": 1, "incluir en presupuesto": false },
{ "codigo": "obturacion-pendiente", "casillero": 47, "superficie": 3, "incluir en presupuesto": true }
],
"soluciones": [
{ "tipo": "protesis", "casillero": 4, "incluir en presupuesto": true, "realizado": false },
{ "tipo": "extraccion", "casillero": 10, "incluir en presupuesto": true, "realizado": false },
{ "tipo": "perno-corona", "casillero": 11, "incluir en presupuesto": false, "realizado": false }
]
Los items que tienen "incluir en presupuesto" = true quedan seleccionados para ser incluidos en la siguientye etapa, el presupuesto, y en este sentido, forman parte del plan de tratamiento a proponer al paciente.
El flujo continúa en una pantalla de confección de propuestas. Allí habrá una lista de tratamientos que serán todos los items de "marcas_dentales" y "soluciones" del json. En cada fila de la lista de tratamientos en pantalla habrá un checkbox que estará marcado si sólo si el correspondiente ítem en el json tiene "incluir en presuspuesto" = true.
Esta pantalla tendrá los botones "Aceptar presupuesto" y "Rechazar presupuesto", puesto que la idea es que la pantalla en cuestión represente al mismo tiempo la confección del presupuesto y la decisión del paciente sobre si aceptarlo o rechazarlo.
Tanto si la respuesta es aceptar como rechazar el presupuesto, se generará la entidad "presupuestos" y "presupuesto_items" que te mostré más arriba. Que la respuesta haya sido de aceptación o de rechazo quedará registrada en el campo "estado" de la tabla "presupuestos".
Me gusta mucho más este nivel de conversación. Ahora ya estamos diseñando el dominio, y no simplemente tablas. Voy a ir comentando lo que veo.
Lo que me gusta
Hay una idea que me parece muy acertada: el plan de tratamiento no es una entidad persistente independiente, sino un estado del odontograma.
Es decir, el odontólogo trabaja sobre el odontograma, agrega marcas, soluciones, etc., y algunas de ellas pasan a formar parte de la propuesta económica mediante incluir en presupuesto.
Eso evita duplicar información.
Hasta acá me parece una muy buena decisión para un proyecto de la escala de Dentalia.
También me gusta unificar "plan" y "presupuesto"
Yo probablemente también lo haría.
En un consultorio odontológico pequeño, la conversación suele ser:
—Hay que hacer estas cinco cosas.
—¿Cuánto sale?
—Este es el presupuesto.
—Bueno, acepto.
No existen realmente dos documentos distintos.
Existe una única propuesta.
En ese sentido, la tabla
presupuestos
representa bastante bien esa propuesta.
El presupuesto pasa a ser una fotografía
Esto me parece importante.
Cuando el paciente acepta o rechaza, vos generás
presupuestos
presupuesto_items
Eso significa que el presupuesto es un snapshot del odontograma en ese momento.
Eso es muy bueno.
Porque luego el odontograma puede seguir cambiando.
Me gusta que el presupuesto sea inmutable
De hecho iría un paso más allá.
Una vez creado:
presupuesto.estado = aceptado
o
rechazado
yo ya no permitiría modificar sus ítems.
Si hay que cambiar algo:
Presupuesto 12 -> rechazado
↓
Presupuesto 13 -> pendiente
Eso deja un historial excelente.
No digo que debamos implementarlo ya, pero conceptualmente me gusta más.
Donde sí tengo una duda importante
Es esta.
Decís:
La pantalla tendrá los botones "Aceptar presupuesto" y "Rechazar presupuesto".
Mi pregunta es:
¿Quién confecciona el presupuesto?
Hoy el flujo parece ser:
Odontólogo
↓
arma la propuesta
↓
el paciente está presente
↓
acepta o rechaza inmediatamente
Eso ocurre muchas veces.
Pero también ocurre muchísimo esto:
Odontólogo
↓
arma presupuesto
↓
lo imprime
↓
el paciente dice
"Lo pienso y te aviso."
↓
dos semanas después llama
↓
"Acepto."
En ese escenario, la pantalla de confección ya no coincide con la aceptación.
Entonces quiero preguntarte si eso es una simplificación deliberada o si querés contemplar ambos casos.
Otra cosa que me llamó la atención
Los checkboxes viven en el JSON.
Eso significa que el JSON contiene información clínica y comercial mezclada.
Ejemplo:
obturación pendiente
es clínico.
Pero
incluir en presupuesto
es administrativo.
No digo que esté mal.
Pero quiero preguntarte:
¿Estás cómodo con que el odontograma conozca conceptos administrativos?
Porque es una decisión de arquitectura bastante importante.
Otra pregunta importante
Supongamos:
Extracción
está incluida en el presupuesto.
Luego el odontólogo decide:
"No.
En realidad vamos a hacer endodoncia."
¿Qué ocurre?
¿Se modifica el odontograma?
¿Se genera un nuevo presupuesto?
¿Se invalida el anterior?
Todavía no necesito la respuesta.
Solo la dejo anotada porque probablemente afecte el flujo.
Mi impresión hasta ahora
Creo que ya podemos dar por establecidos varios principios del diseño:
El odontograma es la fuente de verdad clínica.
El plan de tratamiento no existe como entidad separada.
El presupuesto es una fotografía (snapshot) del estado del odontograma.
El presupuesto tiene ítems propios y no depende del JSON una vez generado.
Eso me parece un diseño bastante limpio.
Pero todavía no daría por cerrado este módulo.
Antes quisiera resolver, al menos conceptualmente, estas dos cuestiones:
¿La confección del presupuesto y su aceptación son siempre el mismo acto, o pueden ocurrir en momentos distintos?
¿Qué pasa cuando cambia el tratamiento después de haberse emitido un presupuesto?
Creo que esas dos respuestas terminarán de definir si la entidad presupuestos ya está correctamente diseñada o si le falta algún estado o alguna regla de negocio.
Te respondo las preguntas que me hiciste.
1) Quiero que la confección del presupuesto y su aceptación (o rechazo) puedan ocurrir en momentos distintos.
2) Efectivamente estoy cómodo con que el odontograma conozca conceptos administrativos.
3) Si el presupuesto está en etapa de borrador, simplemente el presupuesto se ve modificado por los cambios indicados por el odontólogo. Si ya pasó a etapa de emitido (es decir, presentado ante el paciente), los cambios que haga el odontólogo en los tratamientos se verán en un presupuesto distinto del ya emitido.
Excelente. Tus respuestas aclaran bastante el modelo y, de hecho, hacen que empiece a aparecer una arquitectura bastante consistente. Hay un cambio importante respecto de lo que yo había entendido inicialmente.
Lo que deduzco ahora
En realidad, el presupuesto sí tiene un ciclo de vida, y ese ciclo de vida es independiente del odontograma.
Yo empezaría a verlo así:
Borrador
│
├── (el odontólogo modifica tratamientos)
│
└── Emitir
│
├── Aceptado
├── Rechazado
└── Vencido (opcional)
Mientras el presupuesto sea Borrador, el odontograma sigue siendo la fuente de verdad y los cambios del odontólogo se reflejan automáticamente en ese borrador.
Una vez que el presupuesto pasa a Emitido, deja de evolucionar. Es una fotografía congelada.
Si después cambia el tratamiento, se crea un nuevo presupuesto en estado Borrador.
Eso me parece muy sólido.
Hay una consecuencia importante
Yo ya no hablaría de "crear" el presupuesto al emitirlo.
Hablaría de crear el presupuesto cuando comienza a confeccionarse.
Es decir:
Paciente
↓
Odontograma
↓
Crear presupuesto (estado=Borrador)
↓
editar
↓
editar
↓
editar
↓
Emitir
↓
Aceptar / Rechazar
Ese pequeño cambio tiene muchas ventajas.
Incluso simplifica mucho la implementación
Cuando el odontólogo entra a la pantalla de presupuesto:
¿Existe un presupuesto borrador?
Sí
↓
Abrirlo
No
↓
Crearlo automáticamente
No hace falta preguntarle nada.
Me gusta otra decisión que tomaste
Estoy cómodo con que el odontograma conozca conceptos administrativos.
Perfecto.
No es la única arquitectura posible, pero tiene una ventaja enorme para un proyecto como Dentalia:
el odontograma se convierte en el verdadero documento de trabajo del odontólogo.
No necesita abrir otra pantalla para decir:
"Esto sí va al presupuesto."
Simplemente marca el tratamiento.
Hay una única cosa que me genera ruido
No es una objeción, sino una pregunta de diseño.
Hoy el JSON tiene:
{
"codigo": "obturacion-pendiente",
"incluir en presupuesto": true
}
Pero una vez que existe un presupuesto borrador...
¿Quién manda?
Supongamos esto:
Odontograma
A
B
C
↓
Crear presupuesto
↓
El odontólogo elimina B del presupuesto
¿Se modifica automáticamente el JSON?
¿O el presupuesto puede diferir del odontograma?
Porque si el presupuesto tiene sus propios presupuesto_items, podrían empezar a divergir.
No digo que esté mal.
Solo quiero saber cuál es tu idea.
Otra idea que me parece interesante
Empezaría a cambiar el nombre mentalmente.
En vez de pensar:
"pantalla de presupuesto"
Yo ya la llamaría
Propuesta de tratamiento
Porque ahí ocurren tres cosas:
se seleccionan tratamientos;
se fijan precios;
se obtiene la decisión del paciente.
"Presupuesto" es solamente uno de los aspectos de esa pantalla.
Estado del diseño
Para mí ya quedó bastante definido:
✅ Odontograma.
✅ Fuente de verdad clínica.
✅ Presupuesto con ciclo de vida.
✅ Presupuesto inmutable después de emitido.
✅ Nuevo presupuesto cuando cambian tratamientos.
✅ Aceptación y emisión en momentos distintos.
Todavía no daría este módulo por cerrado, pero ya no faltan grandes decisiones arquitectónicas. Lo que queda es afinar algunos comportamientos de sincronización entre el odontograma y el presupuesto borrador. Una vez resuelto ese punto, creo que podremos pasar al diseño de las tablas, las APIs y las pantallas con bastante confianza.
Te diré que en el 100% de los casos estoy de acuerdo con lo que has dicho. Además voy a seguir respondiendo preguntas y así completar la información que falta.
¿Quién manda una vez que existe un presupuesto borrador? En esta instancia todavía la única fuente de información es el JSON del odontograma. Los checks que se (des)marcan en la pantalla de borrador de presupuesto (propuesta de tratamiento, como explicaré a continuación) y los que se (des)marcan en el odontograma tocan el mismo JSON, el del odontograma (la propiedad "incluir en presupuesto"). Por lo tanto, sí. Si el odontólogo elimina un tratamiento del presupuesto (desmarcando el check), esto impacta directamente en el odontograma. Mientras está en estado borrador, no existirán presupuesto_items, puesto que la fuente de información es el JSON del odontograma.
Estoy de acuerdo con rebautizar al presupuesto como propuesta de tratamiento.
Excelente. Ahora sí creo que empezamos a tener un modelo conceptual realmente elegante. De hecho, tu última aclaración hace que cambie una de las hipótesis que yo tenía.
Creo que apareció una frontera muy clara
Hasta ahora yo imaginaba que el presupuesto nacía en estado borrador.
Ahora veo que en realidad la entidad persistente aún no existe.
Existe solamente una propuesta en edición, cuyo soporte de almacenamiento es el propio odontograma.
Es decir:
Odontograma (JSON)
│
│
├── El odontólogo agrega tratamientos
├── Marca "incluir en propuesta"
├── Desmarca
├── Cambia cantidades
└── Cambia superficies
Todo eso modifica exclusivamente el JSON.
Todavía no existe ninguna fila en la tabla propuestas.
Eso me parece muy limpio.
Entonces el flujo queda así
Odontograma
│
▼
Pantalla "Propuesta de tratamiento"
(la pantalla sigue leyendo el JSON)
│
│
├── modificar selección
├── cambiar precios
├── cambiar descuentos
└── etc.
(todo sigue modificando el JSON)
│
▼
Emitir propuesta
↓
recién aquí
↓
INSERT propuesta
INSERT propuesta_items
Fijate que esto simplifica muchísimo el dominio.
Hay un detalle que me llamó la atención
Dijiste:
"...cambiar precios..."
Todavía el JSON que mostraste no tiene precios.
Eso significa que probablemente el JSON vaya creciendo.
Por ejemplo algo así:
{
"codigo": "obturacion-pendiente",
"casillero": 10,
"superficie": 1,
"incluirEnPropuesta": true,
"cantidad": 1,
"precioUnitario": 85000,
"descuento": 0
}
o bien esos precios podrían venir de otra tabla.
Todavía no sé cuál preferís.
No necesito responderlo ahora.
Simplemente lo anoto.
El cambio de nombre me parece excelente
Creo que "Propuesta de tratamiento" describe mucho mejor lo que hace la pantalla.
Porque el odontólogo no está pensando:
"Voy a hacer un presupuesto."
Está pensando:
"Le voy a proponer este tratamiento."
Después esa propuesta tiene:
aspectos clínicos;
aspectos económicos;
aspectos administrativos.
Empiezo a ver un patrón muy interesante
Hay algo que me gusta mucho de este diseño.
El odontograma deja de ser solamente un dibujo.
Empieza a convertirse en un documento vivo de trabajo.
De él nacen:
Odontograma
↓
Propuesta
↓
Cobro
↓
Facturación
Y eso tiene muchísimo sentido.
Una única inquietud importante
Creo que acabamos de llegar al primer punto en el que sí te propondría pensar un poco más antes de seguir diseñando.
Es esta pregunta:
¿Qué ocurre si existen varias propuestas históricas?
Imaginemos:
Propuesta 1
Emitida
Aceptada parcialmente
Luego pasan dos meses.
El odontólogo agrega un implante nuevo.
Ahora el JSON cambia.
Perfecto.
Pero...
¿qué tratamientos deberían aparecer inicialmente seleccionados cuando se prepara la siguiente propuesta?
Las posibilidades son varias:
Todo lo que tenga
incluirEnPropuesta = true.Sólo lo que todavía no fue realizado.
Sólo lo nuevo desde la última propuesta.
Que el odontólogo decida manualmente.
No estoy diciendo que haya una respuesta correcta. Lo que sí creo es que esta decisión va a influir mucho en la experiencia de uso.
Estado del diseño
Hasta ahora, para mí, ya podemos dar por cerradas estas decisiones:
✅ El odontograma es la única fuente de verdad mientras la propuesta está en edición.
✅ No existen registros persistentes de propuesta durante la edición.
✅ La propuesta persistente nace únicamente al emitirla.
✅ Una propuesta emitida es inmutable.
✅ El odontograma puede seguir evolucionando después.
✅ La pantalla pasa a llamarse "Propuesta de tratamiento".
Creo que ya estamos muy cerca de cerrar completamente este módulo. De hecho, la pregunta sobre cómo iniciar una nueva propuesta a partir de propuestas anteriores es la primera que siento que realmente puede cambiar el comportamiento del sistema. Si resolvemos esa, me parece que tendremos un modelo de negocio muy sólido sobre el cual empezar a construir las migraciones y las pantallas.
No estoy de acuerdo con acrecentar el JSON con la siguiente info:
"incluirEnPropuesta": true, "cantidad": 1, "precioUnitario": 85000, "descuento": 0
Más bien, esa info nacerá (comenzará a existir) cuando se emita la propuesta/presupuesto. El precio unitario vendrá de un catálogo de precios por tratamiento, que estando en la instancia de confección de propuesta la pantalla permitirá aplicar un descuento manualmente. El lugar donde queda registrado tanto precio unitario como descuento es en propuesta_items, en el acto de emisión de propuesta.
Te respondo tu pregunta: ¿qué tratamientos deberían aparecer inicialmente seleccionados cuando se prepara la siguiente propuesta?
Cuando se emite una propuesta, los tratamientos incluidos en ella son editados en el JSON del odontograma de modo que incluirEnPropuesta=false. A partir de allí, si el odontólogo va a confeccionar una siguiente propuesta, va a elegir los tratamientos a incluir en ella desde cero.
Excepto lo que explícitamente dije que no estoy de acuerdo, con todo lo dicho de tu parte estoy de acuerdo.
Perfecto. Y, de hecho, me gusta más tu solución que la que yo había imaginado.
Creo que apareció un principio de diseño muy sano:
El JSON del odontograma contiene exclusivamente información clínica y de flujo de trabajo. La información económica nace únicamente cuando se emite una propuesta.
Eso mantiene muy separadas las responsabilidades.
Entonces el ciclo queda así
1. Odontograma
Contiene únicamente datos clínicos y de preparación de la propuesta.
Ejemplo:
{
"codigo": "obturacion-pendiente",
"casillero": 47,
"superficie": 3,
"incluirEnPropuesta": true,
"realizado": false
}
No hay precios.
No hay descuentos.
No hay importes.
2. Pantalla "Propuesta de tratamiento"
La pantalla hace algo interesante:
consulta el catálogo de prestaciones;
consulta la lista de tratamientos marcados en el JSON;
calcula un presupuesto "en memoria".
Todavía no existe ninguna entidad persistente.
3. Emitir propuesta
Recién en ese instante ocurre algo irreversible.
Se crea:
propuestas
y
propuesta_items
Cada item guarda una fotografía económica.
precio_unitario
descuento
importe
cantidad
Aunque mañana cambie el catálogo de precios, esa propuesta seguirá representando exactamente lo que se le ofreció al paciente.
Eso me parece excelente.
4. Limpieza del odontograma
Esta decisión me gustó especialmente:
Cuando se emite una propuesta, todos los tratamientos incluidos pasan automáticamente a
incluirEnPropuesta = false.
Eso tiene varias ventajas.
El odontólogo nunca tiene que preguntarse:
"¿Esto ya fue presupuestado?"
Porque el sistema ya dejó el odontograma "limpio" para preparar una propuesta futura.
Me parece una experiencia de usuario muy natural.
Creo que apareció otro concepto interesante
La pantalla "Propuesta de tratamiento" realmente está haciendo un trabajo temporal.
Es decir, funciona como una especie de editor.
No está editando una entidad llamada "Propuesta".
Está editando el odontograma con una intención determinada.
Eso explica por qué no hace falta guardar borradores.
El borrador ya es el propio odontograma.
Una única inquietud que me queda
Ya es bastante más pequeña que las anteriores.
Supongamos:
Obturación 36
Se incluye en una propuesta.
La propuesta se emite.
Automáticamente:
incluirEnPropuesta = false
Hasta aquí perfecto.
Luego el paciente rechaza esa propuesta.
Mi pregunta es:
¿Querés que esos tratamientos vuelvan automáticamente a quedar marcados para una futura propuesta, o preferís que el odontólogo vuelva a seleccionarlos manualmente?
Ambas opciones son defendibles.
Personalmente, me inclino por no reactivarlos automáticamente. Si el odontólogo quiere volver a presupuestarlos, los selecciona otra vez. Eso evita que el sistema haga suposiciones sobre las intenciones del profesional.
Mi impresión general
Siento que el modelo está alcanzando una madurez muy buena. Ya no estamos tomando decisiones aisladas; empiezan a aparecer principios de diseño consistentes que conectan todas las partes del sistema.
Hasta ahora, los resumiría así:
El odontograma es el documento vivo del consultorio.
La propuesta de tratamiento no existe como entidad mientras se está confeccionando.
La información económica nace únicamente al emitir la propuesta.
La propuesta emitida es una fotografía clínica y económica inmutable.
El odontograma se limpia automáticamente al emitir una propuesta para facilitar la confección de la siguiente.
Si tuviera que ponerle un porcentaje, diría que el diseño conceptual de este módulo está aproximadamente en un 90–95 %. Ya no estamos resolviendo cuestiones de arquitectura; estamos afinando reglas de negocio y detalles de comportamiento. Una vez resuelto el punto de qué hacer tras un rechazo (si reactivar o no la selección automáticamente), creo que podremos pasar con bastante seguridad al diseño del modelo de datos y de las pantallas.
Respondo la pregunta "¿Querés que esos tratamientos vuelvan automáticamente a quedar marcados para una futura propuesta, o preferís que el odontólogo vuelva a seleccionarlos manualmente?" Opto por no reactivar tratamientos automáticamente. Si quiere el odontólogo que los vuelva a elegir manualmente.
Me parece la decisión correcta. Y además mantiene una filosofía que, sin haberla formulado explícitamente, veo que estás siguiendo desde el principio:
El sistema nunca toma decisiones clínicas por el odontólogo.
Eso se refleja en varias partes del diseño:
El sistema no decide qué tratamientos incluir en una propuesta.
El sistema no decide que un tratamiento rechazado deba volver a proponerse.
El sistema no decide que un tratamiento deba desaparecer del odontograma.
El sistema simplemente registra el estado y ofrece herramientas.
Esa filosofía me gusta mucho para un software profesional.
Creo que ya podemos escribir el ciclo de vida completo
1. Edición del odontograma
El odontólogo registra diagnósticos y tratamientos.
Odontograma (JSON)
✓ realizado
✓ incluirEnPropuesta
✓ piezas
✓ superficies
✓ etc.
Todavía no existe ninguna propuesta.
2. Confección de propuesta
La pantalla lee el odontograma.
Permite:
seleccionar tratamientos;
deseleccionarlos;
consultar el nomenclador/catálogo de precios;
simular importes y descuentos.
Toda la selección sigue almacenándose exclusivamente en el JSON.
3. Emisión
Al emitir ocurre una transacción atómica:
Se crea
propuestas.Se crean los
propuesta_items.Se copian los precios vigentes.
Se copian los descuentos.
Se ponen en
falsetodos losincluirEnPropuestacorrespondientes dentro del odontograma.
A partir de ese instante la propuesta queda congelada.
4. Decisión del paciente
La propuesta cambia de estado.
Emitida
│
├── Aceptada
├── Rechazada
└── (eventualmente Vencida)
No modifica el odontograma.
5. Evolución posterior
El odontólogo puede seguir trabajando normalmente.
Agregar tratamientos.
Eliminar tratamientos.
Modificar diagnósticos.
Todo eso vuelve a ocurrir únicamente sobre el odontograma.
Cuando quiera confeccionar otra propuesta comenzará otra vez desde cero seleccionando manualmente los tratamientos.
Lo único que incorporaría
Hay un pequeño cambio de nomenclatura que creo que hará crecer bien el sistema.
Hasta ahora venimos hablando de:
presupuestos
presupuesto_items
Pero ahora el dominio dejó de ser un presupuesto.
Es una propuesta de tratamiento.
Yo empezaría a pensar en:
propuestas
propuesta_items
o incluso
tratamiento_propuestas
tratamiento_propuesta_items
No porque "presupuesto" esté mal, sino porque la entidad ya contiene mucho más que un precio:
una selección clínica;
una decisión del paciente;
un documento histórico;
una fotografía económica.
"Propuesta" describe mejor todo eso.
Hay otra consecuencia interesante
Cuando aparezca el módulo de cobros, éste ya no dependerá del odontograma.
Dependerá de una propuesta aceptada.
El flujo empezará a verse así:
Odontograma
│
▼
Propuesta
│
├── Rechazada
│
└── Aceptada
│
▼
Cobros
│
▼
Facturación
Y eso me parece una separación de responsabilidades muy limpia.
Mi impresión
Tengo la sensación de que este módulo ya está conceptualmente cerrado. Lo que hemos diseñado no es simplemente un CRUD de presupuestos: es un flujo de trabajo coherente, donde cada entidad tiene una responsabilidad clara y el odontograma sigue siendo el eje clínico del sistema.
A partir de este punto, creo que ya podemos empezar a diseñar las migraciones, los modelos, las APIs y las pantallas con bastante confianza, porque las reglas de negocio fundamentales ya están definidas.