194 lines
7.2 KiB
Python
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
|