[Rt-commit] rt branch, 4.0/add-lifecycle-docs, created. rt-4.0.8-240-g50b0d5a
Jim Brandt
jbrandt at bestpractical.com
Thu Dec 13 16:09:05 EST 2012
The branch, 4.0/add-lifecycle-docs has been created
at 50b0d5ad1b02651ff8e904e031eebccf42de3152 (commit)
- Log -----------------------------------------------------------------
commit 50b0d5ad1b02651ff8e904e031eebccf42de3152
Author: Jim Brandt <jbrandt at bestpractical.com>
Date: Thu Dec 13 16:01:32 2012 -0500
Add lifecycle docs
diff --git a/docs/customizing/lifecycles.pod b/docs/customizing/lifecycles.pod
new file mode 100644
index 0000000..c8ba5c6
--- /dev/null
+++ b/docs/customizing/lifecycles.pod
@@ -0,0 +1,408 @@
+=head1 Ticket Lifecycles
+
+By default, RT comes with ticket statuses that work for many types
+of workflows: new, open, stalled, resolved, rejected, and deleted.
+But there can be any number of workflows where these status values
+don't completely fit. RT allows you to add new custom status values and
+define their behavior with a feature called Lifecycles.
+
+This guide demonstrates lifecycles with using an order fulfillment
+system as a real-world example. Lifecycles are further described
+in the L<RT_Config> documentation.
+
+As with all RT custom configuration, if you are customizing the RT
+lifecycle, copy the entire lifecycle configuration from the C<RT_Config.pm>
+file and put it in your C<RT_SiteConfig.pm> file. Then you can safely
+modify or add to the lifecycle configuration.
+
+=head1 Order Processing Example
+
+To show how you might use custom lifecycles, we're going to configure
+an RT lifecycle to process orders of some sort. In our order example,
+each ticket in the queue is considered a separate order and the orders
+have the following statuses:
+
+=over
+
+=item pending
+
+The order just came in untouched, pending purchase validation
+
+=item processing
+
+The order is being looked at for transaction processing
+
+=item delivery
+
+The order is out for delivery
+
+=item delivered
+
+The order was successfully delivered to its destination
+
+=item refunded
+
+The order was delivered but subsequently refunded
+
+=item declined
+
+There was an error in the process validation and the order was denied purchase
+
+=back
+
+In this particular example, the only status an order can start with is
+'pending.' When a process coordinator chooses to take this order, it
+goes into processing. The order can then either be delivered or denied
+processing. Once denied, the lifecycle for that order ends. If it is
+delivered, the order can still be refunded.
+
+The following sections walk through each part of the configuration.
+You can find the full configuration at the end in case you want to
+see the exact syntax or use it to experiment with.
+
+=head2 Defining Status Values
+
+Every queue has a lifecycle assigned to it. Without changing any
+configuration, you are given two lifecycles to choose from: "default"
+and "approvals." The approvals lifecycle is specifically used for
+RT approvals and is best left untouched.
+
+=for html <img alt="Lifecycle choices" src="images/lifecycle-choices.png">
+
+=for :text [Lifecycle choices F<docs/images/lifecycle-choices.png>]
+
+=for :man [Lifecycle choices F<docs/images/lifecycle-choices.png>]
+
+In RT 4.0, the C<@ActiveStatus> and C<@InactiveStatus> configurations
+which were previously available are gone. The logic defined by those
+options is now a subset of RT's lifecycle features, as described here.
+
+A ticket naturally has three states: initial (_new_), active (_open_ and
+_stalled_), and inactive (_resolved_, _rejected_, and _deleted_). These
+default settings look like this in the C<RT_Config.pm> file:
+
+ default => {
+ initial => [ 'new' ],
+ active => [ 'open', 'stalled' ],
+ inactive => [ 'resolved', 'rejected', 'deleted' ],
+
+Now we want to set up some statuses appropriate for order fulfillment,
+so we create a new top-level key called C<orders> and add our new status
+values.
+
+ orders => {
+ initial => [ 'pending' ],
+ active => [ 'processing', 'delivery' ],
+ inactive => [ 'delivered', 'returned', 'declined' ],
+
+We still use the initial, active and inactive categories, but we are
+able to define status values that are appropriate for the workflow
+we want to create. This should make the system more intuitive for users.
+
+=head2 Transitions
+
+The typical lifecycle follows the path initial -> active -> inactive.
+Obviously the path of a ticket can get more complicated than this, which
+is where transitions come into play.
+
+Transitions manage the flow of a ticket from status to status. This
+section of the configuration has keys, which are the current status,
+and values that define which other statuses the ticket can transition
+to. Here are the transitions we define for our order process.
+
+ orders => {
+ # ...,
+ transitions => {
+ '' => [qw(pending processing declined)],
+ pending => [qw(processing declined deleted)],
+ processing => [qw(pending declined delivery delivered deleted)],
+ delivery => [qw(pending delivered returned deleted)],
+ delivered => [qw(pending returned deleted)],
+ returned => [qw(pending delivery deleted)],
+ deleted => [qw(pending processing delivered delivery returned)],
+ },
+ # ...,
+ }
+
+If a ticket is in the delivered status, it doesn't make sense for it to
+transition to processing or declined since the customer already has the
+order. However, it can transition to returned since they could send it back.
+The configuration above defines this for RT.
+
+The C<''> entry defines the valid statuses when a ticket is created.
+
+=head2 Rights and Access Control
+
+Your workflow may have several people working on tickets at different
+steps, and for some you may want to make sure only certain users
+can perform certain actions. For example, the company may have a rule
+that only the quality assurance team is allowed to approve (or decline)
+an order for delivery.
+
+You can apply labels to transitions and assign rights to them to allow
+you to apply this sort of access control. This is done with a rights
+entry:
+
+ orders => {
+ # ...,
+ rights => {
+ '* -> declined' => 'DeclineOrder',
+ '* -> delivery' => 'ApproveOrder',
+ },
+ # ...,
+ }
+
+This configuration tells RT to require the right DeclineOrder for a
+transition from any status (C<*>) to C<declined>. The ApproveOrder
+right is similar, but for C<delivery>.
+
+Once these rights are configured and loaded (by restarting the web
+server), they can be assigned in the web UI to groups, queues, and users.
+The rights show up on the rights pages in a Status tab alongside the
+standard RT rights tabs.
+
+=for html <img alt="Lifecycle group rights" src="images/global-lifecycle-group-rights.png">
+
+=for :text [Lifecycle group rights F<docs/images/global-lifecycle-group-rights.png>]
+
+=for :man [Lifecycle group rights F<docs/images/global-lifecycle-group-rights.png>]
+
+Once a status transition right is granted, users with the right will see
+the option show up in the Actions dropdown. In this example, if we give a
+group the DelineOrder right, members of that group will see a Deline option
+in their Actions menu.
+
+=for html <img alt="Action menu decline" src="images/action-decline.png">
+
+=for :text [Action menu decline F<docs/images/action-decline.png>]
+
+=for :man [Action menu decline F<docs/images/action-decline.png>]
+
+=head2 Default Status
+
+You don't have to specify a status on a ticket, but tickets
+require a status. To resolve this seeming contradiction, you can set
+default status values for RT to use when the user doesn't explicitly set
+a value.
+
+Looking at the defaults section in the standard RT configuration,
+you can see the events for which you can define a default status.
+For example, 'on_create' => 'new' automatically gives newly created tickets
+a C<new> status when the requestor doesn't supply a status. We can do the same
+for our process.
+
+ orders => {
+ defaults => {
+ on_create => 'pending',
+ on_merge => 'delivered',
+ approved => 'delivery',
+ denied => 'declined',
+ },
+ # ...,
+ }
+
+Only a small number of defaults are needed because in practice there are
+relatively few cases where a ticket will find itself without a status or
+in an ambiguous state.
+
+=head2 Actions
+
+To customize how transitions are presented in RT, lifecycles has an
+C<actions> section where you can customize how an action (e.g. changing
+status from new -> open) looks and functions. You can customize the action's
+label, which is how it appears to users, and the type of update, either comment
+or reply. As an example, in the default RT configuration the action
+"new -> open" has the default label "Open it" and an update value of C<Respond>.
+
+Using the lifecycles configuration, you can change the label to anything you
+like. You can set the update option to C<Comment> or C<Respond>, which tells RT
+to process the action as a comment (not sent to requestors) or a reply (sent
+to requestors).
+
+This part of the lifecycles configuration replaces the previous
+C<$ResolveDefaultUpdateType> configuration value. To mimic that option, set
+the update type to C<Comment> for all transitions to C<resolved>.
+
+Here is an example of a change we might make for our order process:
+
+ orders => {
+ # ...,
+ actions => [
+ 'pending -> processing' => {
+ label => 'Open For Processing',
+ update => 'Comment',
+ },
+ # ...
+ ],
+ # ...
+ }
+
+Alternatively, supplying no update type results in a "quick"
+action that changes the status immediately without going through the
+ticket update page. RT's default "Delete" action is a "quick" action,
+for example:
+
+ # from the RT "default" lifecycle
+ 'new -> deleted' => {
+ label => 'Delete',
+ },
+
+=head2 Mapping Between Queues
+
+As we've demonstrated, each queue can have its own custom lifecycle, but
+in RT you sometimes want to move a ticket from one queue to another.
+If the ticket has a status in the current queue, but that status doesn't
+exist in the queue you want to move it to, RT needs to know how to set the
+status appropriately.
+
+The lifecycle configuration has a C<__maps__> entry to allow you to
+specify the mappings you want between different queues. Sometimes statuses
+between queues don't or can't match perfectly, but if you need to move
+tickets between those queues, it's important that you provide a complete
+mapping, defining the most sensible mapping you can.
+
+ orders => {
+ # ...,
+ __maps__ => {
+ 'default -> orders' => {
+ 'new' => 'pending',
+ 'open' => 'processing',
+ # ...,
+ },
+ 'orders -> default' => {
+ 'pending' => 'new',
+ 'processing' => 'open',
+ # ...,
+ },
+ # ...,
+ },
+ # ...,
+ }
+
+In the example above, we first define mappings between the default queue and
+our new orders queue. The second block defines the reverse for tickets that
+might be moved from the orders queue to a queue that uses the default lifecycle.
+
+=head2 Full Configuration
+
+Here is the full congfiguration if you want to add it to your RT instance
+to experiment.
+
+ Set(%Lifecycles,
+ # ...
+
+ # 'orders' shows up as a lifecycle choice when you create a new
+ # queue or modify an existing one
+ orders => {
+ # All the appropriate order statuses
+ initial => [ 'pending' ],
+ active => [ 'processing', 'delivery' ],
+ inactive => [ 'delivered', 'returned', 'declined' ],
+
+ # Default order statuses for certain actions
+ defaults => {
+ on_create => 'pending',
+ on_merge => 'delivered',
+ approved => 'delivery',
+ denied => 'declined',
+ },
+
+ # Status change restrictions
+ transitions => {
+ '' => [qw(pending processing declined)],
+ pending => [qw(processing declined deleted)],
+ processing => [qw(pending declined delivery delivered deleted)],
+ delivery => [qw(pending delivered returned deleted)],
+ delivered => [qw(pending returned deleted)],
+ returned => [qw(pending delivery deleted)],
+ deleted => [qw(pending processing delivered delivery returned)],
+ },
+
+ # Rights for different actions
+ rights => {
+
+ # These rights are in the default lifecycle
+ '* -> deleted' => 'DeleteTicket',
+ '* -> *' => 'ModifyTicket',
+
+ # Maybe we want to create rights to keep QA rigid
+ '* -> declined' => 'DeclineOrder',
+ '* -> delivery' => 'ApproveOrder',
+ },
+
+ # Actions for the web UI
+ actions => [
+ 'pending -> processing' => {
+ label => 'Open For Processing',
+ update => 'Comment',
+ },
+ 'pending -> delivered' => {
+ label => 'Mark as being delivered',
+ update => 'Comment',
+ },
+ 'pending -> declined' => {
+ label => 'Decline',
+ update => 'Respond',
+ },
+ 'pending -> deleted' => {
+ label => 'Delete',
+ },
+ 'processing -> declined' => {
+ label => 'Decline',
+ update => 'Respond',
+ },
+ 'processing -> delivery' => {
+ label => 'Out for delivery',
+ update => 'Comment',
+ },
+ 'delivery -> delivered' => {
+ label => 'Mark as delivered',
+ update => 'Comment',
+ },
+ 'delivery -> returned' => {
+ label => 'Returned to Manufacturer',
+ update => 'Respond',
+ },
+ 'delivered -> returned' => {
+ label => 'Returned to Manufacturer',
+ update => 'Respond',
+ },
+ 'returned -> delivery' => {
+ label => 'Re-deliver Order',
+ update => 'Respond',
+ },
+ 'deleted -> pending' => {
+ label => 'Undelete',
+ update => 'Respond',
+ },
+ ],
+ },
+
+ # Status mapping different different lifecycles
+ __maps__ => {
+ 'default -> orders' => {
+ 'new' => 'pending',
+ 'open' => 'processing',
+ 'stalled' => 'processing',
+ 'resolved' => 'delivered',
+ 'rejected' => 'declined',
+ 'deleted' => 'deleted',
+ },
+ 'orders -> default' => {
+ 'pending' => 'new',
+ 'processing' => 'open',
+ 'delivered' => 'resolved',
+ 'returned' => 'open', # closest matching we have in 'default'
+ 'declined' => 'rejected',
+ 'deleted' => 'deleted',
+ },
+ },
+ );
+
+Here is an example history of a ticket following this lifecycle:
+
+=for html <img alt="Lifecycle history" src="images/order-history-example.png">
+
+=for :text [Lifecycle history F<docs/images/order-history-example.png>]
+
+=for :man [Lifecycle history F<docs/images/order-history-example.png>]
diff --git a/docs/images/action-decline.png b/docs/images/action-decline.png
new file mode 100644
index 0000000..0a93e5a
Binary files /dev/null and b/docs/images/action-decline.png differ
diff --git a/docs/images/global-lifecycle-group-rights.png b/docs/images/global-lifecycle-group-rights.png
new file mode 100644
index 0000000..d87f7b4
Binary files /dev/null and b/docs/images/global-lifecycle-group-rights.png differ
diff --git a/docs/images/lifecycle-choices.png b/docs/images/lifecycle-choices.png
new file mode 100644
index 0000000..1d8e28c
Binary files /dev/null and b/docs/images/lifecycle-choices.png differ
diff --git a/docs/images/order-history-example.png b/docs/images/order-history-example.png
new file mode 100644
index 0000000..8670585
Binary files /dev/null and b/docs/images/order-history-example.png differ
-----------------------------------------------------------------------
More information about the Rt-commit
mailing list