fase 3.1: recursos fisicos en agenda (modelo skeen.recurso con semilla cabina/consultoria, asignacion multiple a citas con validacion de solape, bloqueos por recurso, lista de espera desde recursos, vista/filtro por recurso, reporte de ocupacion); apagado por defecto
This commit is contained in:
@@ -606,6 +606,66 @@ def get_membresias(env):
|
||||
"""Bloque de membresías vigente (copia). Fuente única para modelos y API."""
|
||||
return normalizar_membresias(get_settings(env).get('membresias'))
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Recursos físicos de la agenda (cabinas, salas, consultorios, equipos).
|
||||
#
|
||||
# Bloque anidado del mismo JSON de ajustes, igual que `impuestos`. La regla de
|
||||
# oro: con `activo=False` (default) NADA cambia en la agenda — no aparece la
|
||||
# sección en Configuración ni el selector en el modal de cita, la agenda se ve
|
||||
# igual que hoy y no corre ninguna validación de solape de recursos. Por eso el
|
||||
# default es apagado.
|
||||
#
|
||||
# activo: enciende todo el módulo de recursos
|
||||
# validar_solape: impide dos citas/bloqueos en el mismo recurso a la
|
||||
# misma hora (solo aplica si activo)
|
||||
# obligatorio_al_agendar: exige elegir al menos un recurso al crear la cita
|
||||
# permitir_multiples: permite asignar más de un recurso a una cita
|
||||
# mostrar_en_agenda: muestra el recurso (chips/color) en las tarjetas
|
||||
# filtrar_como_doctores: ofrece el filtro por recurso junto al de doctores
|
||||
# ---------------------------------------------------------------------------
|
||||
RECURSOS_DEFAULT = {
|
||||
'activo': False,
|
||||
'validar_solape': True,
|
||||
'obligatorio_al_agendar': False,
|
||||
'permitir_multiples': True,
|
||||
'mostrar_en_agenda': True,
|
||||
'filtrar_como_doctores': True,
|
||||
}
|
||||
|
||||
RECURSOS_BOOLEANOS = tuple(RECURSOS_DEFAULT)
|
||||
|
||||
|
||||
def normalizar_recursos(raw):
|
||||
"""Bloque `recursos` completo, con defaults. Tolerante: nunca lanza."""
|
||||
out = dict(RECURSOS_DEFAULT)
|
||||
if not isinstance(raw, dict):
|
||||
return out
|
||||
for k in RECURSOS_BOOLEANOS:
|
||||
out[k] = _bool(raw.get(k), RECURSOS_DEFAULT[k])
|
||||
return out
|
||||
|
||||
|
||||
def validar_recursos(raw):
|
||||
"""Valida el bloque `recursos` de un PUT. Lanza ValueError si algo no
|
||||
cuadra (se traduce a 400). Devuelve SOLO las claves presentes y normalizadas
|
||||
para que el merge anidado no reinicie lo que el PUT no tocó."""
|
||||
if raw is None:
|
||||
return None
|
||||
if not isinstance(raw, dict):
|
||||
raise ValueError('El bloque de recursos debe ser un objeto')
|
||||
out = {}
|
||||
for k in RECURSOS_BOOLEANOS:
|
||||
if k in raw:
|
||||
if not isinstance(raw[k], bool):
|
||||
raise ValueError('El campo %s debe ser verdadero o falso' % k)
|
||||
out[k] = raw[k]
|
||||
return out
|
||||
|
||||
|
||||
def get_recursos(env):
|
||||
"""Bloque de recursos vigente (copia). Fuente única para modelos y API."""
|
||||
return normalizar_recursos(get_settings(env).get('recursos'))
|
||||
|
||||
# Horas de agenda de respaldo: el comportamiento de siempre (8:00-19:00).
|
||||
AGENDA_START_DEFAULT = 8.0
|
||||
AGENDA_END_DEFAULT = 19.0
|
||||
@@ -649,6 +709,7 @@ def get_settings(env):
|
||||
'reservas_online': dict(RESERVAS_ONLINE_DEFAULT),
|
||||
'notificaciones': normalizar_notificaciones(None),
|
||||
'membresias': normalizar_membresias(None),
|
||||
'recursos': dict(RECURSOS_DEFAULT),
|
||||
}
|
||||
raw = env['ir.config_parameter'].sudo().get_param(SETTINGS_KEY)
|
||||
if raw:
|
||||
@@ -664,6 +725,7 @@ def get_settings(env):
|
||||
out['reservas_online'] = normalizar_reservas_online(guardado.get('reservas_online'))
|
||||
out['notificaciones'] = normalizar_notificaciones(guardado.get('notificaciones'))
|
||||
out['membresias'] = normalizar_membresias(guardado.get('membresias'))
|
||||
out['recursos'] = normalizar_recursos(guardado.get('recursos'))
|
||||
return out
|
||||
|
||||
|
||||
@@ -692,6 +754,10 @@ def set_settings(env, vals):
|
||||
bloque = validar_membresias(vals['membresias'])
|
||||
if bloque is not None:
|
||||
actual['membresias'] = {**actual['membresias'], **bloque}
|
||||
if 'recursos' in vals:
|
||||
bloque = validar_recursos(vals['recursos'])
|
||||
if bloque is not None:
|
||||
actual['recursos'] = {**actual['recursos'], **bloque}
|
||||
env['ir.config_parameter'].sudo().set_param(
|
||||
SETTINGS_KEY, json.dumps(actual, ensure_ascii=False))
|
||||
return get_settings(env)
|
||||
|
||||
Reference in New Issue
Block a user