Files
SKEEN-Proyecto/odoo-addons/skeen_plataforma/models/eventos.py

194 lines
7.2 KiB
Python

# -*- coding: utf-8 -*-
"""Emisión de eventos de webhook desde los flujos existentes.
Cada override comprueba primero si hay algún webhook activo (una consulta
barata sobre una tabla normalmente vacía); si no lo hay, se comporta
EXACTAMENTE como antes y no crea ninguna fila. La entrega real es asíncrona
(cron), así que aquí solo se encola.
"""
import logging
from odoo import api, models
_logger = logging.getLogger(__name__)
def _emitir(env, evento, payload, clave_unica=None):
"""Encapsula la emisión para que NUNCA tumbe la operación de negocio."""
try:
service = env['skeen.webhook.service'].sudo()
if not service.hay_activos():
return
service.emitir(evento, payload, clave_unica=clave_unica)
except Exception:
_logger.exception('No se pudo emitir el evento de webhook %s', evento)
def _val(record, campo):
valor = getattr(record, campo, None)
if hasattr(valor, 'id'): # many2one
return valor.id or False
if hasattr(valor, 'name'): # recordset
return valor.name
if hasattr(valor, 'isoformat'): # fecha/datetime
return valor.isoformat()
return valor
def _cita_payload(cita):
return {
'id': cita.id,
'reference': cita.name,
'state': cita.state,
'date': cita.date.isoformat() if cita.date else '',
'patient_id': cita.partner_id.id,
'patient': cita.partner_id.name or '',
'service_id': cita.servicio_id.id if cita.servicio_id else None,
'servicio': cita.servicio_id.name if cita.servicio_id else '',
'doctor': cita.doctor_id.name if getattr(cita, 'doctor_id', None) else '',
}
class SkeenCita(models.Model):
_inherit = 'skeen.cita'
@api.model_create_multi
def create(self, vals_list):
citas = super().create(vals_list)
for cita in citas:
_emitir(self.env, 'cita.creada', _cita_payload(cita),
clave_unica='cita.creada:%s' % cita.id)
return citas
def write(self, vals):
if 'state' not in vals:
return super().write(vals)
previo = {c.id: c.state for c in self}
res = super().write(vals)
destinos = {
'confirmed': 'cita.confirmada',
'cancelled': 'cita.cancelada',
'no_show': 'cita.no_show',
'done': 'cita.completada',
}
for cita in self:
evento = destinos.get(cita.state)
if evento and previo.get(cita.id) != cita.state:
_emitir(self.env, evento, _cita_payload(cita),
clave_unica='%s:%s' % (evento, cita.id))
return res
class SkeenVenta(models.Model):
_inherit = 'skeen.venta'
def write(self, vals):
if 'state' not in vals and 'refunded' not in vals:
return super().write(vals)
previo = {v.id: (v.state, v.refunded) for v in self}
res = super().write(vals)
for venta in self:
antes = previo.get(venta.id, (None, None))
if venta.state == 'paid' and antes[0] != 'paid':
_emitir(self.env, 'venta.pagada', {
'id': venta.id, 'reference': venta.name, 'state': venta.state,
'total': _val(venta, 'total'), 'patient_id': venta.partner_id.id,
}, clave_unica='venta.pagada:%s' % venta.id)
if (venta.state == 'cancelled' and antes[0] != 'cancelled') or \
(venta.refunded and not antes[1]):
_emitir(self.env, 'venta.cancelada', {
'id': venta.id, 'reference': venta.name, 'state': venta.state,
'refunded': bool(venta.refunded), 'refund_amount': _val(venta, 'refund_amount'),
}, clave_unica='venta.cancelada:%s' % venta.id)
return res
class SkeenPago(models.Model):
_inherit = 'skeen.pago'
@api.model_create_multi
def create(self, vals_list):
pagos = super().create(vals_list)
for pago in pagos:
_emitir(self.env, 'pago.registrado', {
'id': pago.id, 'reference': pago.name, 'amount': pago.amount,
'payment_method': pago.payment_method, 'state': pago.state,
'patient_id': pago.partner_id.id if pago.partner_id else None,
}, clave_unica='pago.registrado:%s' % pago.id)
return pagos
class ResPartner(models.Model):
_inherit = 'res.partner'
@api.model_create_multi
def create(self, vals_list):
partners = super().create(vals_list)
for partner in partners:
if not partner.is_patient:
continue
_emitir(self.env, 'paciente.creado', {
'id': partner.id, 'name': partner.name,
'phone': partner.phone or '', 'email': partner.email or '',
'is_patient': True,
}, clave_unica='paciente.creado:%s' % partner.id)
return partners
class SkeenMembresia(models.Model):
_inherit = 'skeen.membresia'
def action_renovar(self, *args, **kwargs):
res = super().action_renovar(*args, **kwargs)
for membresia in self:
_emitir(self.env, 'membresia.renovada', {
'id': membresia.id,
'plan': membresia.plan_id.name if membresia.plan_id else '',
'estado': membresia.estado,
'periodo_actual_inicio': _val(membresia, 'periodo_actual_inicio'),
'periodo_actual_fin': _val(membresia, 'periodo_actual_fin'),
'patient_id': membresia.partner_id.id if membresia.partner_id else None,
}, clave_unica='membresia.renovada:%s:%s'
% (membresia.id, _val(membresia, 'periodo_actual_inicio')))
return res
class SkeenFormularioRespuesta(models.Model):
_inherit = 'skeen.formulario.respuesta'
def write(self, vals):
if vals.get('estado') != 'llenado':
return super().write(vals)
previo = {r.id: r.estado for r in self}
res = super().write(vals)
for respuesta in self:
if previo.get(respuesta.id) != 'llenado':
_emitir(self.env, 'formulario.llenado', {
'id': respuesta.id,
'plantilla': _val(getattr(respuesta, 'plantilla_id', None), 'name')
if getattr(respuesta, 'plantilla_id', None) else '',
'estado': respuesta.estado,
'patient_id': respuesta.partner_id.id if getattr(respuesta, 'partner_id', None) else None,
}, clave_unica='formulario.llenado:%s' % respuesta.id)
return res
class SkeenCompra(models.Model):
_inherit = 'skeen.compra'
def write(self, vals):
if 'estado' not in vals:
return super().write(vals)
previo = {c.id: c.estado for c in self}
res = super().write(vals)
for compra in self:
if compra.estado in ('recibida', 'recibida_parcial') \
and previo.get(compra.id) != compra.estado:
_emitir(self.env, 'compra.recibida', {
'id': compra.id,
'referencia': _val(compra, 'name') or _val(compra, 'referencia'),
'estado': compra.estado,
}, clave_unica='compra.recibida:%s:%s' % (compra.id, compra.estado))
return res