Citas: doble confirmacion (1ra telefonica con quien/cuando, 2da = llegada/check-in) + filtro rapido Por confirmar

This commit is contained in:
2026-08-31 00:45:05 +00:00
parent 681c0a9173
commit 1c31eecb8c
4 changed files with 166 additions and 7 deletions

View File

@@ -351,6 +351,10 @@ class SkeenFrontendController(http.Controller):
if kw.get('search'):
s = kw.get('search')
domain += ['|', '|', ('name', 'ilike', s), ('partner_id.name', 'ilike', s), ('servicio_id.name', 'ilike', s)]
# pending_confirm=1: citas activas SIN 1ra confirmación telefónica
if kw.get('pending_confirm') in ('1', 'true', 'True'):
domain.append(('phone_confirmed', '=', False))
domain.append(('state', 'not in', ('cancelled', 'no_show', 'done')))
page = max(int(kw.get('page', 1) or 1), 1)
page_size = min(max(int(kw.get('page_size', 50) or 50), 1), 200)
Citas = request.env['skeen.cita'].sudo()
@@ -585,6 +589,39 @@ class SkeenFrontendController(http.Controller):
except Exception as e:
return json_response({'status': 'error', 'message': str(e)}, 500)
@http.route('/skeen/frontend/v1/appointments/<int:appointment_id>/phone_confirm', type='http', auth='none', methods=['POST', 'OPTIONS'], csrf=False)
@require_role('recepcion')
def appointment_phone_confirm(self, appointment_id, **kw):
"""Toggle de la 1ra confirmación (telefónica) de una cita.
Body: {"confirmed": true|false}. Si no se envía, invierte el valor actual.
Registra quién (login del usuario frontend) y cuándo confirmó.
Permiso: recepción+ (mismo nivel que check-in/no-show; el rol medico
tiene el mismo rango y también puede confirmar).
"""
try:
cita = request.env['skeen.cita'].sudo().browse(appointment_id)
if not cita.exists():
return json_response({'status': 'error', 'message': 'Cita no encontrada'}, 404)
data = _parse_json_body()
confirmed = bool(data.get('confirmed', not cita.phone_confirmed))
if confirmed:
cita.write({
'phone_confirmed': True,
'phone_confirmed_at': fields.Datetime.now(),
'phone_confirmed_by': request.frontend_user.login,
})
else:
cita.write({
'phone_confirmed': False,
'phone_confirmed_at': False,
'phone_confirmed_by': False,
})
return json_response({'status': 'success', 'appointment': self._appointment_to_dict(cita)})
except Exception as e:
request.env.cr.rollback()
return json_response({'status': 'error', 'message': str(e)}, 500)
@http.route('/skeen/frontend/v1/appointments/<int:appointment_id>/package_finished', type='http', auth='none', methods=['POST', 'OPTIONS'], csrf=False)
@require_role('recepcion')
def appointment_package_finished(self, appointment_id, **kw):
@@ -735,6 +772,10 @@ class SkeenFrontendController(http.Controller):
'is_first_visit': False,
'package_finished': cita.package_finished,
'package_finished_date': cita.package_finished_date.strftime('%Y-%m-%d %H:%M') if cita.package_finished_date else None,
# 1ra confirmación (teléfono). La 2da (llegada) se refleja en state.
'phone_confirmed': cita.phone_confirmed,
'phone_confirmed_at': cita.phone_confirmed_at.strftime('%Y-%m-%d %H:%M') if cita.phone_confirmed_at else None,
'phone_confirmed_by': cita.phone_confirmed_by or None,
}
# ============================================================