Workflow para share

cancel
Showing results for 
Search instead for 
Did you mean: 
oscgon
Member II

Workflow para share

Hola
Soy nuevo en Alfresco y tengo instalada la version 3.2 Community.

En la parte de documentlibrary tengo una estructura de directorios de la siguiente forma:
   
- Aprobados
- Rechazados
- Pendientes de validar.

La necesidad que tengo es que necesito un workflow en la parte Share que me permita que una vez se introduzca un documento en la parte de Pendientes de Validar automaticamente lance un workflow a una serie de usuarios o en su defecto a un grupo de usuarios. Dicho workflow debe comportarse de tal forma que si la mitad + 1 de los usuarios aceptan el documento, este será movido a la carpeta de "Aprobados".

He intentado a traves de reglas desde el explorer pero no me permite asignar un grupo de usuarios.

Alguna idea.

Gracias de antemano
Oscar.
5 Replies
venzia
Senior Member

Re: Workflow para share

Hola oscar, la mayor parte del trabajo la puedes realizar en la definición del flujo. Sacado del fichero tomcat\webapps\alfresco\WEB-INF\classes\alfresco\workflow\parallelreview_group_processdefinition.xml :
<?xml version="1.0" encoding="UTF-8"?>

<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="wf:parallelgroupreview">

    <swimlane name="initiator"></swimlane>

    <start-state name="start">
        <task name="wf:submitGroupReviewTask" swimlane="initiator" />
        <transition name="" to="startreview"/>
    </start-state>

    <node name="startreview">
        <action class="org.alfresco.repo.workflow.jbpm.ForEachFork">
            <foreach>#{people.getMembers(bpm_groupAssignee)}</foreach>
            <var>reviewer</var>
        </action>
        <event type="node-enter">
            <script>
                <variable name="wf_approveCount" access="write" />
                <expression>
                    wf_approveCount = 0;
                </expression>
            </script>
        </event>
        <transition name="review" to="review" />
    </node>

    <task-node name="review">
        <task name="wf:reviewTask">
            <assignment class="org.alfresco.repo.workflow.jbpm.AlfrescoAssignment">
               <actor>#{reviewer}</actor>
            </assignment>
        </task>
        <transition name="reject" to="endreview" />
        <transition name="approve" to="endreview">
            <script>
                <variable name="wf_approveCount" access="read,write" />
                <expression>
                    wf_approveCount = wf_approveCount +1;
                 </expression>
            </script>
        </transition>
    </task-node>

    <join name="endreview">
        <transition to="isapproved" />
    </join>

    <decision name="isapproved">
        <event type="node-enter">
           <action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
              <script>
                 <variable name="wf_reviewerCount" access="write"/>
                 <expression>people.getMembers(bpm_groupAssignee).length;</expression>
              </script>
           </action>
           <action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
              <script>
                 <variable name="wf_requiredPercent" access="write"/> <!– esta variable se declara desde el script e indica el porcentaje para dar por finalizado –>
                 <expression>wf_requiredPercent = wf_requiredApprovePercent;</expression>
              </script>
           </action>
           <action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
              <script>
                 <variable name="wf_actualPercent" access="write"/>
                 <expression>wf_actualPercent = ((wf_approveCount * 100) / people.getMembers(bpm_groupAssignee).length);</expression>
              </script>
           </action>
        </event>
        <transition name="reject" to="rejected" />
        <transition name="approve" to="approved">
            <script>
            <!– script que mueve el contenido al espacio de aprobados –>
            <!- tener en cuenta los objetos accesibles desde aqui –>
            </script>
            <condition>#{wf_actualPercent >= wf_requiredApprovePercent}</condition>
        </transition>
    </decision>
              
    <task-node name="rejected">
        <task name="wf:rejectedParallelTask" swimlane="initiator" />
        <transition to="end" />
    </task-node>

    <task-node name="approved">
        <task name="wf:approvedParallelTask" swimlane="initiator" />
        <transition to="end" />
    </task-node>

    <end-state name="end"/>

</process-definition>
Como ves, en el se define una propiedad "wf_requiredPercent" que es comprobada antes de dar por aprobado el flujo. Es en dicha transicion, del paso aprobar a dar la tarea por aprobada, donde puedes ejecutar un script que mueva o copie el contenido a la carpeta aprobados (no he podido realizar pruebas con los objetos accesibles del workflow, asi q no tengo mas detalles fiables a mano respecto a este script).
En resumen, una vez diseñado el fichero de definicion del proceso tendrás que desplegarlo en alfresco http://wiki.alfresco.com/wiki/WorkflowAdministration#Manually_deploying_a_jPDL_XML_file_or_Process_A... (este articulo ademas lleva mucho contenido que te puede servir)
Luego desde el cliente standar de alfresco puedes crear una regla en el espacio del site concreto en share, que ejecuta un script http://livinginjava.blogspot.com/2008/10/starting-alfresco-workflow-using.html, el cual lanza el flujo (estableciendo sus propiedades especificas) para todo el contenido entrante.
Saludos
oscgon
Member II

Re: Workflow para share

Hola de nuevo
He intentado realizar lo que me comentas y no me ha dado resultado. Te cuento los pasos que he seguido.

He creado un script "WorkFlow1" cuyo codigo es el siguiente:
var workflow = actions.create("start-workflow");
workflow.parameters.workflowName = "jbpm$wf:parallelgroupreview";
workflow.parameters.requiredApprovePercent = 100;
workflow.parameters["bpm:workflowDescription"] = "Please review and approve: " + document.name;
workflow.parameters["bpm:groupAssignee"] = people.getGroup("GROUP_Administrador");
var futureDate = new Date();
futureDate.setDate(futureDate.getDate() + 7);
workflow.parameters["bpm:workflowDueDate"] = futureDate;
workflow.execute(document);

Como ves, selecciono el workflow parallelgroupreview y requiero que todos los integrantes del grupo Administrador validen el documento.

En el espacio "Pendiente de aprobar" creo una regla que en cuanto entre algun documento ejecute dicho script.

Al intentar subir un documento me sale el siguiente error:
"Ocurrió un error del sistema durante la operación: 01030002 Failed to execute script 'workspace://SpacesStore/33035d82-7359-478c-bf4b-a315a79f81ca': null"

El archivo que me comentas (paralellreview_group_processdefinition.xml) no lo he tocado ya que solo quiero saber si me crea las tareas de workflow. Lo que si he realizado es un reinicio del alfresco. Te adjunto tambien el codigo de dicho fichero:
<?xml version="1.0" encoding="UTF-8"?>

<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="wf:parallelgroupreview">

    <swimlane name="initiator"></swimlane>

    <start-state name="start">
        <task name="wf:submitGroupReviewTask" swimlane="initiator" />
        <transition name="" to="startreview"/>
    </start-state>

    <node name="startreview">
        <action class="org.alfresco.repo.workflow.jbpm.ForEachFork">
            <foreach>#{people.getMembers(bpm_groupAssignee)}</foreach>
            <var>reviewer</var>
        </action>
        <event type="node-enter">
            <script>
                <variable name="wf_approveCount" access="write" />
                <expression>
                    wf_approveCount = 0;
                </expression>
            </script>
        </event>
        <transition name="review" to="review" />
    </node>

    <task-node name="review">
        <task name="wf:reviewTask">
            <assignment class="org.alfresco.repo.workflow.jbpm.AlfrescoAssignment">
               <actor>#{reviewer}</actor>
            </assignment>
            <event type="task-create">
                <script>
                    if (bpm_workflowDueDate != void) taskInstance.dueDate = bpm_workflowDueDate;
                    if (bpm_workflowPriority != void) taskInstance.priority = bpm_workflowPriority;
                </script>
            </event>
        </task>
        <transition name="reject" to="endreview" />
        <transition name="approve" to="endreview">
            <script>
                <variable name="wf_approveCount" access="read,write" />
                <expression>
                    wf_approveCount = wf_approveCount +1;
                 </expression>
            </script>
        </transition>
    </task-node>

    <join name="endreview">
        <transition to="isapproved" />
    </join>

    <decision name="isapproved">
        <event type="node-enter">
           <action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
              <script>
                 <variable name="wf_reviewerCount" access="write"/>
                 <expression>people.getMembers(bpm_groupAssignee).length;</expression>
              </script>
           </action>
           <action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
              <script>
                 <variable name="wf_requiredPercent" access="write"/>
                 <expression>wf_requiredPercent = wf_requiredApprovePercent;</expression>
              </script>
           </action>
           <action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
              <script>
                 <variable name="wf_actualPercent" access="write"/>
                 <expression>wf_actualPercent = ((wf_approveCount * 100) / people.getMembers(bpm_groupAssignee).length);</expression>
              </script>
           </action>
        </event>
        <transition name="reject" to="rejected" />
        <transition name="approve" to="approved">
            <condition>#{wf_actualPercent >= wf_requiredApprovePercent}</condition>
        </transition>
    </decision>
              
    <task-node name="rejected">
        <task name="wf:rejectedParallelTask" swimlane="initiator" />
        <transition to="end" />
    </task-node>

    <task-node name="approved">
        <task name="wf:approvedParallelTask" swimlane="initiator" />
        <transition to="end" />
    </task-node>

    <end-state name="end"/>

</process-definition>

No se por donde tirar ahora. Alguna idea?. Gracias.
venzia
Senior Member

Re: Workflow para share

Me da que se debe a que no has desplegado este workflow en el sistema. Esto se hace definiendo las propiedades del mismo en el fichero respectivo, para que Alfresco sepa que existe .. a saber en tomcat\shared\classes\alfresco\extension\workflow-context.xml .. tal como dice en el articulo del wiki que te pase http://wiki.alfresco.com/wiki/WorkflowAdministration#Manually_deploying_a_jPDL_XML_file_or_Process_A... (aunque es cierto que alli no indican el path del fichero al que añadir la definición).
Tras el cambio, reinicia alfresco y deberia aparecer en el cliente y poder ser lanzado desde cualquier script.
Otra opción sería meter el fichero parallelreview_group_processdefinition.xml en el espacio Diccionario de Datos\Workflow Definitions y desplegarlo desde la consola de administracion de workflows http://wiki.alfresco.com/wiki/Workflow_Console (lo bueno de este método es que no requiere reinicio del servidor).
Ya me dices que tal ..
Saludos,
oscgon
Member II

Re: Workflow para share

Macho
Eres un fenomeno. He intentado con la primera opcion que me comentaste y efectivamente el problema residia en que no tenia hecho el deploy del workflow en el sistema. De hecho, en la ruta me aparecia el archivo con extension .xml..sample. Simplemente renombrardolo a .xml ya funciono.

Ahora solo me queda ver como meter bien en el script o bien en las propiedades del proceso, la opcion para que me mueva el documento al espacio "Aprobados"  o "Descartados".  Alguna pista por donde tirar?

El tema es que tengo una serie de directorios con la misma estructura es decir:

Espacio 1 : con carpetas Borrador, Aprobados, pendientes de aprobar, Rechazados
Espacio 2 : idem..
Espacio n

a los cuales mi intencion es  generar un script para cada uno de ellos (ya que lo validan grupos distintos)  y crear las reglas correspondientes en las carpetas "Pendientes de aprobar".

Mi pregunta ahora es : ¿Es posible bien en el script o en la regla definir una accion de mover un documento a una carpeta determinada en funcion del resultado del workflow?
Si no es asi, como podria hacerlo.
Gracias.
venzia
Senior Member

Re: Workflow para share

Pues respecto a esta ultima cuestion se me ocurre, a primeras, lo siguiente (que quiza no sea lo mas elegante, pero seguro que te vale :winkSmiley Happy :
0-Modificas la definicion del flujo para dejarla tal y como sigue :
<?xml version="1.0" encoding="UTF-8"?>

<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="wf:parallelgroupreview">

    <swimlane name="initiator"></swimlane>

    <start-state name="start">
        <task name="wf:submitGroupReviewTask" swimlane="initiator" />
        <transition name="" to="startreview"/>
    </start-state>

    <node name="startreview">
        <action class="org.alfresco.repo.workflow.jbpm.ForEachFork">
            <foreach>#{people.getMembers(bpm_groupAssignee)}</foreach>
            <var>reviewer</var>
        </action>
        <event type="node-enter">
            <script>
                <variable name="wf_approveCount" access="write" />
                <expression>
                    wf_approveCount = 0;
                </expression>
            </script>
        </event>
        <transition name="review" to="review" />
    </node>

    <task-node name="review">
        <task name="wf:reviewTask">
            <assignment class="org.alfresco.repo.workflow.jbpm.AlfrescoAssignment">
               <actor>#{reviewer}</actor>
            </assignment>
            <event type="task-create">
                <script>
                    if (bpm_workflowDueDate != void) taskInstance.dueDate = bpm_workflowDueDate;
                    if (bpm_workflowPriority != void) taskInstance.priority = bpm_workflowPriority;
                </script>
            </event>
        </task>
        <transition name="reject" to="endreview" />
        <transition name="approve" to="endreview">
            <script>
                <variable name="wf_approveCount" access="read,write" />
                <expression>
                    wf_approveCount = wf_approveCount +1;
                 </expression>
            </script>
        </transition>
    </task-node>

    <join name="endreview">
        <transition to="isapproved" />
    </join>

    <decision name="isapproved">
        <event type="node-enter">
           <action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
              <script>
                 <variable name="wf_reviewerCount" access="write"/>
                 <expression>people.getMembers(bpm_groupAssignee).length;</expression>
              </script>
           </action>
           <action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
              <script>
                 <variable name="wf_requiredPercent" access="write"/>
                 <expression>wf_requiredPercent = wf_requiredApprovePercent;</expression>
              </script>
           </action>
           <action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
              <script>
                 <variable name="wf_actualPercent" access="write"/>
                 <expression>wf_actualPercent = ((wf_approveCount * 100) / people.getMembers(bpm_groupAssignee).length);</expression>
              </script>
           </action>
        </event>
        <transition name="reject" to="rejected" />
        <transition name="approve" to="approved">
            <script> <!–si no me equivoco el objeto bpm_package.children[0] es el propio contenido–>
            bpm_package.children[0].addAspect("custom:Aprobado"); <!–asociamos aspecto aprobado–>
            bpm_package.children[0].save();
            </script>
            <condition>#{wf_actualPercent >= wf_requiredApprovePercent}</condition>
        </transition>
    </decision>
              
    <task-node name="rejected">
        <task name="wf:rejectedParallelTask" swimlane="initiator" />
        <transition to="end" />
    </task-node>

    <task-node name="approved">
        <task name="wf:approvedParallelTask" swimlane="initiator" />
        <transition to="end" />
    </task-node>

    <end-state name="end"/>

</process-definition>
Si te das cuenta .. en la transicion que pasa a approved he metido un script que añade un aspecto .. este aspecto lo debes crear en los config .. a saber nos va bien con realizar los siguientes pasos (si no tienes definidos modelos propios) :
1-Añadir el siguiente codigo al fichero tomcat\shared\classes\alfresco\extension\customModel.xml :
<?xml version="1.0" encoding="UTF-8"?>

<!– Custom Model –>

<!– Note: This model is pre-configured to load at startup of the Repository.  So, all custom –>
<!–       types and aspects added here will automatically be registered –>

<model name="custom:customModel" xmlns="http://www.alfresco.org/model/dictionary/1.0">

   <!– Optional meta-data about the model –>  
   <description>Custom Model</description>
   <author></author>
   <version>1.0</version>

   <imports>
        <!– Import Alfresco Dictionary Definitions –>
      <import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
      <!– Import Alfresco Content Domain Model Definitions –>
      <import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
   </imports>

   <!– Introduction of new namespaces defined by this model –>
   <!– NOTE: The following namespace custom.model should be changed to reflect your own namespace –>
   <namespaces>
      <namespace uri="custom.model" prefix="custom"/>
   </namespaces>

   <aspects>
       <aspect name="custom:Aprobado">
            <title>Aprobado</title>
        </aspect>
   </aspects>
     
</model>
(Para declarar el aspecto)
2-Renombrar el fichero C:\ALFRESCO3-LIMPIO\tomcat\shared\classes\alfresco\extension\custom-model-context.xml.sample quitando el .sample (el cual hace referencia al fichero anterior para declarar el aspecto del nuevo modelo en el sistema).
3-Añadir al final del fichero web-client-config-custom.xml (antes de la etiqueta </alfresco-config>) lo siguiente :
   <config evaluator="string-compare" condition="Action Wizards">
      <aspects>
         <aspect name="custom:Aprobado"/>
      </aspects>
   </config>
(Esto hace que sea visible desde los wizards de reglas o nuevas acciones).
Bien .. despues de estos pasos reinicias Alfresco (ojo .. asegurate que en el fichero tomcat\shared\classes\alfresco\extension\workflow-context.xml tienes la propiedad <prop key="redeploy">true</prop> .. para que te redespliegue la nueva version del flujo con el script en la transicion .. una vez termines las pruebas lo ideal es quitar dicha propiedad para que no genere una nueva version en cada inicio).
Luego ..
Espacio 1 : con carpetas Borrador, Aprobados, pendientes de aprobar, Rechazados
Espacio 2 : idem..
Espacio n
En cada uno de los espacios de "pendientes de aporbar" creas una regla que ejecute el script que lanza el flujo para todo el contenido de tipo "Entrante". Y .. aqui esta el quid de la cuestion creas otra regla de tipo "Update" que para todo el contenido que tenga el aspecto "Aprobado" aplicado mueva dicho contenido a la carpeta Aprobados.
De esta forma la logica la despliegas desde la regla .. que es más intuitiva .. y por otro lado .. añadir la misma para el caso de "Rechazados" no requiere de mucho esfuerzo mas.
Vamos .. que tienes trabajo por delante .. (y ya te pasare la factura jeje :mrgreenSmiley Happy.
Si tienes algun problema por aqui estamos (aunq no te puedo asegurar la misma dedicacion que en este Smiley Indifferent).
Espero no haber olvidado nada y que este minitutorial te sirva en la implementacion.
Saludos y suerte!