Si necesitas una funcionalidad específica que no está en la biblioteca de automatismos o que el producto haga algo muy concreto para tu proceso de negocio, puedes desarrollar tu propia operación en Python. Las operaciones o automatismos personalizados son atómicos y están desacopladas del núcleo de Athento, lo que significa que puedes instalarlas o desinstalarlas sin afectar el funcionamiento global de la plataforma.
Una operación es un archivo .py que se puede ejecutar en Athento.
Para escribir el código de tu operación, puedes guiarte por la estrucutra y el código de ejemplo en este artículo.
Estructura de una operación
1. Importaciones en una operación personalizada
Las importaciones son la primera sección del archivo .py y definen qué librerías o módulos necesita tu operación para funcionar.
En una operación de Athento suelen convivir tres tipos de importaciones:
a) Librerías estándar de Python (Opcionales)
Se usan para funcionalidades genéricas del lenguaje (manejo de números, fechas, logging, etc.):
import logging
import json
from datetime import datetime👉 Ejemplo: logging permite registrar información en los logs de ejecución.
b) Componentes de Django o dependencias de terceros (Opcionales)
Athento se basa en Django, por lo que muchas operaciones utilizan utilidades de ese framework o de librerías externas.
from django.utils.translation import gettext as _
from pypdf import PdfReader
gettext(_) permite definir textos traducibles.PdfReader(depypdf) sirve para leer archivos PDF.
Estas dependencias deben estar disponibles en el entorno de Athento; de lo contrario, la operación fallará al instalarse.
c) Módulos internos de Athento (Importante)
Son clases, enums y constantes que provee el propio producto y que permiten interactuar con documentos, operaciones y metadatos.
from operations.classes.document_operation import DocumentOperation
from operations.enums import ProcessOperationParameterType, ProcessOperationParameterChoiceType
from metadatatype.literals import MetadataTypeNames
DocumentOperation: clase base que deben heredar todas las operaciones personalizadas.ProcessOperationParameterType: define el tipo de los parámetros configurables (texto, booleano, lista, número, etc.).ProcessOperationParameterChoiceType: define cómo se presentan las opciones de tipo choice (por ejemplo, valores personalizados o automáticos).MetadataTypeNames: contiene nombres internos de “features” o campos especiales del documento (comofeature.textofeature.pdf).
2. Definición de la operación
class MyCustomOperation(DocumentOperation):
version = '1.0'
name = 'My Custom Operation'
description = 'Does something with a document or register'
configuration_parameters = {}
Esta parte:
Declara la clase como una subclase de DocumentOperation (la clase base de las operaciones de Athento).
-
Define las propiedades básicas de la operación:
version: versión del script.name: nombre legible.description: resumen funcional.configuration_parameters: espacio reservado para parámetros configurables. Lo que se especifique aquí, hará que los usuarios puedan configurar los parámetros de forma amigable desde la interfaz del producto.deprecated = FalseSi es True, indica que hay una nueva versión de la operación y que esta debería usarse.documentation = ''Permite añadir un link a la documentación del automatismo.
3. Método principal execute()
def execute(self, *args, **kwargs)El método execute() es el núcleo de la operación. Aquí se define lo que se hace paso a paso sobre el documento actual.
Cada operación se ejecuta sobre un documento en Athento. Para obtener el documento actual:
document = self.documentDentro de este método además, podrás utilizar las expresiones y funciones útiles que se explican en el próximo apartado.
4.Propiedades globales y ejecución externa
Estos valores permiten que Athento reconozca la operación y la muestre en la biblioteca de operaciones.
VERSION = MyCustomOperation.version
NAME = MyCustomOperation.name
DESCRIPTION = MyCustomOperation.description
CONFIGURATION_PARAMETERS = MyCustomOperation.configuration_parameters
ORDER = 100
CATEGORY = ""
POSTLOAD = False
POSTCHARACT = False
POSTCLASSIF = False
POSTEXTRACTION = False- Order: indica el orden de ejecución de la operación cuando se ejecuta desde el procesamiento automático. Es un número entero. Cuanto más grande es el número, menos prioridad de ejecución en el flujo tiene la operación. Esto es muy útil para decidir qué operación o automatismo se ejecuta primero. Este número se pone por defecto, y puede ser configurado por el usuario desde la administración avanzada.
- Categoría: cadena si interesa definir algún tipo de categoría para la operación
- POSTLOAD , POSTCHARACT , POSTCLASSIF , POSTEXTRACTION: Indica en qué fase del procesamiento se ejecutará por defecto la operación. Por ejemplo, si POSTLOAD = True, cuando la operación se instale, se pondrá en la fase Postload, que significa que se ejecutará justo después de la creación o carga del documento.
5.Función run()
Esta función facilita la ejecución directa de la operación.
def run(uuid=None, **params):
return MyCustomOperation(uuid, **params).run()6.Opcional - Parámetros configurables (configuration_parameters)
Si queremos que el usuario pueda configurar de forma amigable los parámetros de la operación, debemos definirlos. Este bloque permite definir opciones de configuración que el usuario podrá ajustar desde la interfaz de Athento, sin modificar el código.
Cada parámetro es un diccionario con propiedades que describen cómo debe mostrarse y comportarse en el panel de administración. A continuación, un ejemplo de dos parámetros:
configuration_parameters = {
'engine_method': {
'label': _('Engine'),
'type': ProcessOperationParameterType.CHOICE.value[0],
'subtype': ProcessOperationParameterChoiceType.CUSTOM.value[0],
'required': True,
'is_multiple': False,
'help_text': _('Engine to extract text from document.'),
'choices': [
{'label': _('All'), 'value': 'all'},
{'label': _('Textract engine'), 'value': 'textract'},
{'label': _('Pypdf2 engine'), 'value': 'pypdf2'}
],
'default_value': [{'label': _('All'), 'value': 'all'}],
},
'use_feature_format_pdf': {
'label': _('Use PDF feature'),
'type': ProcessOperationParameterType.BOOLEAN.value[0],
'default_value': False,
'help_text': _('If checked, extract text from the PDF feature.'),
},
}🧩 Componentes principales de cada parámetro
| Clave | Descripción |
|---|---|
| label | Nombre visible en la interfaz (puede traducirse con _()). |
| type | Tipo de dato esperado: STRING, INTEGER, FLOAT, BOOLEAN, CHOICE, etc. |
| subtype | (Opcional) Subtipo de opciones, por ejemplo CUSTOM si las opciones se definen manualmente. |
| required | Indica si el parámetro es obligatorio (True/False). |
| is_multiple | Si permite seleccionar varios valores (solo para CHOICE). |
| help_text | Texto de ayuda mostrado junto al campo. |
| choices | Lista de opciones disponibles (solo para CHOICE). |
| default_value | Valor inicial que tendrá el parámetro. |
Ejemplo del código de una operación en Athento
class HelloWorldDocumentOperation(DocumentOperation):
# Version of the operation. The version of an operation is defined with X.Y format:
# - X: Is "mayor" and only changes if the behavior of the operation changes or are breaking
# changes (including new parameters). If changes, a new version of the operation file
# must be created (e.g.: hello_world_v3.py) and the old version must be deprecated (indicated in
# the description and name).
# - Y: Is "minor" and changes if small changes, bug fixes, etc. are applied. Not is required to create a new file.
version = '2.1'
name = 'Hello World Document Operation!'
documentation = 'https://athento.zendesk.com/knowledge/articles/360024905974/'
description = """
This operation is the "Hello World Document Operation!" of operations and can be used to test the operation
system.
"""
deprecated = False # If it's true,the operations doesn't appear in the marketplace
configuration_parameters = {
'my-text-parameter-key': {
'label': 'Text parameter',
'help_text': 'My text parameter',
'type': ProcessOperationParameterType.TEXT.value[0],
'default_value': 'Example default value',
},
'my-integer-parameter-key': {
'label': 'Integer parameter',
'help_text': 'My integer parameter',
'type': ProcessOperationParameterType.INTEGER.value[0],
'default_value': 1,
},
'my-float-parameter-key': {
'label': 'Float parameter',
'help_text': 'My float parameter',
'type': ProcessOperationParameterType.FLOAT.value[0],
'default_value': 1.1,
},
'my-evaluable-parameter-key': {
'label': 'Evaluable parameter',
'help_text': 'My evaluable parameter',
'type': ProcessOperationParameterType.EVALUABLE.value[0],
'default_value': '"Default evaluable value"',
},
'my-bool-parameter-key': {
'label': 'Boolean parameter',
'help_text': 'If unchecked, the operation will throw an exception',
'type': ProcessOperationParameterType.BOOLEAN.value[0],
'default_value': True,
},
'my-date-parameter-key': {
'label': 'Date parameter',
'help_text': 'My date parameter',
'type': ProcessOperationParameterType.DATE.value[0],
'default_value': '2022-01-01',
},
'my-datetime-parameter-key': {
'label': 'Datetime parameter',
'help_text': 'My date parameter',
'type': ProcessOperationParameterType.DATETIME.value[0],
'default_value': '2022-01-01 12:00:00',
},
'my-custom-choice-key': {
'label': 'Custom choice parameter',
'help_text': 'My custom choice parameter',
'choices': [{"label": "Custom label A", "value": "value_a"},
{"label": "Custom label B", "value": "value_b"}],
'type': ProcessOperationParameterType.CHOICE.value[0],
'subtype': ProcessOperationParameterChoiceType.CUSTOM.value[0],
'is_multiple': False,
'default_value': {"label": "Custom label B", "value": "value_b"},
},
'my-metadata-type-parameter-key': {
'label': 'Metadata type parameter',
'help_text': 'My metadata type parameter',
'type': ProcessOperationParameterType.CHOICE.value[0],
'subtype': ProcessOperationParameterChoiceType.METADATA_TYPE.value[0],
'is_multiple': False,
},
'my-user-parameter-key': {
'label': 'User parameter',
'help_text': 'My user parameter',
'type': ProcessOperationParameterType.CHOICE.value[0],
'subtype': ProcessOperationParameterChoiceType.USER.value[0],
'is_multiple': False,
},
'my-document-type-parameter-key': {
'label': 'Document type parameter',
'help_text': 'My document type parameter',
'type': ProcessOperationParameterType.CHOICE.value[0],
'subtype': ProcessOperationParameterChoiceType.DOCUMENT_TYPE.value[0],
'is_multiple': False,
},
'my-serie-parameter-key': {
'label': 'Space parameter',
'help_text': 'My space type parameter',
'type': ProcessOperationParameterType.CHOICE.value[0],
'subtype': ProcessOperationParameterChoiceType.SERIE.value[0],
'is_multiple': False,
},
'my-custom-choice-multiple-key': {
'label': 'Custom choice multiple parameter',
'help_text': 'My custom choice parameter',
'choices': [{"label": "Custom label A", "value": "value_a"},
{"label": "Custom label B", "value": "value_b"}],
'type': ProcessOperationParameterType.CHOICE.value[0],
'subtype': ProcessOperationParameterChoiceType.CUSTOM.value[0],
'default_value': [{"label": "Custom label A", "value": "value_a"},
{"label": "Custom label B", "value": "value_b"}],
'is_multiple': True,
},
'my-metadata-type-parameter-multiple-key': {
'label': 'Metadata type multiple parameter',
'help_text': 'My metadata type parameter',
'type': ProcessOperationParameterType.CHOICE.value[0],
'subtype': ProcessOperationParameterChoiceType.METADATA_TYPE.value[0],
'is_multiple': True,
},
'my-user-parameter-multiple-key': {
'label': 'User multiple parameter',
'help_text': 'My user parameter',
'type': ProcessOperationParameterType.CHOICE.value[0],
'subtype': ProcessOperationParameterChoiceType.USER.value[0],
'is_multiple': True,
},
'my-serie-parameter-multiple-key': {
'label': 'Space multiple parameter',
'help_text': 'My Space parameter',
'type': ProcessOperationParameterType.CHOICE.value[0],
'subtype': ProcessOperationParameterChoiceType.SERIE.value[0],
'is_multiple': True,
},
'my-document-workflow-task-type-parameter-multiple-key': {
'label': 'Document workflow task type multiple parameter',
'help_text': 'My Document workflow task type multiple parameter',
'type': ProcessOperationParameterType.CHOICE.value[0],
'subtype': ProcessOperationParameterChoiceType.DOCUMENT_WORKFLOW_TASK_TYPE.value[0],
'is_multiple': True,
},
'my-life-cycle-state-parameter-key': {
'label': 'Life cycle state parameter',
'help_text': 'My life cycle state parameter',
'type': ProcessOperationParameterType.CHOICE.value[0],
'subtype': ProcessOperationParameterChoiceType.LIFE_CYCLE_STATE.value[0],
'is_multiple': False,
},
'my-life-cycle-state-parameter-multiple-key': {
'label': 'Life cycle state multiple parameter',
'help_text': 'My life cycle state multiple parameter',
'type': ProcessOperationParameterType.CHOICE.value[0],
'subtype': ProcessOperationParameterChoiceType.LIFE_CYCLE_STATE.value[0],
'is_multiple': True,
}
}
def execute(self, *args, **kwargs):
"""Here is the code that will be executed by the operation."""
# E.g.: Sum A and B
a = 10
b = 32
result = a + b
# Properties of the operation
# Current operation instance
operation = self.operation
# Execution id
execution_id = self.execution_id
# Operation parameters
parameters = self.parameters
# Current document
document = self.document
# Information debug
self.logger.info('Debug message')
# Information logger
self.logger.info('Info message')
# Error logger
self.logger.error('Error message')
# Warning logger
self.logger.warning('Warning message')
# Exception logger
self.logger.exception('Exception message')
# Critical logger
self.logger.critical('Critical message')
# Raise custom operation error example
is_check = parameters.get('my-bool-parameter-key')
if not is_check:
self.warning(_('Hello world, this is an operation warning exception'))
# self.error(_('Hello world, this is an operation error exception'))
# self.exception(_('Hello world, this is an operation error exception'), type=OperationExceptionType.ERROR)
# The response should be a JSON with some common structure.
return {
'msg_type': 'warning',
'msg': 'The sum of {} + {} is: {}'.format(a, b, result),
}
VERSION = HelloWorldDocumentOperation.version
NAME = HelloWorldDocumentOperation.name
DESCRIPTION = HelloWorldDocumentOperation.description
DOCUMENTATION = HelloWorldDocumentOperation.documentation
DEPRECATED = HelloWorldDocumentOperation.deprecated
ORDER = 100
CATEGORY = ""
POSTLOAD = True
POSTCHARACT = False
POSTCLASSIF = False
POSTEXTRACTION = False
CONFIGURATION_PARAMETERS = HelloWorldDocumentOperation.configuration_parameters
def run(uuid=None, **params):
return HelloWorldDocumentOperation(uuid, **params).run()
Información, métodos y utilidades para usar en tus operaciones personalizadas
To get metadata value: fil.gmv('metadata.name')
To set metadata value: fil.set_metadata('metadata.name', value, overwrite=True)
To get feature value: fil.gfv('feature.name')
To set feature: fil.set_feature('feature.name', value)
Useful methods:
- fil.set_state('new_state')
- fil.validate()
- fil.change_life_cycle()
To get useful File attributes:
- fil.numpages -> gets the number of pages of the document
- fil.state
- fil.file.path()
- fil.serie -> gets the space of the document
- fil.author -> gets the creator of the document
- fil.doctype -> gets the form of the document
- fil.life_cycle_state -> gests the lifecycle state
To give feedback to the final user for operations run from UI, return a dictionary:
{'msg_type':'error',
'msg':'A message for the user',
'document':
{'metadata':
{'metadata.example':'new value',
'metadata.example2':'new value 2'},
'status': 'new status'
}
'redirect_url':'https://a_url_to_redirect_to_the_user'
}
For msg_type options are:
error, warning, success, info (Taken from toastr.js)
Una guía más completa de métodos, expresiones, condiciones y otras utilidades que puedes usar en el desarrollo de una operación personalizada, se encuentra en el artículo:
¿Qué API se puede usar en las operaciones personalizadas y condiciones avanzadas?
En instalaciones on-premise, un administrador avanzado de la aplicación, puede añadir directamente operaciones a medida.
Estas operaciones se ubican en la ruta athentose/custom/operations
En dicha ruta existe un módulo llamado helloworld.py, que puede ser usado como plantilla.
Dicho módulo contiene, además, documentación útil con ejemplos sobre cómo obtener información y realizar operaciones sobre el documento.
Comentarios
0 comentarios
Inicie sesión para dejar un comentario.