7. Workflow y reglas de negocio
Objetivos
- modelar estados explícitos de documentos
- proteger transiciones mediante botones y validación
- hacer idempotentes los efectos irreversibles
Modelo mental
Este concepto debe entenderse como parte de un sistema transaccional: la interfaz ayuda al usuario, el servidor conserva las reglas y la base persiste el resultado. Un workflow es una máquina de estados, no un Selection decorativo. Las transiciones definen movimientos; los botones los exponen; los métodos protegen condiciones y efectos.
Práctica guiada
- Dibuje estados y transiciones antes de programar.
- Declare transiciones y visibilidad de botones.
- Valide requisitos antes de cambiar el estado.
- Ejecute contabilidad, numeración o notificaciones una sola vez.
- Defina una corrección controlada en lugar de SQL directo.
Ejemplo mínimo
from trytond.model import ModelSQL, ModelView, Workflow, fields
class Loan(Workflow, ModelSQL, ModelView):
"Library Loan"
__name__ = 'library.loan'
state = fields.Selection([
('draft', "Draft"), ('confirmed', "Confirmed"),
('done', "Done"), ('cancelled', "Cancelled"),
], "State", required=True, readonly=True)
@classmethod
@ModelView.button
@Workflow.transition('confirmed')
def confirm(cls, loans):
for loan in loans:
loan.check_can_confirm()
@classmethod
def default_state(cls):
return 'draft'
Cómo leer el ejemplo
Mantenga los métodos preparados para lotes. Reabrir documentos fiscales finalizados no es una transición inversa genérica: analice numeración, asientos, reportes, transmisiones externas y auditoría.
Ejercicio
Agregue devolución y cancelación, escriba una tabla de transiciones y pruebe cada arista permitida y prohibida.
Realice el ejercicio primero con un caso mínimo, después agregue un caso inválido y convierta ambos en pruebas repetibles.
Resultado verificable
Repetir una llamada no duplica efectos y las transiciones inválidas fallan con mensajes empresariales traducibles.
Errores frecuentes
- escribir state directamente
- enviar mensajes externos antes de asegurar la transacción
- suponer un registro por llamada
- permitir eliminación en vez de cancelación trazable
Criterio para avanzar
- Puedo explicar la diferencia entre los conceptos sin mirar el código.
- El caso válido y el inválido tienen pruebas.
- Probé con un usuario sin privilegios administrativos.
- Sé cómo actualizar y cómo recuperar la base de entrenamiento.
Versión y referencias
La serie 6.0 requiere como mínimo Python 3.6 según los metadatos oficiales. Esta rama oficial todavía conserva metadatos históricos en setup.py; mantenga compatibilidad con la serie, pero prepare sus paquetes personalizados para la construcción estándar mediante python -m build. No confunda ese mínimo histórico con la versión de Python que haya certificado su organización.
Esta edición fija ejemplos y dependencias en la serie 6.0. Consulte el tutorial oficial 6.0, la API del servidor y el código de esa rama antes de trasladar el patrón a producción.