raoul2000 / yii2-workflow

A simple workflow engine for Yii2
BSD 3-Clause "New" or "Revised" License
171 stars 48 forks source link

Question: A model can have various Workflows? #45

Closed marcoadasilvaa closed 7 years ago

marcoadasilvaa commented 7 years ago

Saludos raoul, estaba evaluando la posibilidad de que un modelo posee 2 tipos de workflow. A modo de pruebas agregue 2 veces en behaviors la declaración de Workflow, en consecuencia los events comenzaron a ejecutarse 2 veces.

Por lo tanto te consulto si es factible agregar 2 workflows distintos a un mismo modelo y cual seria la aplicación adecuada?

Agradecido!


Hello raoul! Was evaluating the possibility that a model has 2 types of workflow. But, for tests i add twice in behaviors the declaration of Workflow, consequently the events execute twice also.

it is possible add 2 different workflows on the same model and what would be appropriate configuration?

raoul2000 commented 7 years ago

Hola @markmarco16, es cierto que usar 2 workflow para el mismo modelo y al mimso tiempo no es un caso normal de uso pero creo que puede andar correcto. Lo que hay que hacer es de configurar 2 behaviors, cada una con su proprio nombre y usar este nombre para acceder al status que corresponde. De hecho, en los tests puedes encontrar un ejemplo muy basico pero que muestra como hacer.

Espero que te ayudo

(pf decime si mi castellano es comprensible 😄 )

raoul2000 commented 7 years ago

mira tambien a este gist

marcoadasilvaa commented 7 years ago

Gracias por tu respuesta, es posible que los 2 behaviors apunten al mismo status field del modelo?

Te comento esto porque haciendo algunas pruebas se ejecuta 2 veces la acción que tengo en el afterEnterStatus, te envió todos los datos para las pruebas:

Model BillingInvoice

namespace app\models;

use Yii;
use raoul2000\workflow\events\WorkflowEvent;
use raoul2000\workflow\helpers\WorkflowHelper;

/**
 * This is the model class for table "billing_invoice".
 *
 * @property string $id
 * @property int $id_account
 * @property string $subtotal
 * @property string $discount
 * @property string $tax
 * @property string $total
 * @property string $currency
 * @property string $status
 * @property int $created_at
 * @property int $updated_at
 */
class BillingInvoice extends \yii\db\ActiveRecord
{
    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return 'billing_invoice';
    }

    public function init()
    {
        $this->on(
            WorkflowEvent::afterEnterStatus('BillingInvoiceWorkflow/draft'),
            [$this, 'generateAcceptace']
        );

        $this->on(
            WorkflowEvent::afterEnterStatus('BillingInvoiceWorkflow/publish'),
            [$this, 'generateAcceptace']
        );
    }

    public function generateAcceptace() {
        $mail = \Yii::$app->mailer->compose([])
            ->setFrom('markmarco16@gmail.com')
            ->setTo('markmarco16@gmail.com')
            ->setSubject('Message subject')
            ->setTextBody('Plain text content')
            ->setHtmlBody('<b>HTML content</b>')
            ->send();
    }

    public function behaviors()
    {
        return [
            'BillingInvoiceWorkflow' => [
                'class' => \raoul2000\workflow\base\SimpleWorkflowBehavior::className(),
                'defaultWorkflowId' => 'BillingInvoice',
            ],
            'BillingInvoiceSaleWorkflow' => [
                'class' => \raoul2000\workflow\base\SimpleWorkflowBehavior::className(),
                'defaultWorkflowId' => 'BillingInvoiceSale'
            ],
        ];
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['id_account', 'created_at', 'updated_at'], 'integer'],
            [['subtotal', 'discount', 'tax', 'total'], 'number'],
            [['id'], 'string', 'max' => 23],
            [['currency'], 'string', 'max' => 3],
            [['status'], 'string', 'max' => 30],
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'id_account' => 'Id Account',
            'subtotal' => 'Subtotal',
            'discount' => 'Discount',
            'tax' => 'Tax',
            'total' => 'Total',
            'currency' => 'Currency',
            'status' => 'Status',
            'created_at' => 'Created At',
            'updated_at' => 'Updated At',
        ];
    }
}

Workflow 1 - BillingInvoiceWorkflow

namespace app\models;

class BillingInvoiceWorkflow implements \raoul2000\workflow\source\file\IWorkflowDefinitionProvider
{
    public function getDefinition() {
        return [
            'initialStatusId' => 'draft',
            'status' => [
                'draft' => [
                    'transition' => ['publish','deleted']
                ],
                'publish' => [
                    'transition' => ['draft','deleted']
                ],
                'deleted' => [
                    'transition' => ['draft']
                ]
            ]
        ];
    }
}

Workflow 2 - BillingInvoiceSaleWorkflow

namespace app\models;

class BillingInvoiceSaleWorkflow implements \raoul2000\workflow\source\file\IWorkflowDefinitionProvider
{
    public function getDefinition() {
        return [
            'initialStatusId' => 'draft',
            'status' => [
                'draft' => [
                    'transition' => ['send','deleted']
                ],
                'send' => [
                    'transition' => ['draft','deleted']
                ],
                'deleted' => [
                    'transition' => ['draft']
                ]
            ]
        ];
    }
}

Al actualizar al estatus publish del workflow 1 se envia 2 veces el correo electrónico

pd: tu español es excelente!

raoul2000 commented 7 years ago

De lo que veo, me parece que estas registrando 2 veces el mismo "event Handler" for el mismo event :

    public function init()
    {
        $this->on(
            WorkflowEvent::afterEnterStatus('BillingInvoiceWorkflow/draft'),
            [$this, 'generateAcceptace']
        );
        // primera vez : BillingInvoiceWorkflow/publish afterEnterStatus
        $this->on(
            WorkflowEvent::afterEnterStatus('BillingInvoiceWorkflow/publish'),
            [$this, 'generateAcceptace']
        );

        // secunda vez :  BillingInvoiceWorkflow/publish afterEnterStatus
        $this->on(
            WorkflowEvent::afterEnterStatus('BillingInvoiceWorkflow/publish'),
            [$this, 'generateAcceptace']
        );
    }

En este caso es normal due el metodo generateAcceptace sea llamada 2 veces. Otra cosa que me parece rara es que en tu modelo BillingInvoice estas configurando 2 behaviors (cada una con su proprio workflow) pero con el mismo nombre (BillingInvoiceWorkflow). Eso creo que no anda y el resulta es que solo el secundo behavior esta tomada en cuenta por Yii.

En conclusion te dijé que usar un solo attribute para manerar 2 workflows al mismo tiempo me parece que no puede andar. Si realmente necesitas a 2 status para tu modelo, cada uno debe ser guardado en su proprio attribute...

ciao

marcoadasilvaa commented 7 years ago

ops fue un error de escritura, por favor prueba de nuevo eliminando uno de los $this->on( WorkflowEvent::afterEnterStatus('BillingInvoiceWorkflow/publish'), [$this, 'generateAcceptace'] );

raoul2000 commented 7 years ago

no sé bien lo que lo siguiente da como resultado :

    public function behaviors()
    {
        return [
            'BillingInvoiceWorkflow' => [
                'class' => \raoul2000\workflow\base\SimpleWorkflowBehavior::className(),
                'defaultWorkflowId' => 'BillingInvoice',
            ],
            'BillingInvoiceWorkflow' => [
                'class' => \raoul2000\workflow\base\SimpleWorkflowBehavior::className(),
                'defaultWorkflowId' => 'BillingInvoiceSale'
            ],
        ];
    }

El hecho es que las dos behavior estan registradas con el mismo nombre BillingInvoiceWorkflow... Eso tambien es un error o es asi que lo implementaste ?

marcoadasilvaa commented 7 years ago

si también fue un error al transcribir:

public function behaviors() { return [ 'BillingInvoiceWorkflow' => [ 'class' => \raoul2000\workflow\base\SimpleWorkflowBehavior::className(), 'defaultWorkflowId' => 'BillingInvoice', ], 'BillingInvoiceSaleWorkflow' => [ 'class' => \raoul2000\workflow\base\SimpleWorkflowBehavior::className(), 'defaultWorkflowId' => 'BillingInvoiceSale' ], ]; }

raoul2000 commented 7 years ago

En el caso de dos behavior configurados en un modelo, con el mismo nombre de field para guardar el valor del status (lo que ma parece es el caso que describes) entonces el comportamiento es normal.

Cuando el modelo entra en el status BillingInvoiceWorkflow/publish y como 2 behaviors estan configurados, los dos van a mandar el evento afterEnterStatus y entonces el metodo generateAcceptance sera llamado dos veces.

No entiendo bien porque hay 2 bahaviors configurados, es decir cual es la necesidad: es para manejar 2 workflows ? en ese caso no hace falta ... y de todos modos, configurar 2 behaviors para el mismo field, no esta entre las posibilidades previstas : estas en "terra incognita" 😄

una precision : puedes usar 2 workflows (o mas) con una sola behavior y tu modelo puede ir desde un workflow al otro si una transicion existe entre los dos.

philippfrenzel commented 6 years ago

Hey, can you pls add a short summary in english? I have an issue which would be solved by this solution ;) Thank you so much! Muchas Gracias Philippe g

philippfrenzel commented 6 years ago

@raoul2000 or @markmarco16 pls. let me know your thoughts? ;)

marcoadasilvaa commented 6 years ago

hello Philipp, can you show your model and settings?

Marco A. Da Silva A

On Jan 8, 2018 9:13 AM, "Philipp Frenzel" notifications@github.com wrote:

@raoul2000 https://github.com/raoul2000 or @markmarco16 https://github.com/markmarco16 pls. let me know your thoughts? ;)

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/raoul2000/yii2-workflow/issues/45#issuecomment-355976924, or mute the thread https://github.com/notifications/unsubscribe-auth/AEAtlZDDdBnAA5uO0tTzxGsrqlKYSx-wks5tIiJwgaJpZM4M-hf7 .

philippfrenzel commented 6 years ago

Hi Marco,

thanks for your reply! And yes model looks like:

/**

<?php

namespace app\modules\timetrack\models\workflow;

class TimetrackWorkflow implements \raoul2000\workflow\source\file\IWorkflowDefinitionProvider { public function getDefinition() { return [ 'initialStatusId' => 'draft', 'status' => [ 'draft' => [ 'label' => 'Antrag erstellt', 'metadata' => [ 'color' => 'info', 'label' => 'Antrag erstellen', ], 'transition' => ['planning','booked','deleted'] //removed ,'booked' as this will only be available for administrators ],

Second Workflow would start with the same Definition…

Thx Philipp

On Jan 8, 2018, at 3:15 PM, Marco A. Da Silva A. notifications@github.com wrote:

hello Philipp, can you show your model and settings?

Marco A. Da Silva A

On Jan 8, 2018 9:13 AM, "Philipp Frenzel" notifications@github.com wrote:

@raoul2000 https://github.com/raoul2000 or @markmarco16 https://github.com/markmarco16 pls. let me know your thoughts? ;)

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/raoul2000/yii2-workflow/issues/45#issuecomment-355976924, or mute the thread https://github.com/notifications/unsubscribe-auth/AEAtlZDDdBnAA5uO0tTzxGsrqlKYSx-wks5tIiJwgaJpZM4M-hf7 . — You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/raoul2000/yii2-workflow/issues/45#issuecomment-355977550, or mute the thread https://github.com/notifications/unsubscribe-auth/ACNmEv8vXSV92h1Hfy-7qcvnQsYPzty1ks5tIiL1gaJpZM4M-hf7.