## Applying Workflow to Content Items

Content Repository : Developer Guide

This document describes the workflow API calls necessary to apply a simple workflow to a content item.

### Workflow Description

Most publishers wish to follow some variation of the following workflow:

State | Task | Description
--- | --- | ---
Created | Authoring | The publisher has created the item.
Authored | Editing | The author has written the item.
Edited | Publishing | The editor has approved the item.
Published | None | The publisher has approved the item.

At any point in the workflow, an assigned user should be able to check out an item, such that other users are advised that someone is working on it. When checking an item in, a user should have up to three options:

1. Check the item in but do not mark the task as finished (allowing someone else to work on the task. The currently enabled task (whether it is authoring, editing or approving) does not change.
2. Check the item in and move to the next task. For the authoring task, this signifies that the authoring is complete. For subsequent tasks, this signifies approval.
3. Check the item in and move to a previous task, indicating rejection.

This simple workflow is defined in `sql/workflows/author-edit-publish.sql`.

### Workflow Creation

Production of a content item frequently begins with a concept which is initiated by the publisher and then executed by the staff. In this scenario, the publisher creates the workflow and then assigns each task in the workflow to one or more people. The API calls to initialize a new workflow are as follows:

    declare
      v_case_id integer;
      sample_object_id integer := 9;
      sample_user_id integer := 10;
    begin

      v_case_id := workflow_case.new(  workflow_key => 'publishing_wf',
                                       context_key => NULL,
                                       object_id => sample_object_id);

      workflow_case.add_manual_assignment(v_case_id, 'authoring', sample_user_id);
      workflow_case.add_manual_assignment(v_case_id, 'editing', sample_user_id);
      workflow_case.add_manual_assignment(v_case_id,'approval', sample_user_id);

      workflow_case.start_case(case_id => v_case_id, msg => 'Here we go.');

    end;
    /

In this case, only one assignment is made per task. You can make as many assignments per task as desired. There is currently no workflow API to set deadlines, so you must write your own DML to insert a row into `wf_case_deadlines` if you wish to allow the publisher to set deadlines ahead of time.

The above workflow is created in the Default context. In practice, you may wish to create one or more contexts in which to create your workflows. Contexts may be used to represent different departments within an organization.

The `start_case` enables the first task in the workflow, in this case Authoring.

### Check Out Item

If multiple persons are assigned to the same task, it is useful to allow a single person to "check out" or lock an item while they are working. This is accomplished with the following API calls:

    declare
      v_journal_id integer;
      sample_task_id := 1000;
      sample_user_id := 10;
      sample_ip := '127.0.0.1';
    begin

      v_journal_id := workflow_case.begin_task_action(sample_task_id, 'start',
        sample_ip, sample_user_id, 'Checking it out');
      workflow_case.end_task_action(v_journal_id, 'start', sample_task_id);

    end;
    /

A mininum of two calls are required to perform any action related to a task. In this case we are simply notifying the workflow engine that someone has started the task. You may specify NULL for the journal message if the user does not wish to comment on the check out.

### Check In Item

Unless given a timeout period, a lock on a content item will persist until the holding user checks the item back in. This involves notifying the workflow engine that the user has finished the task:

    declare
      v_journal_id integer;
      sample_task_id integer := 1000;
      sample_user_id integer := 10;
      sample_ip := '127.0.0.1';
    begin

      v_journal_id := workflow_case.begin_task_action(sample_task_id, 'finish',
        sample_ip, sample_user_id, 'Done for now');
      workflow_case.set_attribute_value(v_journal_id, 'next_place', 'start');
      workflow_case.end_task_action(v_journal_id, 'finish', sample_task_id);

    end;
    /

Upon finishing a task, you must notify the workflow engine where to go next. In this case, an author wishes to simply check an item back in without actually completing the authoring task. The `set_attribute_value` procedure must thus be used to set `next_place` to the starting place of the workflow.

### Finish Task

The process to finish a task varies slightly depending on whether the user has previously checked out the item out or not. If the user has not already checked it out (has been working on the item without locking it, the code looks like this:

    declare
      v_journal_id integer;
      sample_task_id integer := 1002;
      sample_user_id integer := 10;
      sample_ip := '127.0.0.1';
    begin

      -- start the task
      v_journal_id := workflow_case.begin_task_action(sample_task_id, 'start',
        sample_ip, sample_user_id, NULL);
      workflow_case.end_task_action(v_journal_id, 'start', sample_task_id);

      -- finish the task
      v_journal_id := workflow_case.begin_task_action(sample_task_id, 'finish',
        sample_ip, sample_user_id, 'Authoring complete');
      workflow_case.set_attribute_value(v_journal_id, 'next_place', 'authored');
      workflow_case.end_task_action(v_journal_id, 'finish', sample_task_id);

    end;
    /

In this case an author is finishing the Authoring task, upon which the workflow engine will move the workflow to the Authored state (as indicated by the `next_place` attribute). If the author had previously checked out the item, then only the second step is required.

### Approve or Reject

Approval steps more commonly do not involve an explicit check-out process. The code is thus virtually identical to that above:

    declare
      v_journal_id integer;
      sample_task_id integer := 1003;
      sample_user_id integer := 10;
      sample_ip := '127.0.0.1';
    begin

      v_journal_id := workflow_case.begin_task_action(sample_task_id, 'start',
        sample_ip, sample_user_id, NULL);
      workflow_case.end_task_action(v_journal_id, 'start', sample_task_id);

      v_journal_id := workflow_case.begin_task_action(sample_task_id, 'finish',
        sample_ip, sample_user_id, 'Authoring complete');
      workflow_case.set_attribute_value(v_journal_id, 'next_place', 'edited');
      workflow_case.end_task_action(v_journal_id, 'finish', sample_task_id);

    end;
    /

Note the distinction between approval or rejection is determined solely by the value of the `next_place` attribute.

karlg@arsdigita.com
Last Modified: `$Id: workflow.html,v 1.1.1.1 2001/03/13 22:59:26 ben Exp $`