Commit bb2a2c2b authored by Frank Bergmann's avatar Frank Bergmann

cosine 5585: Fixed Restart Workflow and added functionality

parent 469173d4
......@@ -93,7 +93,7 @@ ad_proc -public im_workflow_start_wf {
# Determine the first task in the case to be executed and start+finisch the task.
if {1 == $skip_first_transition_p} {
im_workflow_skip_first_transition -case_id $case_id -case_assignment_id 0
im_workflow_skip_first_transition -case_id $case_id
}
}
return $case_id
......@@ -545,11 +545,31 @@ ad_proc -public im_workflow_graph_component {
$assignee_html
"
if {$reassign_p} {
set debug_case_help "Show extended debug information"
set start_new_case_help "Create a new case of the same workflow and start it from scratch"
set nuke_case_help "Nuke this workflow from the database without a trace"
set restart_case_help "Restart this workflow from the start, maintaining the journal"
append assignee_html "
<tr class=rowplain><td colspan=2>
<ul>
<li><a href='[export_vars -base "/[im_workflow_url]/case?" {case_id}]'>[_ intranet-workflow.Debug_Case]</a>
<li><a href='[export_vars -base "/intranet-workflow/reset-case?" {return_url case_id {place_key "start"} {action_pretty "restart"}}]'>[_ intranet-workflow.Reset_Case]</a>
<li><a href='[export_vars -base "/[im_workflow_url]/case?" {case_id}]'>
[lang::message::lookup "" intranet-workflow.Debug_case "Debug case"]
[im_gif help $debug_case_help]
</a>
<li><a href='[export_vars -base "/intranet-workflow/reset-case?" {return_url case_id {action "copy"} {action_pretty "Copy"}}]'>
[lang::message::lookup "" intranet-workflow.Copy_Case "Copy and start new case"]
[im_gif help $start_new_case_help]
</a>
<li><a href='[export_vars -base "/intranet-workflow/reset-case?" {return_url case_id {action "nuke"} {action_pretty "Nuke"}}]'>
[lang::message::lookup "" intranet-workflow.Nuke_Case "Nuke case"]
[im_gif help $nuke_case_help]
</a>
<li><a href='[export_vars -base "/intranet-workflow/reset-case?" {return_url case_id {action "restart"} {place_key "start"} {action_pretty "Restart"}}]'>
[lang::message::lookup "" intranet-workflow.Restart_Case "Restart case"]
[im_gif help $restart_case_help]
</a>
</ul>
</td></tr>
"
......@@ -1535,7 +1555,6 @@ ad_proc -public im_workflow_home_inbox_component {
# This is useful for the very first transition of an approval WF
ad_proc -public im_workflow_skip_first_transition {
{-case_assignment_id ""}
-case_id:required
} {
Skip the first tasks of the workflow.
......@@ -1547,9 +1566,9 @@ ad_proc -public im_workflow_skip_first_transition {
# Assign the first task to the user himself and start the task
# Fraber 151102: Assign to anonymous user in order to suppress email alerts
set wf_modify_assignee $user_id
if {"" ne $case_assignment_id} { set user_id $case_assignment_id }
# Get the first "enabled" task of the new case_id:
# These enabled tasks should have their normal assignments already
set enabled_tasks [db_list enabled_tasks "
select task_id
from wf_tasks
......@@ -1560,12 +1579,23 @@ ad_proc -public im_workflow_skip_first_transition {
ns_log Notice "im_workflow_skip_first_transition: user_id=$user_id, enabled_tasks=$enabled_tasks"
foreach task_id $enabled_tasks {
set wf_case_assig [db_string wf_assig "select workflow_case__add_task_assignment (:task_id, :wf_modify_assignee, 'f')"]
ns_log Notice "im_workflow_skip_first_transition: task_id=$task_id"
# We are doing a manual assignment for user_id because we are going to 'process' it
# We do the assignment using a manual insert to avoid notifying the user.
set assig_exists_p [db_string assig_exists_p "select count(*) from wf_task_assignments where task_id = :task_id and party_id = :user_id"]
if {!$assig_exists_p} {
db_dml assig "insert into wf_task_assignments (task_id, party_id) values (:task_id, :user_id)"
}
# Start the task. Saves the user the work to press the "Start Task" button.
set journal_id [db_string wf_action "select workflow_case__begin_task_action (:task_id,'start','[ad_conn peeraddr]',:user_id,'')"]
set journal_id2 [db_string wf_start "select workflow_case__start_task (:task_id,:user_id,:journal_id)"]
ns_log Notice "im_workflow_skip_first_transition: select workflow_case__begin_task_action ($task_id, 'start', '[ad_conn peeraddr]', $user_id, '')"
set journal_id [db_string wf_action "select workflow_case__begin_task_action (:task_id, 'start', '[ad_conn peeraddr]', :user_id, '')"]
ns_log Notice "im_workflow_skip_first_transition: select workflow_case__start_task ($task_id, $user_id, $journal_id)"
set journal_id2 [db_string wf_start "select workflow_case__start_task (:task_id, :user_id, :journal_id)"]
# Finish the task. That forwards the token to the next transition.
ns_log Notice "im_workflow_skip_first_transition: select workflow_case__finish_task($task_id, $journal_id)"
set journal_id3 [db_string wf_finish "select workflow_case__finish_task(:task_id, :journal_id)"]
}
}
......
# /packages/intranet-workflow/www/projects/rfc-delete-2.tcl
#
# /packages/intranet-workflow/www/reset-case-2.tcl
ad_page_contract {
View all the info about a specific project.
......@@ -16,14 +15,15 @@ ad_page_contract {
{ case_id:integer 0 }
return_url
{ place_key "tagged" }
{ action_pretty "" }
{ action "undefined" }
{ action_pretty "Undefined" }
}
# ---------------------------------------------------------------------
# Defaults & Security
# ---------------------------------------------------------------------
set user_id [auth::require_login]
set current_user_id [auth::require_login]
set peer_ip [ad_conn peeraddr]
set page_title [lang::message::lookup "" intranet-workflow.Reset_Workflow_Case "Reset Workflow Case"]
set date_format "YYYY-MM-DD"
......@@ -31,62 +31,107 @@ set date_format "YYYY-MM-DD"
set bgcolor(0) " class=roweven"
set bgcolor(1) " class=rowodd"
set user_is_admin_p [im_is_user_site_wide_or_intranet_admin $current_user_id]
if {!$user_is_admin_p} {
ad_return_complaint 1 "You are not an admin"
ad_script_abort
}
# ---------------------------------------------------------------------
# Cancel all transitions and move to "rfc_cancel"
# Check task_id vs. case_id present
# ---------------------------------------------------------------------
if {"" != $button_confirm} {
# Get the general case_id
# "Cancel" all the task in the current case
if {0 == $case_id} {
set case_id [db_string case "select case_id from wf_tasks where task_id = :task_id" -default 0]
}
if {"" eq $button_confirm} {
ad_returnredirect $return_url
ad_script_abort
}
if {0 == $case_id} {
ad_return_complaint 1 "Didn't find case_id"
ad_script_abort
}
# Get the general case_id
if {"" ne $task_id && 0 != $task_id && 0 == $case_id} {
set case_id [db_string case "select case_id from wf_tasks where task_id = :task_id" -default 0]
}
# Get the places of tokens before canceling the case
set places [db_list token_in_places "select place_key||':'||state from wf_tokens where case_id = :case_id and state in ('free', 'locked')"]
set reset_message "Resetting workflow case #$case_id with tokens in [join $places ", "]"
# if {[llength $places] == 0} { set message "Resetting Workflow with no tokens active" }
# set case_journal_id [im_workflow_new_journal -case_id $case_id -action "reset_workflow" -action_pretty "Reset Workflow" -message $message]
# Make sure the case is active
db_dml update_case "update wf_cases set state = 'active' where case_id = :case_id"
# Delete active tokens, leave old ones in their places
db_dml delete_tokens "delete from wf_tokens where case_id = :case_id and state in ('free', 'locked')"
set tasks_sql "
select task_id as wf_task_id
from wf_tasks
where case_id = :case_id
and state in ('started')
"
db_foreach tasks $tasks_sql {
ns_log Notice "new-rfc: canceling task $wf_task_id"
set message "Canceling task #$task_id in case #$case_id as part of WF reset"
set journal_id [im_workflow_new_journal -case_id $case_id -action "cancel" -action_pretty "Cancel Task" -message $message]
db_string cancel_task "select workflow_case__cancel_task(:wf_task_id, :journal_id)"
# set journal_id [im_workflow_task_action -task_id $wf_task_id -action "cancel" -message "Cancel task"]
}
if {0 == $case_id} {
ad_return_complaint 1 "Didn't find case_id"
ad_script_abort
}
# Get the workflow_key and the object_id of the existing WF
set workflow_key ""
db_0or1row case_info "select workflow_key, object_id from wf_cases where case_id = :case_id"
if {"" eq $workflow_key} {
ad_return_complaint 1 "Didn't find workflow_key for case_id=$case_id"
ad_script_abort
}
# ---------------------------------------------------------------------
# Perform action
# ---------------------------------------------------------------------
db_string start "select workflow_case__start_case(:case_id, :user_id, :peer_ip, :reset_message)"
switch $action {
"nuke" {
ns_log Notice "reset-case-2: Nuking case_id=$case_id"
# Just delete the case, the rest should go with on delete cascade
db_dml delete_case "delete from wf_cases where case_id = :case_id"
}
# Re-activate the case. Not sure why the case can get "finished" during wf__start_case, but it seems to happen...
# db_dml update_case "update wf_cases set state = 'active' where case_id = :case_id"
"copy" {
ns_log Notice "reset-case-2: Copying case_id=$case_id"
# Start a new workflow case
set new_case_id [im_workflow_start_wf -object_id $object_id -workflow_key $workflow_key -skip_first_transition_p 1]
}
"restart" {
ns_log Notice "reset-case-2: Restarting case_id=$case_id"
# Get the places of tokens before canceling the case
set places [db_list token_in_places "select place_key||':'||state from wf_tokens where case_id = :case_id and state in ('free', 'locked')"]
set reset_message "Resetting workflow case_id=$case_id with tokens in [join $places ", "]"
if {[llength $places] == 0} { set reset_message "Resetting Workflow with no tokens active" }
set reset_journal_id [im_workflow_new_journal -case_id $case_id -action "reset_workflow" -action_pretty "Reset Workflow" -message $reset_message]
# Cancel any active tasks
set tasks_sql "
select task_id as wf_task_id
from wf_tasks
where case_id = :case_id and state in ('started')
"
db_foreach tasks $tasks_sql {
set message "Canceling task_id=$task_id in case_id=$case_id as part of WF reset"
set journal_id [im_workflow_new_journal -case_id $case_id -action "cancel" -action_pretty "Cancel Task" -message $message]
db_string cancel_task "select workflow_case__cancel_task(:wf_task_id, :journal_id)"
}
# All task should have been canceled.
# The original code for starting a WF is like this:
# select workflow_case__new (:case_id, :workflow_key, :context_key, :object_id, now(), :user_id, :creation_ip);
# select workflow_case__start_case (:case_id, :user_id, :creation_ip, null);
# The case is already there, so we should not execute wf_case__new anymore. It just creates the object.
# Safe option (working): Delete all tokens and tasks:
# db_dml delete_tokens "delete from wf_tokens where case_id = :case_id"
# db_dml delete_tasks "delete from wf_tasks where case_id = :case_id"
# Softwer option (apparently working): Keep old/finished tasks/tokens in place for audit
# Delete active tokens, leave old ones in their places
db_dml delete_tokens "delete from wf_tokens where case_id = :case_id and state in ('free', 'locked')"
db_dml delete_tasks "delete from wf_tasks where case_id = :case_id and state in ('enabled', 'started')"
# Start the workflow:
# Sets wf_case.status = 'active, puts a token in 'start' and sweep_automatic_transitions()
set start_message "Starting case_id=$case_id again"
db_string start "select workflow_case__start_case(:case_id, :current_user_id, :peer_ip, :start_message)"
# Skip the very first transition as always
im_workflow_skip_first_transition -case_id $case_id
}
# Skip the very first transition as always
# im_workflow_skip_first_transition -case_id $case_id
default {
ad_return_complaint 1 "Invalid action '$action'"
ad_script_abort
}
# Continue to "move
# set sweep_journal_id [im_workflow_new_journal -case_id $case_id -action "sweep" -action_pretty "Sweeping workflow" -message "Sweeping workflow"]
# im_exec_dml sweep "workflow_case__sweep_automatic_transitions (:case_id, :sweep_journal_id)"
}
......@@ -8,7 +8,7 @@
<p>&nbsp;</p>
<form action=reset-case-2 method=POST>
<%= [export_vars -form {return_url case_id task_id place_key action_pretty}] %>
<%= [export_vars -form {return_url case_id task_id place_key action action_pretty}] %>
<input type="submit" name="button_cancel" value="<%= [lang::message::lookup "" intranet-workflow.Cancel_Button "Cancel"] %>">
<input type="submit" name="button_confirm" value="<%= [lang::message::lookup "" intranet-workflow.Confirm_Button "Confirm %action_pretty%"] %>">
</form>
......@@ -13,6 +13,7 @@ ad_page_contract {
{ task_id:integer 0}
{ case_id:integer 0}
{ place_key "tagged"}
{ action "undefined" }
{ action_pretty "Undefined" }
{ return_url ""}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment