raoul2000 / yii2-workflow

A simple workflow engine for Yii2

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Question: A model can have various Workflows?

marcoadasilvaa opened this issue · comments

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?

commented

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.

  • el modelo es Item08 y puedes ver que 2 behaviors (w1 y w2) son configuradas, cada una referiendose a su proprio attribut (w1 usa 'status' por defecto, y w2 usa 'status_ex')
  • en MultiWorkflowTest.php puedes ver algunos ejemplos de como usar esas dos behavior.

Espero que te ayudo

(pf decime si mi castellano es comprensible 😄 )

commented

mira tambien a este gist

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!

commented

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

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

commented

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 ?

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'
],
];
}

commented

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.

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

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