Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/acs-workflow-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/acs-workflow-create.sql,v diff -u -r1.1 -r1.2 --- openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/acs-workflow-create.sql 5 Apr 2001 18:23:38 -0000 1.1 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/acs-workflow-create.sql 19 Nov 2001 18:17:46 -0000 1.2 @@ -16,5 +16,6 @@ @@ wf-callback-package @@ jobs-start +/* We create two sample processes */ @@ sample-expenses-create @@ sample-article-create Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/jobs-kill.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/Attic/jobs-kill.sql,v diff -u -r1.2 -r1.3 --- openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/jobs-kill.sql 26 Aug 2001 13:39:26 -0000 1.2 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/jobs-kill.sql 19 Nov 2001 18:17:46 -0000 1.3 @@ -22,8 +22,6 @@ job => job_no ); end if; - close timed_trans_cur; - close hold_timeout_cur; end; / Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/jobs-start.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/Attic/jobs-start.sql,v diff -u -r1.2 -r1.3 --- openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/jobs-start.sql 26 Aug 2001 13:39:26 -0000 1.2 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/jobs-start.sql 19 Nov 2001 18:17:46 -0000 1.3 @@ -40,8 +40,6 @@ interval => 'sysdate + 1/24/4' ); end if; - close timed_trans_cur; - close hold_timeout_cur; end; / Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/sample-article-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/sample-article-create.sql,v diff -u -r1.3 -r1.4 --- openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/sample-article-create.sql 16 Oct 2001 01:36:19 -0000 1.3 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/sample-article-create.sql 19 Nov 2001 18:17:46 -0000 1.4 @@ -19,7 +19,8 @@ declare - v_workflow_key varchar2(40); + v_workflow_key wf_workflows.workflow_key%TYPE; + v_attribute_id acs_attributes.attribute_id%TYPE; begin v_workflow_key := workflow.create_workflow( workflow_key => 'article_wf', @@ -28,73 +29,170 @@ description => 'Workflow for managing the publication of an article', table_name => 'wf_article_cases' ); -end; -/ -show errors -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('start', 'article_wf', 'Initial state', 1); -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('to_be_written', 'article_wf', 'Needs to be written', 2); -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('to_be_reviewed', 'article_wf', 'Needs review', 3); -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('to_go_to_press', 'article_wf', 'Ready to go to press', 4); -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('end', 'article_wf', 'End state', 5); + /***** + * Places + *****/ + + workflow.add_place( + workflow_key => 'article_wf', + place_key => 'start', + place_name => 'Start place', + sort_order => 1 + ); + workflow.add_place( + workflow_key => 'article_wf', + place_key => 'to_be_written', + place_name => 'Needs to be written', + sort_order => 2 + ); -insert into wf_transitions(transition_key, transition_name, workflow_key, sort_order, trigger_type) - values ('specification', 'Description and assignment by editor', 'article_wf', 1, 'user'); -insert into wf_transitions(transition_key, transition_name, workflow_key, sort_order, trigger_type) - values ('writing', 'Writing by author', 'article_wf', 2, 'user'); -insert into wf_transitions(transition_key, transition_name, workflow_key, sort_order, trigger_type) - values ('review', 'Approval by reviewer', 'article_wf', 3, 'user'); -insert into wf_transitions(transition_key, transition_name, workflow_key, sort_order, trigger_type) - values ('press', 'Publication of article', 'article_wf', 4, 'automatic'); + workflow.add_place( + workflow_key => 'article_wf', + place_key => 'to_be_reviewed', + place_name => 'Needs review', + sort_order => 3 + ); + workflow.add_place( + workflow_key => 'article_wf', + place_key => 'to_be_published', + place_name => 'Ready to go to press', + sort_order => 4 + ); --- specification -- --- in -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('article_wf', 'specification', 'start', 'in'); --- out -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('article_wf', 'specification', 'to_be_written', 'out'); + workflow.add_place( + workflow_key => 'article_wf', + place_key => 'end', + place_name => 'End place', + sort_order => 5 + ); + /***** + * Roles + *****/ --- writing --- in -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('article_wf', 'writing', 'to_be_written', 'in'); --- out -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('article_wf', 'writing', 'to_be_reviewed', 'out'); + workflow.add_role( + workflow_key => 'article_wf', + role_key => 'author', + role_name => 'Author', + sort_order => 1 + ); + workflow.add_role( + workflow_key => 'article_wf', + role_key => 'editor', + role_name => 'Editor', + sort_order => 2 + ); --- review (or-split) --- in -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('article_wf', 'review', 'to_be_reviewed', 'in'); --- out -insert into wf_arcs(workflow_key, transition_key, place_key, direction, guard_callback, guard_custom_arg, guard_description) - values ('article_wf', 'review', 'to_go_to_press', 'out', 'wf_callback.guard_attribute_true', 'reviewer_ok', 'Reviewer approved article'); -insert into wf_arcs(workflow_key, transition_key, place_key, direction, guard_callback, guard_description) - values ('article_wf', 'review', 'to_be_written', 'out', '#', 'Reviewer disapproved article'); + /***** + * Transitions + *****/ + workflow.add_transition( + workflow_key => 'article_wf', + transition_key => 'specify', + transition_name => 'Describe task and assign author', + role_key => 'editor', + sort_order => 1, + trigger_type => 'user' + ); + + workflow.add_transition( + workflow_key => 'article_wf', + transition_key => 'write', + transition_name => 'Write article', + role_key => 'author', + sort_order => 2, + trigger_type => 'user' + ); + + workflow.add_transition( + workflow_key => 'article_wf', + transition_key => 'review', + transition_name => 'Review article', + role_key => 'editor', + sort_order => 3, + trigger_type => 'user' + ); + + workflow.add_transition( + workflow_key => 'article_wf', + transition_key => 'publish', + transition_name => 'Publish article', + sort_order => 4, + trigger_type => 'automatic' + ); --- press --- in -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('article_wf', 'press', 'to_go_to_press', 'in'); --- out -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('article_wf', 'press', 'end', 'out'); + /***** + * Arcs + *****/ + workflow.add_arc( + workflow_key => 'article_wf', + from_place_key => 'start', + to_transition_key => 'specify' + ); -declare - v_attribute_id acs_attributes.attribute_id%TYPE; -begin + workflow.add_arc( + workflow_key => 'article_wf', + from_transition_key => 'specify', + to_place_key => 'to_be_written' + ); + + workflow.add_arc( + workflow_key => 'article_wf', + from_place_key => 'to_be_written', + to_transition_key => 'write' + ); + + workflow.add_arc( + workflow_key => 'article_wf', + from_transition_key => 'write', + to_place_key => 'to_be_reviewed' + ); + + workflow.add_arc( + workflow_key => 'article_wf', + from_place_key => 'to_be_reviewed', + to_transition_key => 'review' + ); + + workflow.add_arc( + workflow_key => 'article_wf', + from_transition_key => 'review', + to_place_key => 'to_be_published', + guard_callback => 'wf_callback.guard_attribute_true', + guard_custom_arg => 'reviewer_ok', + guard_description => 'Reviewer approved article' + ); + + workflow.add_arc( + workflow_key => 'article_wf', + from_transition_key => 'review', + to_place_key => 'to_be_written', + guard_callback => '#', + guard_description => 'Reviewer did not approve article' + ); + + workflow.add_arc( + workflow_key => 'article_wf', + from_place_key => 'to_be_published', + to_transition_key => 'publish' + ); + + workflow.add_arc( + workflow_key => 'article_wf', + from_transition_key => 'publish', + to_place_key => 'end' + ); + + /***** + * Attributes + *****/ + v_attribute_id := workflow.create_attribute( workflow_key => 'article_wf', attribute_name => 'reviewer_ok', @@ -103,35 +201,42 @@ default_value => 'f' ); - insert into wf_transition_attribute_map - (workflow_key, transition_key, attribute_id, sort_order) - values - ('article_wf', 'review', v_attribute_id, 1); + workflow.add_trans_attribute_map( + workflow_key => 'article_wf', + transition_key => 'review', + attribute_name => 'reviewer_ok', + sort_order => 1 + ); + /***** + * Assignment + *****/ + + workflow.add_trans_role_assign_map( + workflow_key => 'article_wf', + transition_key => 'specify', + assign_role_key => 'author' + ); + end; / -show errors; +show errors --- assignment as part of workflow -insert into wf_transition_assignment_map - (workflow_key, transition_key, assign_transition_key) -values - ('article_wf', 'specification', 'writing'); - -insert into wf_transition_assignment_map - (workflow_key, transition_key, assign_transition_key) -values - ('article_wf', 'specification', 'review'); - - /* Context stuff */ - insert into wf_context_transition_info ( - context_key, workflow_key, transition_key, hold_timeout_callback, hold_timeout_custom_arg + context_key, + workflow_key, + transition_key, + hold_timeout_callback, + hold_timeout_custom_arg ) values ( - 'default', 'article_wf', 'specification', 'wf_callback.time_sysdate_plus_x', 1/24 + 'default', + 'article_wf', + 'specify', + 'wf_callback.time_sysdate_plus_x', + 1/24 ); commit; @@ -169,7 +274,6 @@ v_object_name varchar2(4000); v_transition_name wf_transitions.transition_name%TYPE; v_name varchar2(1000); - v_request_id integer; begin select to_char(ta.deadline,'Mon fmDDfm, YYYY HH24:MI:SS'), acs_object.name(c.object_id), @@ -196,40 +300,19 @@ body := body ||'Deadline: '||v_deadline_pretty||' '; end if; - - -- NOTICE, NOTICE, NOTICE - -- - -- Since postgresql does not support out parameters, this - -- function call has been moved into the callback function. - -- If you implement a new notification callback, make sure - -- that this function call is included at the end of the - -- callback routine. - - -- The oracle version has been changed to be consistent - -- with the postgresql version, even though technically - -- it is not necessary. - -- - -- DanW (dcwickstrom@earthlink.net) - - v_request_id := acs_mail_nt.post_request ( - party_from => party_from, - party_to => party_to, - expand_group => 'f', - subject => subject, - message => body, - max_retries => 0 - ); end notification; end wf_article_callback; / show errors + + update wf_context_transition_info -set notification_callback = 'wf_article_callback.notification' -where workflow_key = 'article_wf' -and context_key = 'default' -and transition_key = 'specification'; + set notification_callback = 'wf_article_callback.notification' + where workflow_key = 'article_wf' + and context_key = 'default' + and transition_key = 'specify'; commit; Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/sample-expenses-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/sample-expenses-create.sql,v diff -u -r1.3 -r1.4 --- openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/sample-expenses-create.sql 12 Apr 2001 18:28:31 -0000 1.3 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/sample-expenses-create.sql 19 Nov 2001 18:17:46 -0000 1.4 @@ -9,15 +9,18 @@ -- -- @cvs-id $Id$ -- + /* This table will hold one row for each case using this workflow. */ create table wf_expenses_cases ( case_id integer primary key constraint wf_expenses_cases_case_fk references wf_cases on delete cascade ); + declare - v_workflow_key varchar2(40); + v_workflow_key wf_workflows.workflow_key%TYPE; + v_attribute_id acs_attributes.attribute_id%TYPE; begin v_workflow_key := workflow.create_workflow( workflow_key => 'expenses_wf', @@ -26,142 +29,311 @@ description => 'Workflow for authorizing employee''s expenses on the company''s behalf', table_name => 'wf_expenses_cases' ); -end; -/ -show errors -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('start', 'expenses_wf', 'Initial state', 1); -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('assignments_done', 'expenses_wf', 'Tasks have been assigned', 2); -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('supervisor_to_approve', 'expenses_wf', 'Supervisor is to approve', 3); -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('other_to_approve', 'expenses_wf', 'Other is to approve', 4); -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('supervisor_approved', 'expenses_wf', 'Supervisor has approved', 5); -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('other_approved', 'expenses_wf', 'Other has approved', 6); -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('ready_to_buy', 'expenses_wf', 'Both have approved', 8); -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('end', 'expenses_wf', 'End state', 9); + /***** + * Places + *****/ + workflow.add_place( + workflow_key => 'expenses_wf', + place_key => 'start', + place_name => 'Start place', + sort_order => 1 + ); + + workflow.add_place( + workflow_key => 'expenses_wf', + place_key => 'assignments_done', + place_name => 'Tasks have been assigned', + sort_order => 2 + ); -insert into wf_transitions(transition_key, transition_name, workflow_key, sort_order, trigger_type) - values ('assign', 'Assign users to approval', 'expenses_wf', 1, 'user'); -insert into wf_transitions(transition_key, transition_name, workflow_key, sort_order, trigger_type) - values ('and_split', 'Both supervisor and Other approval', 'expenses_wf', 2, 'automatic'); -insert into wf_transitions(transition_key, transition_name, workflow_key, sort_order, trigger_type) - values ('supervisor_approval', 'Supervisor approval', 'expenses_wf', 3, 'user'); -insert into wf_transitions(transition_key, transition_name, workflow_key, sort_order, trigger_type) - values ('other_approval', 'Other approval', 'expenses_wf', 4, 'user'); -insert into wf_transitions(transition_key, transition_name, workflow_key, sort_order, trigger_type) - values ('and_join', 'Supervisor and other approval both done', 'expenses_wf', 5, 'automatic'); -insert into wf_transitions(transition_key, transition_name, workflow_key, sort_order, trigger_type) - values ('buy', 'Buy stuff', 'expenses_wf', 6, 'user'); + workflow.add_place( + workflow_key => 'expenses_wf', + place_key => 'supervisor_to_approve', + place_name => 'Supervisor is to approve', + sort_order => 3 + ); --- assign -- --- in -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'assign', 'start', 'in'); --- out -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'assign', 'assignments_done', 'out'); + workflow.add_place( + workflow_key => 'expenses_wf', + place_key => 'other_to_approve', + place_name => 'Other is to approve', + sort_order => 4 + ); + workflow.add_place( + workflow_key => 'expenses_wf', + place_key => 'supervisor_approved', + place_name => 'Supervisor has approved', + sort_order => 5 + ); --- and-split -- --- in -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'and_split', 'assignments_done', 'in'); --- out -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'and_split', 'supervisor_to_approve', 'out'); -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'and_split', 'other_to_approve', 'out'); + workflow.add_place( + workflow_key => 'expenses_wf', + place_key => 'other_approved', + place_name => 'Other has approved', + sort_order => 6 + ); + workflow.add_place( + workflow_key => 'expenses_wf', + place_key => 'ready_to_buy', + place_name => 'Both have approved', + sort_order => 7 + ); --- supervisor_approval --- in -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'supervisor_approval', 'supervisor_to_approve', 'in'); --- out -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'supervisor_approval', 'supervisor_approved', 'out'); + workflow.add_place( + workflow_key => 'expenses_wf', + place_key => 'end', + place_name => 'End place', + sort_order => 8 + ); + /***** + * Roles + *****/ --- other-approval --- in -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'other_approval', 'other_to_approve', 'in'); --- out -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'other_approval', 'other_approved', 'out'); + workflow.add_role( + workflow_key => 'expenses_wf', + role_key => 'assignor', + role_name => 'Assignor', + sort_order => 1 + ); + workflow.add_role( + workflow_key => 'expenses_wf', + role_key => 'supervisor', + role_name => 'Supervisor', + sort_order => 2 + ); --- and-join and or-split --- in -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'and_join', 'supervisor_approved', 'in'); -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'and_join', 'other_approved', 'in'); --- out -insert into wf_arcs(workflow_key, transition_key, place_key, direction, guard_callback, guard_description) - values ('expenses_wf', 'and_join', 'ready_to_buy', 'out', 'wf_expenses.guard_both_approved_p', 'Both supervisor and CEO approved'); -insert into wf_arcs(workflow_key, transition_key, place_key, direction, guard_callback, guard_description) - values ('expenses_wf', 'and_join', 'end', 'out', '#', 'Either supervisor or CEO did not approve'); + workflow.add_role( + workflow_key => 'expenses_wf', + role_key => 'other', + role_name => 'Other approver', + sort_order => 3 + ); --- buy --- in -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'buy', 'ready_to_buy', 'in'); --- out -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'buy', 'end', 'out'); + workflow.add_role( + workflow_key => 'expenses_wf', + role_key => 'requestor', + role_name => 'Requestor', + sort_order => 4 + ); + /***** + * Transitions + *****/ -declare - v_attribute_id acs_attributes.attribute_id%TYPE; -begin + workflow.add_transition( + workflow_key => 'expenses_wf', + transition_key => 'assign', + transition_name => 'Assign users to approval', + role_key => 'assignor', + sort_order => 1, + trigger_type => 'user' + ); + + workflow.add_transition( + workflow_key => 'expenses_wf', + transition_key => 'and_split', + transition_name => 'Parallel approval by supervisor and other', + sort_order => 2, + trigger_type => 'automatic' + ); + + workflow.add_transition( + workflow_key => 'expenses_wf', + transition_key => 'supervisor_approval', + transition_name => 'Approve (Supervisor)', + role_key => 'supervisor', + sort_order => 3, + trigger_type => 'user' + ); + + workflow.add_transition( + workflow_key => 'expenses_wf', + transition_key => 'other_approval', + transition_name => 'Approve (Other)', + role_key => 'other', + sort_order => 4, + trigger_type => 'user' + ); + + workflow.add_transition( + workflow_key => 'expenses_wf', + transition_key => 'and_join', + transition_name => 'Re-synchronization from approval by supervisor and other', + sort_order => 5, + trigger_type => 'automatic' + ); + + workflow.add_transition( + workflow_key => 'expenses_wf', + transition_key => 'buy', + transition_name => 'Buy stuff', + role_key => 'requestor', + sort_order => 6, + trigger_type => 'user' + ); + + /***** + * Arcs + *****/ + + workflow.add_arc( + workflow_key => 'expenses_wf', + from_place_key => 'start', + to_transition_key => 'assign' + ); + + workflow.add_arc( + workflow_key => 'expenses_wf', + from_transition_key => 'assign', + to_place_key => 'assignments_done' + ); + + workflow.add_arc( + workflow_key => 'expenses_wf', + from_place_key => 'assignments_done', + to_transition_key => 'and_split' + ); + + workflow.add_arc( + workflow_key => 'expenses_wf', + from_transition_key => 'and_split', + to_place_key => 'supervisor_to_approve' + ); + + workflow.add_arc( + workflow_key => 'expenses_wf', + from_transition_key => 'and_split', + to_place_key => 'other_to_approve' + ); + + workflow.add_arc( + workflow_key => 'expenses_wf', + from_place_key => 'supervisor_to_approve', + to_transition_key => 'supervisor_approval' + ); + + workflow.add_arc( + workflow_key => 'expenses_wf', + from_transition_key => 'supervisor_approval', + to_place_key => 'supervisor_approved' + ); + + workflow.add_arc( + workflow_key => 'expenses_wf', + from_place_key => 'other_to_approve', + to_transition_key => 'other_approval' + ); + + workflow.add_arc( + workflow_key => 'expenses_wf', + from_transition_key => 'other_approval', + to_place_key => 'other_approved' + ); + + workflow.add_arc( + workflow_key => 'expenses_wf', + from_place_key => 'supervisor_approved', + to_transition_key => 'and_join' + ); + + workflow.add_arc( + workflow_key => 'expenses_wf', + from_place_key => 'other_approved', + to_transition_key => 'and_join' + ); + + workflow.add_arc( + workflow_key => 'expenses_wf', + from_transition_key => 'and_join', + to_place_key => 'ready_to_buy', + guard_callback => 'wf_expenses.guard_both_approved_p', + guard_description => 'Both Supervisor and the Other approver approved' + ); + + workflow.add_arc( + workflow_key => 'expenses_wf', + from_transition_key => 'and_join', + to_place_key => 'end', + guard_callback => '#', + guard_description => 'Either Supervisor or the Other approver did not approve' + ); + + workflow.add_arc( + workflow_key => 'expenses_wf', + from_place_key => 'ready_to_buy', + to_transition_key => 'buy' + ); + + workflow.add_arc( + workflow_key => 'expenses_wf', + from_transition_key => 'buy', + to_place_key => 'end' + ); + + /***** + * Attributes + *****/ + v_attribute_id := workflow.create_attribute( workflow_key => 'expenses_wf', attribute_name => 'supervisor_ok', datatype => 'boolean', pretty_name => 'Supervisor Approval', - default_value => 'f' + default_value => 'f', + sort_order => 1 ); - insert into wf_transition_attribute_map - (workflow_key, transition_key, attribute_id, sort_order) - values - ('expenses_wf', 'supervisor_approval', v_attribute_id, 1); + workflow.add_trans_attribute_map( + workflow_key => 'expenses_wf', + transition_key => 'supervisor_approval', + attribute_name => 'supervisor_ok', + sort_order => 1 + ); v_attribute_id := workflow.create_attribute( workflow_key => 'expenses_wf', attribute_name => 'other_ok', datatype => 'boolean', pretty_name => 'Other Approval', - default_value => 'f' + default_value => 'f', + sort_order => 2 ); - insert into wf_transition_attribute_map - (workflow_key, transition_key, attribute_id, sort_order) - values - ('expenses_wf', 'other_approval', v_attribute_id, 1); + workflow.add_trans_attribute_map( + workflow_key => 'expenses_wf', + transition_key => 'other_approval', + attribute_name => 'other_ok', + sort_order => 1 + ); + /***** + * Assignment + *****/ + + workflow.add_trans_role_assign_map( + workflow_key => 'expenses_wf', + transition_key => 'assign', + assign_role_key => 'supervisor' + ); + + workflow.add_trans_role_assign_map( + workflow_key => 'expenses_wf', + transition_key => 'assign', + assign_role_key => 'other' + ); + + end; / -show errors; +show errors -insert into wf_transition_assignment_map - (workflow_key, transition_key, assign_transition_key) -values - ('expenses_wf', 'assign', 'supervisor_approval'); -insert into wf_transition_assignment_map - (workflow_key, transition_key, assign_transition_key) -values - ('expenses_wf', 'assign', 'other_approval'); @@ -193,25 +365,25 @@ insert into wf_context_task_panels ( - context_key, workflow_key, transition_key, sort_key, header, template_url + context_key, workflow_key, transition_key, sort_order, header, template_url ) values ( 'default', 'expenses_wf', 'supervisor_approval', 1, 'Claim Info', 'sample/expenses-claim-info' ); insert into wf_context_task_panels ( - context_key, workflow_key, transition_key, sort_key, header, template_url + context_key, workflow_key, transition_key, sort_order, header, template_url ) values ( 'default', 'expenses_wf', 'supervisor_approval', 2, 'Logic and Aids', 'sample/expenses-approval-aids' ); insert into wf_context_task_panels ( - context_key, workflow_key, transition_key, sort_key, header, template_url + context_key, workflow_key, transition_key, sort_order, header, template_url ) values ( 'default', 'expenses_wf', 'other_approval', 1, 'Claim Info', 'sample/expenses-claim-info' ); insert into wf_context_task_panels ( - context_key, workflow_key, transition_key, sort_key, header, template_url + context_key, workflow_key, transition_key, sort_order, header, template_url ) values ( 'default', 'expenses_wf', 'other_approval', 2, 'Logic and Aids', 'sample/expenses-approval-aids' ); @@ -273,4 +445,3 @@ / show errors; - Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/upgrade-4.1.1-4.3.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/upgrade-4.1.1-4.3.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/upgrade-4.1.1-4.3.sql 19 Nov 2001 18:17:46 -0000 1.1 @@ -0,0 +1,541 @@ +/* + * We've added support for roles, which is an intermediate step between + * transitions and assignments. A role is a relationship to a process, e.g., + * an editor, publisher, submitter, fixer, doctor, manager, etc. + * A task is performed by a role, but one role may have many tasks to perform. + * The idea is that when you reassign a role, it affects all the tasks that role + * has been assigned to. + * + * For the upgrade, we simply create one role per transtiion, and change + * all the other tables correspondingly. This will execute exactly equivalent + * to the way it would have without the roles refactoring. + * + * We've also added other minor things, such as task instructions and gotten rid + * of wf_attribute_info. + */ + + + +/* + * Table wf_roles: + * Added. + */ + +create table wf_roles ( + role_key varchar2(100), + workflow_key varchar2(100) + constraint wf_roles_workflow_fk + references wf_workflows(workflow_key) + on delete cascade, + role_name varchar2(100) + constraint wf_role_role_name_nn + not null, + -- so we can display roles in some logical order -- + sort_order integer + constraint wf_roles_order_ck + check (sort_order > 0), + -- table constraints -- + constraint wf_role_pk + primary key (workflow_key, role_key), + constraint wf_roles_wf_key_role_name_un + unique (workflow_key, role_name) +); + +comment on table wf_roles is ' + A process has certain roles associated with it, such as "submitter", + "reviewer", "editor", "claimant", etc. For each transition, then, you + specify what role is to perform that task. Thus, two or more tasks can be + performed by one and the same role, so that when the role is reassigned, + it reflects assignments of both tasks. Users and parties are then assigned + to roles instead of directly to tasks. +'; + + + +/* + * Now populate the roles table: + * We just create a role per transition, then hook them up + */ + +insert into wf_roles + (workflow_key, + role_key, + role_name, + sort_order) +select workflow_key, transition_key, transition_name, sort_order + from wf_transitions; + + +/* + * Table wf_transitions: + * Added column role_key. + * Added foreign key constraint wf_transition_role_fk. + */ + +alter table wf_transitions add ( + role_key varchar2(100) +); + +alter table wf_transitions add ( + constraint wf_transition_role_fk + foreign key (workflow_key,role_key) references wf_roles(workflow_key,role_key) + /* We don't do on delete cascade here, because that would mean that + * when a role is deleted, the transitions associated with that role would be deleted, too */ +); + +/* Now populate the new column corresponding to the roles we just created: + * Since there's a one-to-one role per transition, and the have the same keys, + * we just set role_key = transition_key + */ + +update wf_transitions + set role_key = transition_key; + +/* + * Table wf_transition_role_assign_map: + * Added. + * This replaces wf_transtiion_assign_map, since transitions now assign + * roles instead of other transitions. + */ + +create table wf_transition_role_assign_map ( + workflow_key varchar2(100) + constraint wf_role_asgn_map_workflow_fk + references wf_workflows(workflow_key) + on delete cascade, + transition_key varchar2(100), + assign_role_key varchar2(100), + -- table constraints -- + constraint wf_role_asgn_map_pk + primary key (workflow_key, transition_key, assign_role_key), + constraint wf_role_asgn_map_trans_fk + foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) + on delete cascade, + constraint wf_tr_role_asgn_map_asgn_fk + foreign key (workflow_key, assign_role_key) references wf_roles(workflow_key, role_key) + on delete cascade +); + +create index wf_role_asgn_map_wf_trans_idx on wf_transition_role_assign_map(workflow_key, transition_key); +create index wf_role_asgn_map_wf_as_tr_idx on wf_transition_role_assign_map(workflow_key, assign_role_key); + +comment on table wf_transition_role_assign_map is ' + When part of the output of one task is to assign users to a role, + specify that this is the case by inserting a row here. +'; + +comment on column wf_transition_role_assign_map.transition_key is ' + transition_key is the assigning transition. +'; + +comment on column wf_transition_role_assign_map.assign_role_key is ' + assign_role_key is the role being assigned a user to. +'; + + +/* Populate new wf_transition_role_assign_map with the rows from + * wf_transition_assignment_map. Since role_key map one-to-one with transition_keys + * in this upgrade, that's pretty straight-forward. + */ + +insert into wf_transition_role_assign_map + (workflow_key, + transition_key, + assign_role_key) +select workflow_key, + transition_key, + assign_transition_key + from wf_transition_assignment_map; + +/* + * Table wf_transition_assignment_map: + * Dropped. + * This table is no longer releavnt, since transitions don't assign other + * transitions, they assign roles. + */ + +drop table wf_transition_assignment_map; + + +/* + * Table wf_attribute_info: + * Dropped. + * This table was a hang-over from earlier versions and is no longer necessary. + */ + +drop table wf_attribute_info; + +/* + * Table wf_context_role_info: + * Added. + */ + +create table wf_context_role_info ( + context_key varchar2(100) + constraint wf_context_role_context_fk + references wf_contexts(context_key) + on delete cascade, + workflow_key varchar2(100) + constraint wf_context_role_workflow_fk + references wf_workflows(workflow_key) + on delete cascade, + role_key varchar2(100), + /* + * Callback to programatically assign a role. + * Must call wordflow_case.*_role_assignment to make the assignments. + * Will be called when a transition for that role becomes enabled + * signature: (role_key in varchar2, custom_arg in varchar2) + */ + assignment_callback varchar2(100), + assignment_custom_arg varchar2(4000), + -- table constraints -- + constraint wf_context_role_role_fk + foreign key (workflow_key, role_key) references wf_roles(workflow_key, role_key) + on delete cascade, + constraint wf_context_role_info_pk + primary key (context_key, workflow_key, role_key) +); + +comment on table wf_context_role_info is ' + This table holds context-dependent info for roles, currently only the assignment callback +'; + + +/* Populate by a straight copy from wf_context_transition_info */ + +insert into wf_context_role_info + (context_key, + workflow_key, + role_key, + assignment_callback, + assignment_custom_arg) +select context_key, + workflow_key, + transition_key, + assignment_callback, + assignment_custom_arg + from wf_context_transition_info + where assignment_callback is not null + or assignment_custom_arg is not null; + +/* + * Table wf_context_transition_info: + * Added column 'instructions'. + */ + +alter table wf_context_transition_info add ( + instructions varchar2(4000) +); + + +/* Removed columns assignment_callback/custom_arg. */ + +alter table wf_context_transition_info + drop column assignment_callback; +alter table wf_context_transition_info + drop column assignment_custom_arg; + +/* Added on delete cascade to columns workflow_key and .context_key */ + +alter table wf_context_transition_info + drop constraint wf_context_trans_context_fk; +alter table wf_context_transition_info + add constraint wf_context_trans_context_fk + foreign key (context_key) references wf_contexts (context_key); + +alter table wf_context_transition_info + drop constraint wf_context_trans_workflow_fk; +alter table wf_context_transition_info + add constraint wf_context_trans_workflow_fk + foreign key (workflow_key) references wf_workflows (workflow_key); + + +/* + * Table wf_context_workflow_info: + * Added. + */ + +create table wf_context_workflow_info ( + context_key varchar2(100) + constraint wf_context_wf_context_fk + references wf_contexts + on delete cascade, + workflow_key varchar2(100) + constraint wf_context_wf_workflow_fk + references wf_workflows + on delete cascade, + /* The principal is the user/party that sends out email assignment notifications + * And receives email when a task becomes unassigned (for more than x minutes?) + */ + principal_party integer + constraint wf_context_wf_principal_fk + references parties + on delete set null, + -- table constraints -- + constraint wf_context_workflow_pk + primary key (context_key, workflow_key) +); + +/* Insert someone for all existing processes. Hopefully this will be the administrator user. */ + +insert into wf_context_workflow_info + (context_key, + workflow_key, + principal_party) +select 'default', workflow_key, (select min(party_id) from parties) + from wf_workflows; + + +/* + * Table wf_context_task_panels: + * Added columns overrides_action_p and only_display_when_started_p + * Renamed column sort_key to sort_order for consistency + */ + +alter table wf_context_task_panels add ( + /* Display this panel in place of the action panel */ + overrides_action_p char(1) default 'f' + constraint wf_context_panels_ovrd_p_ck + check (overrides_action_p in ('t','f')), + /* Display this panel only when the task has been started (and not finished) */ + only_display_when_started_p char(1) default 'f' + constraint wf_context_panels_display_p_ck + check (only_display_when_started_p in ('t','f')), + sort_order integer +); + +/* Copy over the existing sort_key to the new sort_order */ +update wf_context_task_panels + set sort_order = sort_key; + +/* Change the primary key */ +alter table wf_context_task_panels drop constraint wf_context_panels_pk; +alter table wf_context_task_panels add + constraint wf_context_panels_pk + primary key (context_key, workflow_key, transition_key, sort_order); + +/* Drop old sort_key column */ +alter table wf_context_task_panels drop column sort_key; + +alter table wf_context_task_panels add constraint wf_context_sort_order_nn + check (sort_order is not null); + +/* + * Table wf_context_assignments + * Replaced transition_key with role_key + */ + +alter table wf_context_assignments add ( + role_key varchar2(100), + constraint wf_context_assign_role_fk + foreign key (workflow_key, role_key) references wf_roles (workflow_key, role_key) + on delete cascade +); + +alter table wf_context_assignments drop constraint wf_context_assign_trans_fk; + +update wf_context_assignments + set role_key = transition_key; + +alter table wf_context_assignments drop constraint wf_context_assign_pk; +alter table wf_context_assignments add constraint wf_context_assign_pk + primary key (context_key, workflow_key, role_key, party_id); + +alter table wf_context_assignments drop column transition_key; + + +/* + * Table wf_case_assignments: + * Changed transition_key to role_key + */ + +alter table wf_case_assignments add ( + role_key varchar2(100), + constraint wf_case_assign_role_fk + foreign key (workflow_key, role_key) references wf_roles (workflow_key, role_key) + on delete cascade +); + +update wf_case_assignments + set role_key = transition_key; + +alter table wf_case_assignments drop constraint wf_case_assign_pk; +alter table wf_case_assignments add + constraint wf_case_assign_pk + primary key (case_id, role_key, party_id); + +alter table wf_case_assignments drop constraint wf_case_assign_trans_fk; + +alter table wf_case_assignments drop column transition_key; + + + +/* + * View wf_transition_contexts: + * Added column role_key. + */ + +create or replace view wf_transition_contexts as +select t.transition_key, + t.transition_name, + t.workflow_key, + t.sort_order, + t.trigger_type, + t.role_key, + c.context_key, + c.context_name +from wf_transitions t, wf_contexts c; + + + +/* + * View wf_transition_info: + * Added columns role_key and instructions. + * Removed columns assignment_callback/custom_arg. + */ + +create or replace view wf_transition_info as +select t.transition_key, + t.transition_name, + t.workflow_key, + t.sort_order, + t.trigger_type, + t.context_key, + t.role_key, + ct.estimated_minutes, + ct.instructions, + ct.enable_callback, + ct.enable_custom_arg, + ct.fire_callback, + ct.fire_custom_arg, + ct.time_callback, + ct.time_custom_arg, + ct.deadline_callback, + ct.deadline_custom_arg, + ct.deadline_attribute_name, + ct.hold_timeout_callback, + ct.hold_timeout_custom_arg, + ct.notification_callback, + ct.notification_custom_arg, + ct.unassigned_callback, + ct.unassigned_custom_arg +from wf_transition_contexts t, wf_context_transition_info ct +where ct.workflow_key (+) = t.workflow_key + and ct.transition_key (+) = t.transition_key + and ct.context_key (+) = t.context_key; + + +/* + * View wf_role_info: + * Added. + */ + +create or replace view wf_role_info as +select r.role_key, + r.role_name, + r.workflow_key, + c.context_key, + cr.assignment_callback, + cr.assignment_custom_arg +from wf_roles r, wf_contexts c, wf_context_role_info cr +where cr.workflow_key (+) = r.workflow_key + and cr.role_key (+) = r.role_key + and cr.context_key = c.context_key; + + +/* + * View wf_enabled_transitions: + * Added columns role_key and instructions. + * Removed columns assignment_callback/custom_arg. + */ + +create or replace view wf_enabled_transitions as +select c.case_id, + t.transition_key, + t.transition_name, + t.workflow_key, + t.sort_order, + t.trigger_type, + t.context_key, + t.role_key, + t.enable_callback, + t.enable_custom_arg, + t.fire_callback, + t.fire_custom_arg, + t.time_callback, + t.time_custom_arg, + t.deadline_callback, + t.deadline_custom_arg, + t.deadline_attribute_name, + t.hold_timeout_callback, + t.hold_timeout_custom_arg, + t.notification_callback, + t.notification_custom_arg, + t.estimated_minutes, + t.instructions, + t.unassigned_callback, + t.unassigned_custom_arg + from wf_transition_info t, + wf_cases c + where t.workflow_key = c.workflow_key + and t.context_key = c.context_key + and c.state = 'active' + and not exists + (select tp.place_key + from wf_transition_places tp + where tp.transition_key = t.transition_key + and tp.workflow_key = t.workflow_key + and tp.direction = 'in' + and not exists + (select tk.token_id + from wf_tokens tk + where tk.place_key = tp.place_key + and tk.case_id = c.case_id + and tk.state = 'free' + ) + ); + + +/* + * View wf_user_tasks: + * Added column instructions + * Added "and tr.workflow_key = ta.workflow_key" to where clause + * (looks like a bug) + */ + +create or replace view wf_user_tasks as +select distinct ta.task_id, + ta.case_id, + ta.workflow_key, + ta.transition_key, + tr.transition_name, + tr.instructions, + ta.enabled_date, + ta.started_date, + u.user_id, + ta.state, + ta.holding_user, + ta.hold_timeout, + ta.deadline, + ta.estimated_minutes +from wf_tasks ta, + wf_task_assignments tasgn, + wf_cases c, + wf_transition_info tr, + party_approved_member_map m, + users u +where ta.state in ( 'enabled','started') +and c.case_id = ta.case_id +and c.state = 'active' +and tr.transition_key = ta.transition_key +and tr.workflow_key = ta.workflow_key +and tr.trigger_type = 'user' +and tr.context_key = c.context_key +and tasgn.task_id = ta.task_id +and m.party_id = tasgn.party_id +and u.user_id = m.member_id; + +@@workflow-package.sql +@@workflow-case-package-head.sql +@@workflow-case-package-body.sql + Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/wf-callback-package-body.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/wf-callback-package-body.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/wf-callback-package-body.sql 19 Nov 2001 18:17:46 -0000 1.1 @@ -0,0 +1,46 @@ +-- +-- acs-workflow/sql/wf-callback-package-body.sql +-- +-- Creates the PL/SQL package that provides a small library of reusable +-- workflow callback functions/procedures. +-- +-- @author Lars Pind (lars@pinds.com) +-- +-- @creation-date 2000-05-18 +-- +-- @cvs-id $Id: wf-callback-package-body.sql,v 1.1 2001/11/19 18:17:46 neophytosd Exp $ +-- + +create or replace package body wf_callback +as + + function guard_attribute_true( + case_id in number, + workflow_key in varchar2, + transition_key in varchar2, + place_key in varchar2, + direction in varchar2, + custom_arg in varchar2 + ) return char + is + begin + return workflow_case.get_attribute_value( + case_id => case_id, + attribute_name => custom_arg + ); + end guard_attribute_true; + + function time_sysdate_plus_x( + case_id in number, + transition_key in varchar2, + custom_arg in varchar2 + ) return date + is + begin + return sysdate + to_number(custom_arg); + end time_sysdate_plus_x; + +end wf_callback; +/ +show errors; + Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/wf-callback-package-head.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/wf-callback-package-head.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/wf-callback-package-head.sql 19 Nov 2001 18:17:46 -0000 1.1 @@ -0,0 +1,34 @@ +-- +-- acs-workflow/sql/wf-callback-package-head.sql +-- +-- Creates the PL/SQL package that provides a small library of reusable +-- workflow callback functions/procedures. +-- +-- @author Lars Pind (lars@pinds.com) +-- +-- @creation-date 2000-05-18 +-- +-- @cvs-id $Id: wf-callback-package-head.sql,v 1.1 2001/11/19 18:17:46 neophytosd Exp $ +-- + +create or replace package wf_callback +as + + function guard_attribute_true( + case_id in number, + workflow_key in varchar2, + transition_key in varchar2, + place_key in varchar2, + direction in varchar2, + custom_arg in varchar2 + ) return char; + + function time_sysdate_plus_x( + case_id in number, + transition_key in varchar2, + custom_arg in varchar2 + ) return date; + +end wf_callback; +/ +show errors; Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/wf-callback-package.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/wf-callback-package.sql,v diff -u -r1.1 -r1.2 --- openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/wf-callback-package.sql 5 Apr 2001 18:23:38 -0000 1.1 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/wf-callback-package.sql 19 Nov 2001 18:17:46 -0000 1.2 @@ -11,58 +11,6 @@ -- @cvs-id $Id$ -- -create or replace package wf_callback -as +@@wf-callback-package-head +@@wf-callback-package-body - function guard_attribute_true( - case_id in number, - workflow_key in varchar2, - transition_key in varchar2, - place_key in varchar2, - direction in varchar2, - custom_arg in varchar2 - ) return char; - - function time_sysdate_plus_x( - case_id in number, - transition_key in varchar2, - custom_arg in varchar2 - ) return date; - -end wf_callback; -/ -show errors; - -create or replace package body wf_callback -as - - function guard_attribute_true( - case_id in number, - workflow_key in varchar2, - transition_key in varchar2, - place_key in varchar2, - direction in varchar2, - custom_arg in varchar2 - ) return char - is - begin - return workflow_case.get_attribute_value( - case_id => case_id, - attribute_name => custom_arg - ); - end guard_attribute_true; - - function time_sysdate_plus_x( - case_id in number, - transition_key in varchar2, - custom_arg in varchar2 - ) return date - is - begin - return sysdate + to_number(custom_arg); - end time_sysdate_plus_x; - -end wf_callback; -/ -show errors; - Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/wf-core-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/wf-core-create.sql,v diff -u -r1.1 -r1.2 --- openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/wf-core-create.sql 5 Apr 2001 18:23:38 -0000 1.1 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/wf-core-create.sql 19 Nov 2001 18:17:46 -0000 1.2 @@ -19,11 +19,11 @@ begin acs_object_type.create_type( - object_type => 'workflow', - pretty_name => 'Workflow', - pretty_plural => 'Workflow', - table_name => 'wf_cases', - id_column => 'case_id' + object_type => 'workflow', + pretty_name => 'Workflow', + pretty_plural => 'Workflow', + table_name => 'wf_cases', + id_column => 'case_id' ); end; / @@ -33,9 +33,9 @@ workflow_key varchar2(100) constraint wf_workflows_pk primary key - constraint wf_workflows_workflow_key_fk - references acs_object_types(object_type) - on delete cascade, + constraint wf_wf_acs_object_types_fk + references acs_object_types(object_type) + on delete cascade, description varchar2(4000) ); @@ -46,27 +46,59 @@ create table wf_places ( place_key varchar2(100), workflow_key varchar2(100) - constraint wf_place_workflow_fk - references wf_workflows(workflow_key) - on delete cascade, + constraint wf_place_workflow_fk + references wf_workflows(workflow_key) + on delete cascade, place_name varchar2(100) - constraint wf_place_name_nn - not null, - -- purely for UI purposes + constraint wf_place_name_nn + not null, + -- so we can display places in some logical order -- sort_order integer - constraint wf_place_order_ck - check (sort_order > 0), + constraint wf_place_order_ck + check (sort_order > 0), + -- table constraints -- constraint wf_place_pk - primary key (workflow_key, place_key), + primary key (workflow_key, place_key), constraint wf_places_wf_key_place_name_un - unique (workflow_key, place_name) + unique (workflow_key, place_name) ); comment on table wf_places is ' The circles of the petri net. These hold the tokens representing the overall state of the workflow. '; + +create table wf_roles ( + role_key varchar2(100), + workflow_key varchar2(100) + constraint wf_roles_workflow_fk + references wf_workflows(workflow_key) + on delete cascade, + role_name varchar2(100) + constraint wf_role_role_name_nn + not null, + -- so we can display roles in some logical order -- + sort_order integer + constraint wf_roles_order_ck + check (sort_order > 0), + -- table constraints -- + constraint wf_role_pk + primary key (workflow_key, role_key), + constraint wf_roles_wf_key_role_name_un + unique (workflow_key, role_name) +); + +comment on table wf_roles is ' + A process has certain roles associated with it, such as "submitter", + "reviewer", "editor", "claimant", etc. For each transition, then, you + specify what role is to perform that task. Thus, two or more tasks can be + performed by one and the same role, so that when the role is reassigned, + it reflects assignments of both tasks. Users and parties are then assigned + to roles instead of directly to tasks. +'; + + create table wf_transitions ( transition_key varchar2(100), transition_name varchar2(100) @@ -75,19 +107,27 @@ workflow_key varchar2(100) constraint wf_transition_workflow_fk references wf_workflows(workflow_key) - on delete cascade, - -- purely for UI purposes + on delete cascade, + -- what role does this transition belong to + -- (only for user-triggered transitions) + role_key varchar2(100), + -- so we can display transitions in some logical order -- sort_order integer constraint wf_transition_order_ck check (sort_order > 0), trigger_type varchar2(40) - constraint wf_transition_trigger_type_ck - check (trigger_type in + constraint wf_transition_trigger_type_ck + check (trigger_type in ('automatic','user','message','time')), + -- table constraints -- constraint wf_transition_pk - primary key (workflow_key, transition_key), + primary key (workflow_key, transition_key), constraint wf_trans_wf_key_trans_name_un - unique (workflow_key, transition_name) + unique (workflow_key, transition_name), + constraint wf_transition_role_fk + foreign key (workflow_key,role_key) references wf_roles(workflow_key,role_key) + /* We don't do on delete cascade here, because that would mean that + * when a role is deleted, the transitions associated with that role would be deleted, too */ ); comment on table wf_transitions is ' @@ -96,15 +136,15 @@ create table wf_arcs ( workflow_key varchar2(100) - constraint wf_ts_arc_workflow_fk - references wf_workflows(workflow_key) - on delete cascade, + constraint wf_ts_arc_workflow_fk + references wf_workflows(workflow_key) + on delete cascade, transition_key varchar2(100), place_key varchar2(100), -- direction is relative to the transition direction varchar2(3) - constraint wf_arc_direction_ck - check (direction in ('in','out')), + constraint wf_arc_direction_ck + check (direction in ('in','out')), /* Must be satisfied for the arc to be traveled by a token * This is the name of a PL/SQL function to execute, which must return t or f * Signature: (case_id in number, workflow_key in varchar2, transition_key in varchar2, @@ -114,16 +154,17 @@ guard_callback varchar2(100), guard_custom_arg varchar2(4000), guard_description varchar2(500), + -- table constraints -- + constraint wf_arc_pk + primary key (workflow_key, transition_key, place_key, direction), constraint wf_arc_guard_on_in_arc_ck - check (guard_callback is null or direction = 'out'), + check (guard_callback is null or direction = 'out'), constraint wf_arc_transition_fk - foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) - on delete cascade, + foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) + on delete cascade, constraint wf_arc_place_fk - foreign key (workflow_key, place_key) references wf_places(workflow_key, place_key) - on delete cascade, - constraint wf_arc_pk - primary key (workflow_key, transition_key, place_key, direction) + foreign key (workflow_key, place_key) references wf_places(workflow_key, place_key) + on delete cascade ); create index wf_arcs_wf_key_trans_key_idx on wf_arcs(workflow_key, transition_key); @@ -137,35 +178,23 @@ away from the transition. '; -create table wf_attribute_info ( - attribute_id integer - constraint wf_attribute_info_attribute_pk - primary key - constraint wf_attribute_info_attribute_fk - references acs_attributes(attribute_id) - on delete cascade, - wf_datatype varchar2(50) - constraint wf_attr_info_wf_datatype_ck - check (wf_datatype in ('none', 'party')) -); - - create table wf_transition_attribute_map ( - workflow_key varchar2(100) - constraint wf_trans_attr_map_workflow_fk - references wf_workflows(workflow_key) - on delete cascade, + workflow_key varchar2(100) + constraint wf_trans_attr_map_workflow_fk + references wf_workflows(workflow_key) + on delete cascade, transition_key varchar2(100), -- so the user can decide in what order the attributes should be presented sort_order integer not null, attribute_id integer - constraint wf_trans_attr_map_attribute_fk - references acs_attributes, + constraint wf_trans_attr_map_attribute_fk + references acs_attributes, + -- table constraints -- constraint wf_trans_attr_map_pk - primary key (workflow_key, transition_key, attribute_id), + primary key (workflow_key, transition_key, attribute_id), constraint wf_trans_attr_map_trans_fk - foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) - on delete cascade + foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) + on delete cascade ); comment on table wf_transition_attribute_map is ' @@ -174,56 +203,55 @@ '; -create table wf_transition_assignment_map ( - workflow_key varchar2(100) - constraint wf_trans_asgn_map_workflow_fk - references wf_workflows(workflow_key) - on delete cascade, +create table wf_transition_role_assign_map ( + workflow_key varchar2(100) + constraint wf_role_asgn_map_workflow_fk + references wf_workflows(workflow_key) + on delete cascade, transition_key varchar2(100), - assign_transition_key varchar2(100), - constraint wf_trans_asgn_map_pk - primary key (workflow_key, transition_key, assign_transition_key), - constraint wf_trans_asgn_map_trans_fk - foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) - on delete cascade, - constraint wf_tr_asgn_map_asgn_trans_fk - foreign key (workflow_key, assign_transition_key) references wf_transitions(workflow_key, transition_key) - on delete cascade + assign_role_key varchar2(100), + -- table constraints -- + constraint wf_role_asgn_map_pk + primary key (workflow_key, transition_key, assign_role_key), + constraint wf_role_asgn_map_trans_fk + foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) + on delete cascade, + constraint wf_tr_role_asgn_map_asgn_fk + foreign key (workflow_key, assign_role_key) references wf_roles(workflow_key, role_key) + on delete cascade ); -create index wf_trans_asgn_map_wf_trans_idx on wf_transition_assignment_map(workflow_key, transition_key); -create index wf_trans_asgn_map_wf_as_tr_idx on wf_transition_assignment_map(workflow_key, assign_transition_key); +create index wf_role_asgn_map_wf_trans_idx on wf_transition_role_assign_map(workflow_key, transition_key); +create index wf_role_asgn_map_wf_as_tr_idx on wf_transition_role_assign_map(workflow_key, assign_role_key); -comment on table wf_transition_assignment_map is ' - When part of the output of one task is to assign users to another task, - specify that this is the case by inserting a row here. +comment on table wf_transition_role_assign_map is ' + When part of the output of one task is to assign users to a role, + specify that this is the case by inserting a row here. '; -comment on column wf_transition_assignment_map.transition_key is ' +comment on column wf_transition_role_assign_map.transition_key is ' transition_key is the assigning transition. '; -comment on column wf_transition_assignment_map.assign_transition_key is ' - transition_key is the transition being assigned a user to. +comment on column wf_transition_role_assign_map.assign_role_key is ' + assign_role_key is the role being assigned a user to. '; - - /* * Contexts */ create table wf_contexts ( - context_key varchar2(100) - constraint wf_context_pk - primary key, - context_name varchar2(100) - constraint wf_contexts_context_name_nn - not null - constraint wf_contexts_context_name_un - unique + context_key varchar2(100) + constraint wf_context_pk + primary key, + context_name varchar2(100) + constraint wf_contexts_context_name_nn + not null + constraint wf_contexts_context_name_un + unique ); comment on table wf_contexts is ' @@ -240,86 +268,105 @@ commit; +create table wf_context_workflow_info ( + context_key varchar2(100) + constraint wf_context_wf_context_fk + references wf_contexts + on delete cascade, + workflow_key varchar2(100) + constraint wf_context_wf_workflow_fk + references wf_workflows + on delete cascade, + /* The principal is the user/party that sends out email assignment notifications + * And receives email when a task becomes unassigned (for more than x minutes?) + */ + principal_party integer + constraint wf_context_wf_principal_fk + references parties + on delete set null, + -- table constraints -- + constraint wf_context_workflow_pk + primary key (context_key, workflow_key) +); +comment on table wf_context_workflow_info is ' + Holds context-dependent information about the workflow, specifically the + principal user. +'; + + create table wf_context_transition_info ( - context_key varchar2(100) - constraint wf_context_trans_context_fk - references wf_contexts, - workflow_key varchar2(100) - constraint wf_context_trans_workflow_fk - references wf_workflows, - transition_key varchar2(100), + context_key varchar2(100) + constraint wf_context_trans_context_fk + references wf_contexts + on delete cascade, + workflow_key varchar2(100) + constraint wf_context_trans_workflow_fk + references wf_workflows + on delete cascade, + transition_key varchar2(100), /* information for the transition in the context */ /* The number of minutes this task is estimated to take */ - estimated_minutes integer, + estimated_minutes integer, + /* Instructions for how to complete the task. Will be displayed on the task page. */ + instructions varchar2(4000), /* * Will be called when the transition is enabled/fired. * signature: (case_id in number, transition_key in varchar2, custom_arg in varchar2) */ - enable_callback varchar2(100), - enable_custom_arg varchar2(4000), - fire_callback varchar2(100), - fire_custom_arg varchar2(4000), + enable_callback varchar2(100), + enable_custom_arg varchar2(4000), + fire_callback varchar2(100), + fire_custom_arg varchar2(4000), /* - * Must insert rows into the wf_task_assignments table. - * Will be called when the transition becomes enabled - * signature: (task_id in number, custom_arg in varchar2) - */ - assignment_callback varchar2(100), - assignment_custom_arg varchar2(4000), - /* * Must return the date that the timed transition should fire * Will be called when the transition is enabled * signature: (case_id in number, transition_key in varchar2, custom_arg in varchar2) return date */ - time_callback varchar2(100), - time_custom_arg varchar2(4000), + time_callback varchar2(100), + time_custom_arg varchar2(4000), /* * Returns the deadline for this task. * Will be called when the transition becomes enabled * Signature: (case_id in number, transition_key in varchar2, custom_arg in varchar2) return date */ - deadline_callback varchar2(100), - deadline_custom_arg varchar2(4000), + deadline_callback varchar2(100), + deadline_custom_arg varchar2(4000), /* The name of an attribute that holds the deadline */ - deadline_attribute_name varchar2(100), + deadline_attribute_name varchar2(100), /* * Must return the date that the user's hold on the task times out. * called when the user starts the task. * signature: (case_id in number, transition_key in varchar2, custom_arg in varchar2) return date */ - hold_timeout_callback varchar2(100), - hold_timeout_custom_arg varchar2(4000), + hold_timeout_callback varchar2(100), + hold_timeout_custom_arg varchar2(4000), /* * Notification callback * Will be called when a notification is sent i.e., when a transition is enabled, * or assignment changes. - * signature: (task_id in number, - * custom_arg in varchar2, - * party_to in integer, - * party_from in out integer, - * subject in out varchar2, - * body in out varchar2) + * signature: (task_id in number, + * custom_arg in varchar2, + * party_to in integer, + * party_from in out integer, + * subject in out varchar2, + * body in out varchar2) */ - notification_callback varchar2(100), - notification_custom_arg varchar2(4000), + notification_callback varchar2(100), + notification_custom_arg varchar2(4000), /* - * Unassigned callback - * Will be called whenever a task becomes unassigned - * Signature: (case_id in number, transition_key in varchar2, custom_arg in varchar2) + * Callback to handle unassigned tasks. + * Will be called when an enabled task becomes unassigned. + * Signature: (task_id in number, custom_arg in varchar2) */ unassigned_callback varchar2(100), unassigned_custom_arg varchar2(4000), - /* name of the privilege we should check before allowing access - * to task information. - */ - access_privilege varchar2(100), - /* table constraints */ + -- table constraints -- constraint wf_context_trans_trans_fk - foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) - on delete cascade, + foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) + on delete cascade, constraint wf_context_transition_pk - primary key (context_key, workflow_key, transition_key) + primary key (context_key, workflow_key, transition_key) ); create index wf_ctx_trans_wf_trans_idx on wf_context_transition_info(workflow_key, transition_key); @@ -330,25 +377,64 @@ '; +create table wf_context_role_info ( + context_key varchar2(100) + constraint wf_context_role_context_fk + references wf_contexts(context_key) + on delete cascade, + workflow_key varchar2(100) + constraint wf_context_role_workflow_fk + references wf_workflows(workflow_key) + on delete cascade, + role_key varchar2(100), + /* + * Callback to programatically assign a role. + * Must call wordflow_case.*_role_assignment to make the assignments. + * Will be called when a transition for that role becomes enabled + * signature: (role_key in varchar2, custom_arg in varchar2) + */ + assignment_callback varchar2(100), + assignment_custom_arg varchar2(4000), + -- table constraints -- + constraint wf_context_role_role_fk + foreign key (workflow_key, role_key) references wf_roles(workflow_key, role_key) + on delete cascade, + constraint wf_context_role_info_pk + primary key (context_key, workflow_key, role_key) +); + +comment on table wf_context_role_info is ' + This table holds context-dependent info for roles, currently only the assignment callback +'; + + create table wf_context_task_panels ( - context_key varchar2(100) not null - constraint wf_context_panels_context_fk - references wf_contexts(context_key) - on delete cascade, - workflow_key varchar2(100) not null - constraint wf_context_panels_workflow_fk - references wf_workflows(workflow_key) - on delete cascade, - transition_key varchar2(100) not null, - sort_key integer not null, - header varchar2(200) not null, - template_url varchar2(500) not null, - /* table constraints */ + context_key varchar2(100) not null + constraint wf_context_panels_context_fk + references wf_contexts(context_key) + on delete cascade, + workflow_key varchar2(100) not null + constraint wf_context_panels_workflow_fk + references wf_workflows(workflow_key) + on delete cascade, + transition_key varchar2(100) not null, + sort_order integer not null, + header varchar2(200) not null, + template_url varchar2(500) not null, + /* Display this panel in place of the action panel */ + overrides_action_p char(1) default 'f' + constraint wf_context_panels_ovrd_p_ck + check (overrides_action_p in ('t','f')), + /* Display this panel only when the task has been started (and not finished) */ + only_display_when_started_p char(1) default 'f' + constraint wf_context_panels_display_p_ck + check (only_display_when_started_p in ('t','f')), + -- table constraints -- constraint wf_context_panels_trans_fk - foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) - on delete cascade, + foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) + on delete cascade, constraint wf_context_panels_pk - primary key (context_key, workflow_key, transition_key, sort_key) + primary key (context_key, workflow_key, transition_key, sort_order) ); create index wf_ctx_panl_workflow_trans_idx on wf_context_task_panels(workflow_key, transition_key); @@ -358,33 +444,32 @@ '; - create table wf_context_assignments ( - context_key varchar2(100) - constraint wf_context_assign_context_fk - references wf_contexts(context_key) - on delete cascade, - workflow_key varchar2(100) - constraint wf_context_assign_workflow_fk - references wf_workflows(workflow_key) - on delete cascade, - transition_key varchar2(100), - party_id integer - constraint wf_context_assign_party_fk - references parties(party_id) - on delete cascade, - /* table constraints */ - constraint wf_context_assign_trans_fk - foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) - on delete cascade, + context_key varchar2(100) + constraint wf_context_assign_context_fk + references wf_contexts(context_key) + on delete cascade, + workflow_key varchar2(100) + constraint wf_context_assign_workflow_fk + references wf_workflows(workflow_key) + on delete cascade, + role_key varchar2(100), + party_id integer + constraint wf_context_assign_party_fk + references parties(party_id) + on delete cascade, + -- table constraints -- constraint wf_context_assign_pk - primary key (context_key, workflow_key, transition_key, party_id) + primary key (context_key, workflow_key, role_key, party_id), + constraint wf_context_assign_role_fk + foreign key (workflow_key, role_key) references wf_roles(workflow_key, role_key) + on delete cascade ); -create index wf_ctx_assg_workflow_trans_idx on wf_context_assignments(workflow_key, transition_key); +create index wf_ctx_assg_workflow_trans_idx on wf_context_assignments(workflow_key, role_key); comment on table wf_context_assignments is ' - Static assignment at the context level. + Static (default) per-context assignments of roles to parties. '; @@ -397,26 +482,26 @@ case_id integer constraint wf_cases_pk primary key - constraint wf_cases_acs_object_fk - references acs_objects(object_id) - on delete cascade, + constraint wf_cases_acs_object_fk + references acs_objects(object_id) + on delete cascade, workflow_key varchar2(100) constraint wf_cases_workflow_fk references wf_workflows(workflow_key) - on delete cascade, - context_key varchar2(100) - constraint wf_cases_context_fk - references wf_contexts(context_key) - on delete cascade, - object_id constraint wf_cases_object_fk - references acs_objects(object_id) - on delete cascade, + on delete cascade, + context_key varchar2(100) + constraint wf_cases_context_fk + references wf_contexts(context_key) + on delete cascade, + object_id constraint wf_cases_object_fk + references acs_objects(object_id) + on delete cascade, -- a toplevel state of the case - state varchar2(40) - default 'created' - constraint wf_cases_state_ck - check (state in ('created', - 'active', + state varchar2(40) + default 'created' + constraint wf_cases_state_ck + check (state in ('created', + 'active', 'suspended', 'canceled', 'finished')) @@ -427,58 +512,64 @@ create index wf_cases_object_id_idx on wf_cases(object_id); comment on table wf_cases is ' - The instance of a workflow, the actual object we''re concerned with in this - workflow. + The instance of a process, e.g. the case of publishing one article, + the case of handling one insurance claim, the case of handling + one ecommerce order, of fixing one ticket-tracker ticket. '; comment on column wf_cases.object_id is ' - A case is itself an acs_object, but moreover, a case will always be about some - other acs_object. E.g. for ticket-tracker, the case_id will refer to an instance of - the ticket-tracker-workflow, while the object_id will refer to the ticket itself. - It is possible to have multiple cases around the same object. + A case is generally about some other object, e.g., an insurance claim, an article, + a ticket, an order, etc. This is the place to store the reference to that object. + It is not uncommong to have more than one case for the same object, e.g., we might + have one process for evaluating and honoring an insurance claim, and another for archiving + legal information about a claim. '; create table wf_case_assignments ( - case_id integer - constraint wf_case_assign_fk - references wf_cases(case_id) - on delete cascade, + case_id integer + constraint wf_case_assign_fk + references wf_cases(case_id) + on delete cascade, workflow_key varchar2(100), - transition_key varchar2(100), - party_id integer - constraint wf_case_assign_party_fk - references parties(party_id) - on delete cascade, - constraint wf_case_assign_trans_fk - foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key), + role_key varchar2(100), + party_id integer + constraint wf_case_assign_party_fk + references parties(party_id) + on delete cascade, + -- table constraints -- constraint wf_case_assign_pk - primary key (case_id, transition_key, party_id) + primary key (case_id, role_key, party_id), + constraint wf_case_assign_role_fk + foreign key (workflow_key, role_key) references wf_roles(workflow_key, role_key) + on delete cascade ); create index wf_case_assgn_party_idx on wf_case_assignments(party_id); comment on table wf_case_assignments is ' - Manual assignment at the per-case level. + Manual per-case assignments of roles to parties. '; create table wf_case_deadlines ( - case_id integer - constraint wf_case_deadline_fk - references wf_cases(case_id) - on delete cascade, + case_id integer + constraint wf_case_deadline_fk + references wf_cases(case_id) + on delete cascade, workflow_key varchar2(100), transition_key varchar2(100), - deadline date - constraint wf_case_deadline_nn - not null, - constraint wf_case_deadline_trans_fk - foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key), + deadline date + constraint wf_case_deadline_nn + not null, + -- table constraints -- constraint wf_case_deadline_pk - primary key (case_id, transition_key) + primary key (case_id, transition_key), + constraint wf_case_deadline_trans_fk + foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) + on delete cascade ); @@ -491,22 +582,22 @@ create sequence wf_task_id_seq start with 1000 increment by 1; create table wf_tasks ( - task_id integer - constraint wf_task_pk - primary key, + task_id integer + constraint wf_task_pk + primary key, case_id integer - constraint wf_task_case_fk - references wf_cases - on delete cascade, - workflow_key varchar2(100) - constraint wf_task_workflow_fk - references wf_workflows(workflow_key), - transition_key varchar2(100), + constraint wf_task_case_fk + references wf_cases + on delete cascade, + workflow_key varchar2(100) + constraint wf_task_workflow_fk + references wf_workflows(workflow_key), + transition_key varchar2(100), /* Information about the task */ - state varchar2(40) - default 'enabled' - constraint wf_task_state_ck - check (state in ('enabled','started','canceled', + state varchar2(40) + default 'enabled' + constraint wf_task_state_ck + check (state in ('enabled','started','canceled', 'finished','overridden')), enabled_date date default sysdate, started_date date, @@ -517,15 +608,15 @@ trigger_time date, /* -- USER transition info */ deadline date, - estimated_minutes integer, + estimated_minutes integer, holding_user integer - constraint wf_task_holding_user_fk - references users(user_id) - on delete cascade, + constraint wf_task_holding_user_fk + references users(user_id) + on delete cascade, hold_timeout date, - /* -- */ + -- table constraints -- constraint wf_task_transition_fk - foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) + foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) ); create index wf_tasks_case_id_idx on wf_tasks(case_id); @@ -539,15 +630,16 @@ create table wf_task_assignments ( task_id integer - constraint wf_task_assign_task_fk - references wf_tasks(task_id) - on delete cascade, + constraint wf_task_assign_task_fk + references wf_tasks(task_id) + on delete cascade, party_id integer - constraint wf_task_party_fk + constraint wf_task_party_fk references parties(party_id) - on delete cascade, + on delete cascade, + -- table constraints -- constraint wf_task_assignments_pk - primary key (task_id, party_id) + primary key (task_id, party_id) ); create index wf_task_asgn_party_id_idx on wf_task_assignments(party_id); @@ -556,43 +648,44 @@ create table wf_tokens ( token_id integer - constraint wf_token_pk - primary key, - case_id integer - constraint wf_token_workflow_instance_fk - references wf_cases(case_id) - on delete cascade, - workflow_key varchar2(100) - constraint wf_token_workflow_fk - references wf_workflows(workflow_key), + constraint wf_token_pk + primary key, + case_id integer + constraint wf_token_workflow_instance_fk + references wf_cases(case_id) + on delete cascade, + workflow_key varchar2(100) + constraint wf_token_workflow_fk + references wf_workflows(workflow_key), -- a token must always be in some place place_key varchar2(100), state varchar2(40) default 'free' - constraint wf_tokens_state_ck - check (state in ('free', 'locked', 'canceled', 'consumed')), + constraint wf_tokens_state_ck + check (state in ('free', 'locked', 'canceled', 'consumed')), -- when the token is locked, by which task locked_task_id integer - constraint wf_token_task_fk - references wf_tasks(task_id), + constraint wf_token_task_fk + references wf_tasks(task_id), -- info on state changes produced_date date default sysdate, locked_date date, - canceled_date date, + canceled_date date, consumed_date date, produced_journal_id integer - constraint wf_token_produced_journal_fk - references journal_entries(journal_id), + constraint wf_token_produced_journal_fk + references journal_entries(journal_id), locked_journal_id integer - constraint wf_token_locked_journal_fk - references journal_entries(journal_id), + constraint wf_token_locked_journal_fk + references journal_entries(journal_id), canceled_journal_id integer - constraint wf_token_canceled_journal_fk - references journal_entries(journal_id), + constraint wf_token_canceled_journal_fk + references journal_entries(journal_id), consumed_journal_id integer - constraint wf_token_consumed_journal_fk - references journal_entries(journal_id), + constraint wf_token_consumed_journal_fk + references journal_entries(journal_id), + -- table constraints -- constraint wf_token_place_fk - foreign key (workflow_key, place_key) references wf_places(workflow_key, place_key) + foreign key (workflow_key, place_key) references wf_places(workflow_key, place_key) ); create index wf_tokens_case_id_idx on wf_tokens(case_id); @@ -607,20 +700,21 @@ /* Should evetually be done by acs_objects automatically */ create table wf_attribute_value_audit ( - case_id integer - constraint wf_attr_val_audit_case_fk - references wf_cases(case_id) - on delete cascade, - attribute_id integer - constraint wf_attr_val_audit_attr_fk - references acs_attributes(attribute_id) - on delete cascade, - journal_id integer - constraint wf_attr_val_audit_journal_fk - references journal_entries(journal_id), - attr_value varchar2(4000), + case_id integer + constraint wf_attr_val_audit_case_fk + references wf_cases(case_id) + on delete cascade, + attribute_id integer + constraint wf_attr_val_audit_attr_fk + references acs_attributes(attribute_id) + on delete cascade, + journal_id integer + constraint wf_attr_val_audit_journal_fk + references journal_entries(journal_id), + attr_value varchar2(4000), + -- table constraints -- constraint wf_attr_val_audit_pk - primary key (case_id, attribute_id, journal_id) + primary key (case_id, attribute_id, journal_id) ); create index wf_attr_val_aud_attr_id_idx on wf_attribute_value_audit(attribute_id); @@ -641,7 +735,8 @@ t.transition_name, t.workflow_key, t.sort_order, - t.trigger_type, + t.trigger_type, + t.role_key, c.context_key, c.context_name from wf_transitions t, wf_contexts c; @@ -660,13 +755,13 @@ t.sort_order, t.trigger_type, t.context_key, + t.role_key, ct.estimated_minutes, + ct.instructions, ct.enable_callback, ct.enable_custom_arg, ct.fire_callback, ct.fire_custom_arg, - ct.assignment_callback, - ct.assignment_custom_arg, ct.time_callback, ct.time_custom_arg, ct.deadline_callback, @@ -677,8 +772,7 @@ ct.notification_callback, ct.notification_custom_arg, ct.unassigned_callback, - ct.unassigned_custom_arg, - ct.access_privilege + ct.unassigned_custom_arg from wf_transition_contexts t, wf_context_transition_info ct where ct.workflow_key (+) = t.workflow_key and ct.transition_key (+) = t.transition_key @@ -687,6 +781,24 @@ /* + * Returns all the information stored about a certain role + * in all contexts. You'll usually want to use this with a + * "where context = " clause. + */ +create or replace view wf_role_info as +select r.role_key, + r.role_name, + r.workflow_key, + c.context_key, + cr.assignment_callback, + cr.assignment_custom_arg +from wf_roles r, wf_contexts c, wf_context_role_info cr +where cr.workflow_key (+) = r.workflow_key + and cr.role_key (+) = r.role_key + and cr.context_key = c.context_key; + + +/* * This view makes it easy to get the input/output places of a transition */ create or replace view wf_transition_places as @@ -726,12 +838,11 @@ t.sort_order, t.trigger_type, t.context_key, + t.role_key, t.enable_callback, t.enable_custom_arg, t.fire_callback, t.fire_custom_arg, - t.assignment_callback, - t.assignment_custom_arg, t.time_callback, t.time_custom_arg, t.deadline_callback, @@ -741,10 +852,10 @@ t.hold_timeout_custom_arg, t.notification_callback, t.notification_custom_arg, - t.unassigned_callback, - t.unassigned_custom_arg, t.estimated_minutes, - t.access_privilege + t.instructions, + t.unassigned_callback, + t.unassigned_custom_arg from wf_transition_info t, wf_cases c where t.workflow_key = c.workflow_key @@ -758,10 +869,10 @@ and tp.direction = 'in' and not exists (select tk.token_id - from wf_tokens tk - where tk.place_key = tp.place_key - and tk.case_id = c.case_id - and tk.state = 'free' + from wf_tokens tk + where tk.place_key = tp.place_key + and tk.case_id = c.case_id + and tk.state = 'free' ) ); @@ -782,6 +893,7 @@ ta.workflow_key, ta.transition_key, tr.transition_name, + tr.instructions, ta.enabled_date, ta.started_date, u.user_id, @@ -800,6 +912,7 @@ and c.case_id = ta.case_id and c.state = 'active' and tr.transition_key = ta.transition_key +and tr.workflow_key = ta.workflow_key and tr.trigger_type = 'user' and tr.context_key = c.context_key and tasgn.task_id = ta.task_id Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/wf-core-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/wf-core-drop.sql,v diff -u -r1.1 -r1.2 --- openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/wf-core-drop.sql 5 Apr 2001 18:23:38 -0000 1.1 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/wf-core-drop.sql 19 Nov 2001 18:17:46 -0000 1.2 @@ -35,6 +35,7 @@ drop view wf_user_tasks; drop view wf_enabled_transitions; drop view wf_transition_places; +drop view wf_role_info; drop view wf_transition_info; drop view wf_transition_contexts; @@ -50,15 +51,17 @@ /* Context level */ drop table wf_context_assignments; drop table wf_context_task_panels; +drop table wf_context_role_info; drop table wf_context_transition_info; +drop table wf_context_workflow_info; drop table wf_contexts; /* Knowledge Level */ -drop table wf_attribute_info; -drop table wf_transition_assignment_map; +drop table wf_transition_role_assign_map; drop table wf_transition_attribute_map; drop table wf_arcs; drop table wf_transitions; +drop table wf_roles; drop table wf_places; drop table wf_workflows; Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/workflow-case-package-body.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/workflow-case-package-body.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/workflow-case-package-body.sql 19 Nov 2001 18:17:46 -0000 1.1 @@ -0,0 +1,1973 @@ +-- +-- acs-workflow/sql/workflow-case-package-body.sql +-- +-- Creates the PL/SQL package that provides the API for interacting +-- with a workflow case. +-- +-- @author Lars Pind (lars@pinds.com) +-- +-- @creation-date 2000-05-18 +-- +-- @cvs-id $Id: workflow-case-package-body.sql,v 1.1 2001/11/19 18:17:46 neophytosd Exp $ +-- + +create or replace package body workflow_case +is + + /* + * FORWARD DECLARATIONS + */ + + procedure add_token ( + case_id in number, + place_key in varchar2, + journal_id in number + ); + + procedure lock_token ( + case_id in number, + place_key in varchar2, + journal_id in number, + task_id in number + ); + + procedure release_token ( + task_id in number, + journal_id in number + ); + + procedure consume_token ( + case_id in number, + place_key in varchar2, + journal_id in number, + task_id in number default null + ); + + procedure execute_unassigned_callback ( + callback in varchar2, + task_id in number, + custom_arg in varchar2 + ); + + procedure enable_transitions ( + case_id in number + ); + + procedure sweep_automatic_transitions ( + case_id in number, + journal_id in number + ); + + function finished_p( + case_id in number, + journal_id in number + ) return char; + + procedure fire_transition_internal ( + task_id in number, + journal_id in number + ); + + procedure start_task( + task_id in number, + user_id in number, + journal_id in number + ); + + procedure cancel_task( + task_id in number, + journal_id in number + ); + + procedure finish_task ( + task_id in number, + journal_id in number + ); + + procedure notify_assignee( + task_id in wf_tasks.task_id%TYPE, + user_id in users.user_id%TYPE, + callback in wf_context_transition_info.notification_callback%TYPE, + custom_arg in wf_context_transition_info.notification_custom_arg%TYPE + ); + + /* + * CURSORS + */ + + cursor input_places( + workflow_key in wf_workflows.workflow_key%TYPE, + transition_key in wf_transitions.transition_key%TYPE + ) + return wf_transition_places%ROWTYPE + is + select * + from wf_transition_places tp + where tp.workflow_key = input_places.workflow_key + and tp.transition_key = input_places.transition_key + and direction = 'in'; + + + cursor output_places ( + workflow_key in wf_workflows.workflow_key%TYPE, + transition_key in wf_transitions.transition_key%TYPE + ) + return wf_transition_places%ROWTYPE + is + select * + from wf_transition_places tp + where tp.workflow_key = output_places.workflow_key + and tp.transition_key = output_places.transition_key + and direction = 'out'; + + + /* + * PUBLIC API + */ + + function new ( + case_id in number default null, + workflow_key in varchar2, + context_key in varchar2 default null, + object_id in integer, + creation_date in date default sysdate, + creation_user in integer default null, + creation_ip in varchar2 default null + ) + return integer + is + v_case_id number; + v_workflow_case_table varchar2(30); + v_context_key_for_query varchar2(100); + begin + if context_key is null then + v_context_key_for_query := 'default'; + else + v_context_key_for_query := context_key; + end if; + + /* insert a row into acs_objects */ + v_case_id := acs_object.new( + object_id => new.case_id, + object_type => new.workflow_key, + creation_date => new.creation_date, + creation_user => new.creation_user, + creation_ip => new.creation_ip + ); + + /* insert the case in to the general wf_cases table */ + insert into wf_cases + (case_id, workflow_key, context_key, object_id, state) + values + (v_case_id, new.workflow_key, v_context_key_for_query, new.object_id, 'created'); + + /* insert the case into the workflow-specific cases table */ + select table_name into v_workflow_case_table + from acs_object_types + where object_type = new.workflow_key; + + execute immediate 'insert into '||v_workflow_case_table||' (case_id) values (:1)' + using v_case_id; + + return v_case_id; + end new; + + + procedure add_manual_assignment ( + case_id in number, + role_key in varchar2, + party_id in number + ) + is + v_workflow_key varchar2(100); + v_num_rows integer; + begin + select count(*) + into v_num_rows + from wf_case_assignments + where case_id = add_manual_assignment.case_id + and role_key = add_manual_assignment.role_key + and party_id = add_manual_assignment.party_id; + + if v_num_rows = 0 then + select workflow_key + into v_workflow_key + from wf_cases + where case_id = add_manual_assignment.case_id; + + insert into wf_case_assignments ( + case_id, + workflow_key, + role_key, + party_id + ) values ( + add_manual_assignment.case_id, + v_workflow_key, + add_manual_assignment.role_key, + add_manual_assignment.party_id + ); + end if; + end add_manual_assignment; + + + procedure remove_manual_assignment ( + case_id in number, + role_key in varchar2, + party_id in number + ) + is + v_workflow_key varchar2(100); + begin + select workflow_key + into v_workflow_key + from wf_cases + where case_id = remove_manual_assignment.case_id; + + delete + from wf_case_assignments + where workflow_key = v_workflow_key + and case_id = remove_manual_assignment.case_id + and role_key = remove_manual_assignment.role_key + and party_id = remove_manual_assignment.party_id; + end remove_manual_assignment; + + procedure clear_manual_assignments ( + case_id in number, + role_key in varchar2 + ) + is + v_workflow_key varchar2(100); + begin + select workflow_key + into v_workflow_key + from wf_cases + where case_id = clear_manual_assignments.case_id; + + delete + from wf_case_assignments + where workflow_key = v_workflow_key + and case_id = clear_manual_assignments.case_id + and role_key = clear_manual_assignments.role_key; + end clear_manual_assignments; + + + procedure start_case ( + case_id in number, + creation_user in integer default null, + creation_ip in varchar2 default null, + msg in varchar2 default null + ) + is + v_journal_id number; + begin + /* Add an entry to the journal */ + v_journal_id := journal_entry.new( + object_id => start_case.case_id, + action => 'case start', + action_pretty => 'Case started', + creation_user => start_case.creation_user, + creation_ip => start_case.creation_ip, + msg => start_case.msg + ); + + update wf_cases set state = 'active' where case_id = start_case.case_id; + + add_token( + case_id => start_case.case_id, + place_key => 'start', + journal_id => v_journal_id + ); + + /* Turn the wheels */ + sweep_automatic_transitions( + case_id => start_case.case_id, + journal_id => v_journal_id + ); + end start_case; + + + procedure delete( + case_id in number + ) + is + v_workflow_case_table varchar2(30); + begin + /* delete attribute_value_audit, tokens, tasks */ + delete from wf_attribute_value_audit where case_id = workflow_case.delete.case_id; + delete from wf_case_assignments where case_id = workflow_case.delete.case_id; + delete from wf_case_deadlines where case_id = workflow_case.delete.case_id; + delete from wf_tokens where case_id = workflow_case.delete.case_id; + delete from wf_task_assignments where task_id in (select task_id from wf_tasks where case_id = workflow_case.delete.case_id); + delete from wf_tasks where case_id = workflow_case.delete.case_id; + + /* delete the journal */ + journal_entry.delete_for_object(workflow_case.delete.case_id); + + /* delete from the workflow-specific cases table */ + select table_name into v_workflow_case_table + from acs_object_types ot, wf_cases c + where c.case_id = workflow_case.delete.case_id + and object_type = c.workflow_key; + + execute immediate 'delete from '||v_workflow_case_table||' where case_id = :case_id' + using in workflow_case.delete.case_id; + + /* delete from the generic cases table */ + delete from wf_cases where case_id = workflow_case.delete.case_id; + + /* delete from acs-objects */ + acs_object.delete(workflow_case.delete.case_id); + end delete; + + + procedure suspend( + case_id in number, + user_id in number default null, + ip_address in varchar2 default null, + msg in varchar2 default null + ) + is + v_state varchar2(40); + v_journal_id number; + begin + select state into v_state + from wf_cases + where case_id = suspend.case_id; + + if v_state != 'active' then + raise_application_error(-20000, 'Only active cases can be suspended'); + end if; + + /* Add an entry to the journal */ + v_journal_id := journal_entry.new( + object_id => suspend.case_id, + action => 'case suspend', + action_pretty => 'case suspended', + creation_user => suspend.user_id, + creation_ip => suspend.ip_address, + msg => suspend.msg + ); + + update wf_cases + set state = 'suspended' + where case_id = suspend.case_id; + end suspend; + + + procedure resume( + case_id in number, + user_id in number default null, + ip_address in varchar2 default null, + msg in varchar2 default null + ) + is + v_state varchar2(40); + v_journal_id number; + begin + select state into v_state + from wf_cases + where case_id = resume.case_id; + + if v_state != 'suspended' and v_state != 'canceled' then + raise_application_error(-20000, 'Only suspended or canceled cases can be resumed'); + end if; + + /* Add an entry to the journal */ + v_journal_id := journal_entry.new( + object_id => resume.case_id, + action => 'case resume', + action_pretty => 'case resumed', + creation_user => resume.user_id, + creation_ip => resume.ip_address, + msg => resume.msg + ); + + update wf_cases + set state = 'active' + where case_id = resume.case_id; + end resume; + + + procedure cancel( + case_id in number, + user_id in number default null, + ip_address in varchar2 default null, + msg in varchar2 default null + ) + is + v_state varchar2(40); + v_journal_id number; + begin + select state into v_state + from wf_cases + where case_id = cancel.case_id; + + if v_state != 'active' and v_state != 'suspended' then + raise_application_error(-20000, 'Only active or suspended cases can be canceled'); + end if; + + /* Add an entry to the journal */ + v_journal_id := journal_entry.new( + object_id => cancel.case_id, + action => 'case cancel', + action_pretty => 'Case canceled', + creation_user => cancel.user_id, + creation_ip => cancel.ip_address, + msg => cancel.msg + ); + + update wf_cases + set state = 'canceled' + where case_id = cancel.case_id; + end cancel; + + + procedure fire_message_transition ( + task_id in number + ) is + v_case_id number; + v_transition_name varchar2(100); + v_trigger_type varchar2(40); + v_journal_id number; + begin + select t.case_id, tr.transition_name, tr.trigger_type + into v_case_id, v_transition_name, v_trigger_type + from wf_tasks t, wf_transitions tr + where t.task_id = fire_message_transition.task_id + and tr.workflow_key = t.workflow_key + and tr.transition_key = t.transition_key; + + if v_trigger_type != 'message' then + raise_application_error(-20000, 'Transition '''||v_transition_name||''' is not message triggered'); + end if; + + /* Add an entry to the journal */ + v_journal_id := journal_entry.new( + object_id => v_case_id, + action => 'task '||fire_message_transition.task_id||' fire', + action_pretty => v_transition_name || ' fired' + ); + + fire_transition_internal( + task_id => fire_message_transition.task_id, + journal_id => v_journal_id + ); + + sweep_automatic_transitions( + case_id => v_case_id, + journal_id => v_journal_id + ); + end fire_message_transition; + + + /* + * A wrapper for user tasks that uses the start/commit/cancel model for firing transitions. + * Returns journal_id. + */ + function begin_task_action ( + task_id in number, + action in varchar2, + action_ip in varchar2, + user_id in number, + msg in varchar2 default null + ) + return number + is + v_state varchar2(40); + v_journal_id number; + v_case_id number; + v_transition_name varchar2(100); + v_num_rows number; + begin + select state into v_state + from wf_tasks + where task_id = begin_task_action.task_id; + + if begin_task_action.action = 'start' then + if v_state != 'enabled' then + raise_application_error(-20000, 'Task is in state '''||v_state||''', '|| + 'but it must be in state ''enabled'' to be started.'); + end if; + + select decode(count(*),0,0,1) into v_num_rows + from wf_user_tasks + where task_id = begin_task_action.task_id + and user_id = begin_task_action.user_id; + + if v_num_rows = 0 then + raise_application_error(-20000, 'You are not assigned to this task.'); + end if; + elsif begin_task_action.action = 'finish' or begin_task_action.action = 'cancel' then + + if v_state = 'started' then + /* Is this user the holding user? */ + select decode(count(*),0,0,1) into v_num_rows + from wf_tasks + where task_id = begin_task_action.task_id + and holding_user = begin_task_action.user_id; + if v_num_rows = 0 then + raise_application_error(-20000, 'You are the user currently working on this task.'); + end if; + elsif v_state = 'enabled' then + if begin_task_action.action = 'cancel' then + raise_application_error(-20000, 'You can only cancel a task in state ''started'', '|| + 'but this task is in state '''||v_state||''''); + end if; + + /* Is this user assigned to this task? */ + select decode(count(*),0,0,1) into v_num_rows + from wf_user_tasks + where task_id = begin_task_action.task_id + and user_id = begin_task_action.user_id; + if v_num_rows = 0 then + raise_application_error(-20000, 'You are not assigned to this task.'); + end if; + + /* This task is finished without an explicit start. + * Store the user as the holding_user */ + update wf_tasks + set holding_user = begin_task_action.user_id + where task_id = begin_task_action.task_id; + else + raise_application_error(-20000, 'Task is in state '''||v_state||''', '|| + 'but it must be in state ''enabled'' or ''started'' to be finished'); + end if; + + elsif begin_task_action.action = 'comment' then + -- We currently allow anyone to comment on a task + -- (need this line because PL/SQL doens't like empty if blocks) + v_num_rows := 0; + end if; + + select t.case_id, tr.transition_name into v_case_id, v_transition_name + from wf_tasks t, + wf_transitions tr + where t.task_id = begin_task_action.task_id + and tr.workflow_key = t.workflow_key + and tr.transition_key = t.transition_key; + + /* Insert a journal entry */ + + v_journal_id := journal_entry.new( + object_id => v_case_id, + action => 'task '||begin_task_action.task_id||' '||begin_task_action.action, + action_pretty => v_transition_name || ' ' || begin_task_action.action, + creation_user => begin_task_action.user_id, + creation_ip => begin_task_action.action_ip, + msg => begin_task_action.msg + ); + + return v_journal_id; + end begin_task_action; + + + procedure end_task_action ( + journal_id in number, + action in varchar2, + task_id in number + ) + is + v_user_id number; + begin + select creation_user into v_user_id + from acs_objects + where object_id = end_task_action.journal_id; + + /* Update the workflow state */ + + if end_task_action.action = 'start' then + start_task(end_task_action.task_id, v_user_id, end_task_action.journal_id); + elsif end_task_action.action = 'finish' then + finish_task(end_task_action.task_id, end_task_action.journal_id); + elsif end_task_action.action = 'cancel' then + cancel_task(end_task_action.task_id, end_task_action.journal_id); + elsif end_task_action.action != 'comment' then + raise_application_error(-20000, 'Unknown action ''' || end_task_action.action || ''''); + end if; + + end end_task_action; + + function task_action ( + task_id in number, + action in varchar2, + action_ip in varchar2, + user_id in number, + msg in varchar2 default null + ) return number + is + v_journal_id integer; + begin + v_journal_id := begin_task_action( + task_id => task_action.task_id, + action => task_action.action, + action_ip => task_action.action_ip, + user_id => task_action.user_id, + msg => task_action.msg + ); + + end_task_action( + journal_id => v_journal_id, + action => task_action.action, + task_id => task_action.task_id + ); + + return v_journal_id; + end task_action; + + + procedure set_attribute_value ( + journal_id in number, + attribute_name in varchar2, + value in varchar2 + ) + is + v_workflow_key varchar2(100); + v_case_id number; + v_attribute_id number; + begin + select o.object_type, o.object_id into v_workflow_key, v_case_id + from journal_entries je, acs_objects o + where je.journal_id = set_attribute_value.journal_id + and o.object_id = je.object_id; + + select attribute_id into v_attribute_id + from acs_attributes + where object_type = v_workflow_key + and attribute_name = set_attribute_value.attribute_name; + + acs_object.set_attribute( + object_id_in => v_case_id, + attribute_name_in => set_attribute_value.attribute_name, + value_in => set_attribute_value.value + ); + + insert into wf_attribute_value_audit + (case_id, attribute_id, journal_id, attr_value) + values + (v_case_id, v_attribute_id, set_attribute_value.journal_id, set_attribute_value.value); + end set_attribute_value; + + + function get_attribute_value ( + case_id in number, + attribute_name in varchar2 + ) + return varchar2 + is + begin + return acs_object.get_attribute( + object_id_in => get_attribute_value.case_id, + attribute_name_in => get_attribute_value.attribute_name + ); + end get_attribute_value; + + + procedure add_task_assignment ( + task_id in number, + party_id in number, + permanent_p in char default 'f' + ) + is + v_count integer; + v_workflow_key wf_workflows.workflow_key%TYPE; + v_context_key wf_contexts.context_key%TYPE; + v_case_id wf_cases.case_id%TYPE; + v_role_key wf_roles.role_key%TYPE; + v_transition_key wf_transitions.transition_key%TYPE; + v_notification_callback wf_context_transition_info.notification_callback%TYPE; + v_notification_custom_arg wf_context_transition_info.notification_custom_arg%TYPE; + + -- might need to tune this query further + cursor c_new_assigned_users is + select distinct u.user_id + from users u + where u.user_id not in ( + select distinct u2.user_id + from wf_task_assignments tasgn2, + party_approved_member_map m2, + users u2 + where tasgn2.task_id = add_task_assignment.task_id + and m2.party_id = tasgn2.party_id + and u2.user_id = m2.member_id) + and exists ( + select 1 + from party_approved_member_map m + where m.member_id = u.user_id + and m.party_id = add_task_assignment.party_id + ); + cursor c_callback is + select notification_callback, + notification_custom_arg + from wf_context_transition_info + where context_key = v_context_key + and workflow_key = v_workflow_key + and transition_key = v_transition_key; + callback_rec c_callback%ROWTYPE; + + begin + -- get some needed information + + select ta.case_id, ta.workflow_key, ta.transition_key, tr.role_key, c.context_key + into v_case_id, v_workflow_key, v_transition_key, v_role_key, v_context_key + from wf_tasks ta, wf_transitions tr, wf_cases c + where ta.task_id = add_task_assignment.task_id + and tr.workflow_key = ta.workflow_key + and tr.transition_key = ta.transition_key + and c.case_id = ta.case_id; + + -- make the same assignment as a manual assignment + + if permanent_p = 't' then + /* We do this up-front, because + * even though the user already had a task assignment, + * he might not have a case assignment. + */ + add_manual_assignment( + case_id => v_case_id, + role_key => v_role_key, + party_id => add_task_assignment.party_id + ); + end if; + + -- check that we don't hit the unique constraint + + select count(*) into v_count + from wf_task_assignments + where task_id = add_task_assignment.task_id + and party_id = add_task_assignment.party_id; + + if v_count > 0 then + return; + end if; + + -- get callback information + + open c_callback; + fetch c_callback into callback_rec; + + if c_callback%FOUND then + v_notification_callback := callback_rec.notification_callback; + v_notification_custom_arg := callback_rec.notification_custom_arg; + else + v_notification_callback := null; + v_notification_custom_arg := null; + end if; + + -- notify any new assignees + + for v_assigned_user in c_new_assigned_users loop + notify_assignee( + task_id => add_task_assignment.task_id, + user_id => v_assigned_user.user_id, + callback => v_notification_callback, + custom_arg => v_notification_custom_arg + ); + end loop; + + -- do the insert + + insert into wf_task_assignments ( + task_id, + party_id + ) values ( + add_task_assignment.task_id, + add_task_assignment.party_id + ); + end add_task_assignment; + + procedure remove_task_assignment ( + task_id in number, + party_id in number, + permanent_p in char default 'f' + ) + is + v_num_assigned number; + v_case_id number; + v_role_key wf_roles.role_key%TYPE; + v_workflow_key varchar2(100); + v_transition_key varchar2(100); + v_context_key varchar2(100); + + cursor c_callback is + select unassigned_callback, unassigned_custom_arg + from wf_context_transition_info + where workflow_key = v_workflow_key + and context_key = v_context_key + and transition_key = v_transition_key; + callback_rec c_callback%ROWTYPE; + begin + -- get some information + + select ta.case_id, ta.transition_key, tr.role_key, ta.workflow_key, c.context_key + into v_case_id, v_transition_key, v_role_key, v_workflow_key, v_context_key + from wf_tasks ta, wf_transitions tr, wf_cases c + where ta.task_id = remove_task_assignment.task_id + and tr.workflow_key = ta.workflow_key + and tr.transition_key = ta.transition_key + and c.case_id = ta.case_id; + + -- make the same assignment as a manual assignment + + if permanent_p = 't' then + remove_manual_assignment( + case_id => v_case_id, + role_key => v_role_key, + party_id => remove_task_assignment.party_id + ); + end if; + + -- now delete the row + + delete + from wf_task_assignments + where task_id = remove_task_assignment.task_id + and party_id = remove_task_assignment.party_id; + + -- check if the task now became unassigned + + select count(*) + into v_num_assigned + from wf_task_assignments + where task_id = remove_task_assignment.task_id; + + if v_num_assigned > 0 then + return; + end if; + + -- yup, the task is now unassigned; fire the callback + + open c_callback; + fetch c_callback into callback_rec; + + if c_callback%FOUND then + execute_unassigned_callback ( + callback => callback_rec.unassigned_callback, + task_id => task_id, + custom_arg => callback_rec.unassigned_custom_arg + ); + end if; + close c_callback; + end remove_task_assignment; + + procedure clear_task_assignments ( + task_id in number, + permanent_p in char default 'f' + ) + is + v_case_id number; + v_transition_key varchar2(100); + v_role_key wf_roles.role_key%TYPE; + v_workflow_key varchar2(100); + v_context_key varchar2(100); + v_callback varchar2(100); + v_custom_arg varchar2(4000); + begin + -- get some information + + select ta.case_id, ta.transition_key, tr.role_key, ta.workflow_key, c.context_key + into v_case_id, v_transition_key, v_role_key, v_workflow_key, v_context_key + from wf_tasks ta, wf_transitions tr, wf_cases c + where ta.task_id = clear_task_assignments.task_id + and tr.workflow_key = ta.workflow_key + and tr.transition_key = ta.transition_key + and c.case_id = ta.case_id; + + -- make the unassignment stick as a manual assignment + + if permanent_p = 't' then + clear_manual_assignments( + case_id => v_case_id, + role_key => v_role_key + ); + end if; + + -- delete the rows + + delete + from wf_task_assignments + where task_id = clear_task_assignments.task_id; + + -- fire the unassigned callback + + select unassigned_callback, unassigned_custom_arg + into v_callback, v_custom_arg + from wf_context_transition_info + where workflow_key = v_workflow_key + and context_key = v_context_key + and transition_key = v_transition_key; + + execute_unassigned_callback( + callback => v_callback, + task_id => task_id, + custom_arg => v_custom_arg + ); + end clear_task_assignments; + + procedure set_case_deadline ( + case_id in wf_cases.case_id%TYPE, + transition_key in wf_transitions.transition_key%TYPE, + deadline date + ) + is + v_workflow_key wf_workflows.workflow_key%TYPE; + begin + -- delete the current deadline row + delete + from wf_case_deadlines + where case_id = set_case_deadline.case_id + and transition_key = set_case_deadline.transition_key; + + if deadline is not null then + -- get some info + select workflow_key + into v_workflow_key + from wf_cases + where case_id = set_case_deadline.case_id; + + -- insert new deadline row + insert into wf_case_deadlines ( + case_id, + workflow_key, + transition_key, + deadline + ) values ( + set_case_deadline.case_id, + v_workflow_key, + set_case_deadline.transition_key, + set_case_deadline.deadline + ); + end if; + end set_case_deadline; + + procedure remove_case_deadline ( + case_id in wf_cases.case_id%TYPE, + transition_key in wf_transitions.transition_key%TYPE + ) + is + begin + set_case_deadline( + case_id => remove_case_deadline.case_id, + transition_key => remove_case_deadline.transition_key, + deadline => null + ); + end remove_case_deadline; + + + + + + + + + + + /* + * PRIVATE + */ + + function evaluate_guard ( + callback in varchar2, + custom_arg in varchar2, + case_id in number, + workflow_key in varchar2, + transition_key in varchar2, + place_key in varchar2, + direction in varchar2 + ) + return char + is + v_guard_happy_p char(1); + begin + if callback is null then + -- null guard evaluates to true + return 't'; + else + if callback = '#' then + return 'f'; + else + execute immediate 'begin :1 := ' || callback + || '(:2, :3, :4, :5, :6, :7); end;' + using out v_guard_happy_p, + in case_id, + in workflow_key, + in transition_key, + in place_key, + in direction, + in custom_arg; + return v_guard_happy_p; + end if; + end if; + end evaluate_guard; + + + procedure execute_transition_callback( + callback in varchar2, + custom_arg in varchar2, + case_id in number, + transition_key in varchar2 + ) + is + begin + if callback is not null then + execute immediate 'begin '||callback + || '(:1, :2, :3); end;' + using in case_id, + in transition_key, + in custom_arg; + end if; + end execute_transition_callback; + + + function execute_time_callback ( + callback in varchar2, + custom_arg in varchar2, + case_id in number, + transition_key in varchar2 + ) + return date + is + v_trigger_time date; + begin + if callback is null then + raise_application_error(-20000, 'There''s no time_callback function for the timed transition ''' || transition_key || ''''); + end if; + + execute immediate 'begin :1 := ' || callback + || '(:2, :3, :4); end;' + using out v_trigger_time, + in case_id, + in transition_key, + in custom_arg; + + return v_trigger_time; + end execute_time_callback; + + + function get_task_deadline ( + callback in varchar2, + custom_arg in varchar2, + attribute_name in varchar2, + case_id in number, + transition_key in varchar2 + ) + return date + is + cursor case_deadline_cur is + select deadline + from wf_case_deadlines + where case_id = get_task_deadline.case_id + and transition_key = get_task_deadline.transition_key; + v_deadline date; + begin + /* + * 1. or if there's a row in wf_case_deadlines, we use that + * 2. if there is a callback, we execute that + * 3. otherwise, if there is an attribute, we use that + */ + + /* wf_case_deadlines */ + open case_deadline_cur; + fetch case_deadline_cur into v_deadline; + if case_deadline_cur%NOTFOUND then + if callback is not null then + /* callback */ + execute immediate 'begin :1 := ' || callback + || '(:2, :3, :4); end;' + using out v_deadline, + in case_id, + in transition_key, + in custom_arg; + elsif attribute_name is not null then + /* attribute */ + v_deadline := acs_object.get_attribute( + object_id_in => get_task_deadline.case_id, + attribute_name_in => get_task_deadline.attribute_name + ); + else + v_deadline := null; + end if; + end if; + + return v_deadline; + end get_task_deadline; + + + function execute_hold_timeout_callback ( + callback in varchar2, + custom_arg in varchar2, + case_id in number, + transition_key in varchar2 + ) + return date + is + v_hold_timeout date; + begin + if callback is null then + return null; + end if; + + execute immediate 'begin :1 := ' || callback + || '(:2, :3, :4); end;' + using out v_hold_timeout, + in case_id, + in transition_key, + in custom_arg; + + return v_hold_timeout; + end execute_hold_timeout_callback; + + + procedure execute_unassigned_callback ( + callback in varchar2, + task_id in number, + custom_arg in varchar2 + ) + is + begin + if callback is not null then + execute immediate 'begin ' || callback + || '(:1, :2); end;' + using in task_id, + in custom_arg; + end if; + end execute_unassigned_callback; + + procedure set_task_assignments( + task_id in number, + callback in varchar2, + custom_arg in varchar2 + ) + is + cursor case_assignments is + select party_id + from wf_case_assignments ca, wf_tasks t, wf_transitions tr + where t.task_id = set_task_assignments.task_id + and ca.case_id = t.case_id + and ca.role_key = tr.role_key + and tr.workflow_key = t.workflow_key + and tr.transition_key = t.transition_key; + cursor context_assignments is + select party_id + from wf_context_assignments ca, wf_cases c, wf_tasks t, wf_transitions tr + where t.task_id = set_task_assignments.task_id + and c.case_id = t.case_id + and ca.context_key = c.context_key + and ca.workflow_key = t.workflow_key + and ca.role_key = tr.role_key + and tr.workflow_key = t.workflow_key + and tr.transition_key = t.transition_key; + v_done_p char(1); + begin + + /* Find out who to assign the given task to. + * + * 1. See if there are rows in wf_case_assignments. + * 2. If not, and a callback is defined, execute that. + * 3. Otherwise, grab the assignment from the workflow context. + * + * (We used to use the callback first, but that makes + * reassignment of tasks difficult.) + */ + + v_done_p := 'f'; + for case_assignment_rec in case_assignments loop + v_done_p := 't'; + add_task_assignment ( + task_id => task_id, + party_id => case_assignment_rec.party_id + ); + end loop; + + if v_done_p != 't' then + + if callback is not null then + execute immediate 'begin '|| set_task_assignments.callback + || '(:1, :2); end;' + using in set_task_assignments.task_id, + in set_task_assignments.custom_arg; + else + for context_assignment_rec in context_assignments loop + add_task_assignment ( + task_id => task_id, + party_id => context_assignment_rec.party_id + ); + end loop; + end if; + end if; + end set_task_assignments; + + + procedure add_token ( + case_id in number, + place_key in varchar2, + journal_id in number + ) + is + v_token_id number; + v_workflow_key varchar2(100); + begin + select wf_token_id_seq.nextval into v_token_id from dual; + + select workflow_key into v_workflow_key + from wf_cases c + where c.case_id = add_token.case_id; + + insert into wf_tokens + (token_id, case_id, workflow_key, place_key, state, produced_journal_id) + values + (v_token_id, add_token.case_id, v_workflow_key, add_token.place_key, 'free', add_token.journal_id); + end add_token; + + + procedure lock_token ( + case_id in number, + place_key in varchar2, + journal_id in number, + task_id in number + ) + is + begin + update wf_tokens + set state = 'locked', + locked_task_id = lock_token.task_id, + locked_date = sysdate, + locked_journal_id = lock_token.journal_id + where case_id = lock_token.case_id + and place_key = lock_token.place_key + and state = 'free' + and rownum = 1; + end lock_token; + + + procedure release_token ( + task_id in number, + journal_id in number + ) + is + cursor token_cur is + select token_id, + case_id, + place_key + from wf_tokens + where state = 'locked' + and locked_task_id = release_token.task_id; + begin + /* Add a new token for each released one */ + for token_rec in token_cur loop + add_token( + case_id => token_rec.case_id, + place_key => token_rec.place_key, + journal_id => release_token.journal_id + ); + end loop; + + /* Mark the released ones canceled */ + update wf_tokens + set state = 'canceled', + canceled_date = sysdate, + canceled_journal_id = release_token.journal_id + where state = 'locked' + and locked_task_id = release_token.task_id; + end release_token; + + + procedure consume_token ( + case_id in number, + place_key in varchar2, + journal_id in number, + task_id in number default null + ) + is + begin + if task_id is null then + update wf_tokens + set state = 'consumed', + consumed_date = sysdate, + consumed_journal_id = consume_token.journal_id + where case_id = consume_token.case_id + and place_key = consume_token.place_key + and state = 'free' + and rownum = 1; + else + update wf_tokens + set state = 'consumed', + consumed_date = sysdate, + consumed_journal_id = consume_token.journal_id + where case_id = consume_token.case_id + and place_key = consume_token.place_key + and state = 'locked' + and locked_task_id = consume_token.task_id; + end if; + end consume_token; + + + procedure sweep_automatic_transitions ( + case_id in number, + journal_id in number + ) is + cursor enabled_automatic_transitions is + select task_id + from wf_tasks ta, wf_transitions tr + where tr.workflow_key = ta.workflow_key + and tr.transition_key = ta.transition_key + and tr.trigger_type = 'automatic' + and ta.state = 'enabled' + and ta.case_id = sweep_automatic_transitions.case_id; + v_done_p char(1); + v_finished_p char(1); + begin + + enable_transitions(case_id => sweep_automatic_transitions.case_id); + + loop + v_done_p := 't'; + v_finished_p := finished_p( + case_id => sweep_automatic_transitions.case_id, + journal_id => sweep_automatic_transitions.journal_id); + + if v_finished_p = 'f' then + for task_rec in enabled_automatic_transitions loop + fire_transition_internal( + task_id => task_rec.task_id, + journal_id => sweep_automatic_transitions.journal_id + ); + v_done_p := 'f'; + end loop; + enable_transitions(case_id => sweep_automatic_transitions.case_id); + end if; + + exit when v_done_p = 't'; + end loop; + end sweep_automatic_transitions; + + + function finished_p ( + case_id in number, + journal_id in number + ) + return char + is + v_case_state varchar2(40); + v_token_id number; + v_num_rows number; + v_journal_id number; + begin + select state into v_case_state + from wf_cases + where case_id = finished_p.case_id; + + if v_case_state = 'finished' then + return 't'; + else + /* Let's see if the case is actually finished, but just not marked so */ + select decode(count(*),0,0,1) into v_num_rows + from wf_tokens + where case_id = finished_p.case_id + and place_key = 'end'; + + if v_num_rows = 0 then + return 'f'; + else + /* There's a token in the end place. + * Count the total number of tokens to make sure the wf is well-constructed. + */ + + select decode(count(*),0,0,1,1,2) into v_num_rows + from wf_tokens + where case_id = finished_p.case_id + and state in ('free', 'locked'); + + if v_num_rows > 1 then + raise_application_error(-20000, 'The workflow net is misconstructed: Some parallel executions have not finished.'); + end if; + + /* Consume that token */ + select token_id into v_token_id + from wf_tokens + where case_id = finished_p.case_id + and state in ('free', 'locked'); + + consume_token( + case_id => finished_p.case_id, + place_key => 'end', + journal_id => finished_p.journal_id + ); + + update wf_cases + set state = 'finished' + where case_id = finished_p.case_id; + + /* Add an extra entry to the journal */ + v_journal_id := journal_entry.new( + object_id => finished_p.case_id, + action => 'case finish', + action_pretty => 'Case finished' + ); + + return 't'; + end if; + end if; + end finished_p; + + + + /* This procedure should be scheduled to run as a dbms_job. */ + procedure sweep_timed_transitions + is + cursor timed_transitions_to_fire is + select t.task_id, t.case_id, tr.transition_name + from wf_tasks t, wf_transitions tr + where trigger_time <= sysdate + and state = 'enabled' + and tr.workflow_key = t.workflow_key + and tr.transition_key = t.transition_key; + v_journal_id number; + begin + for trans_rec in timed_transitions_to_fire loop + + /* Insert an entry to the journal so people will know it fired */ + + v_journal_id := journal_entry.new( + object_id => trans_rec.case_id, + action => 'task '||trans_rec.task_id|| ' fire time', + action_pretty => trans_rec.transition_name || ' automatically finished', + msg => 'Timed transition fired.' + ); + + /* Fire the transition */ + + fire_transition_internal( + task_id => trans_rec.task_id, + journal_id => v_journal_id + ); + + /* Update the workflow internal state */ + + sweep_automatic_transitions( + case_id => trans_rec.case_id, + journal_id => v_journal_id + ); + + end loop; + end sweep_timed_transitions; + + + /* This procedure should be scheduled to run as a dbms_job. */ + procedure sweep_hold_timeout + is + cursor tasks_to_cancel is + select t.task_id, t.case_id, tr.transition_name + from wf_tasks t, wf_transitions tr + where hold_timeout <= sysdate + and state = 'started' + and tr.workflow_key = t.workflow_key + and tr.transition_key = t.transition_key; + v_journal_id number; + begin + for task_rec in tasks_to_cancel loop + + /* Insert an entry to the journal so people will know it was canceled */ + + v_journal_id := journal_entry.new( + object_id => task_rec.case_id, + action => 'task '||task_rec.task_id||' cancel timeout', + action_pretty => task_rec.transition_name || ' timed out', + msg => 'The user''s hold on the task timed out and the task was automatically canceled' + ); + + + /* Cancel the task */ + + cancel_task( + task_id => task_rec.task_id, + journal_id => v_journal_id + ); + + end loop; + end sweep_hold_timeout; + + + + + procedure notify_assignee( + task_id in wf_tasks.task_id%TYPE, + user_id in users.user_id%TYPE, + callback in wf_context_transition_info.notification_callback%TYPE, + custom_arg in wf_context_transition_info.notification_custom_arg%TYPE + ) + is + v_deadline_pretty varchar2(400); + v_object_name varchar2(4000); + v_transition_key wf_transitions.transition_key%TYPE; + v_transition_name wf_transitions.transition_name%TYPE; + v_party_from parties.party_id%TYPE; + v_party_to parties.party_id%TYPE; + v_subject varchar2(4000); + v_body varchar2(4000); + v_request_id integer; + v_workflow_url varchar2(400); + cursor cr_principal is + select wfi.principal_party + from wf_context_workflow_info wfi, wf_tasks ta, wf_cases c + where ta.task_id = notify_assignee.task_id + and c.case_id = ta.case_id + and wfi.workflow_key = c.workflow_key + and wfi.context_key = c.context_key; + begin + select to_char(ta.deadline,'Mon fmDDfm, YYYY HH24:MI:SS'), + acs_object.name(c.object_id), + tr.transition_key, + tr.transition_name + into v_deadline_pretty, + v_object_name, + v_transition_key, + v_transition_name + from wf_tasks ta, wf_transitions tr, wf_cases c + where ta.task_id = notify_assignee.task_id + and c.case_id = ta.case_id + and tr.workflow_key = c.workflow_key + and tr.transition_key = ta.transition_key; + + select apm.get_value(p.package_id,'SystemURL') || site_node.url(s.node_id) + into v_workflow_url + from site_nodes s, + apm_packages a, + (select package_id + from apm_packages + where package_key = 'acs-kernel') p + where s.object_id = a.package_id + and a.package_key = 'acs-workflow'; + + /* Mail sent from */ + open cr_principal; + fetch cr_principal into v_party_from; + if cr_principal%NOTFOUND then + v_party_from := -1; + end if; + + /* Subject */ + v_subject := 'Assignment: '||v_transition_name||' ('||v_object_name||')'; + + /* Body */ + v_body := 'You have been assigned to a task. +'||' +Case : '||v_object_name||' +Task : '||v_transition_name||' +'; + + if v_deadline_pretty != '' then + v_body := v_body||'Deadline : '||v_deadline_pretty||' +'; + end if; + + v_body := v_body ||'Task website: '||v_workflow_url||'task?task_id='||notify_assignee.task_id||' +'; + + /* The notifications should really be sent from the application server layer, not from the database */ + + if notify_assignee.callback is not null then + execute immediate 'begin '||notify_assignee.callback||'(:1, :2, :3, :4, :5, :6); end;' + using in notify_assignee.task_id, + in notify_assignee.custom_arg, + in notify_assignee.user_id, + in out v_party_from, + in out v_subject, + in out v_body; + end if; + + v_request_id := acs_mail_nt.post_request ( + party_from => v_party_from, + party_to => notify_assignee.user_id, + expand_group => 'f' , + subject => v_subject, + message => v_body + ); + + end notify_assignee; + + + + /* + * This procedure synchronizes the actually enabled transitions + * (i.e., the ones where tokens are currently present on the + * input places), with the cached version of that information, + * in wf_tasks. + * It is entirely idempotent and will at any given time sync up with + * the actual state of the workflow (as per the tokens), so we don't + * need to pass in a journal_id. + */ + procedure enable_transitions ( + case_id in number + ) is + cursor tasks_to_create is + select et.transition_key, + et.transition_name, + et.trigger_type, + et.enable_callback, + et.enable_custom_arg, + et.time_callback, + et.time_custom_arg, + et.deadline_callback, + et.deadline_custom_arg, + et.deadline_attribute_name, + et.notification_callback, + et.notification_custom_arg, + et.unassigned_callback, + et.unassigned_custom_arg, + et.estimated_minutes, + cr.assignment_callback, + cr.assignment_custom_arg + from wf_enabled_transitions et, wf_context_role_info cr + where et.case_id = enable_transitions.case_id + and et.workflow_key = cr.workflow_key (+) + and et.role_key = cr.role_key (+) + and not exists (select 1 from wf_tasks + where case_id = enable_transitions.case_id + and transition_key = et.transition_key + and state in ('enabled', 'started')); + v_task_id number; + v_workflow_key varchar2(100); + v_trigger_time date; + v_deadline_date date; + v_party_from integer; + v_subject varchar2(500); + v_body varchar2(4000); + v_num_assigned number; + request_id number; + cursor assignees_cur is + select distinct u.user_id + from wf_task_assignments tasgn, + party_approved_member_map m, + users u + where tasgn.task_id = v_task_id + and m.party_id = tasgn.party_id + and u.user_id = m.member_id; + begin + select workflow_key into v_workflow_key + from wf_cases + where case_id = enable_transitions.case_id; + + /* we mark tasks overridden if they were once enabled, but are no longer so */ + + update wf_tasks + set state = 'overridden', + overridden_date = sysdate + where case_id = enable_transitions.case_id + and state = 'enabled' + and transition_key not in + (select transition_key + from wf_enabled_transitions + where case_id = enable_transitions.case_id); + + + /* insert a task for the transitions that are enabled but have no task row */ + + for trans_rec in tasks_to_create loop + + v_trigger_time := null; + v_deadline_date := null; + + if trans_rec.trigger_type = 'user' then + v_deadline_date := get_task_deadline( + callback => trans_rec.deadline_callback, + custom_arg => trans_rec.deadline_custom_arg, + attribute_name => trans_rec.deadline_attribute_name, + case_id => enable_transitions.case_id, + transition_key => trans_rec.transition_key + ); + elsif trans_rec.trigger_type = 'time' then + v_trigger_time := execute_time_callback(trans_rec.time_callback, + trans_rec.time_custom_arg, + enable_transitions.case_id, trans_rec.transition_key); + end if; + + /* we're ready to insert the row */ + select wf_task_id_seq.nextval into v_task_id from dual; + + insert into wf_tasks ( + task_id, case_id, workflow_key, transition_key, + deadline, trigger_time, estimated_minutes + ) values ( + v_task_id, enable_transitions.case_id, v_workflow_key, + trans_rec.transition_key, + v_deadline_date, v_trigger_time, trans_rec.estimated_minutes + ); + + set_task_assignments( + task_id => v_task_id, + callback => trans_rec.assignment_callback, + custom_arg => trans_rec.assignment_custom_arg + ); + + /* Execute the transition enabled callback */ + execute_transition_callback( + callback => trans_rec.enable_callback, + custom_arg => trans_rec.enable_custom_arg, + case_id => enable_transitions.case_id, + transition_key => trans_rec.transition_key + ); + + select count(*) into v_num_assigned + from wf_task_assignments + where task_id = v_task_id; + + if v_num_assigned = 0 then + execute_unassigned_callback ( + callback => trans_rec.unassigned_callback, + task_id => v_task_id, + custom_arg => trans_rec.unassigned_custom_arg + ); + end if; + + end loop; + end enable_transitions; + + + procedure fire_transition_internal ( + task_id in number, + journal_id in number + ) is + v_case_id number; + v_state varchar2(40); + v_transition_key varchar2(100); + v_workflow_key varchar2(100); + v_place_key varchar2(100); + v_direction varchar2(3); + v_guard_happy_p char(1); + v_fire_callback varchar2(100); + v_fire_custom_arg varchar2(4000); + v_found_happy_guard char(1); + v_locked_task_id number; + begin + select t.case_id, t.state, t.workflow_key, t.transition_key, ti.fire_callback, ti.fire_custom_arg + into v_case_id, v_state, v_workflow_key, v_transition_key, v_fire_callback, v_fire_custom_arg + from wf_tasks t, wf_cases c, wf_transition_info ti + where t.task_id = fire_transition_internal.task_id + and c.case_id = t.case_id + and ti.context_key = c.context_key + and ti.workflow_key = c.workflow_key + and ti.transition_key = t.transition_key; + + /* Check that the state is either started or enabled */ + + if v_state = 'enabled' then + v_locked_task_id := null; + elsif v_state = 'started' then + v_locked_task_id := fire_transition_internal.task_id; + else + raise_application_error(-20000, 'Can''t fire the transition if it''s not in state enabled or started'); + end if; + + + /* Mark the task finished */ + + update wf_tasks + set state = 'finished', + finished_date = sysdate + where task_id = fire_transition_internal.task_id; + + + /* Consume the tokens */ + + for place_rec in input_places(v_workflow_key, v_transition_key) loop + consume_token( + case_id => v_case_id, + place_key => place_rec.place_key, + journal_id => fire_transition_internal.journal_id, + task_id => v_locked_task_id + ); + end loop; + + + /* Spit out new tokens in the output places */ + + v_found_happy_guard := 'f'; + for place_rec in output_places(v_workflow_key, v_transition_key) loop + v_place_key := place_rec.place_key; + v_direction := place_rec.direction; + v_guard_happy_p := evaluate_guard( + callback => place_rec.guard_callback, + custom_arg => place_rec.guard_custom_arg, + case_id => v_case_id, + workflow_key => v_workflow_key, + transition_key => v_transition_key, + place_key => v_place_key, + direction => v_direction + ); + + if v_guard_happy_p = 't' then + v_found_happy_guard := 't'; + add_token( + case_id => v_case_id, + place_key => place_rec.place_key, + journal_id => fire_transition_internal.journal_id + ); + end if; + end loop; + + + /* If we didn't find any happy guards, look for arcs with the special hash (#) guard */ + + if v_found_happy_guard = 'f' then + for place_rec in ( + select place_key + from wf_transition_places tp + where tp.workflow_key = v_workflow_key + and tp.transition_key = v_transition_key + and tp.direction = 'out' + and tp.guard_callback = '#') + loop + add_token( + case_id => v_case_id, + place_key => place_rec.place_key, + journal_id => fire_transition_internal.journal_id + ); + end loop; + end if; + + + /* Execute the transition fire callback */ + + execute_transition_callback( + callback => v_fire_callback, + custom_arg => v_fire_custom_arg, + case_id => v_case_id, + transition_key => v_transition_key + ); + end fire_transition_internal; + + + + /* A small helper to make sure we're in the state we expect to be */ + procedure ensure_task_in_state ( + task_id in number, + state in varchar2 + ) is + v_count number; + begin + select decode(count(*),0,0,1) into v_count + from wf_tasks + where task_id = ensure_task_in_state.task_id + and state = ensure_task_in_state.state; + + if v_count != 1 then + raise_application_error(-20000, 'The task '|| ensure_task_in_state.task_id || ' is not in state ''' || ensure_task_in_state.state || ''''); + end if; + end ensure_task_in_state; + + + + /* Marks a task started and reserves one token from each input place */ + procedure start_task( + task_id in number, + user_id in number, + journal_id in number + ) is + v_case_id number; + v_workflow_key wf_workflows.workflow_key%TYPE; + v_transition_key varchar2(100); + v_hold_timeout_callback varchar2(100); + v_hold_timeout_custom_arg varchar2(4000); + v_hold_timeout date; + begin + ensure_task_in_state(task_id => start_task.task_id, state => 'enabled'); + + select t.case_id, t.workflow_key, t.transition_key, ti.hold_timeout_callback, ti.hold_timeout_custom_arg + into v_case_id, v_workflow_key, v_transition_key, v_hold_timeout_callback, v_hold_timeout_custom_arg + from wf_tasks t, wf_cases c, wf_transition_info ti + where t.task_id = start_task.task_id + and c.case_id = t.case_id + and ti.context_key = c.context_key + and ti.workflow_key = t.workflow_key + and ti.transition_key = t.transition_key; + + v_hold_timeout := execute_hold_timeout_callback(v_hold_timeout_callback, + v_hold_timeout_custom_arg, v_case_id, v_transition_key); + + /* Mark it started */ + + update wf_tasks + set state = 'started', + started_date = sysdate, + holding_user = start_task.user_id, + hold_timeout = v_hold_timeout + where task_id = start_task.task_id; + + + /* Reserve one token from each input place */ + + for place_rec in input_places(v_workflow_key,v_transition_key) loop + lock_token( + case_id => v_case_id, + place_key => place_rec.place_key, + journal_id => start_task.journal_id, + task_id => start_task.task_id + ); + end loop; + end start_task; + + + /* Mark the task canceled and release the reserved tokens */ + procedure cancel_task( + task_id in number, + journal_id in number + ) + is + v_case_id number; + begin + ensure_task_in_state(task_id => cancel_task.task_id, state => 'started'); + select case_id into v_case_id + from wf_tasks + where task_id = cancel_task.task_id; + + /* Mark the task canceled */ + + update wf_tasks + set state = 'canceled', + canceled_date = sysdate + where task_id = cancel_task.task_id; + + + /* Release our reserved tokens */ + + release_token( + task_id => cancel_task.task_id, + journal_id => cancel_task.journal_id + ); + + /* The workflow state has now changed, so we must run this */ + + sweep_automatic_transitions( + case_id => v_case_id, + journal_id => cancel_task.journal_id + ); + end cancel_task; + + + /* Fire the transition */ + procedure finish_task ( + task_id in number, + journal_id in number + ) + is + v_case_id number; + begin + select case_id into v_case_id + from wf_tasks + where task_id = finish_task.task_id; + + fire_transition_internal( + task_id => finish_task.task_id, + journal_id => finish_task.journal_id + ); + + sweep_automatic_transitions( + case_id => v_case_id, + journal_id => finish_task.journal_id + ); + end finish_task; + + +end workflow_case; +/ +show errors; Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/workflow-case-package-head.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/workflow-case-package-head.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/workflow-case-package-head.sql 19 Nov 2001 18:17:46 -0000 1.1 @@ -0,0 +1,161 @@ +-- +-- acs-workflow/sql/workflow-case-package-head.sql +-- +-- Creates the PL/SQL package that provides the API for interacting +-- with a workflow case. +-- +-- @author Lars Pind (lars@pinds.com) +-- +-- @creation-date 2000-05-18 +-- +-- @cvs-id $Id: workflow-case-package-head.sql,v 1.1 2001/11/19 18:17:46 neophytosd Exp $ +-- + +create or replace package workflow_case +is + + function new ( + case_id in number default null, + workflow_key in varchar2, + context_key in varchar2 default null, + object_id in integer, + creation_date in date default sysdate, + creation_user in integer default null, + creation_ip in varchar2 default null + ) return integer; + + procedure add_manual_assignment ( + case_id in number, + role_key in varchar2, + party_id in number + ); + + procedure remove_manual_assignment ( + case_id in number, + role_key in varchar2, + party_id in number + ); + + procedure clear_manual_assignments ( + case_id in number, + role_key in varchar2 + ); + + procedure start_case ( + case_id in number, + creation_user in integer default null, + creation_ip in varchar2 default null, + msg in varchar2 default null + ); + + procedure delete( + case_id in number + ); + + procedure suspend( + case_id in number, + user_id in number default null, + ip_address in varchar2 default null, + msg in varchar2 default null + ); + + procedure resume( + case_id in number, + user_id in number default null, + ip_address in varchar2 default null, + msg in varchar2 default null + ); + + procedure cancel( + case_id in number, + user_id in number default null, + ip_address in varchar2 default null, + msg in varchar2 default null + ); + + procedure fire_message_transition ( + task_id in number + ); + + /* To perform an action on the workflow: + * (numbers in parenthesis is the number of times each function should get called) + * + * 1. begin_task_action (1) (returns journal_id) + * 2. set_attribute_value (0..*) + * 3. clear_manual_assignments (0..1) + * 4. add_manual_assignment (0..*) + * 5. end_task_action (1) + */ + function begin_task_action ( + task_id in number, + action in varchar2, + action_ip in varchar2, + user_id in number, + msg in varchar2 default null + ) return number; + + procedure set_attribute_value ( + journal_id in number, + attribute_name in varchar2, + value in varchar2 + ); + + procedure end_task_action ( + journal_id in number, + action in varchar2, + task_id in number + ); + + /* Shortcut, that does both begin and end, when you have no attributes to set or assignments to make */ + function task_action ( + task_id in number, + action in varchar2, + action_ip in varchar2, + user_id in number, + msg in varchar2 default null + ) return number; + + function get_attribute_value ( + case_id in number, + attribute_name in varchar2 + ) return varchar2; + + procedure add_task_assignment ( + task_id in number, + party_id in number, + permanent_p in char default 'f' + ); + + procedure remove_task_assignment ( + task_id in number, + party_id in number, + permanent_p in char default 'f' + ); + + procedure clear_task_assignments ( + task_id in number, + permanent_p in char default 'f' + ); + + procedure set_case_deadline ( + case_id in wf_cases.case_id%TYPE, + transition_key in wf_transitions.transition_key%TYPE, + deadline date + ); + + procedure remove_case_deadline ( + case_id in wf_cases.case_id%TYPE, + transition_key in wf_transitions.transition_key%TYPE + ); + + + + /* DBMS_JOBS */ + + procedure sweep_timed_transitions; + + procedure sweep_hold_timeout; + +end workflow_case; +/ +show errors; Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/workflow-case-package.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/workflow-case-package.sql,v diff -u -r1.8 -r1.9 --- openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/workflow-case-package.sql 9 Oct 2001 00:03:15 -0000 1.8 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/workflow-case-package.sql 19 Nov 2001 18:17:46 -0000 1.9 @@ -11,1965 +11,15 @@ -- @cvs-id $Id$ -- +@@workflow-case-package-head.sql +@@workflow-case-package-body.sql -create or replace package workflow_case -is - - function new ( - case_id in number default null, - workflow_key in varchar2, - context_key in varchar2 default null, - object_id in integer, - creation_date in date default sysdate, - creation_user in integer default null, - creation_ip in varchar2 default null - ) return integer; - - procedure add_manual_assignment ( - case_id in number, - transition_key in varchar2, - party_id in number - ); - - procedure remove_manual_assignment ( - case_id in number, - transition_key in varchar2, - party_id in number - ); - - procedure clear_manual_assignments ( - case_id in number, - transition_key in varchar2 - ); - - procedure start_case ( - case_id in number, - creation_user in integer default null, - creation_ip in varchar2 default null, - msg in varchar2 default null - ); - - procedure delete( - case_id in number - ); - - procedure suspend( - case_id in number, - user_id in number default null, - ip_address in varchar2 default null, - msg in varchar2 default null - ); - - procedure resume( - case_id in number, - user_id in number default null, - ip_address in varchar2 default null, - msg in varchar2 default null - ); - - procedure cancel( - case_id in number, - user_id in number default null, - ip_address in varchar2 default null, - msg in varchar2 default null - ); - - procedure fire_message_transition ( - task_id in number - ); - - /* To perform an action on the workflow: - * (numbers in parenthesis is the number of times each function should get called) - * - * 1. begin_task_action (1) - * 2. set_attribute_value (0..*) - * 3. clear_manual_assignments (0..1) - * 4. add_manual_assignment (0..*) - * 5. end_task_action (1) - */ - function begin_task_action ( - task_id in number, - action in varchar2, - action_ip in varchar2, - user_id in number, - msg in varchar2 default null - ) return number; - - procedure set_attribute_value ( - journal_id in number, - attribute_name in varchar2, - value in varchar2 - ); - - procedure end_task_action ( - journal_id in number, - action in varchar2, - task_id in number - ); - - /* Shortcut, that does both begin and end, when you have no attributes to set or assignments to make */ - function task_action ( - task_id in number, - action in varchar2, - action_ip in varchar2, - user_id in number, - msg in varchar2 default null - ) return number; - - function get_attribute_value ( - case_id in number, - attribute_name in varchar2 - ) return varchar2; - - procedure add_task_assignment ( - task_id in number, - party_id in number - ); - - procedure remove_task_assignment ( - task_id in number, - party_id in number - ); - - procedure clear_task_assignments ( - task_id in number - ); - - - /* DBMS_JOBS */ - - procedure sweep_timed_transitions; - - procedure sweep_hold_timeout; - -end workflow_case; -/ -show errors; - -create or replace package body workflow_case -is - - /* - * FORWARD DECLARATIONS - */ - - procedure add_token ( - case_id in number, - place_key in varchar2, - journal_id in number - ); - - procedure lock_token ( - case_id in number, - place_key in varchar2, - journal_id in number, - task_id in number - ); - - procedure release_token ( - task_id in number, - journal_id in number - ); - - procedure consume_token ( - case_id in number, - place_key in varchar2, - journal_id in number, - task_id in number default null - ); - - procedure execute_unassigned_callback ( - callback in varchar2, - task_id in number, - custom_arg in varchar2 - ); - - procedure enable_transitions ( - case_id in number - ); - - procedure sweep_automatic_transitions ( - case_id in number, - journal_id in number - ); - - function finished_p( - case_id in number, - journal_id in number - ) return char; - - procedure fire_transition_internal ( - task_id in number, - journal_id in number - ); - - procedure start_task( - task_id in number, - user_id in number, - journal_id in number - ); - - procedure cancel_task( - task_id in number, - journal_id in number - ); - - procedure finish_task ( - task_id in number, - journal_id in number - ); - - procedure notify_assignee( - task_id in wf_tasks.task_id%TYPE, - user_id in users.user_id%TYPE, - callback in wf_context_transition_info.notification_callback%TYPE, - custom_arg in wf_context_transition_info.notification_custom_arg%TYPE - ); - - /* - * CURSORS - */ - - cursor input_places( - workflow_key in wf_workflows.workflow_key%TYPE, - transition_key in wf_transitions.transition_key%TYPE - ) - return wf_transition_places%ROWTYPE - is - select * - from wf_transition_places tp - where tp.workflow_key = input_places.workflow_key - and tp.transition_key = input_places.transition_key - and direction = 'in'; - - - cursor output_places ( - workflow_key in wf_workflows.workflow_key%TYPE, - transition_key in wf_transitions.transition_key%TYPE - ) - return wf_transition_places%ROWTYPE - is - select * - from wf_transition_places tp - where tp.workflow_key = output_places.workflow_key - and tp.transition_key = output_places.transition_key - and direction = 'out'; - - - /* - * PUBLIC API - */ - - function new ( - case_id in number default null, - workflow_key in varchar2, - context_key in varchar2 default null, - object_id in integer, - creation_date in date default sysdate, - creation_user in integer default null, - creation_ip in varchar2 default null - ) - return integer - is - v_case_id number; - v_workflow_case_table varchar2(30); - v_context_key_for_query varchar2(100); - begin - if context_key is null then - v_context_key_for_query := 'default'; - else - v_context_key_for_query := context_key; - end if; - - /* insert a row into acs_objects */ - v_case_id := acs_object.new( - object_id => new.case_id, - object_type => new.workflow_key, - creation_date => new.creation_date, - creation_user => new.creation_user, - creation_ip => new.creation_ip - ); - - /* insert the case in to the general wf_cases table */ - insert into wf_cases - (case_id, workflow_key, context_key, object_id, state) - values - (v_case_id, new.workflow_key, v_context_key_for_query, new.object_id, 'created'); - - /* insert the case into the workflow-specific cases table */ - select table_name into v_workflow_case_table - from acs_object_types - where object_type = new.workflow_key; - - execute immediate 'insert into '||v_workflow_case_table||' (case_id) values (:1)' - using v_case_id; - - return v_case_id; - end new; - - - procedure add_manual_assignment ( - case_id in number, - transition_key in varchar2, - party_id in number - ) - is - v_workflow_key varchar2(100); - begin - select workflow_key into v_workflow_key from wf_cases where case_id = add_manual_assignment.case_id; - - insert into wf_case_assignments - (case_id, workflow_key, transition_key, party_id) - values - (add_manual_assignment.case_id, v_workflow_key, add_manual_assignment.transition_key, add_manual_assignment.party_id); - end add_manual_assignment; - - - procedure remove_manual_assignment ( - case_id in number, - transition_key in varchar2, - party_id in number - ) - is - v_workflow_key varchar2(100); - begin - select workflow_key into v_workflow_key from wf_cases where case_id = remove_manual_assignment.case_id; - - delete from wf_case_assignments - where workflow_key = v_workflow_key - and case_id = remove_manual_assignment.case_id - and transition_key = remove_manual_assignment.transition_key - and party_id = remove_manual_assignment.party_id; - end remove_manual_assignment; - - procedure clear_manual_assignments ( - case_id in number, - transition_key in varchar2 - ) - is - v_workflow_key varchar2(100); - begin - select workflow_key into v_workflow_key from wf_cases where case_id = clear_manual_assignments.case_id; - - delete - from wf_case_assignments - where workflow_key = v_workflow_key - and case_id = clear_manual_assignments.case_id - and transition_key = clear_manual_assignments.transition_key; - end clear_manual_assignments; - - - procedure start_case ( - case_id in number, - creation_user in integer default null, - creation_ip in varchar2 default null, - msg in varchar2 default null - ) - is - v_journal_id number; - begin - /* Add an entry to the journal */ - dbms_output.put_line('creating journal entry'); - v_journal_id := journal_entry.new( - object_id => start_case.case_id, - action => 'case start', - action_pretty => 'Case started', - creation_user => start_case.creation_user, - creation_ip => start_case.creation_ip, - msg => start_case.msg - ); - - update wf_cases set state = 'active' where case_id = start_case.case_id; - - dbms_output.put_line('adding token'); - add_token( - case_id => start_case.case_id, - place_key => 'start', - journal_id => v_journal_id - ); - - /* Turn the wheels */ - dbms_output.put_line('sweeping transitions'); - sweep_automatic_transitions( - case_id => start_case.case_id, - journal_id => v_journal_id - ); - end start_case; - - - procedure delete( - case_id in number - ) - is - v_workflow_case_table varchar2(30); - begin - /* delete attribute_value_audit, tokens, tasks */ - delete from wf_attribute_value_audit where case_id = workflow_case.delete.case_id; - delete from wf_case_assignments where case_id = workflow_case.delete.case_id; - delete from wf_case_deadlines where case_id = workflow_case.delete.case_id; - delete from wf_tokens where case_id = workflow_case.delete.case_id; - delete from wf_task_assignments where task_id in (select task_id from wf_tasks where case_id = workflow_case.delete.case_id); - delete from wf_tasks where case_id = workflow_case.delete.case_id; - - /* delete the journal */ - journal_entry.delete_for_object(workflow_case.delete.case_id); - - /* delete from the workflow-specific cases table */ - select table_name into v_workflow_case_table - from acs_object_types ot, wf_cases c - where c.case_id = workflow_case.delete.case_id - and object_type = c.workflow_key; - - execute immediate 'delete from '||v_workflow_case_table||' where case_id = :case_id' - using in workflow_case.delete.case_id; - - /* delete from the generic cases table */ - delete from wf_cases where case_id = workflow_case.delete.case_id; - - /* delete from acs-objects */ - acs_object.delete(workflow_case.delete.case_id); - end delete; - - - procedure suspend( - case_id in number, - user_id in number default null, - ip_address in varchar2 default null, - msg in varchar2 default null - ) - is - v_state varchar2(40); - v_journal_id number; - begin - select state into v_state - from wf_cases - where case_id = suspend.case_id; - - if v_state != 'active' then - raise_application_error(-20000, 'Only active cases can be suspended'); - end if; - - /* Add an entry to the journal */ - v_journal_id := journal_entry.new( - object_id => suspend.case_id, - action => 'case suspend', - action_pretty => 'case suspended', - creation_user => suspend.user_id, - creation_ip => suspend.ip_address, - msg => suspend.msg - ); - - update wf_cases - set state = 'suspended' - where case_id = suspend.case_id; - end suspend; - - - procedure resume( - case_id in number, - user_id in number default null, - ip_address in varchar2 default null, - msg in varchar2 default null - ) - is - v_state varchar2(40); - v_journal_id number; - begin - select state into v_state - from wf_cases - where case_id = resume.case_id; - - if v_state != 'suspended' and v_state != 'canceled' then - raise_application_error(-20000, 'Only suspended or canceled cases can be resumed'); - end if; - - /* Add an entry to the journal */ - v_journal_id := journal_entry.new( - object_id => resume.case_id, - action => 'case resume', - action_pretty => 'case resumed', - creation_user => resume.user_id, - creation_ip => resume.ip_address, - msg => resume.msg - ); - - update wf_cases - set state = 'active' - where case_id = resume.case_id; - end resume; - - - procedure cancel( - case_id in number, - user_id in number default null, - ip_address in varchar2 default null, - msg in varchar2 default null - ) - is - v_state varchar2(40); - v_journal_id number; - begin - select state into v_state - from wf_cases - where case_id = cancel.case_id; - - if v_state != 'active' and v_state != 'suspended' then - raise_application_error(-20000, 'Only active or suspended cases can be canceled'); - end if; - - /* Add an entry to the journal */ - v_journal_id := journal_entry.new( - object_id => cancel.case_id, - action => 'case cancel', - action_pretty => 'Case canceled', - creation_user => cancel.user_id, - creation_ip => cancel.ip_address, - msg => cancel.msg - ); - - update wf_cases - set state = 'canceled' - where case_id = cancel.case_id; - end cancel; - - - procedure fire_message_transition ( - task_id in number - ) is - v_case_id number; - v_transition_name varchar2(100); - v_trigger_type varchar2(40); - v_journal_id number; - begin - select t.case_id, tr.transition_name, tr.trigger_type - into v_case_id, v_transition_name, v_trigger_type - from wf_tasks t, wf_transitions tr - where t.task_id = fire_message_transition.task_id - and tr.workflow_key = t.workflow_key - and tr.transition_key = t.transition_key; - - if v_trigger_type != 'message' then - raise_application_error(-20000, 'Transition '''||v_transition_name||''' is not message triggered'); - end if; - - /* Add an entry to the journal */ - v_journal_id := journal_entry.new( - object_id => v_case_id, - action => 'task '||fire_message_transition.task_id||' fire', - action_pretty => v_transition_name || ' fired' - ); - - fire_transition_internal( - task_id => fire_message_transition.task_id, - journal_id => v_journal_id - ); - - sweep_automatic_transitions( - case_id => v_case_id, - journal_id => v_journal_id - ); - end fire_message_transition; - - - /* - * A wrapper for user tasks that uses the start/commit/cancel model for firing transitions. - */ - function begin_task_action ( - task_id in number, - action in varchar2, - action_ip in varchar2, - user_id in number, - msg in varchar2 default null - ) - return number - is - v_state varchar2(40); - v_journal_id number; - v_case_id number; - v_transition_name varchar2(100); - v_num_rows number; - begin - select state into v_state - from wf_tasks - where task_id = begin_task_action.task_id; - - if begin_task_action.action = 'start' then - if v_state != 'enabled' then - raise_application_error(-20000, 'Task is in state '''||v_state||''', '|| - 'but it must be in state ''enabled'' to be started.'); - end if; - - select decode(count(*),0,0,1) into v_num_rows - from wf_user_tasks - where task_id = begin_task_action.task_id - and user_id = begin_task_action.user_id; - - if v_num_rows = 0 then - raise_application_error(-20000, 'You are not assigned to this task.'); - end if; - elsif begin_task_action.action = 'finish' or begin_task_action.action = 'cancel' then - - if v_state = 'started' then - /* Is this user the holding user? */ - select decode(count(*),0,0,1) into v_num_rows - from wf_tasks - where task_id = begin_task_action.task_id - and holding_user = begin_task_action.user_id; - if v_num_rows = 0 then - raise_application_error(-20000, 'You are the user currently working on this task.'); - end if; - elsif v_state = 'enabled' then - if begin_task_action.action = 'cancel' then - raise_application_error(-20000, 'You can only cancel a task in state ''started'', '|| - 'but this task is in state '''||v_state||''''); - end if; - - /* Is this user assigned to this task? */ - select decode(count(*),0,0,1) into v_num_rows - from wf_user_tasks - where task_id = begin_task_action.task_id - and user_id = begin_task_action.user_id; - if v_num_rows = 0 then - raise_application_error(-20000, 'You are not assigned to this task.'); - end if; - - /* This task is finished without an explicit start. - * Store the user as the holding_user */ - update wf_tasks - set holding_user = begin_task_action.user_id - where task_id = begin_task_action.task_id; - else - raise_application_error(-20000, 'Task is in state '''||v_state||''', '|| - 'but it must be in state ''enabled'' or ''started'' to be finished'); - end if; - - elsif begin_task_action.action = 'comment' then - -- We currently allow anyone to comment on a task - -- (need this line because PL/SQL doens't like empty if blocks) - v_num_rows := 0; - end if; - - select t.case_id, tr.transition_name into v_case_id, v_transition_name - from wf_tasks t, - wf_transitions tr - where t.task_id = begin_task_action.task_id - and tr.workflow_key = t.workflow_key - and tr.transition_key = t.transition_key; - - /* Insert a journal entry */ - - v_journal_id := journal_entry.new( - object_id => v_case_id, - action => 'task '||begin_task_action.task_id||' '||begin_task_action.action, - action_pretty => v_transition_name || ' ' || begin_task_action.action, - creation_user => begin_task_action.user_id, - creation_ip => begin_task_action.action_ip, - msg => begin_task_action.msg - ); - - return v_journal_id; - end begin_task_action; - - - procedure end_task_action ( - journal_id in number, - action in varchar2, - task_id in number - ) - is - v_user_id number; - begin - select creation_user into v_user_id - from acs_objects - where object_id = end_task_action.journal_id; - - /* Update the workflow state */ - - if end_task_action.action = 'start' then - start_task(end_task_action.task_id, v_user_id, end_task_action.journal_id); - elsif end_task_action.action = 'finish' then - finish_task(end_task_action.task_id, end_task_action.journal_id); - elsif end_task_action.action = 'cancel' then - cancel_task(end_task_action.task_id, end_task_action.journal_id); - elsif end_task_action.action != 'comment' then - raise_application_error(-20000, 'Unknown action ''' || end_task_action.action || ''''); - end if; - - end end_task_action; - - function task_action ( - task_id in number, - action in varchar2, - action_ip in varchar2, - user_id in number, - msg in varchar2 default null - ) return number - is - v_journal_id integer; - begin - v_journal_id := begin_task_action( - task_id => task_action.task_id, - action => task_action.action, - action_ip => task_action.action_ip, - user_id => task_action.user_id, - msg => task_action.msg - ); - - end_task_action( - journal_id => v_journal_id, - action => task_action.action, - task_id => task_action.task_id - ); - - return v_journal_id; - end task_action; - - - procedure set_attribute_value ( - journal_id in number, - attribute_name in varchar2, - value in varchar2 - ) - is - v_workflow_key varchar2(100); - v_case_id number; - v_attribute_id number; - begin - select o.object_type, o.object_id into v_workflow_key, v_case_id - from journal_entries je, acs_objects o - where je.journal_id = set_attribute_value.journal_id - and o.object_id = je.object_id; - - select attribute_id into v_attribute_id - from acs_attributes - where object_type = v_workflow_key - and attribute_name = set_attribute_value.attribute_name; - - acs_object.set_attribute( - object_id_in => v_case_id, - attribute_name_in => set_attribute_value.attribute_name, - value_in => set_attribute_value.value - ); - - insert into wf_attribute_value_audit - (case_id, attribute_id, journal_id, attr_value) - values - (v_case_id, v_attribute_id, set_attribute_value.journal_id, set_attribute_value.value); - end set_attribute_value; - - - function get_attribute_value ( - case_id in number, - attribute_name in varchar2 - ) - return varchar2 - is - begin - return acs_object.get_attribute( - object_id_in => get_attribute_value.case_id, - attribute_name_in => get_attribute_value.attribute_name - ); - end get_attribute_value; - - - procedure add_task_assignment ( - task_id in number, - party_id in number - ) - is - v_count integer; - v_workflow_key wf_workflows.workflow_key%TYPE; - v_context_key wf_contexts.context_key%TYPE; - v_case_id wf_cases.case_id%TYPE; - v_transition_key wf_transitions.transition_key%TYPE; - v_notification_callback wf_context_transition_info.notification_callback%TYPE; - v_notification_custom_arg wf_context_transition_info.notification_custom_arg%TYPE; - - -- might need to tune this query further - cursor c_new_assigned_users is - select distinct u.user_id - from users u - where u.user_id not in ( - select distinct u2.user_id - from wf_task_assignments tasgn2, - party_approved_member_map m2, - users u2 - where tasgn2.task_id = add_task_assignment.task_id - and m2.party_id = tasgn2.party_id - and u2.user_id = m2.member_id) - and exists ( - select 1 - from party_approved_member_map m - where m.member_id = u.user_id - and m.party_id = add_task_assignment.party_id - ); - cursor c_callback is - select notification_callback, - notification_custom_arg - from wf_context_transition_info - where context_key = v_context_key - and workflow_key = v_workflow_key - and transition_key = v_transition_key; - callback_rec c_callback%ROWTYPE; - - begin - -- check that we don't hit the unique constraint - - select count(*) into v_count - from wf_task_assignments - where task_id = add_task_assignment.task_id - and party_id = add_task_assignment.party_id; - - if v_count > 0 then - return; - end if; - - -- get the notification callback info - - select case_id, workflow_key, transition_key - into v_case_id, v_workflow_key, v_transition_key - from wf_tasks - where task_id = add_task_assignment.task_id; - - select context_key - into v_context_key - from wf_cases - where case_id = v_case_id; - - open c_callback; - fetch c_callback into callback_rec; - - if c_callback%FOUND then - v_notification_callback := callback_rec.notification_callback; - v_notification_custom_arg := callback_rec.notification_custom_arg; - else - v_notification_callback := null; - v_notification_custom_arg := null; - end if; - close c_callback; - - -- notify any new assignees - - for v_assigned_user in c_new_assigned_users loop - notify_assignee( - task_id => add_task_assignment.task_id, - user_id => v_assigned_user.user_id, - callback => v_notification_callback, - custom_arg => v_notification_custom_arg - ); - end loop; - - -- do the insert - - insert into wf_task_assignments - (task_id, party_id) - values - (add_task_assignment.task_id, add_task_assignment.party_id); - - - end add_task_assignment; - - procedure remove_task_assignment ( - task_id in number, - party_id in number - ) - is - v_num_assigned number; - v_case_id number; - v_workflow_key varchar2(100); - v_transition_key varchar2(100); - v_context_key varchar2(100); - - cursor c_callback - is - select unassigned_callback, unassigned_custom_arg - from wf_context_transition_info - where workflow_key = v_workflow_key - and context_key = v_context_key - and transition_key = v_transition_key; - callback_rec c_callback%ROWTYPE; - begin - delete - from wf_task_assignments - where task_id = remove_task_assignment.task_id - and party_id = remove_task_assignment.party_id; - - select count(*) into v_num_assigned - from wf_task_assignments - where task_id = remove_task_assignment.task_id; - - if v_num_assigned > 0 then - return; - end if; - - select case_id, transition_key - into v_case_id, v_transition_key - from wf_tasks - where task_id = remove_task_assignment.task_id; - - select workflow_key, context_key - into v_workflow_key, v_context_key - from wf_cases - where case_id = v_case_id; - - open c_callback; - fetch c_callback into callback_rec; - - if c_callback%FOUND then - execute_unassigned_callback ( - callback => callback_rec.unassigned_callback, - task_id => task_id, - custom_arg => callback_rec.unassigned_custom_arg - ); - end if; - close c_callback; - - end remove_task_assignment; - - procedure clear_task_assignments ( - task_id in number - ) - is - v_case_id number; - v_transition_key varchar2(100); - v_workflow_key varchar2(100); - v_context_key varchar2(100); - v_callback varchar2(100); - v_custom_arg varchar2(4000); - begin - delete - from wf_task_assignments - where task_id = clear_task_assignments.task_id; - - select case_id, transition_key - into v_case_id, v_transition_key - from wf_tasks - where task_id = clear_task_assignments.task_id; - - select workflow_key, context_key - into v_workflow_key, v_context_key - from wf_cases - where case_id = v_case_id; - - select unassigned_callback, unassigned_custom_arg - into v_callback, v_custom_arg - from wf_context_transition_info - where workflow_key = v_workflow_key - and context_key = v_context_key - and transition_key = v_transition_key; - - execute_unassigned_callback ( - callback => v_callback, - task_id => task_id, - custom_arg => v_custom_arg - ); - - end clear_task_assignments; - - /* - * PRIVATE - */ - - function evaluate_guard ( - callback in varchar2, - custom_arg in varchar2, - case_id in number, - workflow_key in varchar2, - transition_key in varchar2, - place_key in varchar2, - direction in varchar2 - ) - return char - is - v_guard_happy_p char(1); - begin - if callback is null then - -- null guard evaluates to true - return 't'; - else - if callback = '#' then - return 'f'; - else - execute immediate 'begin :1 := ' || callback - || '(:2, :3, :4, :5, :6, :7); end;' - using out v_guard_happy_p, - in case_id, - in workflow_key, - in transition_key, - in place_key, - in direction, - in custom_arg; - return v_guard_happy_p; - end if; - end if; - end evaluate_guard; - - - procedure execute_transition_callback( - callback in varchar2, - custom_arg in varchar2, - case_id in number, - transition_key in varchar2 - ) - is - begin - if callback is not null then - execute immediate 'begin '||callback - || '(:1, :2, :3); end;' - using in case_id, - in transition_key, - in custom_arg; - end if; - end execute_transition_callback; - - - function execute_time_callback ( - callback in varchar2, - custom_arg in varchar2, - case_id in number, - transition_key in varchar2 - ) - return date - is - v_trigger_time date; - begin - if callback is null then - raise_application_error(-20000, 'There''s no time_callback function for the timed transition ''' || transition_key || ''''); - end if; - - execute immediate 'begin :1 := ' || callback - || '(:2, :3, :4); end;' - using out v_trigger_time, - in case_id, - in transition_key, - in custom_arg; - - return v_trigger_time; - end execute_time_callback; - - - function get_task_deadline ( - callback in varchar2, - custom_arg in varchar2, - attribute_name in varchar2, - case_id in number, - transition_key in varchar2 - ) - return date - is - cursor case_deadline_cur is - select deadline - from wf_case_deadlines - where case_id = get_task_deadline.case_id - and transition_key = get_task_deadline.transition_key; - v_deadline date; - begin - /* - * 1. or if there's a row in wf_case_deadlines, we use that - * 2. if there is a callback, we execute that - * 3. otherwise, if there is an attribute, we use that - */ - - dbms_output.put_line('exec of case_deadline callback'); - /* wf_case_deadlines */ - open case_deadline_cur; - fetch case_deadline_cur into v_deadline; - if case_deadline_cur%NOTFOUND then - if callback is not null then - /* callback */ - execute immediate 'begin :1 := ' || callback - || '(:2, :3, :4); end;' - using out v_deadline, - in case_id, - in transition_key, - in custom_arg; - elsif attribute_name is not null then - /* attribute */ - v_deadline := acs_object.get_attribute( - object_id_in => get_task_deadline.case_id, - attribute_name_in => get_task_deadline.attribute_name - ); - else - v_deadline := null; - end if; - end if; - close case_deadline_cur; - - return v_deadline; - end get_task_deadline; - - - function execute_hold_timeout_callback ( - callback in varchar2, - custom_arg in varchar2, - case_id in number, - transition_key in varchar2 - ) - return date - is - v_hold_timeout date; - begin - if callback is null then - return null; - end if; - - execute immediate 'begin :1 := ' || callback - || '(:2, :3, :4); end;' - using out v_hold_timeout, - in case_id, - in transition_key, - in custom_arg; - - return v_hold_timeout; - end execute_hold_timeout_callback; - - - procedure execute_unassigned_callback ( - callback in varchar2, - task_id in number, - custom_arg in varchar2 - ) - is - begin - if callback is not null then - execute immediate 'begin ' || callback - || '(:1, :2); end;' - using in task_id, - in custom_arg; - end if; - end execute_unassigned_callback; - - procedure set_task_assignments( - task_id in number, - callback in varchar2, - custom_arg in varchar2 - ) - is - cursor case_assignments is - select party_id - from wf_case_assignments ca, wf_tasks t - where t.task_id = set_task_assignments.task_id - and ca.case_id = t.case_id - and ca.transition_key = t.transition_key; - cursor context_assignments is - select party_id - from wf_context_assignments ca, wf_cases c, wf_tasks t - where t.task_id = set_task_assignments.task_id - and c.case_id = t.case_id - and ca.context_key = c.context_key - and ca.workflow_key = t.workflow_key - and ca.transition_key = t.transition_key; - v_done_p char(1); - begin - - /* Find out who to assign the given task to. - * - * 1. See if there are rows in wf_case_assignments. - * 2. If not, and a callback is defined, execute that. - * 3. Otherwise, grab the assignment from the workflow context. - * - * (We used to use the callback first, but that makes - * reassignment of tasks difficult.) - */ - - v_done_p := 'f'; - for case_assignment_rec in case_assignments loop - v_done_p := 't'; - add_task_assignment ( - task_id => task_id, - party_id => case_assignment_rec.party_id - ); - end loop; - - if v_done_p != 't' then - - if callback is not null then - execute immediate 'begin '|| set_task_assignments.callback - || '(:1, :2); end;' - using in set_task_assignments.task_id, - in set_task_assignments.custom_arg; - else - for context_assignment_rec in context_assignments loop - add_task_assignment ( - task_id => task_id, - party_id => context_assignment_rec.party_id - ); - end loop; - end if; - end if; - end set_task_assignments; - - - procedure add_token ( - case_id in number, - place_key in varchar2, - journal_id in number - ) - is - v_token_id number; - v_workflow_key varchar2(100); - begin - select wf_token_id_seq.nextval into v_token_id from dual; - dbms_output.put_line('case_id = ' || case_id || ', place_key = ' || place_key || ', journal_id = ' || journal_id); - select workflow_key into v_workflow_key - from wf_cases c - where c.case_id = add_token.case_id; - - insert into wf_tokens - (token_id, case_id, workflow_key, place_key, state, produced_journal_id) - values - (v_token_id, add_token.case_id, v_workflow_key, add_token.place_key, 'free', add_token.journal_id); - end add_token; - - - procedure lock_token ( - case_id in number, - place_key in varchar2, - journal_id in number, - task_id in number - ) - is - begin - update wf_tokens - set state = 'locked', - locked_task_id = lock_token.task_id, - locked_date = sysdate, - locked_journal_id = lock_token.journal_id - where case_id = lock_token.case_id - and place_key = lock_token.place_key - and state = 'free' - and rownum = 1; - end lock_token; - - - procedure release_token ( - task_id in number, - journal_id in number - ) - is - cursor token_cur is - select token_id, - case_id, - place_key - from wf_tokens - where state = 'locked' - and locked_task_id = release_token.task_id; - begin - /* Add a new token for each released one */ - for token_rec in token_cur loop - add_token( - case_id => token_rec.case_id, - place_key => token_rec.place_key, - journal_id => release_token.journal_id - ); - end loop; - - /* Mark the released ones canceled */ - update wf_tokens - set state = 'canceled', - canceled_date = sysdate, - canceled_journal_id = release_token.journal_id - where state = 'locked' - and locked_task_id = release_token.task_id; - end release_token; - - - procedure consume_token ( - case_id in number, - place_key in varchar2, - journal_id in number, - task_id in number default null - ) - is - begin - if task_id is null then - update wf_tokens - set state = 'consumed', - consumed_date = sysdate, - consumed_journal_id = consume_token.journal_id - where case_id = consume_token.case_id - and place_key = consume_token.place_key - and state = 'free' - and rownum = 1; - else - update wf_tokens - set state = 'consumed', - consumed_date = sysdate, - consumed_journal_id = consume_token.journal_id - where case_id = consume_token.case_id - and place_key = consume_token.place_key - and state = 'locked' - and locked_task_id = consume_token.task_id; - end if; - end consume_token; - - - procedure sweep_automatic_transitions ( - case_id in number, - journal_id in number - ) is - cursor enabled_automatic_transitions is - select task_id - from wf_tasks ta, wf_transitions tr - where tr.workflow_key = ta.workflow_key - and tr.transition_key = ta.transition_key - and tr.trigger_type = 'automatic' - and ta.state = 'enabled' - and ta.case_id = sweep_automatic_transitions.case_id; - v_done_p char(1); - v_finished_p char(1); - begin - dbms_output.put_line('enabling transitions'); - enable_transitions(case_id => sweep_automatic_transitions.case_id); - - loop - v_done_p := 't'; - v_finished_p := finished_p( - case_id => sweep_automatic_transitions.case_id, - journal_id => sweep_automatic_transitions.journal_id); - - if v_finished_p = 'f' then - for task_rec in enabled_automatic_transitions loop - fire_transition_internal( - task_id => task_rec.task_id, - journal_id => sweep_automatic_transitions.journal_id - ); - v_done_p := 'f'; - end loop; - enable_transitions(case_id => sweep_automatic_transitions.case_id); - end if; - - exit when v_done_p = 't'; - end loop; - end sweep_automatic_transitions; - - - function finished_p ( - case_id in number, - journal_id in number - ) - return char - is - v_case_state varchar2(40); - v_token_id number; - v_num_rows number; - v_journal_id number; - begin - select state into v_case_state - from wf_cases - where case_id = finished_p.case_id; - - if v_case_state = 'finished' then - return 't'; - else - /* Let's see if the case is actually finished, but just not marked so */ - select decode(count(*),0,0,1) into v_num_rows - from wf_tokens - where case_id = finished_p.case_id - and place_key = 'end'; - - if v_num_rows = 0 then - return 'f'; - else - /* There's a token in the end place. - * Count the total number of tokens to make sure the wf is well-constructed. - */ - - select decode(count(*),0,0,1,1,2) into v_num_rows - from wf_tokens - where case_id = finished_p.case_id - and state in ('free', 'locked'); - - if v_num_rows > 1 then - raise_application_error(-20000, 'The workflow net is misconstructed: Some parallel executions have not finished.'); - end if; - - /* Consume that token */ - select token_id into v_token_id - from wf_tokens - where case_id = finished_p.case_id - and state in ('free', 'locked'); - - consume_token( - case_id => finished_p.case_id, - place_key => 'end', - journal_id => finished_p.journal_id - ); - - update wf_cases - set state = 'finished' - where case_id = finished_p.case_id; - - /* Add an extra entry to the journal */ - v_journal_id := journal_entry.new( - object_id => finished_p.case_id, - action => 'case finish', - action_pretty => 'Case finished' - ); - - return 't'; - end if; - end if; - end finished_p; - - - - /* This procedure should be scheduled to run as a dbms_job. */ - procedure sweep_timed_transitions - is - cursor timed_transitions_to_fire is - select t.task_id, t.case_id, tr.transition_name - from wf_tasks t, wf_transitions tr - where trigger_time <= sysdate - and state = 'enabled' - and tr.workflow_key = t.workflow_key - and tr.transition_key = t.transition_key; - v_journal_id number; - begin - for trans_rec in timed_transitions_to_fire loop - - /* Insert an entry to the journal so people will know it fired */ - - v_journal_id := journal_entry.new( - object_id => trans_rec.case_id, - action => 'task '||trans_rec.task_id|| ' fire time', - action_pretty => trans_rec.transition_name || ' automatically finished', - msg => 'Timed transition fired.' - ); - - /* Fire the transition */ - - fire_transition_internal( - task_id => trans_rec.task_id, - journal_id => v_journal_id - ); - - /* Update the workflow internal state */ - - sweep_automatic_transitions( - case_id => trans_rec.case_id, - journal_id => v_journal_id - ); - - end loop; - end sweep_timed_transitions; - - - /* This procedure should be scheduled to run as a dbms_job. */ - procedure sweep_hold_timeout - is - cursor tasks_to_cancel is - select t.task_id, t.case_id, tr.transition_name - from wf_tasks t, wf_transitions tr - where hold_timeout <= sysdate - and state = 'started' - and tr.workflow_key = t.workflow_key - and tr.transition_key = t.transition_key; - v_journal_id number; - begin - for task_rec in tasks_to_cancel loop - - /* Insert an entry to the journal so people will know it was canceled */ - - v_journal_id := journal_entry.new( - object_id => task_rec.case_id, - action => 'task '||task_rec.task_id||' cancel timeout', - action_pretty => task_rec.transition_name || ' timed out', - msg => 'The user''s hold on the task timed out and the task was automatically canceled' - ); - - - /* Cancel the task */ - - cancel_task( - task_id => task_rec.task_id, - journal_id => v_journal_id - ); - - end loop; - end sweep_hold_timeout; - - - - - procedure notify_assignee( - task_id in wf_tasks.task_id%TYPE, - user_id in users.user_id%TYPE, - callback in wf_context_transition_info.notification_callback%TYPE, - custom_arg in wf_context_transition_info.notification_custom_arg%TYPE - ) - is - v_deadline_pretty varchar2(400); - v_object_name varchar2(4000); - v_transition_key wf_transitions.transition_key%TYPE; - v_transition_name wf_transitions.transition_name%TYPE; - v_party_from parties.party_id%TYPE; - v_party_to parties.party_id%TYPE; - v_subject varchar2(4000); - v_body varchar2(4000); - v_request_id integer; - begin - select to_char(ta.deadline,'Mon fmDDfm, YYYY HH24:MI:SS'), - acs_object.name(c.object_id), - tr.transition_key, - tr.transition_name - into v_deadline_pretty, - v_object_name, - v_transition_key, - v_transition_name - from wf_tasks ta, wf_transitions tr, wf_cases c - where ta.task_id = notify_assignee.task_id - and c.case_id = ta.case_id - and tr.workflow_key = c.workflow_key - and tr.transition_key = ta.transition_key; - - /* Default values */ - -- changed to null from -1 since acs-mail references users instead of - -- parties. DanW (dcwickstrom@earthlink.net) - v_party_from := -1; /* This default value should probably be pulled from somewhere */ - v_subject := 'Assignment: '||v_transition_name||' '||v_object_name; - v_body := 'You have been assigned to a task. -'||' -Task : '||v_transition_name||' -Object : '||v_object_name||' -'; - - if v_deadline_pretty != '' then - v_body := v_body ||'Deadline: '||v_deadline_pretty||' -'; - end if; - - /* We'd like to add a URL to go visit, but how do we get that URL? */ - /* The notifications should really be sent from the application server layer, not from the database */ - - if notify_assignee.callback is not null then - execute immediate 'begin '||notify_assignee.callback||'(:1, :2, :3, :4, :5, :6); end;' - using in notify_assignee.task_id, - in notify_assignee.custom_arg, - in notify_assignee.user_id, - in out v_party_from, - in out v_subject, - in out v_body; - end if; - - -- NOTICE, NOTICE, NOTICE - -- - -- Since postgresql does not support out parameters, this - -- function call has been moved into the callback function. - -- If you implement a new notification callback, make sure - -- that this function call is included at the end of the - -- callback routine. - - -- The oracle version has been changed to be consistent - -- with the postgresql version, even though technically - -- it is not necessary. - -- - -- DanW (dcwickstrom@earthlink.net) - - -- v_request_id := acs_mail_nt.post_request ( - -- party_from => v_party_from, - -- party_to => notify_assignee.user_id, - -- expand_group => 'f' , - -- subject => v_subject, - -- message => v_body, - -- max_retries => 0 - -- ); - - end notify_assignee; - - - - /* - * This procedure synchronizes the actually enabled transitions - * (i.e., the ones where tokens are currently present on the - * input places), with the cached version of that information, - * in wf_tasks. - * It is entirely idempotent and will at any given time sync up with - * the actual state of the workflow (as per the tokens), so we don't - * need to pass in a journal_id. - */ - procedure enable_transitions ( - case_id in number - ) is - cursor tasks_to_create is - select transition_key, - transition_name, - trigger_type, - enable_callback, - enable_custom_arg, - assignment_callback, - assignment_custom_arg, - time_callback, - time_custom_arg, - deadline_callback, - deadline_custom_arg, - deadline_attribute_name, - notification_callback, - notification_custom_arg, - unassigned_callback, - unassigned_custom_arg, - estimated_minutes - from wf_enabled_transitions et - where et.case_id = enable_transitions.case_id - and not exists (select 1 from wf_tasks - where case_id = enable_transitions.case_id - and transition_key = et.transition_key - and state in ('enabled', 'started')); - v_task_id number; - v_workflow_key varchar2(100); - v_trigger_time date; - v_deadline_date date; - v_party_from integer; - v_subject varchar2(500); - v_body varchar2(4000); - v_num_assigned number; - request_id acs_mail_queue_messages.message_id%TYPE; - cursor assignees_cur is - select distinct u.user_id - from wf_task_assignments tasgn, - party_approved_member_map m, - users u - where tasgn.task_id = v_task_id - and m.party_id = tasgn.party_id - and u.user_id = m.member_id; - begin - select workflow_key into v_workflow_key - from wf_cases - where case_id = enable_transitions.case_id; - - /* we mark tasks overridden if they were once enabled, but are no longer so */ - - update wf_tasks - set state = 'overridden', - overridden_date = sysdate - where case_id = enable_transitions.case_id - and state = 'enabled' - and transition_key not in - (select transition_key - from wf_enabled_transitions - where case_id = enable_transitions.case_id); - - - /* insert a task for the transitions that are enabled but have no task row */ - - for trans_rec in tasks_to_create loop - - v_trigger_time := null; - v_deadline_date := null; - - if trans_rec.trigger_type = 'user' then - v_deadline_date := get_task_deadline( - callback => trans_rec.deadline_callback, - custom_arg => trans_rec.deadline_custom_arg, - attribute_name => trans_rec.deadline_attribute_name, - case_id => enable_transitions.case_id, - transition_key => trans_rec.transition_key - ); - elsif trans_rec.trigger_type = 'time' then - v_trigger_time := execute_time_callback(trans_rec.time_callback, - trans_rec.time_custom_arg, - enable_transitions.case_id, trans_rec.transition_key); - end if; - - /* we're ready to insert the row */ - select wf_task_id_seq.nextval into v_task_id from dual; - - insert into wf_tasks ( - task_id, case_id, workflow_key, transition_key, - deadline, trigger_time, estimated_minutes - ) values ( - v_task_id, enable_transitions.case_id, v_workflow_key, - trans_rec.transition_key, - v_deadline_date, v_trigger_time, trans_rec.estimated_minutes - ); - - set_task_assignments( - task_id => v_task_id, - callback => trans_rec.assignment_callback, - custom_arg => trans_rec.assignment_custom_arg - ); - - /* Execute the transition enabled callback */ - execute_transition_callback( - callback => trans_rec.enable_callback, - custom_arg => trans_rec.enable_custom_arg, - case_id => enable_transitions.case_id, - transition_key => trans_rec.transition_key - ); - - select count(*) into v_num_assigned - from wf_task_assignments - where task_id = v_task_id; - - if v_num_assigned = 0 then - execute_unassigned_callback ( - callback => trans_rec.unassigned_callback, - task_id => v_task_id, - custom_arg => trans_rec.unassigned_custom_arg - ); - end if; - - end loop; - end enable_transitions; - - - procedure fire_transition_internal ( - task_id in number, - journal_id in number - ) is - v_case_id number; - v_state varchar2(40); - v_transition_key varchar2(100); - v_workflow_key varchar2(100); - v_place_key varchar2(100); - v_direction varchar2(3); - v_guard_happy_p char(1); - v_fire_callback varchar2(100); - v_fire_custom_arg varchar2(4000); - v_found_happy_guard char(1); - v_locked_task_id number; - begin - select t.case_id, t.state, t.workflow_key, t.transition_key, ti.fire_callback, ti.fire_custom_arg - into v_case_id, v_state, v_workflow_key, v_transition_key, v_fire_callback, v_fire_custom_arg - from wf_tasks t, wf_cases c, wf_transition_info ti - where t.task_id = fire_transition_internal.task_id - and c.case_id = t.case_id - and ti.context_key = c.context_key - and ti.workflow_key = c.workflow_key - and ti.transition_key = t.transition_key; - - /* Check that the state is either started or enabled */ - - if v_state = 'enabled' then - v_locked_task_id := null; - elsif v_state = 'started' then - v_locked_task_id := fire_transition_internal.task_id; - else - raise_application_error(-20000, 'Can''t fire the transition if it''s not in state enabled or started'); - end if; - - - /* Mark the task finished */ - - update wf_tasks - set state = 'finished', - finished_date = sysdate - where task_id = fire_transition_internal.task_id; - - - /* Consume the tokens */ - - for place_rec in input_places(v_workflow_key, v_transition_key) loop - consume_token( - case_id => v_case_id, - place_key => place_rec.place_key, - journal_id => fire_transition_internal.journal_id, - task_id => v_locked_task_id - ); - end loop; - - - /* Spit out new tokens in the output places */ - - v_found_happy_guard := 'f'; - for place_rec in output_places(v_workflow_key, v_transition_key) loop - v_place_key := place_rec.place_key; - v_direction := place_rec.direction; - v_guard_happy_p := evaluate_guard( - callback => place_rec.guard_callback, - custom_arg => place_rec.guard_custom_arg, - case_id => v_case_id, - workflow_key => v_workflow_key, - transition_key => v_transition_key, - place_key => v_place_key, - direction => v_direction - ); - - if v_guard_happy_p = 't' then - v_found_happy_guard := 't'; - add_token( - case_id => v_case_id, - place_key => place_rec.place_key, - journal_id => fire_transition_internal.journal_id - ); - end if; - end loop; - - - /* If we didn't find any happy guards, look for arcs with the special hash (#) guard */ - - if v_found_happy_guard = 'f' then - for place_rec in ( - select place_key - from wf_transition_places tp - where tp.workflow_key = v_workflow_key - and tp.transition_key = v_transition_key - and tp.direction = 'out' - and tp.guard_callback = '#') - loop - add_token( - case_id => v_case_id, - place_key => place_rec.place_key, - journal_id => fire_transition_internal.journal_id - ); - end loop; - end if; - - - /* Execute the transition fire callback */ - - execute_transition_callback( - callback => v_fire_callback, - custom_arg => v_fire_custom_arg, - case_id => v_case_id, - transition_key => v_transition_key - ); - end fire_transition_internal; - - - - /* A small helper to make sure we're in the state we expect to be */ - procedure ensure_task_in_state ( - task_id in number, - state in varchar2 - ) is - v_count number; - begin - select decode(count(*),0,0,1) into v_count - from wf_tasks - where task_id = ensure_task_in_state.task_id - and state = ensure_task_in_state.state; - - if v_count != 1 then - raise_application_error(-20000, 'The task '|| ensure_task_in_state.task_id || ' is not in state ''' || ensure_task_in_state.state || ''''); - end if; - end ensure_task_in_state; - - - - /* Marks a task started and reserves one token from each input place */ - procedure start_task( - task_id in number, - user_id in number, - journal_id in number - ) is - v_case_id number; - v_workflow_key wf_workflows.workflow_key%TYPE; - v_transition_key varchar2(100); - v_hold_timeout_callback varchar2(100); - v_hold_timeout_custom_arg varchar2(4000); - v_hold_timeout date; - begin - ensure_task_in_state(task_id => start_task.task_id, state => 'enabled'); - - select t.case_id, t.workflow_key, t.transition_key, ti.hold_timeout_callback, ti.hold_timeout_custom_arg - into v_case_id, v_workflow_key, v_transition_key, v_hold_timeout_callback, v_hold_timeout_custom_arg - from wf_tasks t, wf_cases c, wf_transition_info ti - where t.task_id = start_task.task_id - and c.case_id = t.case_id - and ti.context_key = c.context_key - and ti.workflow_key = t.workflow_key - and ti.transition_key = t.transition_key; - - v_hold_timeout := execute_hold_timeout_callback(v_hold_timeout_callback, - v_hold_timeout_custom_arg, v_case_id, v_transition_key); - - /* Mark it started */ - - update wf_tasks - set state = 'started', - started_date = sysdate, - holding_user = start_task.user_id, - hold_timeout = v_hold_timeout - where task_id = start_task.task_id; - - - /* Reserve one token from each input place */ - - for place_rec in input_places(v_workflow_key,v_transition_key) loop - lock_token( - case_id => v_case_id, - place_key => place_rec.place_key, - journal_id => start_task.journal_id, - task_id => start_task.task_id - ); - end loop; - end start_task; - - - /* Mark the task canceled and release the reserved tokens */ - procedure cancel_task( - task_id in number, - journal_id in number - ) - is - v_case_id number; - begin - ensure_task_in_state(task_id => cancel_task.task_id, state => 'started'); - select case_id into v_case_id - from wf_tasks - where task_id = cancel_task.task_id; - - /* Mark the task canceled */ - - update wf_tasks - set state = 'canceled', - canceled_date = sysdate - where task_id = cancel_task.task_id; - - - /* Release our reserved tokens */ - - release_token( - task_id => cancel_task.task_id, - journal_id => cancel_task.journal_id - ); - - /* The workflow state has now changed, so we must run this */ - - sweep_automatic_transitions( - case_id => v_case_id, - journal_id => cancel_task.journal_id - ); - end cancel_task; - - - /* Fire the transition */ - procedure finish_task ( - task_id in number, - journal_id in number - ) - is - v_case_id number; - begin - select case_id into v_case_id - from wf_tasks - where task_id = finish_task.task_id; - - fire_transition_internal( - task_id => finish_task.task_id, - journal_id => finish_task.journal_id - ); - - sweep_automatic_transitions( - case_id => v_case_id, - journal_id => finish_task.journal_id - ); - end finish_task; - - -end workflow_case; -/ -show errors; - --- This is now handled by acs-mail - no longer necessary. --- DanW (dcwickstrom@earthlink.net). -- -- schedule processing of the notification queue -- --- begin --- nt.schedule_process(1,'localhost',25); --- end; --- / --- show errors; +begin + nt.schedule_process(1,'localhost',25); +end; +/ +show errors; Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/workflow-package-body.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/workflow-package-body.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/workflow-package-body.sql 19 Nov 2001 18:17:46 -0000 1.1 @@ -0,0 +1,742 @@ +-- +-- acs-workflow/sql/workflow-package-head.sql +-- +-- Creates the PL/SQL package that provides the API for defining and dropping +-- workflow cases. +-- +-- @author Lars Pind (lars@pinds.com) +-- +-- @creation-date 2000-05-18 +-- +-- @cvs-id $Id: workflow-package-body.sql,v 1.1 2001/11/19 18:17:46 neophytosd Exp $ +-- + + +create or replace package body workflow +as + + function create_workflow ( + workflow_key in varchar2, + pretty_name in varchar2, + pretty_plural in varchar2 default null, + description in varchar2 default null, + table_name in varchar2, + id_column in varchar2 default 'case_id' + ) + return varchar2 + is + v_num_rows number; + v_workflow_key varchar2(100); + begin + select count(*) into v_num_rows from user_tables where table_name = upper(create_workflow.table_name); + if v_num_rows = 0 then + raise_application_error(-20000, 'The table '''||create_workflow.table_name||''' must be created before calling workflow.create_workflow.'); + end if; + + if substr(create_workflow.workflow_key, length(create_workflow.workflow_key) - 2, 3) != '_wf' then + v_workflow_key := create_workflow.workflow_key||'_wf'; + else + v_workflow_key := create_workflow.workflow_key; + end if; + + acs_object_type.create_type( + object_type => v_workflow_key, + pretty_name => create_workflow.pretty_name, + pretty_plural => create_workflow.pretty_plural, + supertype => 'workflow', + table_name => create_workflow.table_name, + id_column => create_workflow.id_column + ); + + insert into wf_workflows + (workflow_key, description) + values + (v_workflow_key, create_workflow.description); + + return v_workflow_key; + end create_workflow; + + + /* Note: The workflow-specific cases table must be dropped before calling this proc */ + procedure drop_workflow ( + workflow_key in varchar2 + ) + is + v_table_name varchar2(100); + v_num_rows number; + cursor attribute_cur is + select attribute_id, attribute_name from acs_attributes where object_type = drop_workflow.workflow_key; + begin + select table_name into v_table_name + from acs_object_types + where object_type = drop_workflow.workflow_key; + + select decode(count(*),0,0,1) into v_num_rows + from user_tables + where table_name = upper(v_table_name); + + if v_num_rows > 0 then + raise_application_error(-20000, 'The table '''||v_table_name||''' must be dropped before calling workflow.drop_workflow.'); + end if; + + select decode(count(*),0,0,1) into v_num_rows + from wf_cases + where workflow_key = drop_workflow.workflow_key; + + if v_num_rows > 0 then + raise_application_error(-20000, 'You must delete all cases of workflow '''||drop_workflow.workflow_key||''' before dropping the workflow definition.'); + end if; + + /* Delete all the auxillary stuff */ + delete from wf_context_task_panels where workflow_key = drop_workflow.workflow_key; + delete from wf_context_assignments where workflow_key = drop_workflow.workflow_key; + delete from wf_context_role_info where workflow_key = drop_workflow.workflow_key; + delete from wf_context_transition_info where workflow_key = drop_workflow.workflow_key; + delete from wf_context_workflow_info where workflow_key = drop_workflow.workflow_key; + delete from wf_arcs where workflow_key = drop_workflow.workflow_key; + delete from wf_places where workflow_key = drop_workflow.workflow_key; + delete from wf_transition_role_assign_map where workflow_key = drop_workflow.workflow_key; + delete from wf_transitions where workflow_key = drop_workflow.workflow_key; + delete from wf_roles where workflow_key = drop_workflow.workflow_key; + + /* Drop all attributes */ + for attribute_rec in attribute_cur loop + /* there's no on delete cascade, so we have to manually delete all the values */ + delete from acs_attribute_values where attribute_id = attribute_rec.attribute_id; + + drop_attribute( + workflow_key => drop_workflow.workflow_key, + attribute_name => attribute_rec.attribute_name + ); + end loop; + + /* Delete the workflow */ + delete from wf_workflows where workflow_key = drop_workflow.workflow_key; + + acs_object_type.drop_type( + object_type => drop_workflow.workflow_key + ); + end drop_workflow; + + + procedure delete_cases ( + workflow_key in varchar2 + ) + is + cursor workflow_cases is select case_id from wf_cases where workflow_key = delete_cases.workflow_key; + begin + for case_rec in workflow_cases loop + workflow_case.delete(case_rec.case_id); + end loop; + end delete_cases; + + + function create_attribute ( + workflow_key in varchar2, + attribute_name in varchar2, + datatype in varchar2, + pretty_name in varchar2, + pretty_plural in varchar2 default null, + table_name in varchar2 default null, + column_name in varchar2 default null, + default_value in varchar2 default null, + min_n_values in integer default 1, + max_n_values in integer default 1, + sort_order in integer default null, + storage in varchar2 default 'generic' + ) return acs_attributes.attribute_id%TYPE + is + v_attribute_id number; + begin + v_attribute_id := acs_attribute.create_attribute( + object_type => create_attribute.workflow_key, + attribute_name => create_attribute.attribute_name, + datatype => create_attribute.datatype, + pretty_name => create_attribute.pretty_name, + pretty_plural => create_attribute.pretty_plural, + table_name => create_attribute.table_name, + column_name => create_attribute.column_name, + default_value => create_attribute.default_value, + min_n_values => create_attribute.min_n_values, + max_n_values => create_attribute.max_n_values, + sort_order => create_attribute.sort_order, + storage => create_attribute.storage + ); + + return v_attribute_id; + end create_attribute; + + + procedure drop_attribute ( + workflow_key in varchar2, + attribute_name in varchar2 + ) + is + v_attribute_id number; + begin + select attribute_id into v_attribute_id + from acs_attributes + where object_type = drop_attribute.workflow_key + and attribute_name = drop_attribute.attribute_name; + + acs_attribute.drop_attribute( + object_type => drop_attribute.workflow_key, + attribute_name => drop_attribute.attribute_name + ); + end drop_attribute; + + + procedure add_place ( + workflow_key in acs_object_types.object_type%TYPE, + place_key in wf_places.place_key%TYPE, + place_name in wf_places.place_name%TYPE, + sort_order in wf_places.sort_order%TYPE default null + ) + is + v_sort_order wf_places.sort_order%TYPE; + begin + if add_place.sort_order is null then + select nvl(max(sort_order)+1, 1) + into v_sort_order + from wf_places + where workflow_key = add_place.workflow_key; + else + v_sort_order := add_place.sort_order; + end if; + insert into wf_places (workflow_key, place_key, place_name, sort_order) + values (add_place.workflow_key, add_place.place_key, add_place.place_name, v_sort_order); + end add_place; + + procedure delete_place ( + workflow_key in acs_object_types.object_type%TYPE, + place_key in wf_places.place_key%TYPE + ) + is + begin + delete from wf_places + where workflow_key = delete_place.workflow_key + and place_key = delete_place.place_key; + end delete_place; + + procedure add_role ( + workflow_key in acs_object_types.object_type%TYPE, + role_key in wf_roles.role_key%TYPE, + role_name in wf_roles.role_name%TYPE, + sort_order in wf_roles.sort_order%TYPE default null + ) + is + v_sort_order wf_roles.sort_order%TYPE; + begin + if add_role.sort_order is null then + select nvl(max(sort_order)+1, 1) + into v_sort_order + from wf_roles + where workflow_key = add_role.workflow_key; + else + v_sort_order := add_role.sort_order; + end if; + insert into wf_roles ( + workflow_key, role_key, role_name, sort_order + ) values ( + add_role.workflow_key, add_role.role_key, add_role.role_name, v_sort_order + ); + end add_role; + + procedure move_role_up( + workflow_key in acs_object_types.object_type%TYPE, + role_key in wf_roles.role_key%TYPE + ) + is + v_this_sort_order wf_roles.sort_order%TYPE; + v_prior_sort_order wf_roles.sort_order%TYPE; + cursor c_prior_sort_order is + select max(sort_order) + from wf_roles + where workflow_key = move_role_up.workflow_key + and sort_order < v_this_sort_order; + begin + select sort_order + into v_this_sort_order + from wf_roles + where workflow_key = move_role_up.workflow_key + and role_key = move_role_up.role_key; + + open c_prior_sort_order; + fetch c_prior_sort_order into v_prior_sort_order; + if c_prior_sort_order%NOTFOUND then + /* already at top of sort order */ + return; + end if; + + /* switch the sort orders around */ + update wf_roles + set sort_order = decode(role_key, move_role_up.role_key, v_prior_sort_order, v_this_sort_order) + where workflow_key = move_role_up.workflow_key + and sort_order in (v_this_sort_order, v_prior_sort_order); + end move_role_up; + + procedure move_role_down( + workflow_key in acs_object_types.object_type%TYPE, + role_key in wf_roles.role_key%TYPE + ) + is + v_this_sort_order wf_roles.sort_order%TYPE; + v_next_sort_order wf_roles.sort_order%TYPE; + cursor c_next_sort_order is + select min(sort_order) + from wf_roles + where workflow_key = move_role_down.workflow_key + and sort_order > v_this_sort_order; + begin + select sort_order + into v_this_sort_order + from wf_roles + where workflow_key = move_role_down.workflow_key + and role_key = move_role_down.role_key; + + open c_next_sort_order; + fetch c_next_sort_order into v_next_sort_order; + if c_next_sort_order%NOTFOUND then + /* already at bottom of sort order */ + return; + end if; + + /* switch the sort orders around */ + update wf_roles + set sort_order = decode(role_key, move_role_down.role_key, v_next_sort_order, v_this_sort_order) + where workflow_key = move_role_down.workflow_key + and sort_order in (v_this_sort_order, v_next_sort_order); + end move_role_down; + + procedure delete_role ( + workflow_key in acs_object_types.object_type%TYPE, + role_key in wf_roles.role_key%TYPE + ) + is + begin + /* First, remove all references to this role from transitions */ + update wf_transitions + set role_key = null + where workflow_key = delete_role.workflow_key + and role_key = delete_role.role_key; + + delete from wf_roles + where workflow_key = delete_role.workflow_key + and role_key = delete_role.role_key; + end delete_role; + + procedure add_transition ( + workflow_key in acs_object_types.object_type%TYPE, + transition_key in wf_transitions.transition_key%TYPE, + transition_name in wf_transitions.transition_name%TYPE, + role_key in wf_roles.role_key%TYPE default null, + sort_order in wf_transitions.sort_order%TYPE default null, + trigger_type in wf_transitions.trigger_type%TYPE default 'user' + ) + is + v_sort_order wf_transitions.sort_order%TYPE; + begin + if add_transition.sort_order is null then + select nvl(max(sort_order)+1, 1) + into v_sort_order + from wf_transitions + where workflow_key = add_transition.workflow_key; + else + v_sort_order := add_transition.sort_order; + end if; + insert into wf_transitions ( + workflow_key, + transition_key, + transition_name, + role_key, + sort_order, + trigger_type + ) values ( + add_transition.workflow_key, + add_transition.transition_key, + add_transition.transition_name, + add_transition.role_key, + v_sort_order, + add_transition.trigger_type + ); + end add_transition; + + procedure delete_transition ( + workflow_key in acs_object_types.object_type%TYPE, + transition_key in wf_transitions.transition_key%TYPE + ) + is + begin + delete from wf_transitions + where workflow_key = delete_transition.workflow_key + and transition_key = delete_transition.transition_key; + end delete_transition; + + procedure add_arc ( + workflow_key in acs_object_types.object_type%TYPE, + transition_key in wf_arcs.transition_key%TYPE, + place_key in wf_arcs.place_key%TYPE, + direction in wf_arcs.direction%TYPE, + guard_callback in wf_arcs.guard_callback%TYPE default null, + guard_custom_arg in wf_arcs.guard_custom_arg%TYPE default null, + guard_description in wf_arcs.guard_description%TYPE default null + ) + is + begin + insert into wf_arcs (workflow_key, transition_key, place_key, direction, + guard_callback, guard_custom_arg, guard_description) + values (add_arc.workflow_key, add_arc.transition_key, add_arc.place_key, add_arc.direction, + add_arc.guard_callback, add_arc.guard_custom_arg, add_arc.guard_description); + end add_arc; + + procedure add_arc ( + workflow_key in acs_object_types.object_type%TYPE, + from_transition_key in wf_arcs.transition_key%TYPE, + to_place_key in wf_arcs.place_key%TYPE, + guard_callback in wf_arcs.guard_callback%TYPE default null, + guard_custom_arg in wf_arcs.guard_custom_arg%TYPE default null, + guard_description in wf_arcs.guard_description%TYPE default null + ) + is + begin + add_arc( + workflow_key => add_arc.workflow_key, + transition_key => add_arc.from_transition_key, + place_key => add_arc.to_place_key, + direction => 'out', + guard_callback => add_arc.guard_callback, + guard_custom_arg => add_arc.guard_custom_arg, + guard_description => add_arc.guard_description + ); + end add_arc; + + procedure add_arc ( + workflow_key in acs_object_types.object_type%TYPE, + from_place_key in wf_arcs.place_key%TYPE, + to_transition_key in wf_arcs.transition_key%TYPE + ) + is + begin + add_arc( + workflow_key => add_arc.workflow_key, + place_key => add_arc.from_place_key, + transition_key => add_arc.to_transition_key, + direction => 'in' + ); + end add_arc; + + procedure delete_arc ( + workflow_key in acs_object_types.object_type%TYPE, + transition_key in wf_arcs.transition_key%TYPE, + place_key in wf_arcs.place_key%TYPE, + direction in wf_arcs.direction%TYPE + ) + is + begin + delete from wf_arcs + where workflow_key = delete_arc.workflow_key + and transition_key = delete_arc.transition_key + and place_key = delete_arc.place_key + and direction = delete_arc.direction; + end delete_arc; + + procedure add_trans_attribute_map( + workflow_key in wf_workflows.workflow_key%TYPE, + transition_key in wf_transitions.transition_key%TYPE, + attribute_id in acs_attributes.attribute_id%TYPE, + sort_order in wf_transition_attribute_map.sort_order%TYPE default null + ) + is + v_num_rows integer; + v_sort_order wf_transition_attribute_map.sort_order%TYPE; + begin + select count(*) + into v_num_rows + from wf_transition_attribute_map + where workflow_key = add_trans_attribute_map.workflow_key + and transition_key = add_trans_attribute_map.transition_key + and attribute_id = add_trans_attribute_map.attribute_id; + + if v_num_rows > 0 then + return; + end if; + if add_trans_attribute_map.sort_order is null then + select nvl(max(sort_order)+1, 1) + into v_sort_order + from wf_transition_attribute_map + where workflow_key = add_trans_attribute_map.workflow_key + and transition_key = add_trans_attribute_map.transition_key; + else + v_sort_order := add_trans_attribute_map.sort_order; + end if; + insert into wf_transition_attribute_map ( + workflow_key, + transition_key, + attribute_id, + sort_order + ) values ( + add_trans_attribute_map.workflow_key, + add_trans_attribute_map.transition_key, + add_trans_attribute_map.attribute_id, + v_sort_order + ); + end add_trans_attribute_map; + + procedure add_trans_attribute_map( + workflow_key in wf_workflows.workflow_key%TYPE, + transition_key in wf_transitions.transition_key%TYPE, + attribute_name in acs_attributes.attribute_name%TYPE, + sort_order in wf_transition_attribute_map.sort_order%TYPE default null + ) + is + v_attribute_id integer; + begin + select attribute_id + into v_attribute_id + from acs_attributes + where object_type = add_trans_attribute_map.workflow_key + and attribute_name = add_trans_attribute_map.attribute_name; + + add_trans_attribute_map( + workflow_key => add_trans_attribute_map.workflow_key, + transition_key => add_trans_attribute_map.transition_key, + attribute_id => v_attribute_id, + sort_order => add_trans_attribute_map.sort_order + ); + end add_trans_attribute_map; + + procedure delete_trans_attribute_map( + workflow_key in wf_workflows.workflow_key%TYPE, + transition_key in wf_transitions.transition_key%TYPE, + attribute_id in acs_attributes.attribute_id%TYPE + ) + is + begin + delete + from wf_transition_attribute_map + where workflow_key = delete_trans_attribute_map.workflow_key + and transition_key = delete_trans_attribute_map.transition_key + and attribute_id = delete_trans_attribute_map.attribute_id; + end delete_trans_attribute_map; + + procedure delete_trans_attribute_map( + workflow_key in wf_workflows.workflow_key%TYPE, + transition_key in wf_transitions.transition_key%TYPE, + attribute_name in acs_attributes.attribute_id%TYPE + ) + is + v_attribute_id integer; + begin + select attribute_id + into v_attribute_id + from acs_attributes + where object_type = delete_trans_attribute_map.workflow_key + and attribute_name = delete_trans_attribute_map.attribute_name; + + delete + from wf_transition_attribute_map + where workflow_key = delete_trans_attribute_map.workflow_key + and transition_key = delete_trans_attribute_map.transition_key + and attribute_id = v_attribute_id; + end delete_trans_attribute_map; + + procedure add_trans_role_assign_map( + workflow_key in wf_workflows.workflow_key%TYPE, + transition_key in wf_transitions.transition_key%TYPE, + assign_role_key in wf_roles.role_key%TYPE + ) + is + v_num_rows integer; + begin + select count(*) + into v_num_rows + from wf_transition_role_assign_map + where workflow_key = add_trans_role_assign_map.workflow_key + and transition_key = add_trans_role_assign_map.transition_key + and assign_role_key = add_trans_role_assign_map.assign_role_key; + + if v_num_rows = 0 then + insert into wf_transition_role_assign_map ( + workflow_key, + transition_key, + assign_role_key + ) values ( + add_trans_role_assign_map.workflow_key, + add_trans_role_assign_map.transition_key, + add_trans_role_assign_map.assign_role_key + ); + end if; + end add_trans_role_assign_map; + + procedure delete_trans_role_assign_map( + workflow_key in wf_workflows.workflow_key%TYPE, + transition_key in wf_transitions.transition_key%TYPE, + assign_role_key in wf_roles.role_key%TYPE + ) + is + begin + delete + from wf_transition_role_assign_map + where workflow_key = delete_trans_role_assign_map.workflow_key + and transition_key = delete_trans_role_assign_map.transition_key + and assign_role_key = delete_trans_role_assign_map.assign_role_key; + end delete_trans_role_assign_map; + + + function simple_p ( + workflow_key in varchar2 + ) + return char + is + type t_place_table is table of wf_places.place_key%TYPE + index by binary_integer; + type t_guard_table is table of wf_arcs.guard_callback%TYPE + index by binary_integer; + + previous_place_list t_place_table; + target_place_list t_place_table; + guard_list t_guard_table; + row_count integer := 0; + v_count integer; + v_count2 integer; + v_place_key wf_places.place_key%TYPE; + v_end_place wf_places.place_key%TYPE; + v_transition_key wf_transitions.transition_key%TYPE; + + cursor transition_targets is + select place_key,guard_callback,rownum + from wf_arcs + where workflow_key = simple_p.workflow_key + and transition_key = v_transition_key + and direction = 'out'; + + begin + /* Let's do some simple checks first */ + + /* Places with more than one arc out */ + select count(*) into v_count + from wf_places p + where p.workflow_key = simple_p.workflow_key + and 1 < (select count(*) + from wf_arcs a + where a.workflow_key = p.workflow_key + and a.place_key = p.place_key + and direction = 'in'); + + if v_count > 0 then + return 'f'; + end if; + + /* Transitions with more than one arc in */ + select count(*) into v_count + from wf_transitions t + where t.workflow_key = simple_p.workflow_key + and 1 < (select count(*) + from wf_arcs a + where a.workflow_key = t.workflow_key + and a.transition_key = t.transition_key + and direction = 'in'); + + if v_count > 0 then + return 'f'; + end if; + + /* Transitions with more than two arcs out */ + select count(*) into v_count + from wf_transitions t + where t.workflow_key = simple_p.workflow_key + and 2 < (select count(*) + from wf_arcs a + where a.workflow_key = t.workflow_key + and a.transition_key = t.transition_key + and direction = 'out'); + + if v_count > 0 then + return 'f'; + end if; + + /* Now we do the more complicated checks. + * We keep a list of visited places because I couldn't think + * of a nicer way that wasn't susceptable to infinite loops. + */ + + + v_place_key := 'start'; + v_end_place := 'end'; + + loop + exit when v_place_key = v_end_place; + + previous_place_list(row_count) := v_place_key; + + select unique transition_key into v_transition_key + from wf_arcs + where workflow_key = simple_p.workflow_key + and place_key = v_place_key + and direction = 'in'; + + select count(*) into v_count + from wf_arcs + where workflow_key = simple_p.workflow_key + and transition_key = v_transition_key + and direction = 'out'; + + if v_count = 1 then + select unique place_key into v_place_key + from wf_arcs + where workflow_key = simple_p.workflow_key + and transition_key = v_transition_key + and direction = 'out'; + + elsif v_count = 0 then + /* deadend! */ + return 'f'; + + else + /* better be two based on our earlier test */ + + for v_target in transition_targets loop + target_place_list(v_target.rownum) := v_target.place_key; + guard_list(v_target.rownum) := v_target.guard_callback; + end loop; + + /* Check that the guard functions are the negation of each other + * by looking for the magic entry "#" (exactly once) + */ + if ((guard_list(1) != '#' and guard_list(2) != '#') or + (guard_list(1) = '#' and guard_list(2) = '#')) then + return 'f'; + end if; + + /* Check that exactly one of the targets is in the previous list */ + + v_count2 := 0; + for i in 0..row_count loop + if target_place_list(1) = previous_place_list(i) then + v_count2 := v_count2 + 1; + v_place_key := target_place_list(2); + end if; + if target_place_list(2) = previous_place_list(i) then + v_count2 := v_count2 + 1; + v_place_key := target_place_list(1); + end if; + end loop; + + if v_count2 != 1 then + return 'f'; + end if; + + end if; + + row_count := row_count + 1; + + end loop; + + /* if we got here, it must be okay */ + return 't'; + + end simple_p; + +end workflow; +/ +show errors Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/workflow-package-head.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/workflow-package-head.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/workflow-package-head.sql 19 Nov 2001 18:17:46 -0000 1.1 @@ -0,0 +1,186 @@ +-- +-- acs-workflow/sql/workflow-package-head.sql +-- +-- Creates the PL/SQL package that provides the API for defining and dropping +-- workflow cases. +-- +-- @author Lars Pind (lars@pinds.com) +-- +-- @creation-date 2000-05-18 +-- +-- @cvs-id $Id: workflow-package-head.sql,v 1.1 2001/11/19 18:17:46 neophytosd Exp $ +-- + +create or replace package workflow +as + + /* Call this function after you have created a table */ + function create_workflow ( + workflow_key in varchar2, + pretty_name in varchar2, + pretty_plural in varchar2 default null, + description in varchar2 default null, + table_name in varchar2, + id_column in varchar2 default 'case_id' + ) return varchar2; + + procedure drop_workflow ( + workflow_key in varchar2 + ); + + procedure delete_cases ( + workflow_key in varchar2 + ); + + function create_attribute ( + workflow_key in varchar2, + attribute_name in varchar2, + datatype in varchar2, + pretty_name in varchar2, + pretty_plural in varchar2 default null, + table_name in varchar2 default null, + column_name in varchar2 default null, + default_value in varchar2 default null, + min_n_values in integer default 1, + max_n_values in integer default 1, + sort_order in integer default null, + storage in varchar2 default 'generic' + ) return acs_attributes.attribute_id%TYPE; + + procedure drop_attribute ( + workflow_key in varchar2, + attribute_name in varchar2 + ); + + procedure add_place ( + workflow_key in acs_object_types.object_type%TYPE, + place_key in wf_places.place_key%TYPE, + place_name in wf_places.place_name%TYPE, + sort_order in wf_places.sort_order%TYPE default null + ); + + procedure delete_place ( + workflow_key in acs_object_types.object_type%TYPE, + place_key in wf_places.place_key%TYPE + ); + + procedure add_role ( + workflow_key in acs_object_types.object_type%TYPE, + role_key in wf_roles.role_key%TYPE, + role_name in wf_roles.role_name%TYPE, + sort_order in wf_roles.sort_order%TYPE default null + ); + + procedure move_role_up( + workflow_key in acs_object_types.object_type%TYPE, + role_key in wf_roles.role_key%TYPE + ); + + procedure move_role_down( + workflow_key in acs_object_types.object_type%TYPE, + role_key in wf_roles.role_key%TYPE + ); + + procedure delete_role ( + workflow_key in acs_object_types.object_type%TYPE, + role_key in wf_roles.role_key%TYPE + ); + + procedure add_transition ( + workflow_key in acs_object_types.object_type%TYPE, + transition_key in wf_transitions.transition_key%TYPE, + transition_name in wf_transitions.transition_name%TYPE, + role_key in wf_roles.role_key%TYPE default null, + sort_order in wf_transitions.sort_order%TYPE default null, + trigger_type in wf_transitions.trigger_type%TYPE default 'user' + ); + + procedure delete_transition ( + workflow_key in acs_object_types.object_type%TYPE, + transition_key in wf_transitions.transition_key%TYPE + ); + + procedure add_arc ( + workflow_key in acs_object_types.object_type%TYPE, + transition_key in wf_arcs.transition_key%TYPE, + place_key in wf_arcs.place_key%TYPE, + direction in wf_arcs.direction%TYPE, + guard_callback in wf_arcs.guard_callback%TYPE default null, + guard_custom_arg in wf_arcs.guard_custom_arg%TYPE default null, + guard_description in wf_arcs.guard_description%TYPE default null + ); + + procedure add_arc ( + workflow_key in acs_object_types.object_type%TYPE, + from_transition_key in wf_arcs.transition_key%TYPE, + to_place_key in wf_arcs.place_key%TYPE, + guard_callback in wf_arcs.guard_callback%TYPE default null, + guard_custom_arg in wf_arcs.guard_custom_arg%TYPE default null, + guard_description in wf_arcs.guard_description%TYPE default null + ); + + procedure add_arc ( + workflow_key in acs_object_types.object_type%TYPE, + from_place_key in wf_arcs.place_key%TYPE, + to_transition_key in wf_arcs.transition_key%TYPE + ); + + procedure delete_arc ( + workflow_key in acs_object_types.object_type%TYPE, + transition_key in wf_arcs.transition_key%TYPE, + place_key in wf_arcs.place_key%TYPE, + direction in wf_arcs.direction%TYPE + ); + + procedure add_trans_attribute_map( + workflow_key in wf_workflows.workflow_key%TYPE, + transition_key in wf_transitions.transition_key%TYPE, + attribute_id in acs_attributes.attribute_id%TYPE, + sort_order in wf_transition_attribute_map.sort_order%TYPE default null + ); + + procedure add_trans_attribute_map( + workflow_key in wf_workflows.workflow_key%TYPE, + transition_key in wf_transitions.transition_key%TYPE, + attribute_name in acs_attributes.attribute_name%TYPE, + sort_order in wf_transition_attribute_map.sort_order%TYPE default null + ); + + procedure delete_trans_attribute_map( + workflow_key in wf_workflows.workflow_key%TYPE, + transition_key in wf_transitions.transition_key%TYPE, + attribute_id in acs_attributes.attribute_id%TYPE + ); + + procedure add_trans_role_assign_map( + workflow_key in wf_workflows.workflow_key%TYPE, + transition_key in wf_transitions.transition_key%TYPE, + assign_role_key in wf_roles.role_key%TYPE + ); + + procedure delete_trans_role_assign_map( + workflow_key in wf_workflows.workflow_key%TYPE, + transition_key in wf_transitions.transition_key%TYPE, + assign_role_key in wf_roles.role_key%TYPE + ); + + /* + * A simple workflow is essentially one that we can display nicely using HTML tables. + * More specifically, it's a workflow containing only sequential routing and + * simple iteration, where the choice is always between moving to the next task + * in the sequence or looping back to some prior task. + */ + + function simple_p ( + workflow_key in varchar2 + ) return char; + +end workflow; +/ +show errors + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/workflow-package.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/workflow-package.sql,v diff -u -r1.1 -r1.2 --- openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/workflow-package.sql 5 Apr 2001 18:23:38 -0000 1.1 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/workflow-package.sql 19 Nov 2001 18:17:46 -0000 1.2 @@ -1,6 +1,6 @@ - -- --- acs-workflow/sql/workflow-package.sql -- +-- acs-workflow/sql/workflow-package-head.sql +-- -- Creates the PL/SQL package that provides the API for defining and dropping -- workflow cases. -- @@ -11,522 +11,5 @@ -- @cvs-id $Id$ -- - -create or replace package workflow -as - - /* Call this function after you have created a table */ - function create_workflow ( - workflow_key in varchar2, - pretty_name in varchar2, - pretty_plural in varchar2 default null, - description in varchar2 default null, - table_name in varchar2, - id_column in varchar2 default 'case_id' - ) return varchar2; - - procedure drop_workflow ( - workflow_key in varchar2 - ); - - procedure delete_cases ( - workflow_key in varchar2 - ); - - function create_attribute ( - workflow_key in varchar2, - attribute_name in varchar2, - datatype in varchar2, - pretty_name in varchar2, - pretty_plural in varchar2 default null, - table_name in varchar2 default null, - column_name in varchar2 default null, - default_value in varchar2 default null, - min_n_values in integer default 1, - max_n_values in integer default 1, - sort_order in integer default null, - storage in varchar2 default 'generic', - wf_datatype in varchar2 default 'none' - ) return acs_attributes.attribute_id%TYPE; - - procedure drop_attribute ( - workflow_key in varchar2, - attribute_name in varchar2 - ); - - procedure add_place ( - workflow_key in acs_object_types.object_type%TYPE, - place_key in wf_places.place_key%TYPE, - place_name in wf_places.place_name%TYPE, - sort_order in wf_places.sort_order%TYPE - ); - - procedure delete_place ( - workflow_key in acs_object_types.object_type%TYPE, - place_key in wf_places.place_key%TYPE - ); - - procedure add_transition ( - workflow_key in acs_object_types.object_type%TYPE, - transition_key in wf_transitions.transition_key%TYPE, - transition_name in wf_transitions.transition_name%TYPE, - sort_order in wf_transitions.sort_order%TYPE, - trigger_type in wf_transitions.trigger_type%TYPE default 'user' - ); - - procedure delete_transition ( - workflow_key in acs_object_types.object_type%TYPE, - transition_key in wf_transitions.transition_key%TYPE - ); - - procedure add_arc ( - workflow_key in acs_object_types.object_type%TYPE, - transition_key in wf_arcs.transition_key%TYPE, - place_key in wf_arcs.place_key%TYPE, - direction in wf_arcs.direction%TYPE, - guard_callback in wf_arcs.guard_callback%TYPE default null, - guard_custom_arg in wf_arcs.guard_custom_arg%TYPE default null, - guard_description in wf_arcs.guard_description%TYPE default null - ); - - procedure delete_arc ( - workflow_key in acs_object_types.object_type%TYPE, - transition_key in wf_arcs.transition_key%TYPE, - place_key in wf_arcs.place_key%TYPE, - direction in wf_arcs.direction%TYPE - ); - - /* - * A simple workflow is essentially one that we can display nicely using HTML tables. - * More specifically, it's a workflow containing only sequential routing and - * simple iteration, where the choice is always between moving to the next task - * in the sequence or looping back to some prior task. - */ - - function simple_p ( - workflow_key in varchar2 - ) return char; - -end workflow; -/ -show errors - -create or replace package body workflow -as - - function create_workflow ( - workflow_key in varchar2, - pretty_name in varchar2, - pretty_plural in varchar2 default null, - description in varchar2 default null, - table_name in varchar2, - id_column in varchar2 default 'case_id' - ) - return varchar2 - is - v_num_rows number; - v_workflow_key varchar2(100); - begin - select count(*) into v_num_rows from user_tables where table_name = upper(create_workflow.table_name); - if v_num_rows = 0 then - raise_application_error(-20000, 'The table '''||create_workflow.table_name||''' must be created before calling workflow.create_workflow.'); - end if; - - if substr(create_workflow.workflow_key, length(create_workflow.workflow_key) - 2, 3) != '_wf' then - v_workflow_key := create_workflow.workflow_key||'_wf'; - else - v_workflow_key := create_workflow.workflow_key; - end if; - - acs_object_type.create_type( - object_type => v_workflow_key, - pretty_name => create_workflow.pretty_name, - pretty_plural => create_workflow.pretty_plural, - supertype => 'workflow', - table_name => create_workflow.table_name, - id_column => create_workflow.id_column - ); - - insert into wf_workflows - (workflow_key, description) - values - (v_workflow_key, create_workflow.description); - - return v_workflow_key; - end create_workflow; - - - /* Note: The workflow-specific cases table must be dropped before calling this proc */ - procedure drop_workflow ( - workflow_key in varchar2 - ) - is - v_table_name varchar2(100); - v_num_rows number; - cursor attribute_cur is - select attribute_id, attribute_name from acs_attributes where object_type = drop_workflow.workflow_key; - begin - select table_name into v_table_name - from acs_object_types - where object_type = drop_workflow.workflow_key; - - select decode(count(*),0,0,1) into v_num_rows - from user_tables - where table_name = upper(v_table_name); - - if v_num_rows > 0 then - raise_application_error(-20000, 'The table '''||v_table_name||''' must be dropped before calling workflow.drop_workflow.'); - end if; - - select decode(count(*),0,0,1) into v_num_rows - from wf_cases - where workflow_key = drop_workflow.workflow_key; - - if v_num_rows > 0 then - raise_application_error(-20000, 'You must delete all cases of workflow '''||drop_workflow.workflow_key||''' before dropping the workflow definition.'); - end if; - - /* Delete all the auxillary stuff */ - delete from wf_context_task_panels where workflow_key = drop_workflow.workflow_key; - delete from wf_context_assignments where workflow_key = drop_workflow.workflow_key; - delete from wf_context_transition_info where workflow_key = drop_workflow.workflow_key; - delete from wf_arcs where workflow_key = drop_workflow.workflow_key; - delete from wf_places where workflow_key = drop_workflow.workflow_key; - delete from wf_transition_attribute_map where workflow_key = drop_workflow.workflow_key; - delete from wf_transition_assignment_map where workflow_key = drop_workflow.workflow_key; - delete from wf_transitions where workflow_key = drop_workflow.workflow_key; - - /* Drop all attributes */ - for attribute_rec in attribute_cur loop - /* there's no on delete cascade, so we have to manually delete all the values */ - delete from acs_attribute_values where attribute_id = attribute_rec.attribute_id; - - drop_attribute( - workflow_key => drop_workflow.workflow_key, - attribute_name => attribute_rec.attribute_name - ); - end loop; - - /* Delete the workflow */ - delete from wf_workflows where workflow_key = drop_workflow.workflow_key; - - acs_object_type.drop_type( - object_type => drop_workflow.workflow_key - ); - end drop_workflow; - - - procedure delete_cases ( - workflow_key in varchar2 - ) - is - cursor workflow_cases is select case_id from wf_cases where workflow_key = delete_cases.workflow_key; - begin - for case_rec in workflow_cases loop - workflow_case.delete(case_rec.case_id); - end loop; - end delete_cases; - - - function create_attribute ( - workflow_key in varchar2, - attribute_name in varchar2, - datatype in varchar2, - pretty_name in varchar2, - pretty_plural in varchar2 default null, - table_name in varchar2 default null, - column_name in varchar2 default null, - default_value in varchar2 default null, - min_n_values in integer default 1, - max_n_values in integer default 1, - sort_order in integer default null, - storage in varchar2 default 'generic', - wf_datatype in varchar2 default 'none' - ) return acs_attributes.attribute_id%TYPE - is - v_attribute_id number; - begin - v_attribute_id := acs_attribute.create_attribute( - object_type => create_attribute.workflow_key, - attribute_name => create_attribute.attribute_name, - datatype => create_attribute.datatype, - pretty_name => create_attribute.pretty_name, - pretty_plural => create_attribute.pretty_plural, - table_name => create_attribute.table_name, - column_name => create_attribute.column_name, - default_value => create_attribute.default_value, - min_n_values => create_attribute.min_n_values, - max_n_values => create_attribute.max_n_values, - sort_order => create_attribute.sort_order, - storage => create_attribute.storage - ); - - insert into wf_attribute_info - (attribute_id, wf_datatype) - values - (v_attribute_id, create_attribute.wf_datatype); - - return v_attribute_id; - end create_attribute; - - - procedure drop_attribute ( - workflow_key in varchar2, - attribute_name in varchar2 - ) - is - v_attribute_id number; - begin - select attribute_id into v_attribute_id - from acs_attributes - where object_type = drop_attribute.workflow_key - and attribute_name = drop_attribute.attribute_name; - - delete from wf_attribute_info where attribute_id = v_attribute_id; - - acs_attribute.drop_attribute( - object_type => drop_attribute.workflow_key, - attribute_name => drop_attribute.attribute_name - ); - end drop_attribute; - - - procedure add_place ( - workflow_key in acs_object_types.object_type%TYPE, - place_key in wf_places.place_key%TYPE, - place_name in wf_places.place_name%TYPE, - sort_order in wf_places.sort_order%TYPE - ) - is - begin - insert into wf_places (workflow_key, place_key, place_name, sort_order) - values (add_place.workflow_key, add_place.place_key, add_place.place_name, add_place.sort_order); - end add_place; - - procedure delete_place ( - workflow_key in acs_object_types.object_type%TYPE, - place_key in wf_places.place_key%TYPE - ) - is - begin - delete from wf_places - where workflow_key = delete_place.workflow_key - and place_key = delete_place.place_key; - end delete_place; - - procedure add_transition ( - workflow_key in acs_object_types.object_type%TYPE, - transition_key in wf_transitions.transition_key%TYPE, - transition_name in wf_transitions.transition_name%TYPE, - sort_order in wf_transitions.sort_order%TYPE, - trigger_type in wf_transitions.trigger_type%TYPE default 'user' - ) - is - begin - insert into wf_transitions (workflow_key, transition_key, transition_name, sort_order, trigger_type) - values (add_transition.workflow_key, add_transition.transition_key, add_transition.transition_name, - add_transition.sort_order, add_transition.trigger_type); - end add_transition; - - procedure delete_transition ( - workflow_key in acs_object_types.object_type%TYPE, - transition_key in wf_transitions.transition_key%TYPE - ) - is - begin - delete from wf_transitions - where workflow_key = delete_transition.workflow_key - and transition_key = delete_transition.transition_key; - end delete_transition; - - procedure add_arc ( - workflow_key in acs_object_types.object_type%TYPE, - transition_key in wf_arcs.transition_key%TYPE, - place_key in wf_arcs.place_key%TYPE, - direction in wf_arcs.direction%TYPE, - guard_callback in wf_arcs.guard_callback%TYPE default null, - guard_custom_arg in wf_arcs.guard_custom_arg%TYPE default null, - guard_description in wf_arcs.guard_description%TYPE default null - ) - is - begin - insert into wf_arcs (workflow_key, transition_key, place_key, direction, - guard_callback, guard_custom_arg, guard_description) - values (add_arc.workflow_key, add_arc.transition_key, add_arc.place_key, add_arc.direction, - add_arc.guard_callback, add_arc.guard_custom_arg, add_arc.guard_description); - end add_arc; - - procedure delete_arc ( - workflow_key in acs_object_types.object_type%TYPE, - transition_key in wf_arcs.transition_key%TYPE, - place_key in wf_arcs.place_key%TYPE, - direction in wf_arcs.direction%TYPE - ) - is - begin - delete from wf_arcs - where workflow_key = delete_arc.workflow_key - and transition_key = delete_arc.transition_key - and place_key = delete_arc.place_key - and direction = delete_arc.direction; - end delete_arc; - - - - function simple_p ( - workflow_key in varchar2 - ) - return char - is - type t_place_table is table of wf_places.place_key%TYPE - index by binary_integer; - type t_guard_table is table of wf_arcs.guard_callback%TYPE - index by binary_integer; - - previous_place_list t_place_table; - target_place_list t_place_table; - guard_list t_guard_table; - row_count integer := 0; - v_count integer; - v_count2 integer; - v_place_key wf_places.place_key%TYPE; - v_end_place wf_places.place_key%TYPE; - v_transition_key wf_transitions.transition_key%TYPE; - - cursor transition_targets is - select place_key,guard_callback,rownum - from wf_arcs - where workflow_key = simple_p.workflow_key - and transition_key = v_transition_key - and direction = 'out'; - - begin - /* Let's do some simple checks first */ - - /* Places with more than one arc out */ - select count(*) into v_count - from wf_places p - where p.workflow_key = simple_p.workflow_key - and 1 < (select count(*) - from wf_arcs a - where a.workflow_key = p.workflow_key - and a.place_key = p.place_key - and direction = 'in'); - - if v_count > 0 then - return 'f'; - end if; - - /* Transitions with more than one arc in */ - select count(*) into v_count - from wf_transitions t - where t.workflow_key = simple_p.workflow_key - and 1 < (select count(*) - from wf_arcs a - where a.workflow_key = t.workflow_key - and a.transition_key = t.transition_key - and direction = 'in'); - - if v_count > 0 then - return 'f'; - end if; - - /* Transitions with more than two arcs out */ - select count(*) into v_count - from wf_transitions t - where t.workflow_key = simple_p.workflow_key - and 2 < (select count(*) - from wf_arcs a - where a.workflow_key = t.workflow_key - and a.transition_key = t.transition_key - and direction = 'out'); - - if v_count > 0 then - return 'f'; - end if; - - /* Now we do the more complicated checks. - * We keep a list of visited places because I couldn't think - * of a nicer way that wasn't susceptable to infinite loops. - */ - - - v_place_key := 'start'; - v_end_place := 'end'; - - loop - exit when v_place_key = v_end_place; - - previous_place_list(row_count) := v_place_key; - - select unique transition_key into v_transition_key - from wf_arcs - where workflow_key = simple_p.workflow_key - and place_key = v_place_key - and direction = 'in'; - - select count(*) into v_count - from wf_arcs - where workflow_key = simple_p.workflow_key - and transition_key = v_transition_key - and direction = 'out'; - - if v_count = 1 then - select unique place_key into v_place_key - from wf_arcs - where workflow_key = simple_p.workflow_key - and transition_key = v_transition_key - and direction = 'out'; - - elsif v_count = 0 then - /* deadend! */ - return 'f'; - - else - /* better be two based on our earlier test */ - - for v_target in transition_targets loop - target_place_list(v_target.rownum) := v_target.place_key; - guard_list(v_target.rownum) := v_target.guard_callback; - end loop; - - /* Check that the guard functions are the negation of each other - * by looking for the magic entry "#" (exactly once) - */ - if ((guard_list(1) != '#' and guard_list(2) != '#') or - (guard_list(1) = '#' and guard_list(2) = '#')) then - return 'f'; - end if; - - /* Check that exactly one of the targets is in the previous list */ - - v_count2 := 0; - for i in 0..row_count loop - if target_place_list(1) = previous_place_list(i) then - v_count2 := v_count2 + 1; - v_place_key := target_place_list(2); - end if; - if target_place_list(2) = previous_place_list(i) then - v_count2 := v_count2 + 1; - v_place_key := target_place_list(1); - end if; - end loop; - - if v_count2 != 1 then - return 'f'; - end if; - - end if; - - row_count := row_count + 1; - - end loop; - - /* if we got here, it must be okay */ - return 't'; - - end simple_p; - -end workflow; -/ -show errors +@@workflow-package-head.sql +@@workflow-package-body.sql Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/test/workflow-case-package-test.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/test/workflow-case-package-test.sql,v diff -u -r1.4 -r1.5 --- openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/test/workflow-case-package-test.sql 3 Sep 2001 05:28:28 -0000 1.4 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/test/workflow-case-package-test.sql 19 Nov 2001 18:18:38 -0000 1.5 @@ -6,56 +6,8 @@ -- -- exec utplsql.setdir('/web/lars-dev2/packages/acs-kernel/sql'); --- exec utplsql.autocompile (false); -create or replace package utassert -as - procedure eq ( - msg_in in varchar2, - check_this_in in integer, - against_this_in in integer - ); +exec utplsql.autocompile (false); - procedure eq ( - msg_in in varchar2, - check_this_in in varchar2, - against_this_in in varchar2 - ); -end utassert; -/ -show errors; - -create or replace package body utassert -as - - procedure eq ( - msg_in in varchar2, - check_this_in in integer, - against_this_in in integer - ) - is - begin - if check_this_in <> against_this_in then - dbms_output.put_line('ERROR ' || msg_in || ' failed'); - end if; - end eq; - - procedure eq ( - msg_in in varchar2, - check_this_in in varchar2, - against_this_in in varchar2 - ) - is - begin - if check_this_in <> against_this_in then - dbms_output.put_line('ERROR ' || msg_in || ' failed'); - end if; - end eq; - -end utassert; -/ -show errors; - - create or replace package ut#workflow_case as @@ -87,8 +39,8 @@ - -- utplsql.setpkg('workflow_case'); - -- utplsql.addtest('run'); + utplsql.setpkg('workflow_case'); + utplsql.addtest('run'); end; procedure teardown @@ -554,18 +506,11 @@ against_this_in => v_state ); - -- utresult.show; + utresult.show; end; end ut#workflow_case; / show errors --- exec utplsql.test('workflow_case'); - -begin - ut#workflow_case.setup; - ut#workflow_case.run; -end; -/ -show errors +exec utplsql.test('workflow_case'); \ No newline at end of file Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/upgrade/upgrade-4.1b-4.3.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/upgrade/upgrade-4.1b-4.3.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/oracle/upgrade/upgrade-4.1b-4.3.sql 19 Nov 2001 18:19:31 -0000 1.1 @@ -0,0 +1,557 @@ +/* + * We've added support for roles, which is an intermediate step between + * transitions and assignments. A role is a relationship to a process, e.g., + * an editor, publisher, submitter, fixer, doctor, manager, etc. + * A task is performed by a role, but one role may have many tasks to perform. + * The idea is that when you reassign a role, it affects all the tasks that role + * has been assigned to. + * + * For the upgrade, we simply create one role per transtiion, and change + * all the other tables correspondingly. This will execute exactly equivalent + * to the way it would have without the roles refactoring. + * + * We've also added other minor things, such as task instructions and gotten rid + * of wf_attribute_info. + */ + +/* + * NOTE: + * + * After running this script, you must reload the following two PL/SQL packages: + * + * package/acs-workflow/sql/workflow-package.sql + * package/acs-workflow/sql/workflow-case-package.sql + */ + + + + + +/* + * Table wf_roles: + * Added. + */ + +create table wf_roles ( + role_key varchar2(100), + workflow_key varchar2(100) + constraint wf_roles_workflow_fk + references wf_workflows(workflow_key) + on delete cascade, + role_name varchar2(100) + constraint wf_role_role_name_nn + not null, + -- so we can display roles in some logical order -- + sort_order integer + constraint wf_roles_order_ck + check (sort_order > 0), + -- table constraints -- + constraint wf_role_pk + primary key (workflow_key, role_key), + constraint wf_roles_wf_key_role_name_un + unique (workflow_key, role_name) +); + +comment on table wf_roles is ' + A process has certain roles associated with it, such as "submitter", + "reviewer", "editor", "claimant", etc. For each transition, then, you + specify what role is to perform that task. Thus, two or more tasks can be + performed by one and the same role, so that when the role is reassigned, + it reflects assignments of both tasks. Users and parties are then assigned + to roles instead of directly to tasks. +'; + + + +/* + * Now populate the roles table: + * We just create a role per transition, then hook them up + */ + +insert into wf_roles + (workflow_key, + role_key, + role_name, + sort_order) +select workflow_key, transition_key, transition_name, sort_order + from wf_transitions; + + +/* + * Table wf_transitions: + * Added column role_key. + * Added foreign key constraint wf_transition_role_fk. + */ + +alter table wf_transitions add ( + role_key varchar2(100) +); + +alter table wf_transitions add ( + constraint wf_transition_role_fk + foreign key (workflow_key,role_key) references wf_roles(workflow_key,role_key) + /* We don't do on delete cascade here, because that would mean that + * when a role is deleted, the transitions associated with that role would be deleted, too */ +); + +/* Now populate the new column corresponding to the roles we just created: + * Since there's a one-to-one role per transition, and the have the same keys, + * we just set role_key = transition_key + */ + +update wf_transitions + set role_key = transition_key; + +/* + * Table wf_transition_role_assign_map: + * Added. + * This replaces wf_transtiion_assign_map, since transitions now assign + * roles instead of other transitions. + */ + +create table wf_transition_role_assign_map ( + workflow_key varchar2(100) + constraint wf_role_asgn_map_workflow_fk + references wf_workflows(workflow_key) + on delete cascade, + transition_key varchar2(100), + assign_role_key varchar2(100), + -- table constraints -- + constraint wf_role_asgn_map_pk + primary key (workflow_key, transition_key, assign_role_key), + constraint wf_role_asgn_map_trans_fk + foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) + on delete cascade, + constraint wf_tr_role_asgn_map_asgn_fk + foreign key (workflow_key, assign_role_key) references wf_roles(workflow_key, role_key) + on delete cascade +); + +create index wf_role_asgn_map_wf_trans_idx on wf_transition_role_assign_map(workflow_key, transition_key); +create index wf_role_asgn_map_wf_as_tr_idx on wf_transition_role_assign_map(workflow_key, assign_role_key); + +comment on table wf_transition_role_assign_map is ' + When part of the output of one task is to assign users to a role, + specify that this is the case by inserting a row here. +'; + +comment on column wf_transition_role_assign_map.transition_key is ' + transition_key is the assigning transition. +'; + +comment on column wf_transition_role_assign_map.assign_role_key is ' + assign_role_key is the role being assigned a user to. +'; + + +/* Populate new wf_transition_role_assign_map with the rows from + * wf_transition_assignment_map. Since role_key map one-to-one with transition_keys + * in this upgrade, that's pretty straight-forward. + */ + +insert into wf_transition_role_assign_map + (workflow_key, + transition_key, + assign_role_key) +select workflow_key, + transition_key, + assign_transition_key + from wf_transition_assignment_map; + +/* + * Table wf_transition_assignment_map: + * Dropped. + * This table is no longer releavnt, since transitions don't assign other + * transitions, they assign roles. + */ + +drop table wf_transition_assignment_map; + + +/* + * Table wf_attribute_info: + * Dropped. + * This table was a hang-over from earlier versions and is no longer necessary. + */ + +drop table wf_attribute_info; + +/* + * Table wf_context_role_info: + * Added. + */ + +create table wf_context_role_info ( + context_key varchar2(100) + constraint wf_context_role_context_fk + references wf_contexts(context_key) + on delete cascade, + workflow_key varchar2(100) + constraint wf_context_role_workflow_fk + references wf_workflows(workflow_key) + on delete cascade, + role_key varchar2(100), + /* + * Callback to programatically assign a role. + * Must call wordflow_case.*_role_assignment to make the assignments. + * Will be called when a transition for that role becomes enabled + * signature: (role_key in varchar2, custom_arg in varchar2) + */ + assignment_callback varchar2(100), + assignment_custom_arg varchar2(4000), + -- table constraints -- + constraint wf_context_role_role_fk + foreign key (workflow_key, role_key) references wf_roles(workflow_key, role_key) + on delete cascade, + constraint wf_context_role_info_pk + primary key (context_key, workflow_key, role_key) +); + +comment on table wf_context_role_info is ' + This table holds context-dependent info for roles, currently only the assignment callback +'; + + +/* Populate by a straight copy from wf_context_transition_info */ + +insert into wf_context_role_info + (context_key, + workflow_key, + role_key, + assignment_callback, + assignment_custom_arg) +select context_key, + workflow_key, + transition_key, + assignment_callback, + assignment_custom_arg + from wf_context_transition_info + where assignment_callback is not null + or assignment_custom_arg is not null; + +/* + * Table wf_context_transition_info: + * Added column 'instructions'. + */ + +alter table wf_context_transition_info add ( + instructions varchar2(4000) +); + + +/* Removed columns assignment_callback/custom_arg. */ + +alter table wf_context_transition_info + drop column assignment_callback; +alter table wf_context_transition_info + drop column assignment_custom_arg; + +/* Added on delete cascade to columns workflow_key and .context_key */ + +alter table wf_context_transition_info + drop constraint wf_context_trans_context_fk; +alter table wf_context_transition_info + add constraint wf_context_trans_context_fk + foreign key (context_key) references wf_contexts (context_key); + +alter table wf_context_transition_info + drop constraint wf_context_trans_workflow_fk; +alter table wf_context_transition_info + add constraint wf_context_trans_workflow_fk + foreign key (workflow_key) references wf_workflows (workflow_key); + + +/* + * Table wf_context_workflow_info: + * Added. + */ + +create table wf_context_workflow_info ( + context_key varchar2(100) + constraint wf_context_wf_context_fk + references wf_contexts + on delete cascade, + workflow_key varchar2(100) + constraint wf_context_wf_workflow_fk + references wf_workflows + on delete cascade, + /* The principal is the user/party that sends out email assignment notifications + * And receives email when a task becomes unassigned (for more than x minutes?) + */ + principal_party integer + constraint wf_context_wf_principal_fk + references parties + on delete set null, + -- table constraints -- + constraint wf_context_workflow_pk + primary key (context_key, workflow_key) +); + +/* Insert someone for all existing processes. Hopefully this will be the administrator user. */ + +insert into wf_context_workflow_info + (context_key, + workflow_key, + principal_party) +select 'default', workflow_key, (select min(party_id) from parties) + from wf_workflows; + + +/* + * Table wf_context_task_panels: + * Added columns overrides_action_p and only_display_when_started_p + * Renamed column sort_key to sort_order for consistency + */ + +alter table wf_context_task_panels add ( + /* Display this panel in place of the action panel */ + overrides_action_p char(1) default 'f' + constraint wf_context_panels_ovrd_p_ck + check (overrides_action_p in ('t','f')), + /* Display this panel only when the task has been started (and not finished) */ + only_display_when_started_p char(1) default 'f' + constraint wf_context_panels_display_p_ck + check (only_display_when_started_p in ('t','f')), + sort_order integer +); + +/* Copy over the existing sort_key to the new sort_order */ +update wf_context_task_panels + set sort_order = sort_key; + +/* Change the primary key */ +alter table wf_context_task_panels drop constraint wf_context_panels_pk; +alter table wf_context_task_panels add + constraint wf_context_panels_pk + primary key (context_key, workflow_key, transition_key, sort_order); + +/* Drop old sort_key column */ +alter table wf_context_task_panels drop column sort_key; + +alter table wf_context_task_panels add constraint wf_context_sort_order_nn + check (sort_order is not null); + +/* + * Table wf_context_assignments + * Replaced transition_key with role_key + */ + +alter table wf_context_assignments add ( + role_key varchar2(100), + constraint wf_context_assign_role_fk + foreign key (workflow_key, role_key) references wf_roles (workflow_key, role_key) + on delete cascade +); + +alter table wf_context_assignments drop constraint wf_context_assign_trans_fk; + +update wf_context_assignments + set role_key = transition_key; + +alter table wf_context_assignments drop constraint wf_context_assign_pk; +alter table wf_context_assignments add constraint wf_context_assign_pk + primary key (context_key, workflow_key, role_key, party_id); + +alter table wf_context_assignments drop column transition_key; + + +/* + * Table wf_case_assignments: + * Changed transition_key to role_key + */ + +alter table wf_case_assignments add ( + role_key varchar2(100), + constraint wf_case_assign_role_fk + foreign key (workflow_key, role_key) references wf_roles (workflow_key, role_key) + on delete cascade +); + +update wf_case_assignments + set role_key = transition_key; + +alter table wf_case_assignments drop constraint wf_case_assign_pk; +alter table wf_case_assignments add + constraint wf_case_assign_pk + primary key (case_id, role_key, party_id); + +alter table wf_case_assignments drop constraint wf_case_assign_trans_fk; + +alter table wf_case_assignments drop column transition_key; + + + +/* + * View wf_transition_contexts: + * Added column role_key. + */ + +create or replace view wf_transition_contexts as +select t.transition_key, + t.transition_name, + t.workflow_key, + t.sort_order, + t.trigger_type, + t.role_key, + c.context_key, + c.context_name +from wf_transitions t, wf_contexts c; + + + +/* + * View wf_transition_info: + * Added columns role_key and instructions. + * Removed columns assignment_callback/custom_arg. + */ + +create or replace view wf_transition_info as +select t.transition_key, + t.transition_name, + t.workflow_key, + t.sort_order, + t.trigger_type, + t.context_key, + t.role_key, + ct.estimated_minutes, + ct.instructions, + ct.enable_callback, + ct.enable_custom_arg, + ct.fire_callback, + ct.fire_custom_arg, + ct.time_callback, + ct.time_custom_arg, + ct.deadline_callback, + ct.deadline_custom_arg, + ct.deadline_attribute_name, + ct.hold_timeout_callback, + ct.hold_timeout_custom_arg, + ct.notification_callback, + ct.notification_custom_arg, + ct.unassigned_callback, + ct.unassigned_custom_arg +from wf_transition_contexts t, wf_context_transition_info ct +where ct.workflow_key (+) = t.workflow_key + and ct.transition_key (+) = t.transition_key + and ct.context_key (+) = t.context_key; + + +/* + * View wf_role_info: + * Added. + */ + +create or replace view wf_role_info as +select r.role_key, + r.role_name, + r.workflow_key, + c.context_key, + cr.assignment_callback, + cr.assignment_custom_arg +from wf_roles r, wf_contexts c, wf_context_role_info cr +where cr.workflow_key (+) = r.workflow_key + and cr.role_key (+) = r.role_key + and cr.context_key = c.context_key; + + +/* + * View wf_enabled_transitions: + * Added columns role_key and instructions. + * Removed columns assignment_callback/custom_arg. + */ + +create or replace view wf_enabled_transitions as +select c.case_id, + t.transition_key, + t.transition_name, + t.workflow_key, + t.sort_order, + t.trigger_type, + t.context_key, + t.role_key, + t.enable_callback, + t.enable_custom_arg, + t.fire_callback, + t.fire_custom_arg, + t.time_callback, + t.time_custom_arg, + t.deadline_callback, + t.deadline_custom_arg, + t.deadline_attribute_name, + t.hold_timeout_callback, + t.hold_timeout_custom_arg, + t.notification_callback, + t.notification_custom_arg, + t.estimated_minutes, + t.instructions, + t.unassigned_callback, + t.unassigned_custom_arg + from wf_transition_info t, + wf_cases c + where t.workflow_key = c.workflow_key + and t.context_key = c.context_key + and c.state = 'active' + and not exists + (select tp.place_key + from wf_transition_places tp + where tp.transition_key = t.transition_key + and tp.workflow_key = t.workflow_key + and tp.direction = 'in' + and not exists + (select tk.token_id + from wf_tokens tk + where tk.place_key = tp.place_key + and tk.case_id = c.case_id + and tk.state = 'free' + ) + ); + + +/* + * View wf_user_tasks: + * Added column instructions + * Added "and tr.workflow_key = ta.workflow_key" to where clause + * (looks like a bug) + */ + +create or replace view wf_user_tasks as +select distinct ta.task_id, + ta.case_id, + ta.workflow_key, + ta.transition_key, + tr.transition_name, + tr.instructions, + ta.enabled_date, + ta.started_date, + u.user_id, + ta.state, + ta.holding_user, + ta.hold_timeout, + ta.deadline, + ta.estimated_minutes +from wf_tasks ta, + wf_task_assignments tasgn, + wf_cases c, + wf_transition_info tr, + party_approved_member_map m, + users u +where ta.state in ( 'enabled','started') +and c.case_id = ta.case_id +and c.state = 'active' +and tr.transition_key = ta.transition_key +and tr.workflow_key = ta.workflow_key +and tr.trigger_type = 'user' +and tr.context_key = c.context_key +and tasgn.task_id = ta.task_id +and m.party_id = tasgn.party_id +and u.user_id = m.member_id; + + +/* + * NOTE: + * + * You must reload the following two PL/SQL packages now: + * + * package/acs-workflow/sql/workflow-package.sql + * package/acs-workflow/sql/workflow-case-package.sql + */ Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/acs-workflow-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/acs-workflow-create.sql,v diff -u -r1.2 -r1.3 --- openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/acs-workflow-create.sql 13 Apr 2001 00:29:01 -0000 1.2 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/acs-workflow-create.sql 19 Nov 2001 18:20:33 -0000 1.3 @@ -10,11 +10,13 @@ -- @cvs-id $Id$ -- +/* We create two sample processes */ + \i wf-core-create.sql \i workflow-case-package.sql \i workflow-package.sql \i wf-callback-package.sql -- \i jobs-start.sql -\i sample-expenses-create.sql +-- \i sample-expenses-create.sql \i sample-article-create.sql Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/acs-workflow-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/acs-workflow-drop.sql,v diff -u -r1.1 -r1.2 --- openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/acs-workflow-drop.sql 11 Apr 2001 04:55:54 -0000 1.1 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/acs-workflow-drop.sql 19 Nov 2001 18:20:33 -0000 1.2 @@ -11,8 +11,26 @@ -- -\i jobs-kill.sql +--\i jobs-kill.sql +\i sample-article-drop.sql \i wf-core-drop.sql + + +drop function __workflow__simple_p (varchar,integer); +drop table guard_list; +drop table target_place_list; +drop table previous_place_list; +drop sequence workflow_session_id; +drop function sweep_hold_timeout (); +drop function sweep_timed_transitions (); + select drop_package('wf_callback'); select drop_package('workflow'); select drop_package('workflow_case'); + + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/sample-article-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/sample-article-create.sql,v diff -u -r1.8 -r1.9 --- openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/sample-article-create.sql 16 Oct 2001 02:34:21 -0000 1.8 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/sample-article-create.sql 19 Nov 2001 18:20:33 -0000 1.9 @@ -17,91 +17,194 @@ references wf_cases on delete cascade ); - create function inline_0 () returns integer as ' declare - v_workflow_key varchar(40); + v_workflow_key wf_workflows.workflow_key%TYPE; + v_attribute_id acs_attributes.attribute_id%TYPE; begin v_workflow_key := workflow__create_workflow( - ''article_wf'', - ''Article Publication'', - ''Article Publications'', - ''Workflow for managing the publication of an article'', - ''wf_article_cases'', - ''case_id'' + ''article_wf'', + ''Article Publication'', + ''Article Publications'', + ''Workflow for managing the publication of an article'', + ''wf_article_cases'', + ''case_id'' ); - return null; -end;' language 'plpgsql'; + /***** + * Places + *****/ + + perform workflow__add_place( + ''article_wf'', + ''start'', + ''Start place'', + 1 + ); -select inline_0 (); + perform workflow__add_place( + ''article_wf'', + ''to_be_written'', + ''Needs to be written'', + 2 + ); -drop function inline_0 (); + perform workflow__add_place( + ''article_wf'', + ''to_be_reviewed'', + ''Needs review'', + 3 + ); -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('start', 'article_wf', 'Initial state', 1); -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('to_be_written', 'article_wf', 'Needs to be written', 2); -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('to_be_reviewed', 'article_wf', 'Needs review', 3); -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('to_go_to_press', 'article_wf', 'Ready to go to press', 4); -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('end', 'article_wf', 'End state', 5); + perform workflow__add_place( + ''article_wf'', + ''to_be_published'', + ''Ready to go to press'', + 4 + ); + perform workflow__add_place( + ''article_wf'', + ''end'', + ''End place'', + 5 + ); -insert into wf_transitions(transition_key, transition_name, workflow_key, sort_order, trigger_type) - values ('specification', 'Description and assignment by editor', 'article_wf', 1, 'user'); -insert into wf_transitions(transition_key, transition_name, workflow_key, sort_order, trigger_type) - values ('writing', 'Writing by author', 'article_wf', 2, 'user'); -insert into wf_transitions(transition_key, transition_name, workflow_key, sort_order, trigger_type) - values ('review', 'Approval by reviewer', 'article_wf', 3, 'user'); -insert into wf_transitions(transition_key, transition_name, workflow_key, sort_order, trigger_type) - values ('press', 'Publication of article', 'article_wf', 4, 'automatic'); + /***** + * Roles + *****/ + perform workflow__add_role( + ''article_wf'', + ''author'', + ''Author'', + 1 + ); --- specification -- --- in -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('article_wf', 'specification', 'start', 'in'); --- out -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('article_wf', 'specification', 'to_be_written', 'out'); + perform workflow__add_role( + ''article_wf'', + ''editor'', + ''Editor'', + 2 + ); + /***** + * Transitions + *****/ --- writing --- in -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('article_wf', 'writing', 'to_be_written', 'in'); --- out -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('article_wf', 'writing', 'to_be_reviewed', 'out'); + perform workflow__add_transition( + ''article_wf'', + ''specify'', + ''Describe task and assign author'', + ''editor'', + 1, + ''user'' + ); + + perform workflow__add_transition( + ''article_wf'', + ''write'', + ''Write article'', + ''author'', + 2, + ''user'' + ); + + perform workflow__add_transition( + ''article_wf'', + ''review'', + ''Review article'', + ''editor'', + 3, + ''user'' + ); + + perform workflow__add_transition( + ''article_wf'', + ''publish'', + ''Publish article'', + null, + 4, + ''automatic'' + ); + /***** + * Arcs + *****/ --- review (or-split) --- in -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('article_wf', 'review', 'to_be_reviewed', 'in'); --- out -insert into wf_arcs(workflow_key, transition_key, place_key, direction, guard_callback, guard_custom_arg, guard_description) - values ('article_wf', 'review', 'to_go_to_press', 'out', 'wf_callback__guard_attribute_true', 'reviewer_ok', 'Reviewer approved article'); -insert into wf_arcs(workflow_key, transition_key, place_key, direction, guard_callback, guard_description) - values ('article_wf', 'review', 'to_be_written', 'out', '#', 'Reviewer disapproved article'); + perform workflow__add_arc( + ''article_wf'', + ''start'', + ''specify'' + ); + perform workflow__add_arc( + ''article_wf'', + ''specify'', + ''to_be_written'', + null, + null, + null + ); --- press --- in -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('article_wf', 'press', 'to_go_to_press', 'in'); --- out -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('article_wf', 'press', 'end', 'out'); + perform workflow__add_arc( + ''article_wf'', + ''to_be_written'', + ''write'' + ); + perform workflow__add_arc( + ''article_wf'', + ''write'', + ''to_be_reviewed'', + null, + null, + null + ); -create function inline_1 () returns integer as ' -declare - v_attribute_id acs_attributes.attribute_id%TYPE; -begin + perform workflow__add_arc( + ''article_wf'', + ''to_be_reviewed'', + ''review'' + ); + + perform workflow__add_arc( + ''article_wf'', + ''review'', + ''to_be_published'', + ''wf_callback__guard_attribute_true'', + ''reviewer_ok'', + ''Reviewer approved article'' + ); + + perform workflow__add_arc( + ''article_wf'', + ''review'', + ''to_be_written'', + ''#'', + null, + ''Reviewer did not approve article'' + ); + + perform workflow__add_arc( + ''article_wf'', + ''to_be_published'', + ''publish'' + ); + + perform workflow__add_arc( + ''article_wf'', + ''publish'', + ''end'', + null, + null, + null + ); + + /***** + * Attributes + *****/ + v_attribute_id := workflow__create_attribute( ''article_wf'', ''reviewer_ok'', @@ -110,65 +213,57 @@ null, null, null, - ''f'', + ''f'', 1, 1, null, - ''generic'', - ''none'' + ''generic'' ); - insert into wf_transition_attribute_map - (workflow_key, transition_key, attribute_id, sort_order) - values - (''article_wf'', ''review'', v_attribute_id, 1); + perform workflow__add_trans_attribute_map( + ''article_wf'', + ''review'', + ''reviewer_ok'', + 1 + ); - return null; + /***** + * Assignment + *****/ -end;' language 'plpgsql'; + perform workflow__add_trans_role_assign_map( + ''article_wf'', + ''specify'', + ''author'' + ); -select inline_1 (); -drop function inline_1 (); + return 0; --- assignment as part of workflow -insert into wf_transition_assignment_map - (workflow_key, transition_key, assign_transition_key) -values - ('article_wf', 'specification', 'writing'); +end;' language 'plpgsql'; -insert into wf_transition_assignment_map - (workflow_key, transition_key, assign_transition_key) -values - ('article_wf', 'specification', 'review'); +select inline_0 (); +drop function inline_0 (); + /* Context stuff */ - insert into wf_context_transition_info ( - context_key, workflow_key, transition_key, hold_timeout_callback, hold_timeout_custom_arg + context_key, + workflow_key, + transition_key, + hold_timeout_callback, + hold_timeout_custom_arg ) values ( - 'default', 'article_wf', 'specification', 'wf_callback__time_sysdate_plus_x', 1/24 + 'default', + 'article_wf', + 'specify', + 'wf_callback__time_sysdate_plus_x', + 1/24 ); --- create or replace package wf_article_callback --- is --- procedure notification( --- task_id in integer, --- custom_arg in varchar2, --- party_to in integer, --- party_from in out integer, --- subject in out varchar2, --- body in out varchar2 --- ); --- --- end wf_article_callback; --- / --- show errors - - -- create or replace package body wf_article_callback -- FIXME: last three variables are in/out variables. @@ -244,10 +339,9 @@ - update wf_context_transition_info -set notification_callback = 'wf_article_callback__notification' -where workflow_key = 'article_wf' -and context_key = 'default' -and transition_key = 'specification'; + set notification_callback = 'wf_article_callback__notification' + where workflow_key = 'article_wf' + and context_key = 'default' + and transition_key = 'specify'; Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/sample-article-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/sample-article-drop.sql,v diff -u -r1.1 -r1.2 --- openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/sample-article-drop.sql 12 Apr 2001 00:12:06 -0000 1.1 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/sample-article-drop.sql 19 Nov 2001 18:20:33 -0000 1.2 @@ -10,11 +10,31 @@ -- @cvs-id $Id$ -- +create function inline_0 () returns integer as ' +begin + perform workflow__delete_cases(''article_wf''); + return 0; +end;' language 'plpgsql'; -select workflow__delete_cases('article_wf'); - drop table wf_article_cases; -select workflow__drop_workflow('article_wf'); +select inline_0 (); +drop function inline_0 (); + + + +create function inline_0 () returns integer as ' +begin + perform workflow__drop_workflow(''article_wf''); + return 0; +end;' language 'plpgsql'; + + +select inline_0 (); + +drop function inline_0 (); + +drop function wf_article_callback__notification(integer,varchar,integer,integer,varchar,varchar); + Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/sample-expenses-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/sample-expenses-create.sql,v diff -u -r1.4 -r1.5 --- openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/sample-expenses-create.sql 13 Apr 2001 04:31:27 -0000 1.4 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/sample-expenses-create.sql 19 Nov 2001 18:20:33 -0000 1.5 @@ -9,188 +9,334 @@ -- -- @cvs-id $Id$ -- + /* This table will hold one row for each case using this workflow. */ create table wf_expenses_cases ( case_id integer primary key constraint wf_expenses_cases_case_fk references wf_cases on delete cascade ); -create function inline_0 () returns integer as ' + declare - v_workflow_key varchar; + v_workflow_key wf_workflows.workflow_key%TYPE; + v_attribute_id acs_attributes.attribute_id%TYPE; begin - v_workflow_key := workflow__create_workflow( - ''expenses_wf'', - ''Expense Authorization'', - ''Expense authorizations'', - ''Workflow for authorizing employee''''s expenses on the company''''s behalf'', - ''wf_expenses_cases'', - ''case_id'' + v_workflow_key := workflow.create_workflow( + workflow_key => 'expenses_wf', + pretty_name => 'Expense Authorization', + pretty_plural => 'Expense authorizations', + description => 'Workflow for authorizing employee''s expenses on the company''s behalf', + table_name => 'wf_expenses_cases' ); - return null; -end;' language 'plpgsql'; + /***** + * Places + *****/ -select inline_0 (); -drop function inline_0 (); + workflow.add_place( + workflow_key => 'expenses_wf', + place_key => 'start', + place_name => 'Start place', + sort_order => 1 + ); + + workflow.add_place( + workflow_key => 'expenses_wf', + place_key => 'assignments_done', + place_name => 'Tasks have been assigned', + sort_order => 2 + ); -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('start', 'expenses_wf', 'Initial state', 1); -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('assignments_done', 'expenses_wf', 'Tasks have been assigned', 2); -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('supervisor_to_approve', 'expenses_wf', 'Supervisor is to approve', 3); -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('other_to_approve', 'expenses_wf', 'Other is to approve', 4); -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('supervisor_approved', 'expenses_wf', 'Supervisor has approved', 5); -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('other_approved', 'expenses_wf', 'Other has approved', 6); -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('ready_to_buy', 'expenses_wf', 'Both have approved', 8); -insert into wf_places(place_key, workflow_key, place_name, sort_order) - values ('end', 'expenses_wf', 'End state', 9); + workflow.add_place( + workflow_key => 'expenses_wf', + place_key => 'supervisor_to_approve', + place_name => 'Supervisor is to approve', + sort_order => 3 + ); + workflow.add_place( + workflow_key => 'expenses_wf', + place_key => 'other_to_approve', + place_name => 'Other is to approve', + sort_order => 4 + ); -insert into wf_transitions(transition_key, transition_name, workflow_key, sort_order, trigger_type) - values ('assign', 'Assign users to approval', 'expenses_wf', 1, 'user'); -insert into wf_transitions(transition_key, transition_name, workflow_key, sort_order, trigger_type) - values ('and_split', 'Both supervisor and Other approval', 'expenses_wf', 2, 'automatic'); -insert into wf_transitions(transition_key, transition_name, workflow_key, sort_order, trigger_type) - values ('supervisor_approval', 'Supervisor approval', 'expenses_wf', 3, 'user'); -insert into wf_transitions(transition_key, transition_name, workflow_key, sort_order, trigger_type) - values ('other_approval', 'Other approval', 'expenses_wf', 4, 'user'); -insert into wf_transitions(transition_key, transition_name, workflow_key, sort_order, trigger_type) - values ('and_join', 'Supervisor and other approval both done', 'expenses_wf', 5, 'automatic'); -insert into wf_transitions(transition_key, transition_name, workflow_key, sort_order, trigger_type) - values ('buy', 'Buy stuff', 'expenses_wf', 6, 'user'); + workflow.add_place( + workflow_key => 'expenses_wf', + place_key => 'supervisor_approved', + place_name => 'Supervisor has approved', + sort_order => 5 + ); --- assign -- --- in -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'assign', 'start', 'in'); --- out -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'assign', 'assignments_done', 'out'); + workflow.add_place( + workflow_key => 'expenses_wf', + place_key => 'other_approved', + place_name => 'Other has approved', + sort_order => 6 + ); + workflow.add_place( + workflow_key => 'expenses_wf', + place_key => 'ready_to_buy', + place_name => 'Both have approved', + sort_order => 7 + ); --- and-split -- --- in -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'and_split', 'assignments_done', 'in'); --- out -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'and_split', 'supervisor_to_approve', 'out'); -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'and_split', 'other_to_approve', 'out'); + workflow.add_place( + workflow_key => 'expenses_wf', + place_key => 'end', + place_name => 'End place', + sort_order => 8 + ); + /***** + * Roles + *****/ --- supervisor_approval --- in -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'supervisor_approval', 'supervisor_to_approve', 'in'); --- out -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'supervisor_approval', 'supervisor_approved', 'out'); + workflow.add_role( + workflow_key => 'expenses_wf', + role_key => 'assignor', + role_name => 'Assignor', + sort_order => 1 + ); + workflow.add_role( + workflow_key => 'expenses_wf', + role_key => 'supervisor', + role_name => 'Supervisor', + sort_order => 2 + ); --- other-approval --- in -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'other_approval', 'other_to_approve', 'in'); --- out -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'other_approval', 'other_approved', 'out'); + workflow.add_role( + workflow_key => 'expenses_wf', + role_key => 'other', + role_name => 'Other approver', + sort_order => 3 + ); + workflow.add_role( + workflow_key => 'expenses_wf', + role_key => 'requestor', + role_name => 'Requestor', + sort_order => 4 + ); --- and-join and or-split --- in -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'and_join', 'supervisor_approved', 'in'); -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'and_join', 'other_approved', 'in'); --- out -insert into wf_arcs(workflow_key, transition_key, place_key, direction, guard_callback, guard_description) - values ('expenses_wf', 'and_join', 'ready_to_buy', 'out', 'wf_expenses__guard_both_approved_p', 'Both supervisor and CEO approved'); -insert into wf_arcs(workflow_key, transition_key, place_key, direction, guard_callback, guard_description) - values ('expenses_wf', 'and_join', 'end', 'out', '#', 'Either supervisor or CEO did not approve'); + /***** + * Transitions + *****/ --- buy --- in -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'buy', 'ready_to_buy', 'in'); --- out -insert into wf_arcs(workflow_key, transition_key, place_key, direction) - values ('expenses_wf', 'buy', 'end', 'out'); + workflow.add_transition( + workflow_key => 'expenses_wf', + transition_key => 'assign', + transition_name => 'Assign users to approval', + role_key => 'assignor', + sort_order => 1, + trigger_type => 'user' + ); + workflow.add_transition( + workflow_key => 'expenses_wf', + transition_key => 'and_split', + transition_name => 'Parallel approval by supervisor and other', + sort_order => 2, + trigger_type => 'automatic' + ); -create function inline_1 () returns integer as ' -declare - v_attribute_id acs_attributes.attribute_id%TYPE; -begin - v_attribute_id := workflow__create_attribute( - ''expenses_wf'', - ''supervisor_ok'', - ''boolean'', - ''Supervisor Approval'', - null, - null, - null, - ''f'', - 1, - 1, - null, - ''generic'', - ''none'' + workflow.add_transition( + workflow_key => 'expenses_wf', + transition_key => 'supervisor_approval', + transition_name => 'Approve (Supervisor)', + role_key => 'supervisor', + sort_order => 3, + trigger_type => 'user' ); - insert into wf_transition_attribute_map - (workflow_key, transition_key, attribute_id, sort_order) - values - (''expenses_wf'', ''supervisor_approval'', v_attribute_id, 1); + workflow.add_transition( + workflow_key => 'expenses_wf', + transition_key => 'other_approval', + transition_name => 'Approve (Other)', + role_key => 'other', + sort_order => 4, + trigger_type => 'user' + ); - v_attribute_id := workflow__create_attribute( - ''expenses_wf'', - ''other_ok'', - ''boolean'', - ''Other Approval'', - null, - null, - null, - ''f'', - 1, - 1, - null, - ''generic'', - ''none'' + workflow.add_transition( + workflow_key => 'expenses_wf', + transition_key => 'and_join', + transition_name => 'Re-synchronization from approval by supervisor and other', + sort_order => 5, + trigger_type => 'automatic' ); - insert into wf_transition_attribute_map - (workflow_key, transition_key, attribute_id, sort_order) - values - (''expenses_wf'', ''other_approval'', v_attribute_id, 1); + workflow.add_transition( + workflow_key => 'expenses_wf', + transition_key => 'buy', + transition_name => 'Buy stuff', + role_key => 'requestor', + sort_order => 6, + trigger_type => 'user' + ); + + /***** + * Arcs + *****/ - return null; + workflow.add_arc( + workflow_key => 'expenses_wf', + from_place_key => 'start', + to_transition_key => 'assign' + ); -end;' language 'plpgsql'; + workflow.add_arc( + workflow_key => 'expenses_wf', + from_transition_key => 'assign', + to_place_key => 'assignments_done' + ); -select inline_1 (); + workflow.add_arc( + workflow_key => 'expenses_wf', + from_place_key => 'assignments_done', + to_transition_key => 'and_split' + ); -drop function inline_1 (); + workflow.add_arc( + workflow_key => 'expenses_wf', + from_transition_key => 'and_split', + to_place_key => 'supervisor_to_approve' + ); -insert into wf_transition_assignment_map - (workflow_key, transition_key, assign_transition_key) -values - ('expenses_wf', 'assign', 'supervisor_approval'); + workflow.add_arc( + workflow_key => 'expenses_wf', + from_transition_key => 'and_split', + to_place_key => 'other_to_approve' + ); -insert into wf_transition_assignment_map - (workflow_key, transition_key, assign_transition_key) -values - ('expenses_wf', 'assign', 'other_approval'); + workflow.add_arc( + workflow_key => 'expenses_wf', + from_place_key => 'supervisor_to_approve', + to_transition_key => 'supervisor_approval' + ); + workflow.add_arc( + workflow_key => 'expenses_wf', + from_transition_key => 'supervisor_approval', + to_place_key => 'supervisor_approved' + ); + workflow.add_arc( + workflow_key => 'expenses_wf', + from_place_key => 'other_to_approve', + to_transition_key => 'other_approval' + ); + workflow.add_arc( + workflow_key => 'expenses_wf', + from_transition_key => 'other_approval', + to_place_key => 'other_approved' + ); + + workflow.add_arc( + workflow_key => 'expenses_wf', + from_place_key => 'supervisor_approved', + to_transition_key => 'and_join' + ); + + workflow.add_arc( + workflow_key => 'expenses_wf', + from_place_key => 'other_approved', + to_transition_key => 'and_join' + ); + + workflow.add_arc( + workflow_key => 'expenses_wf', + from_transition_key => 'and_join', + to_place_key => 'ready_to_buy', + guard_callback => 'wf_expenses.guard_both_approved_p', + guard_description => 'Both Supervisor and the Other approver approved' + ); + + workflow.add_arc( + workflow_key => 'expenses_wf', + from_transition_key => 'and_join', + to_place_key => 'end', + guard_callback => '#', + guard_description => 'Either Supervisor or the Other approver did not approve' + ); + + workflow.add_arc( + workflow_key => 'expenses_wf', + from_place_key => 'ready_to_buy', + to_transition_key => 'buy' + ); + + workflow.add_arc( + workflow_key => 'expenses_wf', + from_transition_key => 'buy', + to_place_key => 'end' + ); + + /***** + * Attributes + *****/ + + v_attribute_id := workflow.create_attribute( + workflow_key => 'expenses_wf', + attribute_name => 'supervisor_ok', + datatype => 'boolean', + pretty_name => 'Supervisor Approval', + default_value => 'f', + sort_order => 1 + ); + + workflow.add_trans_attribute_map( + workflow_key => 'expenses_wf', + transition_key => 'supervisor_approval', + attribute_name => 'supervisor_ok', + sort_order => 1 + ); + + v_attribute_id := workflow.create_attribute( + workflow_key => 'expenses_wf', + attribute_name => 'other_ok', + datatype => 'boolean', + pretty_name => 'Other Approval', + default_value => 'f', + sort_order => 2 + ); + + workflow.add_trans_attribute_map( + workflow_key => 'expenses_wf', + transition_key => 'other_approval', + attribute_name => 'other_ok', + sort_order => 1 + ); + + /***** + * Assignment + *****/ + + workflow.add_trans_role_assign_map( + workflow_key => 'expenses_wf', + transition_key => 'assign', + assign_role_key => 'supervisor' + ); + + workflow.add_trans_role_assign_map( + workflow_key => 'expenses_wf', + transition_key => 'assign', + assign_role_key => 'other' + ); + + +end; +/ +show errors + + + + + /* Context stuff */ insert into wf_context_transition_info ( @@ -202,7 +348,7 @@ insert into wf_context_transition_info ( context_key, workflow_key, transition_key, hold_timeout_callback, hold_timeout_custom_arg, estimated_minutes ) values ( - 'default', 'expenses_wf', 'supervisor_approval', 'wf_callback__time_sysdate_plus_x', 1/24, 15 + 'default', 'expenses_wf', 'supervisor_approval', 'wf_callback.time_sysdate_plus_x', 1/24, 15 ); insert into wf_context_transition_info ( @@ -219,79 +365,83 @@ insert into wf_context_task_panels ( - context_key, workflow_key, transition_key, sort_key, header, template_url + context_key, workflow_key, transition_key, sort_order, header, template_url ) values ( 'default', 'expenses_wf', 'supervisor_approval', 1, 'Claim Info', 'sample/expenses-claim-info' ); insert into wf_context_task_panels ( - context_key, workflow_key, transition_key, sort_key, header, template_url + context_key, workflow_key, transition_key, sort_order, header, template_url ) values ( 'default', 'expenses_wf', 'supervisor_approval', 2, 'Logic and Aids', 'sample/expenses-approval-aids' ); insert into wf_context_task_panels ( - context_key, workflow_key, transition_key, sort_key, header, template_url + context_key, workflow_key, transition_key, sort_order, header, template_url ) values ( 'default', 'expenses_wf', 'other_approval', 1, 'Claim Info', 'sample/expenses-claim-info' ); insert into wf_context_task_panels ( - context_key, workflow_key, transition_key, sort_key, header, template_url + context_key, workflow_key, transition_key, sort_order, header, template_url ) values ( 'default', 'expenses_wf', 'other_approval', 2, 'Logic and Aids', 'sample/expenses-approval-aids' ); +commit; /* Callbacks for the workflow */ --- create or replace package wf_expenses ---is --- --- function guard_both_approved_p ( --- case_id in integer, --- workflow_key in varchar2, --- transition_key in varchar2, --- place_key in varchar2, --- direction_in varchar2, --- custom_arg in varchar2 --- ) --- return char; --- ---end wf_expenses; ---/ ---show errors; +create or replace package wf_expenses +is + function guard_both_approved_p ( + case_id in number, + workflow_key in varchar2, + transition_key in varchar2, + place_key in varchar2, + direction_in varchar2, + custom_arg in varchar2 + ) + return char; ---create or replace package body wf_expenses -create function wf_expenses__guard_both_approved_p (integer,varchar,varchar,varchar,varchar,varchar) -returns boolean as ' -declare - guard_both_approved_p__case_id alias for $1; - guard_both_approved_p__workflow_key alias for $2; - guard_both_approved_p__transition_key alias for $3; - guard_both_approved_p__place_key alias for $4; - guard_both_approved_p__direction_in alias for $5; - guard_both_approved_p__custom_arg alias for $6; - v_other_ok_p boolean; - v_supervisor_ok_p boolean; -begin - v_other_ok_p := workflow_case__get_attribute_value( - guard_both_approved_p__case_id, - ''other_ok'' +end wf_expenses; +/ +show errors; + + +create or replace package body wf_expenses +is + function guard_both_approved_p ( + case_id in number, + workflow_key in varchar2, + transition_key in varchar2, + place_key in varchar2, + direction_in varchar2, + custom_arg in varchar2 + ) + return char + is + v_other_ok_p char(1); + v_supervisor_ok_p char(1); + begin + v_other_ok_p := workflow_case.get_attribute_value( + case_id => guard_both_approved_p.case_id, + attribute_name => 'other_ok' ); - if v_other_ok_p = ''f'' then - return ''f''; + if v_other_ok_p = 'f' then + return 'f'; end if; - v_supervisor_ok_p := workflow_case__get_attribute_value( - guard_both_approved_p__case_id, - ''supervisor_ok'' + v_supervisor_ok_p := workflow_case.get_attribute_value( + case_id => guard_both_approved_p.case_id, + attribute_name => 'supervisor_ok' ); - return v_supervisor_ok_p; + end guard_both_approved_p; -end;' language 'plpgsql'; +end wf_expenses; +/ +show errors; - Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/sample-expenses-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/sample-expenses-drop.sql,v diff -u -r1.1 -r1.2 --- openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/sample-expenses-drop.sql 12 Apr 2001 00:12:06 -0000 1.1 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/sample-expenses-drop.sql 19 Nov 2001 18:20:33 -0000 1.2 @@ -10,11 +10,18 @@ -- @cvs-id $Id$ -- +begin + workflow.delete_cases(workflow_key => 'expenses_wf'); +end; +/ +show errors; -select workflow__delete_cases('expenses_wf'); - drop table wf_expenses_cases; -select workflow__drop_workflow('expenses_wf'); +begin + workflow.drop_workflow(workflow_key => 'expenses_wf'); +end; +/ +show errors; Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/upgrade-4.1.1-4.3.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/upgrade-4.1.1-4.3.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/upgrade-4.1.1-4.3.sql 19 Nov 2001 18:20:33 -0000 1.1 @@ -0,0 +1,697 @@ +/* + * We've added support for roles, which is an intermediate step between + * transitions and assignments. A role is a relationship to a process, e.g., + * an editor, publisher, submitter, fixer, doctor, manager, etc. + * A task is performed by a role, but one role may have many tasks to perform. + * The idea is that when you reassign a role, it affects all the tasks that role + * has been assigned to. + * + * For the upgrade, we simply create one role per transtiion, and change + * all the other tables correspondingly. This will execute exactly equivalent + * to the way it would have without the roles refactoring. + * + * We've also added other minor things, such as task instructions and gotten rid + * of wf_attribute_info. + */ + + + +/* + * Table wf_roles: + * Added. + */ + +create table wf_roles ( + role_key varchar(100), + workflow_key varchar(100) + constraint wf_roles_workflow_fk + references wf_workflows(workflow_key) + on delete cascade, + role_name varchar(100) + constraint wf_role_role_name_nn + not null, + -- so we can display roles in some logical order -- + sort_order integer + constraint wf_roles_order_ck + check (sort_order > 0), + -- table constraints -- + constraint wf_role_pk + primary key (workflow_key, role_key), + constraint wf_roles_wf_key_role_name_un + unique (workflow_key, role_name) +); + +comment on table wf_roles is ' + A process has certain roles associated with it, such as "submitter", + "reviewer", "editor", "claimant", etc. For each transition, then, you + specify what role is to perform that task. Thus, two or more tasks can be + performed by one and the same role, so that when the role is reassigned, + it reflects assignments of both tasks. Users and parties are then assigned + to roles instead of directly to tasks. +'; + + + +/* + * Now populate the roles table: + * We just create a role per transition, then hook them up + */ + +insert into wf_roles + (workflow_key, + role_key, + role_name, + sort_order) +select workflow_key, transition_key, transition_name, sort_order + from wf_transitions; + + +/* + * Table wf_transitions: + * Added column role_key. + * Added foreign key constraint wf_transition_role_fk. + */ + +alter table wf_transitions add role_key varchar(100); + + +alter table wf_transitions add constraint wf_transition_role_fk + foreign key (workflow_key,role_key) references wf_roles(workflow_key,role_key); + /* We don't do on delete cascade here, because that would mean that + * when a role is deleted, the transitions associated with that role would be deleted, too */ + + +/* Now populate the new column corresponding to the roles we just created: + * Since there's a one-to-one role per transition, and the have the same keys, + * we just set role_key = transition_key + */ + +update wf_transitions + set role_key = transition_key; + +/* + * Table wf_transition_role_assign_map: + * Added. + * This replaces wf_transtiion_assign_map, since transitions now assign + * roles instead of other transitions. + */ + +create table wf_transition_role_assign_map ( + workflow_key varchar(100) + constraint wf_role_asgn_map_workflow_fk + references wf_workflows(workflow_key) + on delete cascade, + transition_key varchar(100), + assign_role_key varchar(100), + -- table constraints -- + constraint wf_role_asgn_map_pk + primary key (workflow_key, transition_key, assign_role_key), + constraint wf_role_asgn_map_trans_fk + foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) + on delete cascade, + constraint wf_tr_role_asgn_map_asgn_fk + foreign key (workflow_key, assign_role_key) references wf_roles(workflow_key, role_key) + on delete cascade +); + +create index wf_role_asgn_map_wf_trans_idx on wf_transition_role_assign_map(workflow_key, transition_key); +create index wf_role_asgn_map_wf_as_tr_idx on wf_transition_role_assign_map(workflow_key, assign_role_key); + +comment on table wf_transition_role_assign_map is ' + When part of the output of one task is to assign users to a role, + specify that this is the case by inserting a row here. +'; + +comment on column wf_transition_role_assign_map.transition_key is ' + transition_key is the assigning transition. +'; + +comment on column wf_transition_role_assign_map.assign_role_key is ' + assign_role_key is the role being assigned a user to. +'; + + +/* Populate new wf_transition_role_assign_map with the rows from + * wf_transition_assignment_map. Since role_key map one-to-one with transition_keys + * in this upgrade, that's pretty straight-forward. + */ + +insert into wf_transition_role_assign_map + (workflow_key, + transition_key, + assign_role_key) +select workflow_key, + transition_key, + assign_transition_key + from wf_transition_assignment_map; + +/* + * Table wf_transition_assignment_map: + * Dropped. + * This table is no longer releavnt, since transitions don't assign other + * transitions, they assign roles. + */ + +drop table wf_transition_assignment_map; + + +/* + * Table wf_attribute_info: + * Dropped. + * This table was a hang-over from earlier versions and is no longer necessary. + */ + +drop table wf_attribute_info; + +/* + * Table wf_context_role_info: + * Added. + */ + +create table wf_context_role_info ( + context_key varchar(100) + constraint wf_context_role_context_fk + references wf_contexts(context_key) + on delete cascade, + workflow_key varchar(100) + constraint wf_context_role_workflow_fk + references wf_workflows(workflow_key) + on delete cascade, + role_key varchar(100), + /* + * Callback to programatically assign a role. + * Must call wordflow_case.*_role_assignment to make the assignments. + * Will be called when a transition for that role becomes enabled + * signature: (role_key in varchar2, custom_arg in varchar2) + */ + assignment_callback varchar(100), + assignment_custom_arg text, + -- table constraints -- + constraint wf_context_role_role_fk + foreign key (workflow_key, role_key) references wf_roles(workflow_key, role_key) + on delete cascade, + constraint wf_context_role_info_pk + primary key (context_key, workflow_key, role_key) +); + +comment on table wf_context_role_info is ' + This table holds context-dependent info for roles, currently only the assignment callback +'; + + +/* Populate by a straight copy from wf_context_transition_info */ + +insert into wf_context_role_info + (context_key, + workflow_key, + role_key, + assignment_callback, + assignment_custom_arg) +select context_key, + workflow_key, + transition_key, + assignment_callback, + assignment_custom_arg + from wf_context_transition_info + where assignment_callback is not null + or assignment_custom_arg is not null; + +/* + * Table wf_context_transition_info: + */ +create table temp as select + context_key, + workflow_key, + transition_key, + estimated_minutes, + enable_callback, + enable_custom_arg, + fire_callback, + fire_custom_arg, + time_callback, + time_custom_arg, + deadline_callback, + deadline_custom_arg, + deadline_attribute_name, + hold_timeout_callback, + hold_timeout_custom_arg, + notification_callback, + notification_custom_arg, + unassigned_callback, + unassigned_custom_arg, + access_privilege +from wf_context_transition_info; + +drop table wf_context_transition_info; + +create table wf_context_transition_info ( + context_key varchar(100) + constraint wf_context_trans_context_fk + references wf_contexts, + workflow_key varchar(100) + constraint wf_context_trans_workflow_fk + references wf_workflows, + transition_key varchar(100), + /* information for the transition in the context */ + /* The integer of minutes this task is estimated to take */ + estimated_minutes integer, + /* Instructions for how to complete the task. Will be displayed on the task page. */ + instructions text, + /* + * Will be called when the transition is enabled/fired. + * signature: (case_id in integer, transition_key in varchar, custom_arg in varchar2) + */ + enable_callback varchar(100), + enable_custom_arg text, + fire_callback varchar(100), + fire_custom_arg text, + /* + * Must return the date that the timed transition should fire + * Will be called when the transition is enabled + * signature: (case_id in integer, transition_key in varchar, custom_arg in varchar2) return date + */ + time_callback varchar(100), + time_custom_arg text, + /* + * Returns the deadline for this task. + * Will be called when the transition becomes enabled + * Signature: (case_id in integer, transition_key in varchar, custom_arg in varchar2) return date + */ + deadline_callback varchar(100), + deadline_custom_arg text, + /* The name of an attribute that holds the deadline */ + deadline_attribute_name varchar(100), + /* + * Must return the date that the user's hold on the task times out. + * called when the user starts the task. + * signature: (case_id in integer, transition_key in varchar, custom_arg in varchar2) return date + */ + hold_timeout_callback varchar(100), + hold_timeout_custom_arg text, + /* + * Notification callback + * Will be called when a notification is sent i.e., when a transition is enabled, + * or assignment changes. + * signature: (task_id in integer, + * custom_arg in varchar, + * party_to in integer, + * party_from in out integer, + * subject in out varchar, + * body in out varchar) + */ + notification_callback varchar(100), + notification_custom_arg text, + /* + * Callback to handle unassigned tasks. + * Will be called when an enabled task becomes unassigned. + * Signature: (task_id in number, custom_arg in varchar2) + */ + unassigned_callback varchar(100), + unassigned_custom_arg text, + -- table constraints -- + constraint wf_context_trans_trans_fk + foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) + on delete cascade, + constraint wf_context_transition_pk + primary key (context_key, workflow_key, transition_key) +); + +create index wf_ctx_trans_wf_trans_idx on wf_context_transition_info(workflow_key, transition_key); + +comment on table wf_context_transition_info is ' + This table holds information that pertains to a transition in a specific context. + It will specifically hold +'; + +insert into wf_context_transition_info select * from temp; +drop table temp; + + +/* + * Table wf_context_workflow_info: + * Added. + */ + +create table wf_context_workflow_info ( + context_key varchar(100) + constraint wf_context_wf_context_fk + references wf_contexts + on delete cascade, + workflow_key varchar(100) + constraint wf_context_wf_workflow_fk + references wf_workflows + on delete cascade, + /* The principal is the user/party that sends out email assignment notifications + * And receives email when a task becomes unassigned (for more than x minutes?) + */ + principal_party integer + constraint wf_context_wf_principal_fk + references parties + on delete set null, + -- table constraints -- + constraint wf_context_workflow_pk + primary key (context_key, workflow_key) +); + +/* Insert someone for all existing processes. Hopefully this will be the administrator user. */ + +insert into wf_context_workflow_info + (context_key, + workflow_key, + principal_party) +select 'default', workflow_key, (select min(party_id) from parties) + from wf_workflows; + + +/* + * Table wf_context_task_panels: + * Added columns overrides_action_p and only_display_when_started_p + * Renamed column sort_key to sort_order for consistency + */ +create table temp as select +context_key, +workflow_key, +transition_key, +sort_key as sort_order, +header, +template_url +from wf_context_task_panels; + +drop table wf_context_task_panels; + + +create table wf_context_task_panels ( + context_key varchar(100) not null + constraint wf_context_panels_context_fk + references wf_contexts(context_key) + on delete cascade, + workflow_key varchar(100) not null + constraint wf_context_panels_workflow_fk + references wf_workflows(workflow_key) + on delete cascade, + transition_key varchar(100) not null, + sort_order integer not null, + header varchar(200) not null, + template_url varchar(500) not null, + /* Display this panel in place of the action panel */ + overrides_action_p char(1) default 'f' + constraint wf_context_panels_ovrd_p_ck + check (overrides_action_p in ('t','f')), + /* Display this panel only when the task has been started (and not finished) */ + only_display_when_started_p char(1) default 'f' + constraint wf_context_panels_display_p_ck + check (only_display_when_started_p in ('t','f')), + -- table constraints -- + constraint wf_context_panels_trans_fk + foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) + on delete cascade, + constraint wf_context_panels_pk + primary key (context_key, workflow_key, transition_key, sort_order) +); + +create index wf_ctx_panl_workflow_trans_idx on wf_context_task_panels(workflow_key, transition_key); + +comment on table wf_context_task_panels is ' + Holds information about the panels to be displayed on the task page. +'; + +insert into wf_context_task_panels select * from temp; +drop table temp; + + + +/* + * Table wf_context_assignments + * Replaced transition_key with role_key + */ +create table temp as select + context_key, + workflow_key, + transition_key as role_key, + party_id +from wf_context_assignments; + +drop table wf_context_assignments; + +create table wf_context_assignments ( + context_key varchar(100) + constraint wf_context_assign_context_fk + references wf_contexts(context_key) + on delete cascade, + workflow_key varchar(100) + constraint wf_context_assign_workflow_fk + references wf_workflows(workflow_key) + on delete cascade, + role_key varchar(100), + party_id integer + constraint wf_context_assign_party_fk + references parties(party_id) + on delete cascade, + -- table constraints -- + constraint wf_context_assign_pk + primary key (context_key, workflow_key, role_key, party_id), + constraint wf_context_assign_role_fk + foreign key (workflow_key, role_key) references wf_roles(workflow_key, role_key) + on delete cascade +); + +create index wf_ctx_assg_workflow_trans_idx on wf_context_assignments(workflow_key, role_key); + +comment on table wf_context_assignments is ' + Static (default) per-context assignments of roles to parties. +'; + +insert into wf_context_assignments select * from temp; +drop table temp; + + + +/* + * Table wf_case_assignments: + * Changed transition_key to role_key + */ + +create table temp as select + case_id, + workflow_key, + transition_key as role_key, + party_id +from wf_case_assignments; + +drop table wf_case_assignments; + +create table wf_case_assignments ( + case_id integer + constraint wf_case_assign_fk + references wf_cases(case_id) + on delete cascade, + workflow_key varchar(100), + role_key varchar(100), + party_id integer + constraint wf_case_assign_party_fk + references parties(party_id) + on delete cascade, + -- table constraints -- + constraint wf_case_assign_pk + primary key (case_id, role_key, party_id), + constraint wf_case_assign_role_fk + foreign key (workflow_key, role_key) references wf_roles(workflow_key, role_key) + on delete cascade +); + +create index wf_case_assgn_party_idx on wf_case_assignments(party_id); + +comment on table wf_case_assignments is ' + Manual per-case assignments of roles to parties. +'; + +insert into wf_case_assignments select * from temp; +drop table temp; + + +/* + * View wf_transition_contexts: + * Added column role_key. + */ +drop view wf_transition_contexts; +create view wf_transition_contexts as +select t.transition_key, + t.transition_name, + t.workflow_key, + t.sort_order, + t.trigger_type, + t.role_key, + c.context_key, + c.context_name +from wf_transitions t, wf_contexts c; + + + +/* + * View wf_transition_info: + * Added columns role_key and instructions. + * Removed columns assignment_callback/custom_arg. + */ +drop view wf_transition_info; +create view wf_transition_info as +select t.transition_key, + t.transition_name, + t.workflow_key, + t.sort_order, + t.trigger_type, + t.context_key, + t.role_key, + ct.estimated_minutes, + ct.instructions, + ct.enable_callback, + ct.enable_custom_arg, + ct.fire_callback, + ct.fire_custom_arg, + ct.time_callback, + ct.time_custom_arg, + ct.deadline_callback, + ct.deadline_custom_arg, + ct.deadline_attribute_name, + ct.hold_timeout_callback, + ct.hold_timeout_custom_arg, + ct.notification_callback, + ct.notification_custom_arg, + ct.unassigned_callback, + ct.unassigned_custom_arg +from wf_transition_contexts t LEFT OUTER JOIN wf_context_transition_info ct ON ( + ct.workflow_key = t.workflow_key + and ct.transition_key = t.transition_key + and ct.context_key = t.context_key); + + +/* + * View wf_role_info: + * Added. + */ + +-- drop view wf_role_info; +create view wf_role_info as +select r.role_key, + r.role_name, + r.workflow_key, + c.context_key, + cr.assignment_callback, + cr.assignment_custom_arg +from wf_contexts c, wf_roles r LEFT OUTER JOIN wf_context_role_info cr ON ( + cr.workflow_key = r.workflow_key + and cr.role_key = r.role_key) +where cr.context_key = c.context_key; + + +/* + * View wf_enabled_transitions: + * Added columns role_key and instructions. + * Removed columns assignment_callback/custom_arg. + */ + +drop view wf_enabled_transitions; +create view wf_enabled_transitions as +select c.case_id, + t.transition_key, + t.transition_name, + t.workflow_key, + t.sort_order, + t.trigger_type, + t.context_key, + t.role_key, + t.enable_callback, + t.enable_custom_arg, + t.fire_callback, + t.fire_custom_arg, + t.time_callback, + t.time_custom_arg, + t.deadline_callback, + t.deadline_custom_arg, + t.deadline_attribute_name, + t.hold_timeout_callback, + t.hold_timeout_custom_arg, + t.notification_callback, + t.notification_custom_arg, + t.estimated_minutes, + t.instructions, + t.unassigned_callback, + t.unassigned_custom_arg + from wf_transition_info t, + wf_cases c + where t.workflow_key = c.workflow_key + and t.context_key = c.context_key + and c.state = 'active' + and not exists + (select tp.place_key + from wf_transition_places tp + where tp.transition_key = t.transition_key + and tp.workflow_key = t.workflow_key + and tp.direction = 'in' + and not exists + (select tk.token_id + from wf_tokens tk + where tk.place_key = tp.place_key + and tk.case_id = c.case_id + and tk.state = 'free' + ) + ); + + +/* + * View wf_user_tasks: + * Added column instructions + * Added "and tr.workflow_key = ta.workflow_key" to where clause + * (looks like a bug) + */ + +drop view wf_user_tasks; +create view wf_user_tasks as +select distinct ta.task_id, + ta.case_id, + ta.workflow_key, + ta.transition_key, + tr.transition_name, + tr.instructions, + ta.enabled_date, + ta.started_date, + u.user_id, + ta.state, + ta.holding_user, + ta.hold_timeout, + ta.deadline, + ta.estimated_minutes +from wf_tasks ta, + wf_task_assignments tasgn, + wf_cases c, + wf_transition_info tr, + party_approved_member_map m, + users u +where ta.state in ( 'enabled','started') +and c.case_id = ta.case_id +and c.state = 'active' +and tr.transition_key = ta.transition_key +and tr.workflow_key = ta.workflow_key +and tr.trigger_type = 'user' +and tr.context_key = c.context_key +and tasgn.task_id = ta.task_id +and m.party_id = tasgn.party_id +and u.user_id = m.member_id; + + + +drop function __workflow__simple_p (varchar,integer); +drop table guard_list; +drop table target_place_list; +drop table previous_place_list; +drop sequence workflow_session_id; +drop function sweep_hold_timeout (); +drop function sweep_timed_transitions (); + +select drop_package('workflow'); +select drop_package('workflow_case'); + + +\i workflow-package.sql +\i workflow-case-package-head.sql +\i workflow-case-package-body.sql + Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/wf-callback-package-body.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/wf-callback-package-body.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/wf-callback-package-body.sql 19 Nov 2001 18:20:33 -0000 1.1 @@ -0,0 +1,37 @@ + +-- create or replace package body wf_callback +-- function guard_attribute_true +create function wf_callback__guard_attribute_true (integer,varchar,varchar,varchar,varchar,varchar) +returns boolean as ' +declare + guard_attribute_true__case_id alias for $1; + guard_attribute_true__workflow_key alias for $2; + guard_attribute_true__transition_key alias for $3; + guard_attribute_true__place_key alias for $4; + guard_attribute_true__direction alias for $5; + guard_attribute_true__custom_arg alias for $6; +begin + return workflow_case__get_attribute_value( + guard_attribute_true__case_id, + guard_attribute_true__custom_arg + ); + +end;' language 'plpgsql'; + + +-- function time_sysdate_plus_x +create function wf_callback__time_sysdate_plus_x (integer,varchar,text) +returns timestamp as ' +declare + time_sysdate_plus_x__case_id alias for $1; + time_sysdate_plus_x__transition_key alias for $2; + time_sysdate_plus_x__custom_arg alias for $3; +begin + return now() + (time_sysdate_plus_x__custom_arg || '' days'')::interval; + +end;' language 'plpgsql'; + + + +-- show errors + Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/wf-callback-package-head.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/wf-callback-package-head.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/wf-callback-package-head.sql 19 Nov 2001 18:20:33 -0000 1.1 @@ -0,0 +1,2 @@ + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/wf-callback-package.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/wf-callback-package.sql,v diff -u -r1.4 -r1.5 --- openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/wf-callback-package.sql 14 May 2001 23:16:08 -0000 1.4 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/wf-callback-package.sql 19 Nov 2001 18:20:33 -0000 1.5 @@ -11,61 +11,5 @@ -- @cvs-id $Id$ -- --- create or replace package wf_callback --- as --- --- function guard_attribute_true( --- case_id in integer, --- workflow_key in varchar2, --- transition_key in varchar2, --- place_key in varchar2, --- direction in varchar2, --- custom_arg in varchar2 --- ) return char; --- --- function time_sysdate_plus_x( --- case_id in integer, --- transition_key in varchar2, --- custom_arg in varchar2 --- ) return date; --- --- end wf_callback; - --- show errors - --- create or replace package body wf_callback --- function guard_attribute_true -create function wf_callback__guard_attribute_true (integer,varchar,varchar,varchar,varchar,varchar) -returns boolean as ' -declare - guard_attribute_true__case_id alias for $1; - guard_attribute_true__workflow_key alias for $2; - guard_attribute_true__transition_key alias for $3; - guard_attribute_true__place_key alias for $4; - guard_attribute_true__direction alias for $5; - guard_attribute_true__custom_arg alias for $6; -begin - return workflow_case__get_attribute_value( - guard_attribute_true__case_id, - guard_attribute_true__custom_arg - ); - -end;' language 'plpgsql'; - - --- function time_sysdate_plus_x -create function wf_callback__time_sysdate_plus_x (integer,varchar,text) -returns timestamp as ' -declare - time_sysdate_plus_x__case_id alias for $1; - time_sysdate_plus_x__transition_key alias for $2; - time_sysdate_plus_x__custom_arg alias for $3; -begin - return now() + (time_sysdate_plus_x__custom_arg || '' days'')::interval; - -end;' language 'plpgsql'; - - - --- show errors - +\i wf-callback-package-head.sql +\i wf-callback-package-body.sql Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/wf-core-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/wf-core-create.sql,v diff -u -r1.4 -r1.5 --- openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/wf-core-create.sql 28 Apr 2001 19:58:39 -0000 1.4 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/wf-core-create.sql 19 Nov 2001 18:20:33 -0000 1.5 @@ -66,10 +66,11 @@ place_name varchar(100) constraint wf_place_name_nn not null, - -- purely for UI purposes + -- so we can display places in some logical order -- sort_order integer constraint wf_place_order_ck check (sort_order > 0), + -- table constraints -- constraint wf_place_pk primary key (workflow_key, place_key), constraint wf_places_wf_key_place_name_un @@ -81,6 +82,35 @@ state of the workflow. '; +create table wf_roles ( + role_key varchar(100), + workflow_key varchar(100) + constraint wf_roles_workflow_fk + references wf_workflows(workflow_key) + on delete cascade, + role_name varchar(100) + constraint wf_role_role_name_nn + not null, + -- so we can display roles in some logical order -- + sort_order integer + constraint wf_roles_order_ck + check (sort_order > 0), + -- table constraints -- + constraint wf_role_pk + primary key (workflow_key, role_key), + constraint wf_roles_wf_key_role_name_un + unique (workflow_key, role_name) +); + +comment on table wf_roles is ' + A process has certain roles associated with it, such as "submitter", + "reviewer", "editor", "claimant", etc. For each transition, then, you + specify what role is to perform that task. Thus, two or more tasks can be + performed by one and the same role, so that when the role is reassigned, + it reflects assignments of both tasks. Users and parties are then assigned + to roles instead of directly to tasks. +'; + create table wf_transitions ( transition_key varchar(100), transition_name varchar(100) @@ -90,18 +120,26 @@ constraint wf_transition_workflow_fk references wf_workflows(workflow_key) on delete cascade, - -- purely for UI purposes + -- what role does this transition belong to + -- (only for user-triggered transitions) + role_key varchar(100), + -- so we can display transitions in some logical order -- sort_order integer constraint wf_transition_order_ck check (sort_order > 0), trigger_type varchar(40) constraint wf_transition_trigger_type_ck check (trigger_type in ('','automatic','user','message','time')), + -- table constraints -- constraint wf_transition_pk primary key (workflow_key, transition_key), constraint wf_trans_wf_key_trans_name_un - unique (workflow_key, transition_name) + unique (workflow_key, transition_name), + constraint wf_transition_role_fk + foreign key (workflow_key,role_key) references wf_roles(workflow_key,role_key) + /* We don't do on delete cascade here, because that would mean that + * when a role is deleted, the transitions associated with that role would be deleted, too */ ); comment on table wf_transitions is ' @@ -128,16 +166,17 @@ guard_callback varchar(100), guard_custom_arg text, guard_description varchar(500), + -- table constraints -- + constraint wf_arc_pk + primary key (workflow_key, transition_key, place_key, direction), constraint wf_arc_guard_on_in_arc_ck - check (guard_callback = '' or direction = 'out'), + check (guard_callback = '' or direction = 'out'), constraint wf_arc_transition_fk - foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) - on delete cascade, + foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) + on delete cascade, constraint wf_arc_place_fk - foreign key (workflow_key, place_key) references wf_places(workflow_key, place_key) - on delete cascade, - constraint wf_arc_pk - primary key (workflow_key, transition_key, place_key, direction) + foreign key (workflow_key, place_key) references wf_places(workflow_key, place_key) + on delete cascade ); create index wf_arcs_wf_key_trans_key_idx on wf_arcs(workflow_key, transition_key); @@ -151,19 +190,6 @@ away from the transition. '; -create table wf_attribute_info ( - attribute_id integer - constraint wf_attribute_info_attribute_pk - primary key - constraint wf_attribute_info_attribute_fk - references acs_attributes(attribute_id) - on delete cascade, - wf_datatype varchar(50) - constraint wf_attr_info_wf_datatype_ck - check (wf_datatype in ('', 'none', 'party')) -); - - create table wf_transition_attribute_map ( workflow_key varchar(100) constraint wf_trans_attr_map_workflow_fk @@ -175,11 +201,12 @@ attribute_id integer constraint wf_trans_attr_map_attribute_fk references acs_attributes, + -- table constraints -- constraint wf_trans_attr_map_pk - primary key (workflow_key, transition_key, attribute_id), + primary key (workflow_key, transition_key, attribute_id), constraint wf_trans_attr_map_trans_fk - foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) - on delete cascade + foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) + on delete cascade ); comment on table wf_transition_attribute_map is ' @@ -188,43 +215,42 @@ '; -create table wf_transition_assignment_map ( +create table wf_transition_role_assign_map ( workflow_key varchar(100) - constraint wf_trans_asgn_map_workflow_fk + constraint wf_role_asgn_map_workflow_fk references wf_workflows(workflow_key) on delete cascade, transition_key varchar(100), - assign_transition_key varchar(100), - constraint wf_trans_asgn_map_pk - primary key (workflow_key, transition_key, assign_transition_key), - constraint wf_trans_asgn_map_trans_fk - foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) - on delete cascade, - constraint wf_tr_asgn_map_asgn_trans_fk - foreign key (workflow_key, assign_transition_key) references wf_transitions(workflow_key, transition_key) - on delete cascade + assign_role_key varchar(100), + -- table constraints -- + constraint wf_role_asgn_map_pk + primary key (workflow_key, transition_key, assign_role_key), + constraint wf_role_asgn_map_trans_fk + foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) + on delete cascade, + constraint wf_tr_role_asgn_map_asgn_fk + foreign key (workflow_key, assign_role_key) references wf_roles(workflow_key, role_key) + on delete cascade ); -create index wf_trans_asgn_map_wf_trans_idx on wf_transition_assignment_map(workflow_key, transition_key); -create index wf_trans_asgn_map_wf_as_tr_idx on wf_transition_assignment_map(workflow_key, assign_transition_key); +create index wf_role_asgn_map_wf_trans_idx on wf_transition_role_assign_map(workflow_key, transition_key); +create index wf_role_asgn_map_wf_as_tr_idx on wf_transition_role_assign_map(workflow_key, assign_role_key); -comment on table wf_transition_assignment_map is ' - When part of the output of one task is to assign users to another task, - specify that this is the case by inserting a row here. +comment on table wf_transition_role_assign_map is ' + When part of the output of one task is to assign users to a role, + specify that this is the case by inserting a row here. '; -comment on column wf_transition_assignment_map.transition_key is ' +comment on column wf_transition_role_assign_map.transition_key is ' transition_key is the assigning transition. '; -comment on column wf_transition_assignment_map.assign_transition_key is ' - transition_key is the transition being assigned a user to. +comment on column wf_transition_role_assign_map.assign_role_key is ' + assign_role_key is the role being assigned a user to. '; - - /* * Contexts */ @@ -256,9 +282,35 @@ insert into wf_contexts (context_key, context_name) values ('default', 'Default Context'); -commit; +create table wf_context_workflow_info ( + context_key varchar(100) + constraint wf_context_wf_context_fk + references wf_contexts + on delete cascade, + workflow_key varchar(100) + constraint wf_context_wf_workflow_fk + references wf_workflows + on delete cascade, + /* The principal is the user/party that sends out email assignment notifications + * And receives email when a task becomes unassigned (for more than x minutes?) + */ + principal_party integer + constraint wf_context_wf_principal_fk + references parties + on delete set null, + -- table constraints -- + constraint wf_context_workflow_pk + primary key (context_key, workflow_key) +); + +comment on table wf_context_workflow_info is ' + Holds context-dependent information about the workflow, specifically the + principal user. +'; + + create table wf_context_transition_info ( context_key varchar(100) constraint wf_context_trans_context_fk @@ -270,6 +322,8 @@ /* information for the transition in the context */ /* The integer of minutes this task is estimated to take */ estimated_minutes integer, + /* Instructions for how to complete the task. Will be displayed on the task page. */ + instructions text, /* * Will be called when the transition is enabled/fired. * signature: (case_id in integer, transition_key in varchar, custom_arg in varchar2) @@ -279,13 +333,6 @@ fire_callback varchar(100), fire_custom_arg text, /* - * Must insert rows into the wf_task_assignments table. - * Will be called when the transition becomes enabled - * signature: (task_id in integer, custom_arg in varchar) - */ - assignment_callback varchar(100), - assignment_custom_arg text, - /* * Must return the date that the timed transition should fire * Will be called when the transition is enabled * signature: (case_id in integer, transition_key in varchar, custom_arg in varchar2) return date @@ -322,22 +369,18 @@ notification_callback varchar(100), notification_custom_arg text, /* - * Unassigned callback - * Will be called whenever a task becomes unassigned - * Signature: (case_id in integer, transition_key in varchar, custom_arg in varchar2) + * Callback to handle unassigned tasks. + * Will be called when an enabled task becomes unassigned. + * Signature: (task_id in number, custom_arg in varchar2) */ unassigned_callback varchar(100), unassigned_custom_arg text, - /* name of the privilege we should check before allowing access - * to task information. - */ - access_privilege text, - /* table constraints */ + -- table constraints -- constraint wf_context_trans_trans_fk - foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) - on delete cascade, + foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) + on delete cascade, constraint wf_context_transition_pk - primary key (context_key, workflow_key, transition_key) + primary key (context_key, workflow_key, transition_key) ); create index wf_ctx_trans_wf_trans_idx on wf_context_transition_info(workflow_key, transition_key); @@ -348,6 +391,37 @@ '; +create table wf_context_role_info ( + context_key varchar(100) + constraint wf_context_role_context_fk + references wf_contexts(context_key) + on delete cascade, + workflow_key varchar(100) + constraint wf_context_role_workflow_fk + references wf_workflows(workflow_key) + on delete cascade, + role_key varchar(100), + /* + * Callback to programatically assign a role. + * Must call wordflow_case.*_role_assignment to make the assignments. + * Will be called when a transition for that role becomes enabled + * signature: (role_key in varchar2, custom_arg in varchar2) + */ + assignment_callback varchar(100), + assignment_custom_arg varchar(4000), + -- table constraints -- + constraint wf_context_role_role_fk + foreign key (workflow_key, role_key) references wf_roles(workflow_key, role_key) + on delete cascade, + constraint wf_context_role_info_pk + primary key (context_key, workflow_key, role_key) +); + +comment on table wf_context_role_info is ' + This table holds context-dependent info for roles, currently only the assignment callback +'; + + create table wf_context_task_panels ( context_key varchar(100) not null constraint wf_context_panels_context_fk @@ -358,15 +432,23 @@ references wf_workflows(workflow_key) on delete cascade, transition_key varchar(100) not null, - sort_key integer not null, + sort_order integer not null, header varchar(200) not null, template_url varchar(500) not null, - /* table constraints */ + /* Display this panel in place of the action panel */ + overrides_action_p char(1) default 'f' + constraint wf_context_panels_ovrd_p_ck + check (overrides_action_p in ('t','f')), + /* Display this panel only when the task has been started (and not finished) */ + only_display_when_started_p char(1) default 'f' + constraint wf_context_panels_display_p_ck + check (only_display_when_started_p in ('t','f')), + -- table constraints -- constraint wf_context_panels_trans_fk - foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) - on delete cascade, + foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) + on delete cascade, constraint wf_context_panels_pk - primary key (context_key, workflow_key, transition_key, sort_key) + primary key (context_key, workflow_key, transition_key, sort_order) ); create index wf_ctx_panl_workflow_trans_idx on wf_context_task_panels(workflow_key, transition_key); @@ -386,23 +468,23 @@ constraint wf_context_assign_workflow_fk references wf_workflows(workflow_key) on delete cascade, - transition_key varchar(100), + role_key varchar(100), party_id integer constraint wf_context_assign_party_fk references parties(party_id) on delete cascade, - /* table constraints */ - constraint wf_context_assign_trans_fk - foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) - on delete cascade, + -- table constraints -- constraint wf_context_assign_pk - primary key (context_key, workflow_key, transition_key, party_id) + primary key (context_key, workflow_key, role_key, party_id), + constraint wf_context_assign_role_fk + foreign key (workflow_key, role_key) references wf_roles(workflow_key, role_key) + on delete cascade ); -create index wf_ctx_assg_workflow_trans_idx on wf_context_assignments(workflow_key, transition_key); +create index wf_ctx_assg_workflow_trans_idx on wf_context_assignments(workflow_key, role_key); comment on table wf_context_assignments is ' - Static assignment at the context level. + Static (default) per-context assignments of roles to parties. '; @@ -426,7 +508,8 @@ constraint wf_cases_context_fk references wf_contexts(context_key) on delete cascade, - object_id integer constraint wf_cases_object_fk + object_id integer + constraint wf_cases_object_fk references acs_objects(object_id) on delete cascade, -- a toplevel state of the case @@ -445,41 +528,45 @@ create index wf_cases_object_id_idx on wf_cases(object_id); comment on table wf_cases is ' - The instance of a workflow, the actual object we''re concerned with in this - workflow. + The instance of a process, e.g. the case of publishing one article, + the case of handling one insurance claim, the case of handling + one ecommerce order, of fixing one ticket-tracker ticket. '; + comment on column wf_cases.object_id is ' - A case is itself an acs_object, but moreover, a case will always be about some - other acs_object. E.g. for ticket-tracker, the case_id will refer to an instance of - the ticket-tracker-workflow, while the object_id will refer to the ticket itself. - It is possible to have multiple cases around the same object. + A case is generally about some other object, e.g., an insurance claim, an article, + a ticket, an order, etc. This is the place to store the reference to that object. + It is not uncommong to have more than one case for the same object, e.g., we might + have one process for evaluating and honoring an insurance claim, and another for archiving + legal information about a claim. '; - create table wf_case_assignments ( case_id integer constraint wf_case_assign_fk references wf_cases(case_id) on delete cascade, workflow_key varchar(100), - transition_key varchar(100), + role_key varchar(100), party_id integer constraint wf_case_assign_party_fk references parties(party_id) on delete cascade, - constraint wf_case_assign_trans_fk - foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key), + -- table constraints -- constraint wf_case_assign_pk - primary key (case_id, transition_key, party_id) + primary key (case_id, role_key, party_id), + constraint wf_case_assign_role_fk + foreign key (workflow_key, role_key) references wf_roles(workflow_key, role_key) + on delete cascade ); create index wf_case_assgn_party_idx on wf_case_assignments(party_id); comment on table wf_case_assignments is ' - Manual assignment at the per-case level. + Manual per-case assignments of roles to parties. '; @@ -493,10 +580,12 @@ deadline timestamp constraint wf_case_deadline_nn not null, - constraint wf_case_deadline_trans_fk - foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key), + -- table constraints -- constraint wf_case_deadline_pk - primary key (case_id, transition_key) + primary key (case_id, transition_key), + constraint wf_case_deadline_trans_fk + foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) + on delete cascade ); @@ -543,9 +632,9 @@ references users(user_id) on delete cascade, hold_timeout timestamp, - /* -- */ + -- table constraints -- constraint wf_task_transition_fk - foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) + foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) ); create index wf_tasks_case_id_idx on wf_tasks(case_id); @@ -566,8 +655,9 @@ constraint wf_task_party_fk references parties(party_id) on delete cascade, + -- table constraints -- constraint wf_task_assignments_pk - primary key (task_id, party_id) + primary key (task_id, party_id) ); create index wf_task_asgn_party_id_idx on wf_task_assignments(party_id); @@ -613,8 +703,9 @@ consumed_journal_id integer constraint wf_token_consumed_journal_fk references journal_entries(journal_id), + -- table constraints -- constraint wf_token_place_fk - foreign key (workflow_key, place_key) references wf_places(workflow_key, place_key) + foreign key (workflow_key, place_key) references wf_places(workflow_key, place_key) ); create index wf_tokens_case_id_idx on wf_tokens(case_id); @@ -641,8 +732,9 @@ constraint wf_attr_val_audit_journal_fk references journal_entries(journal_id), attr_value text, + -- table constraints -- constraint wf_attr_val_audit_pk - primary key (case_id, attribute_id, journal_id) + primary key (case_id, attribute_id, journal_id) ); create index wf_attr_val_aud_attr_id_idx on wf_attribute_value_audit(attribute_id); @@ -664,6 +756,7 @@ t.workflow_key, t.sort_order, t.trigger_type, + t.role_key, c.context_key, c.context_name from wf_transitions t, wf_contexts c; @@ -682,13 +775,13 @@ t.sort_order, t.trigger_type, t.context_key, + t.role_key, ct.estimated_minutes, + ct.instructions, ct.enable_callback, ct.enable_custom_arg, ct.fire_callback, ct.fire_custom_arg, - ct.assignment_callback, - ct.assignment_custom_arg, ct.time_callback, ct.time_custom_arg, ct.deadline_callback, @@ -699,8 +792,7 @@ ct.notification_callback, ct.notification_custom_arg, ct.unassigned_callback, - ct.unassigned_custom_arg, - ct.access_privilege + ct.unassigned_custom_arg from wf_transition_contexts t LEFT OUTER JOIN wf_context_transition_info ct on (ct.workflow_key = t.workflow_key and ct.transition_key = t.transition_key and @@ -709,6 +801,25 @@ /* + * Returns all the information stored about a certain role + * in all contexts. You'll usually want to use this with a + * "where context = " clause. + */ +create view wf_role_info as +select r.role_key, + r.role_name, + r.workflow_key, + c.context_key, + cr.assignment_callback, + cr.assignment_custom_arg +from wf_contexts c, wf_roles r LEFT OUTER JOIN wf_context_role_info cr +on (cr.workflow_key = r.workflow_key and + cr.role_key = r.role_key) +where cr.context_key = c.context_key; + + + +/* * This view makes it easy to get the input/output places of a transition */ create view wf_transition_places as @@ -748,12 +859,11 @@ t.sort_order, t.trigger_type, t.context_key, + t.role_key, t.enable_callback, t.enable_custom_arg, t.fire_callback, t.fire_custom_arg, - t.assignment_callback, - t.assignment_custom_arg, t.time_callback, t.time_custom_arg, t.deadline_callback, @@ -763,10 +873,10 @@ t.hold_timeout_custom_arg, t.notification_callback, t.notification_custom_arg, - t.unassigned_callback, - t.unassigned_custom_arg, t.estimated_minutes, - t.access_privilege + t.instructions, + t.unassigned_callback, + t.unassigned_custom_arg from wf_transition_info t, wf_cases c where t.workflow_key = c.workflow_key @@ -822,6 +932,7 @@ and c.case_id = ta.case_id and c.state = 'active' and tr.transition_key = ta.transition_key +and tr.workflow_key = ta.workflow_key and tr.trigger_type = 'user' and tr.context_key = c.context_key and tasgn.task_id = ta.task_id Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/wf-core-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/wf-core-drop.sql,v diff -u -r1.1 -r1.2 --- openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/wf-core-drop.sql 11 Apr 2001 05:00:13 -0000 1.1 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/wf-core-drop.sql 19 Nov 2001 18:20:33 -0000 1.2 @@ -26,21 +26,23 @@ end loop; return null; -end; +end;' language 'plpgsql'; select inline_0 (); drop function inline_0 (); /* Sequences */ -drop sequence wf_task_id_seq; -drop sequence wf_token_id_seq; +drop sequence t_wf_task_id_seq; +drop sequence t_wf_token_id_seq; /* Views */ - +drop view wf_task_id_seq; +drop view wf_token_id_seq; drop view wf_user_tasks; drop view wf_enabled_transitions; drop view wf_transition_places; +drop view wf_role_info; drop view wf_transition_info; drop view wf_transition_contexts; @@ -56,15 +58,17 @@ /* Context level */ drop table wf_context_assignments; drop table wf_context_task_panels; +drop table wf_context_role_info; drop table wf_context_transition_info; +drop table wf_context_workflow_info; drop table wf_contexts; /* Knowledge Level */ -drop table wf_attribute_info; -drop table wf_transition_assignment_map; +drop table wf_transition_role_assign_map; drop table wf_transition_attribute_map; drop table wf_arcs; drop table wf_transitions; +drop table wf_roles; drop table wf_places; drop table wf_workflows; Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/workflow-case-package-body.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/workflow-case-package-body.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/workflow-case-package-body.sql 19 Nov 2001 18:20:33 -0000 1.1 @@ -0,0 +1,2056 @@ +-- create or replace package body workflow_case +-- function new +create function workflow_case__new (integer,varchar,varchar,integer,timestamp,integer,varchar) +returns integer as ' +declare + new__case_id alias for $1; -- default null + new__workflow_key alias for $2; + new__context_key alias for $3; -- default null + new__object_id alias for $4; + new__creation_date alias for $5; -- default now() + new__creation_user alias for $6; -- default null + new__creation_ip alias for $7; -- default null + v_case_id integer; + v_workflow_case_table varchar; + v_context_key_for_query varchar; +begin + if new__context_key = '''' or new__context_key is null then + v_context_key_for_query := ''default''; + else + v_context_key_for_query := new__context_key; + end if; + + /* insert a row into acs_objects */ + v_case_id := acs_object__new( + new__case_id, + new__workflow_key, + new__creation_date, + new__creation_user, + new__creation_ip, + null + ); + + /* insert the case in to the general wf_cases table */ + insert into wf_cases + (case_id, workflow_key, context_key, object_id, state) + values + (v_case_id, new__workflow_key, v_context_key_for_query, new__object_id, ''created''); + + /* insert the case into the workflow-specific cases table */ + select table_name into v_workflow_case_table + from acs_object_types + where object_type = new__workflow_key; + + execute ''insert into '' || v_workflow_case_table || '' (case_id) values ('' || v_case_id || '')''; + + return v_case_id; + +end;' language 'plpgsql'; + + +-- procedure add_manual_assignment +create function workflow_case__add_manual_assignment (integer,varchar,integer) +returns integer as ' +declare + add_manual_assignment__case_id alias for $1; + add_manual_assignment__role_key alias for $2; + add_manual_assignment__party_id alias for $3; + v_workflow_key varchar; + v_num_rows integer; +begin + select count(*) + into v_num_rows + from wf_case_assignments + where case_id = add_manual_assignment__case_id + and role_key = add_manual_assignment__role_key + and party_id = add_manual_assignment__party_id; + + if v_num_rows = 0 then + select workflow_key + into v_workflow_key + from wf_cases + where case_id = add_manual_assignment__case_id; + + insert into wf_case_assignments ( + case_id, + workflow_key, + role_key, + party_id + ) values ( + add_manual_assignment__case_id, + v_workflow_key, + add_manual_assignment__role_key, + add_manual_assignment__party_id + ); + end if; + + return 0; +end;' language 'plpgsql'; + + +-- procedure remove_manual_assignment +create function workflow_case__remove_manual_assignment (integer,varchar,integer) +returns integer as ' +declare + remove_manual_assignment__case_id alias for $1; + remove_manual_assignment__role_key alias for $2; + remove_manual_assignment__party_id alias for $3; + v_workflow_key varchar; +begin + select workflow_key + into v_workflow_key + from wf_cases + where case_id = remove_manual_assignment__case_id; + + delete + from wf_case_assignments + where workflow_key = v_workflow_key + and case_id = remove_manual_assignment__case_id + and role_key = remove_manual_assignment__role_key + and party_id = remove_manual_assignment__party_id; + + return 0; +end;' language 'plpgsql'; + + +-- procedure clear_manual_assignments +create function workflow_case__clear_manual_assignments (integer,varchar) +returns integer as ' +declare + clear_manual_assignments__case_id alias for $1; + clear_manual_assignments__role_key alias for $2; + v_workflow_key varchar; +begin + select workflow_key + into v_workflow_key + from wf_cases + where case_id = clear_manual_assignments__case_id; + + delete + from wf_case_assignments + where workflow_key = v_workflow_key + and case_id = clear_manual_assignments__case_id + and role_key = clear_manual_assignments__role_key; + return 0; +end;' language 'plpgsql'; + + +-- procedure start_case +create function workflow_case__start_case (integer,integer,varchar,varchar) +returns integer as ' +declare + start_case__case_id alias for $1; + start_case__creation_user alias for $2; -- default null + start_case__creation_ip alias for $3; -- default null + start_case__msg alias for $4; -- default null + v_journal_id integer; +begin + /* Add an entry to the journal */ + v_journal_id := journal_entry__new( + null, + start_case__case_id, + ''case start'', + ''Case started'', + now(), + start_case__creation_user, + start_case__creation_ip, + start_case__msg + ); + + update wf_cases + set state = ''active'' + where case_id = start_case__case_id; + + PERFORM workflow_case__add_token ( + start_case__case_id, + ''start'', + v_journal_id + ); + + -- Turn the wheels + PERFORM workflow_case__sweep_automatic_transitions ( + start_case__case_id, + v_journal_id + ); + + return 0; +end;' language 'plpgsql'; + + +-- procedure delete +create function workflow_case__delete (integer) +returns integer as ' +declare + delete__case_id alias for $1; + v_workflow_case_table varchar; +begin + /* delete attribute_value_audit, tokens, tasks */ + delete from wf_attribute_value_audit + where case_id = delete__case_id; + + delete from wf_case_assignments + where case_id = delete__case_id; + + delete from wf_case_deadlines + where case_id = delete__case_id; + + delete from wf_tokens + where case_id = delete__case_id; + + delete from wf_task_assignments + where task_id in (select task_id + from wf_tasks + where case_id = delete__case_id); + + delete from wf_tasks + where case_id = delete__case_id; + + /* delete the journal */ + PERFORM journal_entry__delete_for_object(delete__case_id); + + /* delete from the workflow-specific cases table */ + select table_name into v_workflow_case_table + from acs_object_types ot, wf_cases c + where c.case_id = delete__case_id + and object_type = c.workflow_key; + + execute ''delete from '' || v_workflow_case_table || '' where case_id = '' || delete__case_id; + + /* delete from the generic cases table */ + delete from wf_cases where case_id = delete__case_id; + + /* delete from acs-objects */ + PERFORM acs_object__delete(delete__case_id); + + return 0; +end;' language 'plpgsql'; + + +-- procedure suspend +create function workflow_case__suspend (integer,integer,varchar,varchar) +returns integer as ' +declare + suspend__case_id alias for $1; + suspend__user_id alias for $2; -- default null + suspend__ip_address alias for $3; -- default null + suspend__msg alias for $4; -- default null + v_state varchar; + v_journal_id integer; +begin + select state into v_state + from wf_cases + where case_id = suspend__case_id; + + if v_state != ''active'' then + raise EXCEPTION ''-20000: Only active cases can be suspended''; + end if; + + /* Add an entry to the journal */ + v_journal_id := journal_entry__new( + null, + suspend__case_id, + ''case suspend'', + ''case suspended'', + now(), + suspend__user_id, + suspend__ip_address, + suspend__msg + ); + + update wf_cases + set state = ''suspended'' + where case_id = suspend__case_id; + + return 0; +end;' language 'plpgsql'; + + +-- procedure resume +create function workflow_case__resume (integer,integer,varchar,varchar) +returns integer as ' +declare + resume__case_id alias for $1; + resume__user_id alias for $2; -- default null + resume__ip_address alias for $3; -- default null + resume__msg alias for $4; -- default null + v_state varchar; + v_journal_id integer; +begin + select state into v_state + from wf_cases + where case_id = resume__case_id; + + if v_state != ''suspended'' and v_state != ''canceled'' then + raise EXCEPTION ''-20000: Only suspended or canceled cases can be resumed''; + end if; + + /* Add an entry to the journal */ + v_journal_id := journal_entry__new( + null, + resume__case_id, + ''case resume'', + ''case resumed'', + now(), + resume__user_id, + resume__ip_address, + resume__msg + ); + + update wf_cases + set state = ''active'' + where case_id = resume__case_id; + + return 0; +end;' language 'plpgsql'; + + +-- procedure cancel +create function workflow_case__cancel (integer,integer,varchar,varchar) +returns integer as ' +declare + cancel__case_id alias for $1; + cancel__user_id alias for $2; -- default null + cancel__ip_address alias for $3; -- default null + cancel__msg alias for $4; -- default null + v_state varchar; + v_journal_id integer; +begin + select state into v_state + from wf_cases + where case_id = cancel__case_id; + + if v_state != ''active'' and v_state != ''suspended'' then + raise EXCEPTION ''-20000: Only active or suspended cases can be canceled''; + end if; + + /* Add an entry to the journal */ + v_journal_id := journal_entry__new( + null, + cancel__case_id, + ''case cancel'', + ''Case canceled'', + now(), + cancel__user_id, + cancel__ip_address, + cancel__msg + ); + + update wf_cases + set state = ''canceled'' + where case_id = cancel__case_id; + + return 0; +end;' language 'plpgsql'; + + +-- procedure fire_message_transition +create function workflow_case__fire_message_transition (integer) +returns integer as ' +declare + fire_message_transition__task_id alias for $1; + v_case_id integer; + v_transition_name varchar; + v_trigger_type varchar; + v_journal_id integer; +begin + select t.case_id, tr.transition_name, tr.trigger_type + into v_case_id, v_transition_name, v_trigger_type + from wf_tasks t, wf_transitions tr + where t.task_id = fire_message_transition__task_id + and tr.workflow_key = t.workflow_key + and tr.transition_key = t.transition_key; + + if v_trigger_type != ''message'' then + raise EXCEPTION ''-20000: Transition "%" is not message triggered'', v_transition_name; + end if; + + /* Add an entry to the journal */ + v_journal_id := journal_entry__new ( + null, + v_case_id, + ''task '' || fire_message_transition__task_id || '' fire'', + v_transition_name || '' fired'', + now(), + null, + null, + null + ); + + PERFORM workflow_case__fire_transition_internal( + fire_message_transition__task_id, + v_journal_id + ); + + PERFORM workflow_case__sweep_automatic_transitions ( + v_case_id, + v_journal_id + ); + + return 0; +end;' language 'plpgsql'; + + + /* + * A wrapper for user tasks that uses the start/commit/cancel model for firing transitions. + * Returns journal_id. + */ +-- function begin_task_action +create function workflow_case__begin_task_action (integer,varchar,varchar,integer,varchar) +returns integer as ' +declare + begin_task_action__task_id alias for $1; + begin_task_action__action alias for $2; + begin_task_action__action_ip alias for $3; + begin_task_action__user_id alias for $4; + begin_task_action__msg alias for $5; -- default null + v_state varchar; + v_journal_id integer; + v_case_id integer; + v_transition_name varchar; + v_num_rows integer; +begin + select state into v_state + from wf_tasks + where task_id = begin_task_action__task_id; + + if begin_task_action__action = ''start'' then + if v_state != ''enabled'' then + raise EXCEPTION ''-20000: Task is in state "%", but it must be in state "enabled" to be started.'', v_state; + end if; + + select case when count(*) = 0 then 0 else 1 end into v_num_rows + from wf_user_tasks + where task_id = begin_task_action__task_id + and user_id = begin_task_action__user_id; + + if v_num_rows = 0 then + raise EXCEPTION ''-20000: You are not assigned to this task.''; + end if; + else if begin_task_action__action = ''finish'' or begin_task_action__action = ''cancel'' then + + if v_state = ''started'' then + /* Is this user the holding user? */ + select case when count(*) = 0 then 0 else 1 end into v_num_rows + from wf_tasks + where task_id = begin_task_action__task_id + and holding_user = begin_task_action__user_id; + if v_num_rows = 0 then + raise EXCEPTION ''-20000: You are the user currently working on this task.''; + end if; + else if v_state = ''enabled'' then + if begin_task_action__action = ''cancel'' then + raise EXCEPTION ''-20000: You can only cancel a task in state "started", but this task is in state "%"'', v_state; + end if; + + /* Is this user assigned to this task? */ + select case when count(*) = 0 then 0 else 1 end into v_num_rows + from wf_user_tasks + where task_id = begin_task_action__task_id + and user_id = begin_task_action__user_id; + if v_num_rows = 0 then + raise EXCEPTION ''-20000: You are not assigned to this task.''; + end if; + + /* This task is finished without an explicit start. + * Store the user as the holding_user */ + update wf_tasks + set holding_user = begin_task_action__user_id + where task_id = begin_task_action__task_id; + else + raise EXCEPTION ''-20000: Task is in state "%", but it must be in state "enabled" or "started" to be finished'', v_state; + end if; end if; + + else if begin_task_action__action = ''comment'' then + -- We currently allow anyone to comment on a task + -- (need this line because PL/SQL does not like empty if blocks) + v_num_rows := 0; + end if; end if; end if; + + select t.case_id, tr.transition_name into v_case_id, v_transition_name + from wf_tasks t, + wf_transitions tr + where t.task_id = begin_task_action__task_id + and tr.workflow_key = t.workflow_key + and tr.transition_key = t.transition_key; + + /* Insert a journal entry */ + + v_journal_id := journal_entry__new ( + null, + v_case_id, + ''task '' || begin_task_action__task_id || '' '' || begin_task_action__action, + v_transition_name || '' '' || begin_task_action__action, + now(), + begin_task_action__user_id, + begin_task_action__action_ip, + begin_task_action__msg + ); + + return v_journal_id; + +end;' language 'plpgsql'; + + +-- procedure end_task_action +create function workflow_case__end_task_action (integer,varchar,integer) +returns integer as ' +declare + end_task_action__journal_id alias for $1; + end_task_action__action alias for $2; + end_task_action__task_id alias for $3; + v_user_id integer; +begin + select creation_user into v_user_id + from acs_objects + where object_id = end_task_action__journal_id; + + /* Update the workflow state */ + + if end_task_action__action = ''start'' then + PERFORM workflow_case__start_task(end_task_action__task_id, + v_user_id, + end_task_action__journal_id + ); + else if end_task_action__action = ''finish'' then + PERFORM workflow_case__finish_task(end_task_action__task_id, + end_task_action__journal_id + ); + else if end_task_action__action = ''cancel'' then + PERFORM workflow_case__cancel_task(end_task_action__task_id, + end_task_action__journal_id + ); + else if end_task_action__action != ''comment'' then + raise EXCEPTION ''-20000: Unknown action "%"'', end_task_action__action; + end if; end if; end if; end if; + + return 0; +end;' language 'plpgsql'; + + +-- function task_action +create function workflow_case__task_action (integer,varchar,varchar,integer,varchar) +returns integer as ' +declare + task_action__task_id alias for $1; + task_action__action alias for $2; + task_action__action_ip alias for $3; + task_action__user_id alias for $4; + task_action__msg alias for $5; -- default null + v_journal_id integer; +begin + v_journal_id := workflow_case__begin_task_action ( + task_action__task_id, + task_action__action, + task_action__action_ip, + task_action__user_id, + task_action__msg + ); + + PERFORM workflow_case__end_task_action ( + v_journal_id, + task_action__action, + task_action__task_id + ); + + return v_journal_id; + +end;' language 'plpgsql'; + + +-- procedure set_attribute_value +create function workflow_case__set_attribute_value (integer,varchar,varchar) +returns integer as ' +declare + set_attribute_value__journal_id alias for $1; + set_attribute_value__attribute_name alias for $2; + set_attribute_value__value alias for $3; + v_workflow_key varchar; + v_case_id integer; + v_attribute_id integer; +begin + select o.object_type, o.object_id into v_workflow_key, v_case_id + from journal_entries je, acs_objects o + where je.journal_id = set_attribute_value__journal_id + and o.object_id = je.object_id; + + select attribute_id into v_attribute_id + from acs_attributes + where object_type = v_workflow_key + and attribute_name = set_attribute_value__attribute_name; + + PERFORM acs_object__set_attribute ( + v_case_id, + set_attribute_value__attribute_name, + set_attribute_value__value + ); + + insert into wf_attribute_value_audit + (case_id, attribute_id, journal_id, attr_value) + values + (v_case_id, v_attribute_id, set_attribute_value__journal_id, + set_attribute_value__value); + + return 0; +end;' language 'plpgsql'; + + +-- function get_attribute_value +create function workflow_case__get_attribute_value (integer,varchar) +returns varchar as ' +declare + get_attribute_value__case_id alias for $1; + get_attribute_value__attribute_name alias for $2; +begin + return acs_object__get_attribute ( + get_attribute_value__case_id, + get_attribute_value__attribute_name + ); + +end;' language 'plpgsql'; + + +-- procedure add_task_assignment +create function workflow_case__add_task_assignment (integer,integer,boolean) +returns integer as ' +declare + add_task_assignment__task_id alias for $1; + add_task_assignment__party_id alias for $2; + add_task_assignment__permanent_p alias for $3; + v_count integer; + v_workflow_key wf_workflows.workflow_key%TYPE; + v_context_key wf_contexts.context_key%TYPE; + v_case_id wf_cases.case_id%TYPE; + v_role_key wf_roles.role_key%TYPE; + v_transition_key wf_transitions.transition_key%TYPE; + v_notification_callback wf_context_transition_info.notification_callback%TYPE; + v_notification_custom_arg wf_context_transition_info.notification_custom_arg%TYPE; + callback_rec record; + v_assigned_user record; +begin + -- get some needed information + + select ta.case_id, ta.workflow_key, ta.transition_key, tr.role_key, c.context_key + into v_case_id, v_workflow_key, v_transition_key, v_role_key, v_context_key + from wf_tasks ta, wf_transitions tr, wf_cases c + where ta.task_id = add_task_assignment__task_id + and tr.workflow_key = ta.workflow_key + and tr.transition_key = ta.transition_key + and c.case_id = ta.case_id; + + -- make the same assignment as a manual assignment + + if add_task_assignment__permanent_p = ''t'' then + /* We do this up-front, because + * even though the user already had a task assignment, + * he might not have a case assignment. + */ + perform workflow_case__add_manual_assignment ( + v_case_id, + v_role_key, + add_task_assignment__party_id + ); + end if; + + -- check that we do not hit the unique constraint + + select count(*) into v_count + from wf_task_assignments + where task_id = add_task_assignment__task_id + and party_id = add_task_assignment__party_id; + + if v_count > 0 then + return null; + end if; + + -- get callback information + + select notification_callback, + notification_custom_arg into callback_rec + from wf_context_transition_info + where context_key = v_context_key + and workflow_key = v_workflow_key + and transition_key = v_transition_key; + + + if FOUND then + v_notification_callback := callback_rec.notification_callback; + v_notification_custom_arg := callback_rec.notification_custom_arg; + else + v_notification_callback := null; + v_notification_custom_arg := null; + end if; + + -- notify any new assignees + + for v_assigned_user in + select distinct u.user_id + from users u + where u.user_id not in ( + select distinct u2.user_id + from wf_task_assignments tasgn2, + party_approved_member_map m2, + users u2 + where tasgn2.task_id = add_task_assignment__task_id + and m2.party_id = tasgn2.party_id + and u2.user_id = m2.member_id) + and exists ( + select 1 + from party_approved_member_map m + where m.member_id = u.user_id + and m.party_id = add_task_assignment__party_id + ) + LOOP + PERFORM workflow_case__notify_assignee ( + add_task_assignment__task_id, + v_assigned_user.user_id, + v_notification_callback, + v_notification_custom_arg + ); + end loop; + + -- do the insert + + insert into wf_task_assignments ( + task_id, + party_id + ) values ( + add_task_assignment__task_id, + add_task_assignment__party_id + ); + + return 0; +end;' language 'plpgsql'; + + +-- procedure remove_task_assignment +create function workflow_case__remove_task_assignment (integer,integer,boolean) +returns integer as ' +declare + remove_task_assignment__task_id alias for $1; + remove_task_assignment__party_id alias for $2; + remove_task_assignment__permanent_p alias for $3; + v_num_assigned integer; + v_case_id integer; + v_role_key wf_roles.role_key%TYPE; + v_workflow_key varchar; + v_transition_key varchar; + v_context_key varchar; + callback_rec record; +begin + -- get some information + + select ta.case_id, ta.transition_key, tr.role_key, ta.workflow_key, c.context_key + into v_case_id, v_transition_key, v_role_key, v_workflow_key, v_context_key + from wf_tasks ta, wf_transitions tr, wf_cases c + where ta.task_id = remove_task_assignment__task_id + and tr.workflow_key = ta.workflow_key + and tr.transition_key = ta.transition_key + and c.case_id = ta.case_id; + + -- make the same assignment as a manual assignment + + if remove_task_assignment__permanent_p = ''t'' then + perform workflow_case__remove_manual_assignment ( + v_case_id, + v_role_key, + remove_task_assignment__party_id + ); + end if; + + -- now delete the row + + delete + from wf_task_assignments + where task_id = remove_task_assignment__task_id + and party_id = remove_task_assignment__party_id; + + -- check if the task now became unassigned + + select count(*) + into v_num_assigned + from wf_task_assignments + where task_id = remove_task_assignment__task_id; + + if v_num_assigned > 0 then + return 0; + end if; + + -- yup, the task is now unassigned; fire the callback + + select unassigned_callback, unassigned_custom_arg + into callback_rec + from wf_context_transition_info + where workflow_key = v_workflow_key + and context_key = v_context_key + and transition_key = v_transition_key; + if FOUND then + PERFORM workflow_case__execute_unassigned_callback ( + callback_rec.unassigned_callback, + remove_task_assignment__task_id, + callback_rec.unassigned_custom_arg + ); + end if; + + return 0; +end;' language 'plpgsql'; + + +-- procedure clear_task_assignments +create function workflow_case__clear_task_assignments (integer,boolean) +returns integer as ' +declare + clear_task_assignments__task_id alias for $1; + clear_task_assignments__permanent_p alias for $2; + v_case_id integer; + v_transition_key varchar; + v_role_key wf_roles.role_key%TYPE; + v_workflow_key varchar; + v_context_key varchar; + v_callback varchar; + v_custom_arg varchar; +begin + -- get some information + + select ta.case_id, ta.transition_key, tr.role_key, ta.workflow_key, c.context_key + into v_case_id, v_transition_key, v_role_key, v_workflow_key, v_context_key + from wf_tasks ta, wf_transitions tr, wf_cases c + where ta.task_id = clear_task_assignments__task_id + and tr.workflow_key = ta.workflow_key + and tr.transition_key = ta.transition_key + and c.case_id = ta.case_id; + + -- make the unassignment stick as a manual assignment + + if clear_task_assignments__permanent_p = ''t'' then + perform workflow_case__clear_manual_assignments ( + v_case_id, + v_role_key + ); + end if; + + -- delete the rows + + + delete + from wf_task_assignments + where task_id = clear_task_assignments__task_id; + + -- fire the unassigned callback + + select unassigned_callback, unassigned_custom_arg + into v_callback, v_custom_arg + from wf_context_transition_info + where workflow_key = v_workflow_key + and context_key = v_context_key + and transition_key = v_transition_key; + + PERFORM workflow_case__execute_unassigned_callback ( + v_callback, + clear_task_assignments__task_id, + v_custom_arg + ); + + return 0; +end;' language 'plpgsql'; + + +-- procedure set_case_deadline +create function workflow_case__set_case_deadline (integer,varchar,timestamp) +returns integer as ' +declare + set_case_deadline__case_id alias for $1; + set_case_deadline__transition_key alias for $2; + set_case_deadline__deadline alias for $3; + v_workflow_key wf_workflows.workflow_key%TYPE; +begin + -- delete the current deadline row + delete + from wf_case_deadlines + where case_id = set_case_deadline__case_id + and transition_key = set_case_deadline__transition_key; + + if set_case_deadline__deadline is not null then + -- get some info + select workflow_key + into v_workflow_key + from wf_cases + where case_id = set_case_deadline__case_id; + + -- insert new deadline row + insert into wf_case_deadlines ( + case_id, + workflow_key, + transition_key, + deadline + ) values ( + set_case_deadline__case_id, + v_workflow_key, + set_case_deadline__transition_key, + set_case_deadline__deadline + ); + end if; + return 0; +end;' language 'plpgsql'; + + +-- procedure remove_case_deadline +create function workflow_case__remove_case_deadline (integer,varchar) +returns integer as ' +declare + remove_case_deadline__case_id alias for $1; + remove_case_deadline__transition_key alias for $2; +begin + perform workflow_case__set_case_deadline ( + remove_case_deadline__case_id, + remove_case_deadline__transition_key, + null + ); + + return 0; +end;' language 'plpgsql'; + + + + + + + + + +-- function evaluate_guard +create function workflow_case__evaluate_guard (varchar,varchar,integer,varchar,varchar,varchar,varchar) +returns boolean as ' +declare + evaluate_guard__callback alias for $1; + evaluate_guard__custom_arg alias for $2; + evaluate_guard__case_id alias for $3; + evaluate_guard__workflow_key alias for $4; + evaluate_guard__transition_key alias for $5; + evaluate_guard__place_key alias for $6; + evaluate_guard__direction alias for $7; + v_guard_happy_p boolean; + v_rec record; + v_str text default ''''; +begin + if evaluate_guard__callback = '''' or + evaluate_guard__callback is null then + -- null guard evaluates to true + return ''t''; + else + if evaluate_guard__callback = ''#'' then + return ''f''; + else + v_str := ''select '' || evaluate_guard__callback + || ''('' || + evaluate_guard__case_id || '','' || + quote_literal(evaluate_guard__workflow_key) || '','' || + quote_literal(evaluate_guard__transition_key) || '','' || + quote_literal(evaluate_guard__place_key) || '','' || + quote_literal(evaluate_guard__direction) || '','' || + coalesce(quote_literal(evaluate_guard__custom_arg),''null'') || '') as guard_happy_p''; + raise notice ''str = %'', v_str; + for v_rec in + execute v_str + LOOP + return v_rec.guard_happy_p; + end LOOP; + end if; + end if; + + return null; + +end;' language 'plpgsql'; + + +-- procedure execute_transition_callback +create function workflow_case__execute_transition_callback (varchar,varchar,integer,varchar) +returns integer as ' +declare + execute_transition_callback__callback alias for $1; + execute_transition_callback__custom_arg alias for $2; + execute_transition_callback__case_id alias for $3; + execute_transition_callback__transition_key alias for $4; + v_str text; +begin + if execute_transition_callback__callback != '''' and execute_transition_callback__callback is not null then + v_str := ''select '' || execute_transition_callback__callback + || ''('' || execute_transition_callback__case_id || '','' || + quote_literal(execute_transition_callback__transition_key) || '','' || + coalesce(quote_literal(execute_transition_callback__custom_arg),''null'') || '')''; + execute v_str; + end if; + + return 0; +end;' language 'plpgsql'; + + +-- function execute_time_callback +create function workflow_case__execute_time_callback (varchar,varchar,integer,varchar) +returns timestamp as ' +declare + execute_time_callback__callback alias for $1; + execute_time_callback__custom_arg alias for $2; + execute_time_callback__case_id alias for $3; + execute_time_callback__transition_key alias for $4; + v_rec record; + v_str text; +begin + if execute_time_callback__callback = '''' or execute_time_callback__callback is null then + raise EXCEPTION ''-20000: There''''s no time_callback function for the timed transition "%"'', execute_time_callback__transition_key; + end if; + + v_str := ''select '' || execute_time_callback__callback || ''('' || + execute_time_callback__case_id || '','' || + quote_literal(execute_time_callback__transition_key) || '','' || + coalesce(quote_literal(execute_time_callback__custom_arg),''null'') || '') as trigger_time''; + + for v_rec in execute v_str + LOOP + return v_rec.trigger_time; + end LOOP; + + return null; + +end;' language 'plpgsql'; + + +-- function get_task_deadline +create function workflow_case__get_task_deadline (varchar,varchar,varchar,integer,varchar) +returns timestamp as ' +declare + get_task_deadline__callback alias for $1; + get_task_deadline__custom_arg alias for $2; + get_task_deadline__attribute_name alias for $3; + get_task_deadline__case_id alias for $4; + get_task_deadline__transition_key alias for $5; + v_deadline timestamp; + v_rec record; + v_str varchar; +begin + /* + * 1. or if there is a row in wf_case_deadlines, we use that + * 2. if there is a callback, we execute that + * 3. otherwise, if there is an attribute, we use that + */ + + /* wf_case_deadlines */ + select deadline into v_deadline + from wf_case_deadlines + where case_id = get_task_deadline__case_id + and transition_key = get_task_deadline__transition_key; + + if NOT FOUND then + if get_task_deadline__callback != '''' and get_task_deadline__callback is not null then + /* callback */ + v_str := ''select '' || get_task_deadline__callback || ''('' || + get_task_deadline__case_id || '','' || + quote_literal(get_task_deadline__transition_key) || '','' || + coalesce(quote_literal(get_task_deadline__custom_arg),''null'') || '') as deadline''; + + for v_rec in execute v_str + LOOP + v_deadline := v_rec.deadline; + exit; + end LOOP; + else if get_task_deadline__attribute_name != '''' and get_task_deadline__attribute_name is not null then + /* attribute */ + v_deadline := acs_object__get_attribute ( + get_task_deadline__case_id, + get_task_deadline__attribute_name + ); + else + v_deadline := null; + end if; end if; + end if; + + return v_deadline; + +end;' language 'plpgsql'; + + +-- function execute_hold_timeout_callback +create function workflow_case__execute_hold_timeout_callback (varchar,varchar,integer,varchar) +returns timestamp as ' +declare + execute_hold_timeout_callback__callback alias for $1; + execute_hold_timeout_callback__custom_arg alias for $2; + execute_hold_timeout_callback__case_id alias for $3; + execute_hold_timeout_callback__transition_key alias for $4; + v_hold_timeout timestamp; + v_rec record; + v_str text; +begin + if execute_hold_timeout_callback__callback = '''' or execute_hold_timeout_callback__callback is null then + return null; + end if; + + v_str := ''select '' || execute_hold_timeout_callback__callback + || ''('' || + execute_hold_timeout_callback__case_id || '','' || + quote_literal(execute_hold_timeout_callback__transition_key) || + '','' || + coalesce(quote_literal(execute_hold_timeout_callback__custom_arg),''null'') || '') as hold_timeout''; + + for v_rec in execute v_str + LOOP + return v_rec.hold_timeout; + end LOOP; + + return null; + +end;' language 'plpgsql'; + + +-- procedure execute_unassigned_callback +create function workflow_case__execute_unassigned_callback (varchar,integer,varchar) +returns integer as ' +declare + callback alias for $1; + task_id alias for $2; + custom_arg alias for $3; + v_str text; +begin + if callback != '''' and callback is not null then + v_str := ''select '' || callback + || ''('' || task_id || '','' || + coalesce(quote_literal(custom_arg),''null'') + || '')''; + + execute v_str; + end if; + + return 0; +end;' language 'plpgsql'; + + +-- procedure set_task_assignments +create function workflow_case__set_task_assignments (integer,varchar,varchar) +returns integer as ' +declare + set_task_assignments__task_id alias for $1; + set_task_assignments__callback alias for $2; + set_task_assignments__custom_arg alias for $3; + v_done_p boolean; + case_assignment_rec record; + context_assignment_rec record; + v_str text; +begin + + /* Find out who to assign the given task to. + * + * 1. See if there are rows in wf_case_assignments. + * 2. If not, and a callback is defined, execute that. + * 3. Otherwise, grab the assignment from the workflow context. + * + * (We used to use the callback first, but that makes + * reassignment of tasks difficult.) + */ + + v_done_p := ''f''; + for case_assignment_rec in select party_id + from wf_case_assignments ca, wf_tasks t, wf_transitions tr + where t.task_id = set_task_assignments__task_id + and ca.case_id = t.case_id + and ca.role_key = tr.role_key + and tr.workflow_key = t.workflow_key + and tr.transition_key = t.transition_key + LOOP + v_done_p := ''t''; + PERFORM workflow_case__add_task_assignment ( + set_task_assignments__task_id, + case_assignment_rec.party_id, + ''f'' + ); + end loop; + if v_done_p != ''t'' then + + if set_task_assignments__callback != '''' and set_task_assignments__callback is not null then + v_str := ''select ''|| set_task_assignments__callback || ''('' || + set_task_assignments__task_id || '','' || + coalesce(quote_literal(set_task_assignments__custom_arg),''null'') || '')''; + execute v_str; + else + for context_assignment_rec in + select party_id + from wf_context_assignments ca, wf_cases c, wf_tasks t, wf_transitions tr + where t.task_id = set_task_assignments__task_id + and c.case_id = t.case_id + and ca.context_key = c.context_key + and ca.workflow_key = t.workflow_key + and ca.role_key = tr.role_key + and tr.workflow_key = t.workflow_key + and tr.transition_key = t.transition_key + LOOP + PERFORM workflow_case__add_task_assignment ( + set_task_assignments__task_id, + context_assignment_rec.party_id, + ''f'' + ); + end LOOP; + end if; + end if; + + return 0; +end;' language 'plpgsql'; + + +-- procedure add_token +create function workflow_case__add_token (integer,varchar,integer) +returns integer as ' +declare + add_token__case_id alias for $1; + add_token__place_key alias for $2; + add_token__journal_id alias for $3; + v_token_id integer; + v_workflow_key varchar; +begin + select wf_token_id_seq.nextval into v_token_id from dual; + + select workflow_key into v_workflow_key + from wf_cases c + where c.case_id = add_token__case_id; + + insert into wf_tokens + (token_id, case_id, workflow_key, place_key, state, produced_journal_id) + values + (v_token_id, add_token__case_id, v_workflow_key, add_token__place_key, + ''free'', add_token__journal_id); + + return 0; +end;' language 'plpgsql'; + + +-- procedure lock_token +create function workflow_case__lock_token (integer,varchar,integer,integer) +returns integer as ' +declare + lock_token__case_id alias for $1; + lock_token__place_key alias for $2; + lock_token__journal_id alias for $3; + lock_token__task_id alias for $4; +begin + -- FIXME: rownum +-- update wf_tokens +-- set state = ''locked'', +-- locked_task_id = lock_token__task_id, +-- locked_date = now(), +-- locked_journal_id = lock_token__journal_id +-- where case_id = lock_token__case_id +-- and place_key = lock_token__place_key +-- and state = ''free'' +-- and rownum = 1; + + update wf_tokens + set state = ''locked'', + locked_task_id = lock_token__task_id, + locked_date = now(), + locked_journal_id = lock_token__journal_id + where token_id = (select token_id + from wf_tokens + where case_id = lock_token__case_id + and place_key = lock_token__place_key + and state = ''free'' + limit 1); + + return 0; +end;' language 'plpgsql'; + + +-- procedure release_token +create function workflow_case__release_token (integer,integer) +returns integer as ' +declare + release_token__task_id alias for $1; + release_token__journal_id alias for $2; + token_rec record; +begin + /* Add a new token for each released one */ + for token_rec in + select token_id, + case_id, + place_key + from wf_tokens + where state = ''locked'' + and locked_task_id = release_token__task_id + LOOP + PERFORM workflow_case__add_token ( + token_rec.case_id, + token_rec.place_key, + release_token__journal_id + ); + end loop; + + /* Mark the released ones canceled */ + update wf_tokens + set state = ''canceled'', + canceled_date = now(), + canceled_journal_id = release_token__journal_id + where state = ''locked'' + and locked_task_id = release_token__task_id; + + return 0; +end;' language 'plpgsql'; + + +-- procedure consume_token +create function workflow_case__consume_token (integer,varchar,integer,integer) +returns integer as ' +declare + consume_token__case_id alias for $1; + consume_token__place_key alias for $2; + consume_token__journal_id alias for $3; + consume_token__task_id alias for $4; -- default null +begin + if consume_token__task_id is null then + update wf_tokens + set state = ''consumed'', + consumed_date = now(), + consumed_journal_id = consume_token__journal_id + where token_id = (select token_id + from wf_tokens + where case_id = consume_token__case_id + and place_key = consume_token__place_key + and state = ''free'' + limit 1); + else + update wf_tokens + set state = ''consumed'', + consumed_date = now(), + consumed_journal_id = consume_token__journal_id + where case_id = consume_token__case_id + and place_key = consume_token__place_key + and state = ''locked'' + and locked_task_id = consume_token__task_id; + end if; + + return 0; +end;' language 'plpgsql'; + + +-- procedure sweep_automatic_transitions +create function workflow_case__sweep_automatic_transitions (integer,integer) +returns integer as ' +declare + sweep_automatic_transitions__case_id alias for $1; + sweep_automatic_transitions__journal_id alias for $2; + v_done_p boolean:=''f''; + v_finished_p boolean; + task_rec record; +begin + + PERFORM workflow_case__enable_transitions(sweep_automatic_transitions__case_id); + while v_done_p != ''t'' loop + v_done_p := ''t''; + v_finished_p := workflow_case__finished_p ( + sweep_automatic_transitions__case_id, + sweep_automatic_transitions__journal_id); + + if v_finished_p = ''f'' then + for task_rec in + select task_id + from wf_tasks ta, wf_transitions tr + where tr.workflow_key = ta.workflow_key + and tr.transition_key = ta.transition_key + and tr.trigger_type = ''automatic'' + and ta.state = ''enabled'' + and ta.case_id = sweep_automatic_transitions__case_id + LOOP + PERFORM workflow_case__fire_transition_internal ( + task_rec.task_id, + sweep_automatic_transitions__journal_id + ); + + v_done_p := ''f''; + end loop; + PERFORM workflow_case__enable_transitions(sweep_automatic_transitions__case_id); + end if; + + end loop; + + return 0; +end;' language 'plpgsql'; + + +-- function finished_p +create function workflow_case__finished_p (integer,integer) +returns boolean as ' +declare + finished_p__case_id alias for $1; + finished_p__journal_id alias for $2; + v_case_state varchar; + v_token_id integer; + v_num_rows integer; + v_journal_id integer; +begin + select state into v_case_state + from wf_cases + where case_id = finished_p__case_id; + + if v_case_state = ''finished'' then + return ''t''; + else + /* Let us see if the case is actually finished, but just not marked so */ + select case when count(*) = 0 then 0 else 1 end into v_num_rows + from wf_tokens + where case_id = finished_p__case_id + and place_key = ''end''; + + if v_num_rows = 0 then + return ''f''; + else + /* There is a token in the end place. + * Count the total integer of tokens to make sure the wf is well-constructed. + */ + + select case when count(*) = 0 then 0 + when count(*) = 1 then 1 + else 2 + end into v_num_rows + from wf_tokens + where case_id = finished_p__case_id + and state in (''free'', ''locked''); + + if v_num_rows > 1 then + raise EXCEPTION ''-20000: The workflow net is misconstructed: Some parallel executions have not finished.''; + end if; + + /* Consume that token */ + select token_id into v_token_id + from wf_tokens + where case_id = finished_p__case_id + and state in (''free'', ''locked''); + + PERFORM workflow_case__consume_token ( + finished_p__case_id, + ''end'', + finished_p__journal_id, + null + ); + + update wf_cases + set state = ''finished'' + where case_id = finished_p__case_id; + + /* Add an extra entry to the journal */ + v_journal_id := journal_entry__new ( + null, + finished_p__case_id, + ''case finish'', + ''Case finished'', + now(), + null, + null, + null + ); + + return ''t''; + end if; + end if; + +end;' language 'plpgsql'; + + + + /* This procedure should be scheduled to run as a dbms_job. */ +create function sweep_timed_transitions () returns integer as ' +declare + v_journal_id integer; + trans_rec record; +begin + for trans_rec in select t.task_id, t.case_id, tr.transition_name + from wf_tasks t, wf_transitions tr + where trigger_time <= now() + and state = ''enabled'' + and tr.workflow_key = t.workflow_key + and tr.transition_key = t.transition_key + LOOP + + /* Insert an entry to the journal so people will know it fired */ + + v_journal_id := journal_entry__new ( + null, + trans_rec.case_id, + ''task '' || trans_rec.task_id || '' fire time'', + trans_rec.transition_name || '' automatically finished'', + now(), + null, + null, + ''Timed transition fired.'' + ); + + /* Fire the transition */ + + PERFORM workflow_case__fire_transition_internal ( + trans_rec.task_id, + v_journal_id + ); + + /* Update the workflow internal state */ + + PERFORM workflow_case__sweep_automatic_transitions( + trans_rec.case_id, + v_journal_id + ); + + end loop; + + return 0; +end;' language 'plpgsql'; + + + /* This procedure should be scheduled to run as a dbms_job. */ +create function sweep_hold_timeout () returns integer as ' +declare + v_journal_id integer; + task_rec record; +begin + for task_rec in select t.task_id, t.case_id, tr.transition_name + from wf_tasks t, wf_transitions tr + where hold_timeout <= now() + and state = ''started'' + and tr.workflow_key = t.workflow_key + and tr.transition_key = t.transition_key + LOOP + + /* Insert an entry to the journal so people will know it was canceled */ + + v_journal_id := journal_entry__new ( + null, + task_rec.case_id, + ''task '' || task_rec.task_id || '' cancel timeout'', + task_rec.transition_name || '' timed out'', + now(), + null, + null, + ''The user''''s hold on the task timed out and the task was automatically canceled'' + ); + + + /* Cancel the task */ + + PERFORM workflow_case__cancel_task ( + task_rec.task_id, + v_journal_id + ); + + end loop; + + returns 0; +end;' language 'plpgsql'; + +-- procedure notify_assignee +create function workflow_case__notify_assignee (integer,integer,varchar,varchar) +returns integer as ' +declare + notify_assignee__task_id alias for $1; + notify_assignee__user_id alias for $2; + notify_assignee__callback alias for $3; + notify_assignee__custom_arg alias for $4; + v_deadline_pretty varchar; + v_object_name text; + v_transition_key wf_transitions.transition_key%TYPE; + v_transition_name wf_transitions.transition_name%TYPE; + v_party_from parties.party_id%TYPE; + v_party_to parties.party_id%TYPE; + v_subject text; + v_body text; + v_request_id integer; + v_workflow_url text; + v_str text; +begin + select to_char(ta.deadline,''Mon fmDDfm, YYYY HH24:MI:SS''), + acs_object__name(c.object_id), + tr.transition_key, + tr.transition_name + into v_deadline_pretty, + v_object_name, + v_transition_key, + v_transition_name + from wf_tasks ta, wf_transitions tr, wf_cases c + where ta.task_id = notify_assignee__task_id + and c.case_id = ta.case_id + and tr.workflow_key = c.workflow_key + and tr.transition_key = ta.transition_key; + + select apm__get_value(p.package_id,''SystemURL'') || site_node__url(s.node_id) + into v_workflow_url + from site_nodes s, + apm_packages a, + (select package_id + from apm_packages + where package_key = ''acs-kernel'') p + where s.object_id = a.package_id + and a.package_key = ''acs-workflow''; + + /* Mail sent from */ + select wfi.principal_party + into v_party_from + from wf_context_workflow_info wfi, wf_tasks ta, wf_cases c + where ta.task_id = notify_assignee__task_id + and c.case_id = ta.case_id + and wfi.workflow_key = c.workflow_key + and wfi.context_key = c.context_key; + if NOT FOUND then + v_party_from := -1; + end if; + + /* Subject */ + v_subject := ''Assignment: '' || v_transition_name || '' '' || v_object_name; + + /* Body */ + v_body := ''You have been assigned to a task. +'' || '' +Case : '' || v_object_name || '' +Task : '' || v_transition_name || '' +''; + + if v_deadline_pretty != '''' and v_deadline_pretty is not null then + v_body := v_body || ''Deadline : '' || v_deadline_pretty || '' +''; + end if; + + v_body := v_body ||''Task website: ''||v_workflow_url||''task?task_id=''||notify_assignee__task_id||'' +''; + + /* + * We would like to add a URL to go visit, but how do we get that URL? + * + * The notifications should really be sent from the application + * server layer, not from the database + */ + + -- FIXME: last three args are also out varibles. + + if notify_assignee__callback != '''' and notify_assignee__callback is not null then + v_str := ''select '' || notify_assignee__callback || '' ('' || + notify_assignee__task_id || '','' || + coalesce(quote_literal(notify_assignee__custom_arg),''null'') || + '','' || + notify_assignee__user_id || '','' || + v_party_from || '','' || + quote_literal(v_subject) || '','' || + quote_literal(v_body) || '')''; + + execute v_str; + end if; + + v_request_id := acs_mail_nt__post_request ( + v_party_from, -- party_from + notify_assignee__user_id, -- party_to + ''f'', -- expand_group + v_subject, -- subject + v_body, -- message + 0 -- max_retries + ); + + return 0; +end;' language 'plpgsql'; + + +-- procedure enable_transitions +create function workflow_case__enable_transitions (integer) +returns integer as ' +declare + enable_transitions__case_id alias for $1; + v_task_id integer; + v_workflow_key varchar; + v_trigger_time timestamp; + v_deadline_date timestamp; + v_party_from integer; + v_subject varchar; + v_body text; + v_num_assigned integer; + trans_rec record; +begin + select workflow_key into v_workflow_key + from wf_cases + where case_id = enable_transitions__case_id; + + /* we mark tasks overridden if they were once enabled, but are no longer so */ + + update wf_tasks + set state = ''overridden'', + overridden_date = now() + where case_id = enable_transitions__case_id + and state = ''enabled'' + and transition_key not in + (select transition_key + from wf_enabled_transitions + where case_id = enable_transitions__case_id); + + + /* insert a task for the transitions that are enabled but have no task row */ + + for trans_rec in select et.transition_key, + et.transition_name, + et.trigger_type, + et.enable_callback, + et.enable_custom_arg, + et.time_callback, + et.time_custom_arg, + et.deadline_callback, + et.deadline_custom_arg, + et.deadline_attribute_name, + et.notification_callback, + et.notification_custom_arg, + et.unassigned_callback, + et.unassigned_custom_arg, + et.estimated_minutes, + cr.assignment_callback, + cr.assignment_custom_arg + from wf_enabled_transitions et left outer join wf_context_role_info cr + on (et.workflow_key = cr.workflow_key and et.role_key = cr.role_key) + where et.case_id = enable_transitions__case_id + and not exists (select 1 from wf_tasks + where case_id = enable_transitions__case_id + and transition_key = et.transition_key + and state in (''enabled'', ''started'')) + LOOP + + v_trigger_time := null; + v_deadline_date := null; + + if trans_rec.trigger_type = ''user'' then + v_deadline_date := workflow_case__get_task_deadline ( + trans_rec.deadline_callback, + trans_rec.deadline_custom_arg, + trans_rec.deadline_attribute_name, + enable_transitions__case_id, + trans_rec.transition_key + ); + else if trans_rec.trigger_type = ''time'' then + v_trigger_time := workflow_case__execute_time_callback ( + trans_rec.time_callback, + trans_rec.time_custom_arg, + enable_transitions__case_id, + trans_rec.transition_key); + end if; + end if; + + /* we are ready to insert the row */ + select wf_task_id_seq.nextval into v_task_id from dual; + + insert into wf_tasks ( + task_id, case_id, workflow_key, transition_key, + deadline, trigger_time, estimated_minutes + ) values ( + v_task_id, enable_transitions__case_id, v_workflow_key, + trans_rec.transition_key, + v_deadline_date, v_trigger_time, trans_rec.estimated_minutes + ); + + PERFORM workflow_case__set_task_assignments ( + v_task_id, + trans_rec.assignment_callback, + trans_rec.assignment_custom_arg + ); + + /* Execute the transition enabled callback */ + PERFORM workflow_case__execute_transition_callback ( + trans_rec.enable_callback, + trans_rec.enable_custom_arg, + enable_transitions__case_id, + trans_rec.transition_key + ); + + select count(*) into v_num_assigned + from wf_task_assignments + where task_id = v_task_id; + + if v_num_assigned = 0 then + PERFORM workflow_case__execute_unassigned_callback ( + trans_rec.unassigned_callback, + v_task_id, + trans_rec.unassigned_custom_arg + ); + end if; + + end loop; + + return 0; +end;' language 'plpgsql'; + + +-- procedure fire_transition_internal +create function workflow_case__fire_transition_internal (integer,integer) +returns integer as ' +declare + fire_transition_internal__task_id alias for $1; + fire_transition_internal__journal_id alias for $2; + v_case_id integer; + v_state varchar; + v_transition_key varchar; + v_workflow_key varchar; + v_place_key varchar; + v_direction varchar; + v_guard_happy_p boolean; + v_fire_callback varchar; + v_fire_custom_arg text; + v_found_happy_guard boolean; + v_locked_task_id integer; + place_rec record; +begin + select t.case_id, t.state, t.workflow_key, t.transition_key, ti.fire_callback, ti.fire_custom_arg + into v_case_id, v_state, v_workflow_key, v_transition_key, v_fire_callback, v_fire_custom_arg + from wf_tasks t, wf_cases c, wf_transition_info ti + where t.task_id = fire_transition_internal__task_id + and c.case_id = t.case_id + and ti.context_key = c.context_key + and ti.workflow_key = c.workflow_key + and ti.transition_key = t.transition_key; + + /* Check that the state is either started or enabled */ + + if v_state = ''enabled'' then + v_locked_task_id := null; + else if v_state = ''started'' then + v_locked_task_id := fire_transition_internal__task_id; + else + raise EXCEPTION ''-20000: Can''''t fire the transition if it''''s not in state enabled or started''; + end if; end if; + + /* Mark the task finished */ + + update wf_tasks + set state = ''finished'', + finished_date = now() + where task_id = fire_transition_internal__task_id; + + + /* Consume the tokens */ + + for place_rec in select * + from wf_transition_places tp + where tp.workflow_key = v_workflow_key + and tp.transition_key = v_transition_key + LOOP + PERFORM workflow_case__consume_token ( + v_case_id, + place_rec.place_key, + fire_transition_internal__journal_id, + v_locked_task_id + ); + end loop; + + + /* Spit out new tokens in the output places */ + + v_found_happy_guard := ''f''; + for place_rec in + select * + from wf_transition_places tp + where tp.workflow_key = v_workflow_key + and tp.transition_key = v_transition_key + and direction = ''out'' + LOOP + v_place_key := place_rec.place_key; + v_direction := place_rec.direction; + + v_guard_happy_p := workflow_case__evaluate_guard( + place_rec.guard_callback, + place_rec.guard_custom_arg, + v_case_id, + v_workflow_key, + v_transition_key, + v_place_key, + v_direction + ); + + if v_guard_happy_p = ''t'' then + v_found_happy_guard := ''t''; + PERFORM workflow_case__add_token ( + v_case_id, + place_rec.place_key, + fire_transition_internal__journal_id + ); + end if; + end loop; + + + /* If we did not find any happy guards, look for arcs with the special hash (#) guard */ + + if v_found_happy_guard = ''f'' then + for place_rec in + select place_key + from wf_transition_places tp + where tp.workflow_key = v_workflow_key + and tp.transition_key = v_transition_key + and tp.direction = ''out'' + and tp.guard_callback = ''#'' + loop + + PERFORM workflow_case__add_token ( + v_case_id, + place_rec.place_key, + fire_transition_internal__journal_id + ); + end loop; + end if; + + + /* Execute the transition fire callback */ + + PERFORM workflow_case__execute_transition_callback ( + v_fire_callback, + v_fire_custom_arg, + v_case_id, + v_transition_key + ); + + return 0; +end;' language 'plpgsql'; + + +-- procedure ensure_task_in_state +create function workflow_case__ensure_task_in_state (integer,varchar) +returns integer as ' +declare + ensure_task_in_state__task_id alias for $1; + ensure_task_in_state__state alias for $2; + v_count integer; +begin + select case when count(*) = 0 then 0 else 1 end into v_count + from wf_tasks + where task_id = ensure_task_in_state__task_id + and state = ensure_task_in_state__state; + + if v_count != 1 then + raise EXCEPTION ''-20000: The task % is not in state "%"'', ensure_task_in_state__task_id, ensure_task_in_state__state; + end if; + + return 0; +end;' language 'plpgsql'; + + +-- procedure start_task +create function workflow_case__start_task (integer,integer,integer) +returns integer as ' +declare + start_task__task_id alias for $1; + start_task__user_id alias for $2; + start_task__journal_id alias for $3; + v_case_id integer; + v_workflow_key wf_workflows.workflow_key%TYPE; + v_transition_key varchar(100); + v_hold_timeout_callback varchar(100); + v_hold_timeout_custom_arg varchar(4000); + v_hold_timeout timestamp; + place_rec record; +begin + PERFORM workflow_case__ensure_task_in_state(start_task__task_id, + ''enabled''); + + select t.case_id, t.workflow_key, t.transition_key, ti.hold_timeout_callback, ti.hold_timeout_custom_arg + into v_case_id, v_workflow_key, v_transition_key, v_hold_timeout_callback, v_hold_timeout_custom_arg + from wf_tasks t, wf_cases c, wf_transition_info ti + where t.task_id = start_task__task_id + and c.case_id = t.case_id + and ti.context_key = c.context_key + and ti.workflow_key = t.workflow_key + and ti.transition_key = t.transition_key; + + v_hold_timeout := workflow_case__execute_hold_timeout_callback ( + v_hold_timeout_callback, + v_hold_timeout_custom_arg, + v_case_id, v_transition_key); + + /* Mark it started */ + + update wf_tasks + set state = ''started'', + started_date = now(), + holding_user = start_task__user_id, + hold_timeout = v_hold_timeout + where task_id = start_task__task_id; + + + /* Reserve one token from each input place */ + + for place_rec in select * + from wf_transition_places tp + where tp.workflow_key = v_workflow_key + and tp.transition_key = v_transition_key + and direction = ''in'' + LOOP + PERFORM workflow_case__lock_token ( + v_case_id, + place_rec.place_key, + start_task__journal_id, + start_task__task_id + ); + end loop; + + return 0; +end;' language 'plpgsql'; + + +-- procedure cancel_task +create function workflow_case__cancel_task (integer,integer) +returns integer as ' +declare + cancel_task__task_id alias for $1; + cancel_task__journal_id alias for $2; + v_case_id integer; +begin + PERFORM workflow_case__ensure_task_in_state (cancel_task__task_id, + ''started''); + select case_id into v_case_id + from wf_tasks + where task_id = cancel_task__task_id; + + /* Mark the task canceled */ + + update wf_tasks + set state = ''canceled'', + canceled_date = now() + where task_id = cancel_task__task_id; + + + /* Release our reserved tokens */ + + PERFORM workflow_case__release_token ( + cancel_task__task_id, + cancel_task__journal_id + ); + + /* The workflow state has now changed, so we must run this */ + + PERFORM workflow_case__sweep_automatic_transitions ( + v_case_id, + cancel_task__journal_id + ); + + return 0; +end;' language 'plpgsql'; + + +-- procedure finish_task +create function workflow_case__finish_task (integer,integer) +returns integer as ' +declare + finish_task__task_id alias for $1; + finish_task__journal_id alias for $2; + v_case_id integer; +begin + select case_id into v_case_id + from wf_tasks + where task_id = finish_task__task_id; + + PERFORM workflow_case__fire_transition_internal ( + finish_task__task_id, + finish_task__journal_id + ); + + PERFORM workflow_case__sweep_automatic_transitions ( + v_case_id, + finish_task__journal_id + ); + + return 0; +end;' language 'plpgsql'; + + + +-- show errors + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/workflow-case-package-head.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/workflow-case-package-head.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/workflow-case-package-head.sql 19 Nov 2001 18:20:33 -0000 1.1 @@ -0,0 +1 @@ \ No newline at end of file Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/workflow-case-package.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/workflow-case-package.sql,v diff -u -r1.18 -r1.19 --- openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/workflow-case-package.sql 9 Oct 2001 00:03:15 -0000 1.18 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/workflow-case-package.sql 19 Nov 2001 18:20:33 -0000 1.19 @@ -11,2029 +11,5 @@ -- @cvs-id $Id$ -- - --- create or replace package workflow_case --- is --- --- function new ( --- case_id in integer default null, --- workflow_key in varchar2, --- context_key in varchar2 default null, --- object_id in integer, --- creation_date in date default sysdate, --- creation_user in integer default null, --- creation_ip in varchar2 default null --- ) return integer; --- --- procedure add_manual_assignment ( --- case_id in integer, --- transition_key in varchar2, --- party_id in integer --- ); --- --- procedure remove_manual_assignment ( --- case_id in integer, --- transition_key in varchar2, --- party_id in integer --- ); --- --- procedure clear_manual_assignments ( --- case_id in integer, --- transition_key in varchar2 --- ); --- --- procedure start_case ( --- case_id in integer, --- creation_user in integer default null, --- creation_ip in varchar2 default null, --- msg in varchar2 default null --- ); --- --- procedure delete( --- case_id in integer --- ); --- --- procedure suspend( --- case_id in integer, --- user_id in integer default null, --- ip_address in varchar2 default null, --- msg in varchar2 default null --- ); --- --- procedure resume( --- case_id in integer, --- user_id in integer default null, --- ip_address in varchar2 default null, --- msg in varchar2 default null --- ); --- --- procedure cancel( --- case_id in integer, --- user_id in integer default null, --- ip_address in varchar2 default null, --- msg in varchar2 default null --- ); --- --- procedure fire_message_transition ( --- task_id in integer --- ); --- --- /* To perform an action on the workflow: --- * (integers in parenthesis is the integer of times each function should get called) --- * --- * 1. begin_task_action (1) --- * 2. set_attribute_value (0..*) --- * 3. clear_manual_assignments (0..1) --- * 4. add_manual_assignment (0..*) --- * 5. end_task_action (1) --- */ --- function begin_task_action ( --- task_id in integer, --- action in varchar2, --- action_ip in varchar2, --- user_id in integer, --- msg in varchar2 default null --- ) return integer; --- --- procedure set_attribute_value ( --- journal_id in integer, --- attribute_name in varchar2, --- value in varchar2 --- ); --- --- procedure end_task_action ( --- journal_id in integer, --- action in varchar2, --- task_id in integer --- ); --- --- /* Shortcut, that does both begin and end, when you have no attributes to set or assignments to make */ --- function task_action ( --- task_id in integer, --- action in varchar2, --- action_ip in varchar2, --- user_id in integer, --- msg in varchar2 default null --- ) return integer; --- --- function get_attribute_value ( --- case_id in integer, --- attribute_name in varchar2 --- ) return varchar2; --- --- procedure add_task_assignment ( --- task_id in integer, --- party_id in integer --- ); --- --- procedure remove_task_assignment ( --- task_id in integer, --- party_id in integer --- ); --- --- procedure clear_task_assignments ( --- task_id in integer --- ); --- --- --- /* DBMS_JOBS */ --- --- procedure sweep_timed_transitions; --- --- procedure sweep_hold_timeout; --- --- end workflow_case; - --- show errors - --- create or replace package body workflow_case --- function new -create function workflow_case__new (integer,varchar,varchar,integer,timestamp,integer,varchar) -returns integer as ' -declare - new__case_id alias for $1; -- default null - new__workflow_key alias for $2; - new__context_key alias for $3; -- default null - new__object_id alias for $4; - new__creation_date alias for $5; -- default now() - new__creation_user alias for $6; -- default null - new__creation_ip alias for $7; -- default null - v_case_id integer; - v_workflow_case_table varchar; - v_context_key_for_query varchar; -begin - if new__context_key = '''' or new__context_key is null then - v_context_key_for_query := ''default''; - else - v_context_key_for_query := new__context_key; - end if; - - /* insert a row into acs_objects */ - v_case_id := acs_object__new( - new__case_id, - new__workflow_key, - new__creation_date, - new__creation_user, - new__creation_ip, - null - ); - - /* insert the case in to the general wf_cases table */ - insert into wf_cases - (case_id, workflow_key, context_key, object_id, state) - values - (v_case_id, new__workflow_key, v_context_key_for_query, new__object_id, ''created''); - - /* insert the case into the workflow-specific cases table */ - select table_name into v_workflow_case_table - from acs_object_types - where object_type = new__workflow_key; - - execute ''insert into '' || v_workflow_case_table || '' (case_id) values ('' || v_case_id || '')''; - - return v_case_id; - -end;' language 'plpgsql'; - - --- procedure add_manual_assignment -create function workflow_case__add_manual_assignment (integer,varchar,integer) -returns integer as ' -declare - add_manual_assignment__case_id alias for $1; - add_manual_assignment__transition_key alias for $2; - add_manual_assignment__party_id alias for $3; - v_workflow_key varchar; -begin - select workflow_key into v_workflow_key - from wf_cases - where case_id = add_manual_assignment__case_id; - - insert into wf_case_assignments - (case_id, workflow_key, transition_key, party_id) - values - (add_manual_assignment__case_id, v_workflow_key, - add_manual_assignment__transition_key, - add_manual_assignment__party_id); - - return 0; -end;' language 'plpgsql'; - - --- procedure remove_manual_assignment -create function workflow_case__remove_manual_assignment (integer,varchar,integer) -returns integer as ' -declare - remove_manual_assignment__case_id alias for $1; - remove_manual_assignment__transition_key alias for $2; - remove_manual_assignment__party_id alias for $3; -begin - delete - from wf_case_assignments - where workflow_key = (select workflow_key - from wf_cases - where case_id = remove_manual_assignment__case_id) - and case_id = remove_manual_assignment__case_id - and transition_key = remove_manual_assignment__transition_key - and party_id = remove_manual_assignment__party_id; - - return 0; -end;' language 'plpgsql'; - - --- procedure clear_manual_assignments -create function workflow_case__clear_manual_assignments (integer,varchar) -returns integer as ' -declare - clear_manual_assignments__case_id alias for $1; - clear_manual_assignments__transition_key alias for $2; -begin - - delete - from wf_case_assignments - where workflow_key = (select workflow_key - from wf_cases - where case_id = clear_manual_assignments__case_id) - and case_id = clear_manual_assignments__case_id - and transition_key = clear_manual_assignments__transition_key; - - return 0; -end;' language 'plpgsql'; - - --- procedure start_case -create function workflow_case__start_case (integer,integer,varchar,varchar) -returns integer as ' -declare - start_case__case_id alias for $1; - start_case__creation_user alias for $2; -- default null - start_case__creation_ip alias for $3; -- default null - start_case__msg alias for $4; -- default null - v_journal_id integer; -begin - /* Add an entry to the journal */ - v_journal_id := journal_entry__new( - null, - start_case__case_id, - ''case start'', - ''Case started'', - now(), - start_case__creation_user, - start_case__creation_ip, - start_case__msg - ); - - update wf_cases - set state = ''active'' - where case_id = start_case__case_id; - - PERFORM workflow_case__add_token( - start_case__case_id, - ''start'', - v_journal_id - ); - - /* Turn the wheels */ - PERFORM workflow_case__sweep_automatic_transitions( - start_case__case_id, - v_journal_id - ); - - return 0; -end;' language 'plpgsql'; - - --- procedure delete -create function workflow_case__delete (integer) -returns integer as ' -declare - delete__case_id alias for $1; - v_workflow_case_table varchar; -begin - /* delete attribute_value_audit, tokens, tasks */ - delete from wf_attribute_value_audit - where case_id = delete__case_id; - - delete from wf_case_assignments - where case_id = delete__case_id; - - delete from wf_case_deadlines - where case_id = delete__case_id; - - delete from wf_tokens - where case_id = delete__case_id; - - delete from wf_task_assignments - where task_id in (select task_id - from wf_tasks - where case_id = delete__case_id); - - delete from wf_tasks - where case_id = delete__case_id; - - /* delete the journal */ - PERFORM journal_entry__delete_for_object(delete__case_id); - - /* delete from the workflow-specific cases table */ - select table_name into v_workflow_case_table - from acs_object_types ot, wf_cases c - where c.case_id = delete__case_id - and object_type = c.workflow_key; - - execute ''delete from '' || v_workflow_case_table || '' where case_id = '' || delete__case_id; - - /* delete from the generic cases table */ - delete from wf_cases where case_id = delete__case_id; - - /* delete from acs-objects */ - PERFORM acs_object__delete(delete__case_id); - - return 0; -end;' language 'plpgsql'; - - --- procedure suspend -create function workflow_case__suspend (integer,integer,varchar,varchar) -returns integer as ' -declare - suspend__case_id alias for $1; - suspend__user_id alias for $2; -- default null - suspend__ip_address alias for $3; -- default null - suspend__msg alias for $4; -- default null - v_state varchar; - v_journal_id integer; -begin - select state into v_state - from wf_cases - where case_id = suspend__case_id; - - if v_state != ''active'' then - raise EXCEPTION ''-20000: Only active cases can be suspended''; - end if; - - /* Add an entry to the journal */ - v_journal_id := journal_entry__new( - null, - suspend__case_id, - ''case suspend'', - ''case suspended'', - now(), - suspend__user_id, - suspend__ip_address, - suspend__msg - ); - - update wf_cases - set state = ''suspended'' - where case_id = suspend__case_id; - - return 0; -end;' language 'plpgsql'; - - --- procedure resume -create function workflow_case__resume (integer,integer,varchar,varchar) -returns integer as ' -declare - resume__case_id alias for $1; - resume__user_id alias for $2; -- default null - resume__ip_address alias for $3; -- default null - resume__msg alias for $4; -- default null - v_state varchar; - v_journal_id integer; -begin - select state into v_state - from wf_cases - where case_id = resume__case_id; - - if v_state != ''suspended'' and v_state != ''canceled'' then - raise EXCEPTION ''-20000: Only suspended or canceled cases can be resumed''; - end if; - - /* Add an entry to the journal */ - v_journal_id := journal_entry__new( - null, - resume__case_id, - ''case resume'', - ''case resumed'', - now(), - resume__user_id, - resume__ip_address, - resume__msg - ); - - update wf_cases - set state = ''active'' - where case_id = resume__case_id; - - return 0; -end;' language 'plpgsql'; - - --- procedure cancel -create function workflow_case__cancel (integer,integer,varchar,varchar) -returns integer as ' -declare - cancel__case_id alias for $1; - cancel__user_id alias for $2; -- default null - cancel__ip_address alias for $3; -- default null - cancel__msg alias for $4; -- default null - v_state varchar; - v_journal_id integer; -begin - select state into v_state - from wf_cases - where case_id = cancel__case_id; - - if v_state != ''active'' and v_state != ''suspended'' then - raise EXCEPTION ''-20000: Only active or suspended cases can be canceled''; - end if; - - /* Add an entry to the journal */ - v_journal_id := journal_entry__new( - null, - cancel__case_id, - ''case cancel'', - ''Case canceled'', - now(), - cancel__user_id, - cancel__ip_address, - cancel__msg - ); - - update wf_cases - set state = ''canceled'' - where case_id = cancel__case_id; - - return 0; -end;' language 'plpgsql'; - - --- procedure fire_message_transition -create function workflow_case__fire_message_transition (integer) -returns integer as ' -declare - fire_message_transition__task_id alias for $1; - v_case_id integer; - v_transition_name varchar; - v_trigger_type varchar; - v_journal_id integer; -begin - select t.case_id, tr.transition_name, tr.trigger_type - into v_case_id, v_transition_name, v_trigger_type - from wf_tasks t, wf_transitions tr - where t.task_id = fire_message_transition__task_id - and tr.workflow_key = t.workflow_key - and tr.transition_key = t.transition_key; - - if v_trigger_type != ''message'' then - raise EXCEPTION ''-20000: Transition "'' || v_transition_name || ''" is not message triggered''; - end if; - - /* Add an entry to the journal */ - v_journal_id := journal_entry__new( - null, - v_case_id, - ''task '' || fire_message_transition__task_id || '' fire'', - v_transition_name || '' fired'', - now(), - null, - null, - null - ); - - PERFORM workflow_case__fire_transition_internal( - fire_message_transition__task_id, - v_journal_id - ); - - PERFORM workflow_case__sweep_automatic_transitions( - v_case_id, - v_journal_id - ); - - return 0; -end;' language 'plpgsql'; - - --- function begin_task_action -create function workflow_case__begin_task_action (integer,varchar,varchar,integer,varchar) -returns integer as ' -declare - begin_task_action__task_id alias for $1; - begin_task_action__action alias for $2; - begin_task_action__action_ip alias for $3; - begin_task_action__user_id alias for $4; - begin_task_action__msg alias for $5; -- default null - v_state varchar; - v_journal_id integer; - v_case_id integer; - v_transition_name varchar; - v_num_rows integer; -begin - select state into v_state - from wf_tasks - where task_id = begin_task_action__task_id; - - if begin_task_action__action = ''start'' then - if v_state != ''enabled'' then - raise EXCEPTION ''-20000: Task is in state "%", but it must be in state "enabled" to be started.'', v_state; - end if; - - select case when count(*) = 0 then 0 else 1 end into v_num_rows - from wf_user_tasks - where task_id = begin_task_action__task_id - and user_id = begin_task_action__user_id; - - if v_num_rows = 0 then - raise EXCEPTION ''-20000: You are not assigned to this task.''; - end if; - else if begin_task_action__action = ''finish'' or begin_task_action__action = ''cancel'' then - - if v_state = ''started'' then - /* Is this user the holding user? */ - select case when count(*) = 0 then 0 else 1 end into v_num_rows - from wf_tasks - where task_id = begin_task_action__task_id - and holding_user = begin_task_action__user_id; - if v_num_rows = 0 then - raise EXCEPTION ''-20000: You are the user currently working on this task.''; - end if; - else if v_state = ''enabled'' then - if begin_task_action__action = ''cancel'' then - raise EXCEPTION ''-20000: You can only cancel a task in state "started", but this task is in state "%"'', v_state; - end if; - - /* Is this user assigned to this task? */ - select case when count(*) = 0 then 0 else 1 end into v_num_rows - from wf_user_tasks - where task_id = begin_task_action__task_id - and user_id = begin_task_action__user_id; - if v_num_rows = 0 then - raise EXCEPTION ''-20000: You are not assigned to this task.''; - end if; - - /* This task is finished without an explicit start. - * Store the user as the holding_user */ - update wf_tasks - set holding_user = begin_task_action__user_id - where task_id = begin_task_action__task_id; - else - raise EXCEPTION ''-20000: Task is in state "%", but it must be in state "enabled" or "started" to be finished'', v_state; - end if; end if; - - else if begin_task_action__action = ''comment'' then - -- We currently allow anyone to comment on a task - -- (need this line because PL/SQL does not like empty if blocks) - v_num_rows := 0; - end if; end if; end if; - - select t.case_id, tr.transition_name into v_case_id, v_transition_name - from wf_tasks t, - wf_transitions tr - where t.task_id = begin_task_action__task_id - and tr.workflow_key = t.workflow_key - and tr.transition_key = t.transition_key; - - /* Insert a journal entry */ - - v_journal_id := journal_entry__new( - null, - v_case_id, - ''task '' || begin_task_action__task_id || '' '' || begin_task_action__action, - v_transition_name || '' '' || begin_task_action__action, - now(), - begin_task_action__user_id, - begin_task_action__action_ip, - begin_task_action__msg - ); - - return v_journal_id; - -end;' language 'plpgsql'; - - --- procedure end_task_action -create function workflow_case__end_task_action (integer,varchar,integer) -returns integer as ' -declare - end_task_action__journal_id alias for $1; - end_task_action__action alias for $2; - end_task_action__task_id alias for $3; - v_user_id integer; -begin - select creation_user into v_user_id - from acs_objects - where object_id = end_task_action__journal_id; - - /* Update the workflow state */ - - if end_task_action__action = ''start'' then - PERFORM workflow_case__start_task(end_task_action__task_id, - v_user_id, - end_task_action__journal_id - ); - else if end_task_action__action = ''finish'' then - PERFORM workflow_case__finish_task(end_task_action__task_id, - end_task_action__journal_id - ); - else if end_task_action__action = ''cancel'' then - PERFORM workflow_case__cancel_task(end_task_action__task_id, - end_task_action__journal_id - ); - else if end_task_action__action != ''comment'' then - raise EXCEPTION ''-20000: Unknown action "%"'', end_task_action__action; - end if; end if; end if; end if; - - return 0; -end;' language 'plpgsql'; - - --- function task_action -create function workflow_case__task_action (integer,varchar,varchar,integer,varchar) -returns integer as ' -declare - task_action__task_id alias for $1; - task_action__action alias for $2; - task_action__action_ip alias for $3; - task_action__user_id alias for $4; - task_action__msg alias for $5; -- default null - v_journal_id integer; -begin - v_journal_id := workflow_case__begin_task_action( - task_action__task_id, - task_action__action, - task_action__action_ip, - task_action__user_id, - task_action__msg - ); - - PERFORM workflow_case__end_task_action( - v_journal_id, - task_action__action, - task_action__task_id - ); - - return v_journal_id; - -end;' language 'plpgsql'; - - --- procedure set_attribute_value -create function workflow_case__set_attribute_value (integer,varchar,varchar) -returns integer as ' -declare - set_attribute_value__journal_id alias for $1; - set_attribute_value__attribute_name alias for $2; - set_attribute_value__value alias for $3; - v_workflow_key varchar; - v_case_id integer; - v_attribute_id integer; -begin - select o.object_type, o.object_id into v_workflow_key, v_case_id - from journal_entries je, acs_objects o - where je.journal_id = set_attribute_value__journal_id - and o.object_id = je.object_id; - - select attribute_id into v_attribute_id - from acs_attributes - where object_type = v_workflow_key - and attribute_name = set_attribute_value__attribute_name; - - PERFORM acs_object__set_attribute( - v_case_id, - set_attribute_value__attribute_name, - set_attribute_value__value - ); - - insert into wf_attribute_value_audit - (case_id, attribute_id, journal_id, attr_value) - values - (v_case_id, v_attribute_id, set_attribute_value__journal_id, - set_attribute_value__value); - - return 0; -end;' language 'plpgsql'; - - --- function get_attribute_value -create function workflow_case__get_attribute_value (integer,varchar) -returns varchar as ' -declare - get_attribute_value__case_id alias for $1; - get_attribute_value__attribute_name alias for $2; -begin - return acs_object__get_attribute( - get_attribute_value__case_id, - get_attribute_value__attribute_name - ); - -end;' language 'plpgsql'; - - --- procedure add_task_assignment -create function workflow_case__add_task_assignment (integer,integer) -returns integer as ' -declare - add_task_assignment__task_id alias for $1; - add_task_assignment__party_id alias for $2; - v_count integer; - v_workflow_key wf_workflows.workflow_key%TYPE; - v_context_key wf_contexts.context_key%TYPE; - v_case_id wf_cases.case_id%TYPE; - v_transition_key wf_transitions.transition_key%TYPE; - v_notification_callback wf_context_transition_info.notification_callback%TYPE; - v_notification_custom_arg wf_context_transition_info.notification_custom_arg%TYPE; - callback_rec record; - v_assigned_user record; -begin - -- check that we do not hit the unique constraint - - select count(*) into v_count - from wf_task_assignments - where task_id = add_task_assignment__task_id - and party_id = add_task_assignment__party_id; - - if v_count > 0 then - return null; - end if; - - -- get the notification callback info - - select case_id, workflow_key, transition_key - into v_case_id, v_workflow_key, v_transition_key - from wf_tasks - where task_id = add_task_assignment__task_id; - - select context_key - into v_context_key - from wf_cases - where case_id = v_case_id; - - select notification_callback, - notification_custom_arg into callback_rec - from wf_context_transition_info - where context_key = v_context_key - and workflow_key = v_workflow_key - and transition_key = v_transition_key; - - - if FOUND then - v_notification_callback := callback_rec.notification_callback; - v_notification_custom_arg := callback_rec.notification_custom_arg; - else - v_notification_callback := null; - v_notification_custom_arg := null; - end if; - - -- notify any new assignees - - for v_assigned_user in - select distinct u.user_id - from users u - where u.user_id not in ( - select distinct u2.user_id - from wf_task_assignments tasgn2, - party_approved_member_map m2, - users u2 - where tasgn2.task_id = add_task_assignment__task_id - and m2.party_id = tasgn2.party_id - and u2.user_id = m2.member_id) - and exists ( - select 1 - from party_approved_member_map m - where m.member_id = u.user_id - and m.party_id = add_task_assignment__party_id - ) - LOOP - PERFORM workflow_case__notify_assignee( - add_task_assignment__task_id, - v_assigned_user.user_id, - v_notification_callback, - v_notification_custom_arg - ); - end loop; - - -- do the insert - - insert into wf_task_assignments - (task_id, party_id) - values - (add_task_assignment__task_id, add_task_assignment__party_id); - - - return 0; -end;' language 'plpgsql'; - - --- procedure remove_task_assignment -create function workflow_case__remove_task_assignment (integer,integer) -returns integer as ' -declare - remove_task_assignment__task_id alias for $1; - remove_task_assignment__party_id alias for $2; - v_num_assigned integer; - v_case_id integer; - v_workflow_key varchar; - v_transition_key varchar; - v_context_key varchar; - callback_rec record; -begin - delete - from wf_task_assignments - where task_id = remove_task_assignment__task_id - and party_id = remove_task_assignment__party_id; - - select count(*) into v_num_assigned - from wf_task_assignments - where task_id = remove_task_assignment__task_id; - - if v_num_assigned > 0 then - return null; - end if; - - select case_id, transition_key - into v_case_id, v_transition_key - from wf_tasks - where task_id = remove_task_assignment__task_id; - - select workflow_key, context_key - into v_workflow_key, v_context_key - from wf_cases - where case_id = v_case_id; - - select unassigned_callback, unassigned_custom_arg - into callback_rec - from wf_context_transition_info - where workflow_key = v_workflow_key - and context_key = v_context_key - and transition_key = v_transition_key; - if FOUND then - PERFORM workflow_case__execute_unassigned_callback ( - callback_rec.unassigned_callback, - remove_task_assignment__task_id, - callback_rec.unassigned_custom_arg - ); - end if; - - return 0; -end;' language 'plpgsql'; - - --- procedure clear_task_assignments -create function workflow_case__clear_task_assignments (integer) -returns integer as ' -declare - clear_task_assignments__task_id alias for $1; - v_case_id integer; - v_transition_key varchar; - v_workflow_key varchar; - v_context_key varchar; - v_callback varchar; - v_custom_arg varchar; -begin - delete - from wf_task_assignments - where task_id = clear_task_assignments__task_id; - - select case_id, transition_key - into v_case_id, v_transition_key - from wf_tasks - where task_id = clear_task_assignments__task_id; - - select workflow_key, context_key - into v_workflow_key, v_context_key - from wf_cases - where case_id = v_case_id; - - select unassigned_callback, unassigned_custom_arg - into v_callback, v_custom_arg - from wf_context_transition_info - where workflow_key = v_workflow_key - and context_key = v_context_key - and transition_key = v_transition_key; - - PERFORM workflow_case__execute_unassigned_callback ( - v_callback, - clear_task_assignments__task_id, - v_custom_arg - ); - - return 0; -end;' language 'plpgsql'; - - --- function evaluate_guard -create function workflow_case__evaluate_guard (varchar,varchar,integer,varchar,varchar,varchar,varchar) -returns boolean as ' -declare - evaluate_guard__callback alias for $1; - evaluate_guard__custom_arg alias for $2; - evaluate_guard__case_id alias for $3; - evaluate_guard__workflow_key alias for $4; - evaluate_guard__transition_key alias for $5; - evaluate_guard__place_key alias for $6; - evaluate_guard__direction alias for $7; - v_guard_happy_p boolean; - v_rec record; - v_str text default ''''; -begin - if evaluate_guard__callback = '''' or - evaluate_guard__callback is null then - -- null guard evaluates to true - return ''t''; - else - if evaluate_guard__callback = ''#'' then - return ''f''; - else - v_str := ''select '' || evaluate_guard__callback - || ''('' || - evaluate_guard__case_id || '','' || - quote_literal(evaluate_guard__workflow_key) || '','' || - quote_literal(evaluate_guard__transition_key) || '','' || - quote_literal(evaluate_guard__place_key) || '','' || - quote_literal(evaluate_guard__direction) || '','' || - coalesce(quote_literal(evaluate_guard__custom_arg),''null'') || '') as guard_happy_p''; - raise notice ''str = %'', v_str; - for v_rec in - execute v_str - LOOP - return v_rec.guard_happy_p; - end LOOP; - end if; - end if; - - return null; - -end;' language 'plpgsql'; - - --- procedure execute_transition_callback -create function workflow_case__execute_transition_callback (varchar,varchar,integer,varchar) -returns integer as ' -declare - execute_transition_callback__callback alias for $1; - execute_transition_callback__custom_arg alias for $2; - execute_transition_callback__case_id alias for $3; - execute_transition_callback__transition_key alias for $4; - v_str text; -begin - if execute_transition_callback__callback != '''' and execute_transition_callback__callback is not null then - v_str := ''select '' || execute_transition_callback__callback - || ''('' || execute_transition_callback__case_id || '','' || - quote_literal(execute_transition_callback__transition_key) || '','' || - coalesce(quote_literal(execute_transition_callback__custom_arg),''null'') || '')''; - execute v_str; - end if; - - return 0; -end;' language 'plpgsql'; - - --- function execute_time_callback -create function workflow_case__execute_time_callback (varchar,varchar,integer,varchar) -returns timestamp as ' -declare - execute_time_callback__callback alias for $1; - execute_time_callback__custom_arg alias for $2; - execute_time_callback__case_id alias for $3; - execute_time_callback__transition_key alias for $4; - v_rec record; - v_str text; -begin - if execute_time_callback__callback = '''' or execute_time_callback__callback is null then - raise EXCEPTION ''-20000: There''''s no time_callback function for the timed transition "%"'', execute_time_callback__transition_key; - end if; - - v_str := ''select '' || execute_time_callback__callback || ''('' || - execute_time_callback__case_id || '','' || - quote_literal(execute_time_callback__transition_key) || '','' || - coalesce(quote_literal(execute_time_callback__custom_arg),''null'') || '') as trigger_time'' - - for v_rec in execute v_str - LOOP - return v_rec.trigger_time; - end LOOP; - - return null; - -end;' language 'plpgsql'; - - --- function get_task_deadline -create function workflow_case__get_task_deadline (varchar,varchar,varchar,integer,varchar) -returns timestamp as ' -declare - get_task_deadline__callback alias for $1; - get_task_deadline__custom_arg alias for $2; - get_task_deadline__attribute_name alias for $3; - get_task_deadline__case_id alias for $4; - get_task_deadline__transition_key alias for $5; - v_deadline timestamp; - v_rec record; - v_str varchar; -begin - /* - * 1. or if there is a row in wf_case_deadlines, we use that - * 2. if there is a callback, we execute that - * 3. otherwise, if there is an attribute, we use that - */ - - /* wf_case_deadlines */ - select deadline into v_deadline - from wf_case_deadlines - where case_id = get_task_deadline__case_id - and transition_key = get_task_deadline__transition_key; - - if NOT FOUND then - if get_task_deadline__callback != '''' and get_task_deadline__callback is not null then - /* callback */ - v_str := ''select '' || get_task_deadline__callback || ''('' || - get_task_deadline__case_id || '','' || - quote_literal(get_task_deadline__transition_key) || '','' || - coalesce(quote_literal(get_task_deadline__custom_arg),''null'') || '') as deadline''; - - for v_rec in execute v_str - LOOP - v_deadline := v_rec.deadline; - exit; - end LOOP; - else if get_task_deadline__attribute_name != '''' and get_task_deadline__attribute_name is not null then - /* attribute */ - v_deadline := acs_object__get_attribute( - get_task_deadline__case_id, - get_task_deadline__attribute_name - ); - else - v_deadline := null; - end if; end if; - end if; - - return v_deadline; - -end;' language 'plpgsql'; - - --- function execute_hold_timeout_callback -create function workflow_case__execute_hold_timeout_callback (varchar,varchar,integer,varchar) -returns timestamp as ' -declare - execute_hold_timeout_callback__callback alias for $1; - execute_hold_timeout_callback__custom_arg alias for $2; - execute_hold_timeout_callback__case_id alias for $3; - execute_hold_timeout_callback__transition_key alias for $4; - v_hold_timeout timestamp; - v_rec record; - v_str text; -begin - if execute_hold_timeout_callback__callback = '''' or execute_hold_timeout_callback__callback is null then - return null; - end if; - - v_str := ''select '' || execute_hold_timeout_callback__callback - || ''('' || - execute_hold_timeout_callback__case_id || '','' || - quote_literal(execute_hold_timeout_callback__transition_key) || - '','' || - coalesce(quote_literal(execute_hold_timeout_callback__custom_arg),''null'') || '') as hold_timeout''; - - for v_rec in execute v_str - LOOP - return v_rec.hold_timeout; - end LOOP; - - return null; - -end;' language 'plpgsql'; - - --- procedure execute_unassigned_callback -create function workflow_case__execute_unassigned_callback (varchar,integer,varchar) -returns integer as ' -declare - callback alias for $1; - task_id alias for $2; - custom_arg alias for $3; - v_str text; -begin - if callback != '''' and callback is not null then - v_str := ''select '' || callback - || ''('' || task_id || '','' || - coalesce(quote_literal(custom_arg),''null'') - || '')''; - - execute v_str; - end if; - - return 0; -end;' language 'plpgsql'; - - --- procedure set_task_assignments -create function workflow_case__set_task_assignments (integer,varchar,varchar) -returns integer as ' -declare - set_task_assignments__task_id alias for $1; - set_task_assignments__callback alias for $2; - set_task_assignments__custom_arg alias for $3; - v_done_p boolean; - case_assignment_rec record; - context_assignment_rec record; - v_str text; -begin - - /* Find out who to assign the given task to. - * - * 1. See if there are rows in wf_case_assignments. - * 2. If not, and a callback is defined, execute that. - * 3. Otherwise, grab the assignment from the workflow context. - * - * (We used to use the callback first, but that makes - * reassignment of tasks difficult.) - */ - - v_done_p := ''f''; - for case_assignment_rec in select party_id - from wf_case_assignments ca, wf_tasks t - where t.task_id = set_task_assignments__task_id - and ca.case_id = t.case_id - and ca.transition_key = t.transition_key - LOOP - v_done_p := ''t''; - PERFORM workflow_case__add_task_assignment ( - set_task_assignments__task_id, - case_assignment_rec.party_id - ); - end loop; - if v_done_p != ''t'' then - - if set_task_assignments__callback != '''' and set_task_assignments__callback is not null then - v_str := ''select ''|| set_task_assignments__callback || ''('' || - set_task_assignments__task_id || '','' || - coalesce(quote_literal(set_task_assignments__custom_arg),''null'') || '')''; - execute v_str; - else - for context_assignment_rec in - select party_id - from wf_context_assignments ca, wf_cases c, wf_tasks t - where t.task_id = set_task_assignments__task_id - and c.case_id = t.case_id - and ca.context_key = c.context_key - and ca.workflow_key = t.workflow_key - and ca.transition_key = t.transition_key - LOOP - PERFORM workflow_case__add_task_assignment ( - set_task_assignments__task_id, - context_assignment_rec.party_id - ); - end LOOP; - end if; - end if; - - return 0; -end;' language 'plpgsql'; - - --- procedure add_token -create function workflow_case__add_token (integer,varchar,integer) -returns integer as ' -declare - add_token__case_id alias for $1; - add_token__place_key alias for $2; - add_token__journal_id alias for $3; - v_token_id integer; - v_workflow_key varchar; -begin - select wf_token_id_seq.nextval into v_token_id from dual; - - select workflow_key into v_workflow_key - from wf_cases c - where c.case_id = add_token__case_id; - - insert into wf_tokens - (token_id, case_id, workflow_key, place_key, state, produced_journal_id) - values - (v_token_id, add_token__case_id, v_workflow_key, add_token__place_key, - ''free'', add_token__journal_id); - - return 0; -end;' language 'plpgsql'; - - --- procedure lock_token -create function workflow_case__lock_token (integer,varchar,integer,integer) -returns integer as ' -declare - lock_token__case_id alias for $1; - lock_token__place_key alias for $2; - lock_token__journal_id alias for $3; - lock_token__task_id alias for $4; -begin - -- FIXME: rownum --- update wf_tokens --- set state = ''locked'', --- locked_task_id = lock_token__task_id, --- locked_date = now(), --- locked_journal_id = lock_token__journal_id --- where case_id = lock_token__case_id --- and place_key = lock_token__place_key --- and state = ''free'' --- and rownum = 1; - - update wf_tokens - set state = ''locked'', - locked_task_id = lock_token__task_id, - locked_date = now(), - locked_journal_id = lock_token__journal_id - where token_id = (select token_id - from wf_tokens - where case_id = lock_token__case_id - and place_key = lock_token__place_key - and state = ''free'' - limit 1); - - return 0; -end;' language 'plpgsql'; - - --- procedure release_token -create function workflow_case__release_token (integer,integer) -returns integer as ' -declare - release_token__task_id alias for $1; - release_token__journal_id alias for $2; - token_rec record; -begin - /* Add a new token for each released one */ - for token_rec in - select token_id, - case_id, - place_key - from wf_tokens - where state = ''locked'' - and locked_task_id = release_token__task_id - LOOP - PERFORM workflow_case__add_token( - token_rec.case_id, - token_rec.place_key, - release_token__journal_id - ); - end loop; - - /* Mark the released ones canceled */ - update wf_tokens - set state = ''canceled'', - canceled_date = now(), - canceled_journal_id = release_token__journal_id - where state = ''locked'' - and locked_task_id = release_token__task_id; - - return 0; -end;' language 'plpgsql'; - - --- procedure consume_token -create function workflow_case__consume_token (integer,varchar,integer,integer) -returns integer as ' -declare - consume_token__case_id alias for $1; - consume_token__place_key alias for $2; - consume_token__journal_id alias for $3; - consume_token__task_id alias for $4; -- default null -begin - if consume_token__task_id is null then - update wf_tokens - set state = ''consumed'', - consumed_date = now(), - consumed_journal_id = consume_token__journal_id - where token_id = (select token_id - from wf_tokens - where case_id = consume_token__case_id - and place_key = consume_token__place_key - and state = ''free'' - limit 1); - else - update wf_tokens - set state = ''consumed'', - consumed_date = now(), - consumed_journal_id = consume_token__journal_id - where case_id = consume_token__case_id - and place_key = consume_token__place_key - and state = ''locked'' - and locked_task_id = consume_token__task_id; - end if; - - return 0; -end;' language 'plpgsql'; - - --- procedure sweep_automatic_transitions -create function workflow_case__sweep_automatic_transitions (integer,integer) -returns integer as ' -declare - sweep_automatic_transitions__case_id alias for $1; - sweep_automatic_transitions__journal_id alias for $2; - v_done_p boolean; - v_finished_p boolean; - task_rec record; -begin - - PERFORM workflow_case__enable_transitions(sweep_automatic_transitions__case_id); - LOOP - v_done_p := ''t''; - v_finished_p := workflow_case__finished_p( - sweep_automatic_transitions__case_id, - sweep_automatic_transitions__journal_id); - - if v_finished_p = ''f'' then - for task_rec in - select task_id - from wf_tasks ta, wf_transitions tr - where tr.workflow_key = ta.workflow_key - and tr.transition_key = ta.transition_key - and tr.trigger_type = ''automatic'' - and ta.state = ''enabled'' - and ta.case_id = sweep_automatic_transitions__case_id - LOOP - PERFORM workflow_case__fire_transition_internal( - task_rec.task_id, - sweep_automatic_transitions__journal_id - ); - - v_done_p := ''f''; - end loop; - PERFORM workflow_case__enable_transitions(sweep_automatic_transitions__case_id); - end if; - - exit when v_done_p = ''t''; - end loop; - - return 0; -end;' language 'plpgsql'; - - --- function finished_p -create function workflow_case__finished_p (integer,integer) -returns boolean as ' -declare - finished_p__case_id alias for $1; - finished_p__journal_id alias for $2; - v_case_state varchar; - v_token_id integer; - v_num_rows integer; - v_journal_id integer; -begin - select state into v_case_state - from wf_cases - where case_id = finished_p__case_id; - - if v_case_state = ''finished'' then - return ''t''; - else - /* Let us see if the case is actually finished, but just not marked so */ - select case when count(*) = 0 then 0 else 1 end into v_num_rows - from wf_tokens - where case_id = finished_p__case_id - and place_key = ''end''; - - if v_num_rows = 0 then - return ''f''; - else - /* There is a token in the end place. - * Count the total integer of tokens to make sure the wf is well-constructed. - */ - - select case when count(*) = 0 then 0 - when count(*) = 1 then 1 - else 2 - end into v_num_rows - from wf_tokens - where case_id = finished_p__case_id - and state in (''free'', ''locked''); - - if v_num_rows > 1 then - raise EXCEPTION ''-20000: The workflow net is misconstructed: Some parallel executions have not finished.''; - end if; - - /* Consume that token */ - select token_id into v_token_id - from wf_tokens - where case_id = finished_p__case_id - and state in (''free'', ''locked''); - - PERFORM workflow_case__consume_token( - finished_p__case_id, - ''end'', - finished_p__journal_id, - null - ); - - update wf_cases - set state = ''finished'' - where case_id = finished_p__case_id; - - /* Add an extra entry to the journal */ - v_journal_id := journal_entry__new( - null, - finished_p__case_id, - ''case finish'', - ''Case finished'', - now(), - null, - null, - null - ); - - return ''t''; - end if; - end if; - -end;' language 'plpgsql'; - - - - /* This procedure should be scheduled to run as a dbms_job. */ -create function sweep_timed_transitions () returns integer as ' -declare - v_journal_id integer; - trans_rec record; -begin - for trans_rec in select t.task_id, t.case_id, tr.transition_name - from wf_tasks t, wf_transitions tr - where trigger_time <= now() - and state = ''enabled'' - and tr.workflow_key = t.workflow_key - and tr.transition_key = t.transition_key - LOOP - - /* Insert an entry to the journal so people will know it fired */ - - v_journal_id := journal_entry__new( - null, - trans_rec.case_id, - ''task '' || trans_rec.task_id || '' fire time'', - trans_rec.transition_name || '' automatically finished'', - now(), - null, - null, - ''Timed transition fired.'' - ); - - /* Fire the transition */ - - PERFORM workflow_case__fire_transition_internal( - trans_rec.task_id, - v_journal_id - ); - - /* Update the workflow internal state */ - - PERFORM workflow_case___sweep_automatic_transitions( - trans_rec.case_id, - v_journal_id - ); - - end loop; - - return 0; -end;' language 'plpgsql'; - - - /* This procedure should be scheduled to run as a dbms_job. */ -create function sweep_hold_timeout () returns integer as ' -declare - v_journal_id integer; - task_rec record; -begin - for task_rec in select t.task_id, t.case_id, tr.transition_name - from wf_tasks t, wf_transitions tr - where hold_timeout <= now() - and state = ''started'' - and tr.workflow_key = t.workflow_key - and tr.transition_key = t.transition_key - LOOP - - /* Insert an entry to the journal so people will know it was canceled */ - - v_journal_id := journal_entry__new( - null, - task_rec.case_id, - ''task '' || task_rec.task_id || '' cancel timeout'', - task_rec.transition_name || '' timed out'', - now(), - null, - null, - ''The user''''s hold on the task timed out and the task was automatically canceled'' - ); - - - /* Cancel the task */ - - PERFORM workflow_case__cancel_task( - task_rec.task_id, - v_journal_id - ); - - end loop; - - returns 0; -end;' language 'plpgsql'; - --- procedure notify_assignee -create function workflow_case__notify_assignee (integer,integer,varchar,varchar) -returns integer as ' -declare - notify_assignee__task_id alias for $1; - notify_assignee__user_id alias for $2; - notify_assignee__callback alias for $3; - notify_assignee__custom_arg alias for $4; - v_deadline_pretty varchar; - v_object_name text; - v_transition_key wf_transitions.transition_key%TYPE; - v_transition_name wf_transitions.transition_name%TYPE; - v_party_from parties.party_id%TYPE; - v_party_to parties.party_id%TYPE; - v_subject text; - v_body text; - v_request_id integer; - v_str text; -begin - select to_char(ta.deadline,''Mon fmDDfm, YYYY HH24:MI:SS''), - acs_object__name(c.object_id), - tr.transition_key, - tr.transition_name - into v_deadline_pretty, - v_object_name, - v_transition_key, - v_transition_name - from wf_tasks ta, wf_transitions tr, wf_cases c - where ta.task_id = notify_assignee__task_id - and c.case_id = ta.case_id - and tr.workflow_key = c.workflow_key - and tr.transition_key = ta.transition_key; - - /* Default values */ - /* This default value should probably be pulled from somewhere */ - v_party_from := -1; - v_subject := ''Assignment: '' || v_transition_name || '' '' || v_object_name; - v_body := ''You have been assigned to a task. -'' || '' -Task : '' || v_transition_name || '' -Object : '' || v_object_name || '' -''; - - if v_deadline_pretty != '''' and v_deadline_pretty is not null then - v_body := v_body || ''Deadline: '' || v_deadline_pretty || '' -''; - end if; - - /* - * We would like to add a URL to go visit, but how do we get that URL? - * - * The notifications should really be sent from the application - * server layer, not from the database - */ - - -- FIXME: last three args are also out varibles. - - if notify_assignee__callback != '''' and notify_assignee__callback is not null then - v_str := ''select '' || notify_assignee__callback || ''('' || - notify_assignee__task_id || '','' || - coalesce(quote_literal(notify_assignee__custom_arg),''null'') || - '','' || - notify_assignee__user_id || '','' || - v_party_from || '','' || - quote_literal(v_subject) || '','' || - quote_literal(v_body) || '')''; - - execute v_str; - end if; - - -- NOTICE, NOTICE, NOTICE - -- - -- Since postgresql does not support out parameters, this - -- function call has been moved into the callback function. - -- If you implement a new notification callback, make sure - -- that this function call is included at the end of the - -- callback routine. - -- - -- DanW (dcwickstrom@earthlink.net) - - -- v_request_id := acs_mail_nt__post_request ( - -- v_party_from, -- party_from - -- notify_assignee__user_id, -- party_to - -- ''f'', -- expand_group - -- v_subject, -- subject - -- v_body, -- message - -- 0 -- max_retries - --); - - return 0; -end;' language 'plpgsql'; - - --- procedure enable_transitions -create function workflow_case__enable_transitions (integer) -returns integer as ' -declare - enable_transitions__case_id alias for $1; - v_task_id integer; - v_workflow_key varchar; - v_trigger_time timestamp; - v_deadline_date timestamp; - v_party_from integer; - v_subject varchar; - v_body text; - v_num_assigned integer; - trans_rec record; -begin - select workflow_key into v_workflow_key - from wf_cases - where case_id = enable_transitions__case_id; - - /* we mark tasks overridden if they were once enabled, but are no longer so */ - - update wf_tasks - set state = ''overridden'', - overridden_date = now() - where case_id = enable_transitions__case_id - and state = ''enabled'' - and transition_key not in - (select transition_key - from wf_enabled_transitions - where case_id = enable_transitions__case_id); - - - /* insert a task for the transitions that are enabled but have no task row */ - - for trans_rec in select transition_key, - transition_name, - trigger_type, - enable_callback, - enable_custom_arg, - assignment_callback, - assignment_custom_arg, - time_callback, - time_custom_arg, - deadline_callback, - deadline_custom_arg, - deadline_attribute_name, - notification_callback, - notification_custom_arg, - unassigned_callback, - unassigned_custom_arg, - estimated_minutes - from wf_enabled_transitions et - where et.case_id = enable_transitions__case_id - and not exists (select 1 from wf_tasks - where case_id = enable_transitions__case_id - and transition_key = et.transition_key - and state in (''enabled'', ''started'')) - LOOP - - v_trigger_time := null; - v_deadline_date := null; - - if trans_rec.trigger_type = ''user'' then - v_deadline_date := workflow_case__get_task_deadline( - trans_rec.deadline_callback, - trans_rec.deadline_custom_arg, - trans_rec.deadline_attribute_name, - enable_transitions__case_id, - trans_rec.transition_key - ); - else if trans_rec.trigger_type = ''time'' then - v_trigger_time := workflow_case__execute_time_callback( - trans_rec.time_callback, - trans_rec.time_custom_arg, - enable_transitions__case_id, - trans_rec.transition_key); - end if; end if; - - /* we are ready to insert the row */ - select wf_task_id_seq.nextval into v_task_id from dual; - - insert into wf_tasks ( - task_id, case_id, workflow_key, transition_key, - deadline, trigger_time, estimated_minutes - ) values ( - v_task_id, enable_transitions__case_id, v_workflow_key, - trans_rec.transition_key, - v_deadline_date, v_trigger_time, trans_rec.estimated_minutes - ); - - PERFORM workflow_case__set_task_assignments( - v_task_id, - trans_rec.assignment_callback, - trans_rec.assignment_custom_arg - ); - - /* Execute the transition enabled callback */ - PERFORM workflow_case__execute_transition_callback( - trans_rec.enable_callback, - trans_rec.enable_custom_arg, - enable_transitions__case_id, - trans_rec.transition_key - ); - - select count(*) into v_num_assigned - from wf_task_assignments - where task_id = v_task_id; - - if v_num_assigned = 0 then - PERFORM workflow_case__execute_unassigned_callback ( - trans_rec.unassigned_callback, - v_task_id, - trans_rec.unassigned_custom_arg - ); - end if; - - end loop; - - return 0; -end;' language 'plpgsql'; - - --- procedure fire_transition_internal -create function workflow_case__fire_transition_internal (integer,integer) -returns integer as ' -declare - fire_transition_internal__task_id alias for $1; - fire_transition_internal__journal_id alias for $2; - v_case_id integer; - v_state varchar; - v_transition_key varchar; - v_workflow_key varchar; - v_place_key varchar; - v_direction varchar; - v_guard_happy_p boolean; - v_fire_callback varchar; - v_fire_custom_arg text; - v_found_happy_guard boolean; - v_locked_task_id integer; - place_rec record; -begin - select t.case_id, t.state, t.workflow_key, t.transition_key, ti.fire_callback, ti.fire_custom_arg - into v_case_id, v_state, v_workflow_key, v_transition_key, v_fire_callback, v_fire_custom_arg - from wf_tasks t, wf_cases c, wf_transition_info ti - where t.task_id = fire_transition_internal__task_id - and c.case_id = t.case_id - and ti.context_key = c.context_key - and ti.workflow_key = c.workflow_key - and ti.transition_key = t.transition_key; - - /* Check that the state is either started or enabled */ - - if v_state = ''enabled'' then - v_locked_task_id := null; - else if v_state = ''started'' then - v_locked_task_id := fire_transition_internal__task_id; - else - raise EXCEPTION ''-20000: Can''''t fire the transition if it''''s not in state enabled or started''; - end if; end if; - - /* Mark the task finished */ - - update wf_tasks - set state = ''finished'', - finished_date = now() - where task_id = fire_transition_internal__task_id; - - - /* Consume the tokens */ - - for place_rec in select * - from wf_transition_places tp - where tp.workflow_key = v_workflow_key - and tp.transition_key = v_transition_key - LOOP - PERFORM workflow_case__consume_token( - v_case_id, - place_rec.place_key, - fire_transition_internal__journal_id, - v_locked_task_id - ); - end loop; - - - /* Spit out new tokens in the output places */ - - v_found_happy_guard := ''f''; - for place_rec in - select * - from wf_transition_places tp - where tp.workflow_key = v_workflow_key - and tp.transition_key = v_transition_key - and direction = ''out'' - LOOP - v_place_key := place_rec.place_key; - v_direction := place_rec.direction; - - v_guard_happy_p := workflow_case__evaluate_guard( - place_rec.guard_callback, - place_rec.guard_custom_arg, - v_case_id, - v_workflow_key, - v_transition_key, - v_place_key, - v_direction - ); - - if v_guard_happy_p = ''t'' then - v_found_happy_guard := ''t''; - PERFORM workflow_case__add_token( - v_case_id, - place_rec.place_key, - fire_transition_internal__journal_id - ); - end if; - end loop; - - - /* If we did not find any happy guards, look for arcs with the special hash (#) guard */ - - if v_found_happy_guard = ''f'' then - for place_rec in - select place_key - from wf_transition_places tp - where tp.workflow_key = v_workflow_key - and tp.transition_key = v_transition_key - and tp.direction = ''out'' - and tp.guard_callback = ''#'' - loop - - PERFORM workflow_case__add_token( - v_case_id, - place_rec.place_key, - fire_transition_internal__journal_id - ); - end loop; - end if; - - - /* Execute the transition fire callback */ - - PERFORM workflow_case__execute_transition_callback( - v_fire_callback, - v_fire_custom_arg, - v_case_id, - v_transition_key - ); - - return 0; -end;' language 'plpgsql'; - - --- procedure ensure_task_in_state -create function workflow_case__ensure_task_in_state (integer,varchar) -returns integer as ' -declare - ensure_task_in_state__task_id alias for $1; - ensure_task_in_state__state alias for $2; - v_count integer; -begin - select case when count(*) = 0 then 0 else 1 end into v_count - from wf_tasks - where task_id = ensure_task_in_state__task_id - and state = ensure_task_in_state__state; - - if v_count != 1 then - raise EXCEPTION ''-20000: The task % is not in state "%"'', ensure_task_in_state__task_id, ensure_task_in_state__state; - end if; - - return 0; -end;' language 'plpgsql'; - - --- procedure start_task -create function workflow_case__start_task (integer,integer,integer) -returns integer as ' -declare - start_task__task_id alias for $1; - start_task__user_id alias for $2; - start_task__journal_id alias for $3; - v_case_id integer; - v_workflow_key wf_workflows.workflow_key%TYPE; - v_transition_key varchar(100); - v_hold_timeout_callback varchar(100); - v_hold_timeout_custom_arg varchar(4000); - v_hold_timeout timestamp; - place_rec record; -begin - PERFORM workflow_case__ensure_task_in_state(start_task__task_id, - ''enabled''); - - select t.case_id, t.workflow_key, t.transition_key, ti.hold_timeout_callback, ti.hold_timeout_custom_arg - into v_case_id, v_workflow_key, v_transition_key, v_hold_timeout_callback, v_hold_timeout_custom_arg - from wf_tasks t, wf_cases c, wf_transition_info ti - where t.task_id = start_task__task_id - and c.case_id = t.case_id - and ti.context_key = c.context_key - and ti.workflow_key = t.workflow_key - and ti.transition_key = t.transition_key; - - v_hold_timeout := workflow_case__execute_hold_timeout_callback( - v_hold_timeout_callback, - v_hold_timeout_custom_arg, - v_case_id, v_transition_key); - - /* Mark it started */ - - update wf_tasks - set state = ''started'', - started_date = now(), - holding_user = start_task__user_id, - hold_timeout = v_hold_timeout - where task_id = start_task__task_id; - - - /* Reserve one token from each input place */ - - for place_rec in select * - from wf_transition_places tp - where tp.workflow_key = v_workflow_key - and tp.transition_key = v_transition_key - and direction = ''in'' - LOOP - PERFORM workflow_case__lock_token( - v_case_id, - place_rec.place_key, - start_task__journal_id, - start_task__task_id - ); - end loop; - - return 0; -end;' language 'plpgsql'; - - --- procedure cancel_task -create function workflow_case__cancel_task (integer,integer) -returns integer as ' -declare - cancel_task__task_id alias for $1; - cancel_task__journal_id alias for $2; - v_case_id integer; -begin - PERFORM workflow_case__ensure_task_in_state(cancel_task__task_id, - ''started''); - select case_id into v_case_id - from wf_tasks - where task_id = cancel_task__task_id; - - /* Mark the task canceled */ - - update wf_tasks - set state = ''canceled'', - canceled_date = now() - where task_id = cancel_task__task_id; - - - /* Release our reserved tokens */ - - PERFORM workflow_case__release_token( - cancel_task__task_id, - cancel_task__journal_id - ); - - /* The workflow state has now changed, so we must run this */ - - PERFORM workflow_case__sweep_automatic_transitions( - v_case_id, - cancel_task__journal_id - ); - - return 0; -end;' language 'plpgsql'; - - --- procedure finish_task -create function workflow_case__finish_task (integer,integer) -returns integer as ' -declare - finish_task__task_id alias for $1; - finish_task__journal_id alias for $2; - v_case_id integer; -begin - select case_id into v_case_id - from wf_tasks - where task_id = finish_task__task_id; - - PERFORM workflow_case__fire_transition_internal( - finish_task__task_id, - finish_task__journal_id - ); - - PERFORM workflow_case__sweep_automatic_transitions( - v_case_id, - finish_task__journal_id - ); - - return 0; -end;' language 'plpgsql'; - - - --- show errors - - +\i workflow-case-package-head.sql +\i workflow-case-package-body.sql \ No newline at end of file Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/workflow-package-body.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/workflow-package-body.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/workflow-package-body.sql 19 Nov 2001 18:20:33 -0000 1.1 @@ -0,0 +1,921 @@ +-- create or replace package body workflow +-- function create_workflow +create function workflow__create_workflow (varchar,varchar,varchar,varchar,varchar,varchar) +returns varchar as ' +declare + create_workflow__workflow_key alias for $1; + create_workflow__pretty_name alias for $2; + create_workflow__pretty_plural alias for $3; -- default null + create_workflow__description alias for $4; -- default null + create_workflow__table_name alias for $5; + create_workflow__id_column alias for $6; -- default ''case_id'' + v_num_rows integer; + v_workflow_key varchar; +begin + select count(*) into v_num_rows + from pg_class + where relname = lower(create_workflow__table_name); + + if v_num_rows = 0 then + raise EXCEPTION ''-20000: The table "%"must be created before calling workflow.create_workflow.'', create_workflow__table_name; + end if; + + if substr(create_workflow__workflow_key, + length(create_workflow__workflow_key) - 2, 3) != ''_wf'' then + v_workflow_key := create_workflow__workflow_key || ''_wf''; + else + v_workflow_key := create_workflow__workflow_key; + end if; + + PERFORM acs_object_type__create_type ( + v_workflow_key, + create_workflow__pretty_name, + create_workflow__pretty_plural, + ''workflow'', + create_workflow__table_name, + create_workflow__id_column, + null, + ''f'', + null, + null + ); + + insert into wf_workflows + (workflow_key, description) + values + (v_workflow_key, create_workflow__description); + + return v_workflow_key; + +end;' language 'plpgsql'; + + +/* Note: The workflow-specific cases table must be dropped before calling this proc */ +create function workflow__drop_workflow (varchar) +returns integer as ' +declare + drop_workflow__workflow_key alias for $1; + v_table_name varchar; + v_num_rows integer; + attribute_rec record; +begin + select table_name into v_table_name + from acs_object_types + where object_type = drop_workflow__workflow_key; + + select case when count(*) = 0 then 0 else 1 end into v_num_rows + from pg_class + where relname = lower(v_table_name); + + if v_num_rows > 0 then + raise EXCEPTION ''-20000: The table "%" must be dropped before calling workflow__drop_workflow.'', v_table_name; + end if; + + select case when count(*) = 0 then 0 else 1 end into v_num_rows + from wf_cases + where workflow_key = drop_workflow__workflow_key; + + if v_num_rows > 0 then + raise EXCEPTION ''-20000: You must delete all cases of workflow "%" before dropping the workflow definition.'', drop_workflow__workflow_key; + end if; + + /* Delete all the auxillary stuff */ + delete from wf_context_task_panels where workflow_key = drop_workflow__workflow_key; + delete from wf_context_assignments where workflow_key = drop_workflow__workflow_key; + delete from wf_context_role_info where workflow_key = drop_workflow__workflow_key; + delete from wf_context_transition_info where workflow_key = drop_workflow__workflow_key; + delete from wf_context_workflow_info where workflow_key = drop_workflow__workflow_key; + delete from wf_arcs where workflow_key = drop_workflow__workflow_key; + delete from wf_places where workflow_key = drop_workflow__workflow_key; + delete from wf_transition_role_assign_map where workflow_key = drop_workflow__workflow_key; + delete from wf_transitions where workflow_key = drop_workflow__workflow_key; + delete from wf_roles where workflow_key = drop_workflow__workflow_key; + + /* Drop all attributes */ + for attribute_rec in + select attribute_id, attribute_name + from acs_attributes + where object_type = drop_workflow__workflow_key + LOOP + /* there is no on delete cascade, so we have to manually + * delete all the values + */ + + delete from acs_attribute_values where attribute_id = attribute_rec.attribute_id; + + PERFORM workflow__drop_attribute ( + drop_workflow__workflow_key, + attribute_rec.attribute_name + ); + end loop; + + /* Delete the workflow */ + delete from wf_workflows where workflow_key = drop_workflow__workflow_key; + + PERFORM acs_object_type__drop_type ( + drop_workflow__workflow_key, + ''f'' + ); + + return 0; +end;' language 'plpgsql'; + + +-- procedure delete_cases +create function workflow__delete_cases (varchar) +returns integer as ' +declare + delete_cases__workflow_key alias for $1; + case_rec record; +begin + for case_rec in + select case_id + from wf_cases + where workflow_key = delete_cases__workflow_key + LOOP + PERFORM workflow_case__delete(case_rec.case_id); + end loop; + + return 0; +end;' language 'plpgsql'; + + +-- function create_attribute +create function workflow__create_attribute (varchar,varchar,varchar,varchar,varchar,varchar,varchar,varchar,integer,integer,integer,varchar) +returns integer as ' +declare + create_attribute__workflow_key alias for $1; + create_attribute__attribute_name alias for $2; + create_attribute__datatype alias for $3; + create_attribute__pretty_name alias for $4; + create_attribute__pretty_plural alias for $5; -- default null + create_attribute__table_name alias for $6; -- default null + create_attribute__column_name alias for $7; -- default null + create_attribute__default_value alias for $8; -- default null + create_attribute__min_n_values alias for $9; -- default 1 + create_attribute__max_n_values alias for $10; -- default 1 + create_attribute__sort_order alias for $11; -- default null + create_attribute__storage alias for $12; -- default ''generic'' + v_attribute_id integer; +begin + v_attribute_id := acs_attribute__create_attribute( + create_attribute__workflow_key, + create_attribute__attribute_name, + create_attribute__datatype, + create_attribute__pretty_name, + create_attribute__pretty_plural, + create_attribute__table_name, + create_attribute__column_name, + create_attribute__default_value, + create_attribute__min_n_values, + create_attribute__max_n_values, + create_attribute__sort_order, + create_attribute__storage, + ''f'' + ); + + return v_attribute_id; + +end;' language 'plpgsql'; + + +-- procedure drop_attribute +create function workflow__drop_attribute (varchar,varchar) +returns integer as ' +declare + drop_attribute__workflow_key alias for $1; + drop_attribute__attribute_name alias for $2; + v_attribute_id integer; +begin + select attribute_id into v_attribute_id + from acs_attributes + where object_type = drop_attribute__workflow_key + and attribute_name = drop_attribute__attribute_name; + + PERFORM acs_attribute__drop_attribute ( + drop_attribute__workflow_key, + drop_attribute__attribute_name + ); + + return 0; +end;' language 'plpgsql'; + + +-- procedure add_place +create function workflow__add_place (varchar,varchar,varchar,integer) +returns integer as ' +declare + add_place__workflow_key alias for $1; + add_place__place_key alias for $2; + add_place__place_name alias for $3; + add_place__sort_order alias for $4; + v_sort_order integer; +begin + if add_place__sort_order is null then + select coalesce(max(sort_order)+1, 1) + into v_sort_order + from wf_places + where workflow_key = add_place__workflow_key; + else + v_sort_order := add_place__sort_order; + end if; + insert into wf_places (workflow_key, place_key, place_name, sort_order) + values (add_place__workflow_key, add_place__place_key,add_place__place_name, add_place__sort_order); + + return 0; +end;' language 'plpgsql'; + + +-- procedure delete_place +create function workflow__delete_place (varchar,varchar) +returns integer as ' +declare + delete_place__workflow_key alias for $1; + delete_place__place_key alias for $2; +begin + delete from wf_places + where workflow_key = delete_place__workflow_key + and place_key = delete_place__place_key; + + return 0; +end;' language 'plpgsql'; + + +-- procedure add_role +create function workflow__add_role (varchar,varchar,varchar,integer) +returns integer as ' +declare + add_role__workflow_key alias for $1; + add_role__role_key alias for $2; + add_role__role_name alias for $3; + add_role__sort_order alias for $4; + v_sort_order integer; +begin + if add_role__sort_order is null then + select coalesce(max(sort_order)+1, 1) + into v_sort_order + from wf_roles + where workflow_key = add_role__workflow_key; + else + v_sort_order := add_role__sort_order; + end if; + insert into wf_roles ( + workflow_key, role_key, role_name, sort_order + ) values ( + add_role__workflow_key, add_role__role_key, add_role__role_name, v_sort_order + ); + return 0; +end;' language 'plpgsql'; + + +-- procedure move_role_up +create function workflow__move_role_up (varchar,varchar) +returns integer as ' +declare + move_role_up__workflow_key alias for $1; + move_role_up__role_key alias for $2; + v_this_sort_order integer; + v_prior_sort_order integer; +begin + select sort_order + into v_this_sort_order + from wf_roles + where workflow_key = move_role_up__workflow_key + and role_key = move_role_up__role_key; + + select max(sort_order) + into v_prior_sort_order + from wf_roles + where workflow_key = move_role_up__workflow_key + and sort_order < v_this_sort_order; + + if not found then + /* already at top of sort order */ + return; + end if; + + /* switch the sort orders around */ + update wf_roles + set sort_order = (case when role_key=move_role_up__role_key then v_prior_sort_order else v_this_sort_order end) + where workflow_key = move_role_up__workflow_key + and sort_order in (v_this_sort_order, v_prior_sort_order); + + return 0; +end;' language 'plpgsql'; + + +-- procedure move_role_down +create function workflow__move_role_down (varchar,varchar) +returns integer as ' +declare + move_role_down__workflow_key alias for $1; + move_role_down__role_key alias for $2; + v_this_sort_order integer; + v_next_sort_order integer; +begin + select sort_order + into v_this_sort_order + from wf_roles + where workflow_key = move_role_down__workflow_key + and role_key = move_role_down__role_key; + + select min(sort_order) + into v_next_sort_order + from wf_roles + where workflow_key = move_role_down__workflow_key + and sort_order > v_this_sort_order; + + if not found then + /* already at bottom of sort order */ + return; + end if; + + /* switch the sort orders around */ + update wf_roles + set sort_order = (case when role_key=move_role_down__role_key then v_next_sort_order else v_this_sort_order end) + where workflow_key = move_role_down__workflow_key + and sort_order in (v_this_sort_order, v_next_sort_order); + + return 0; +end;' language 'plpgsql'; + + +-- procedure delete_role +create function workflow__delete_role (varchar,varchar) +returns integer as ' +declare + delete_role__workflow_key alias for $1; + delete_role__role_key alias for $2; +begin + /* First, remove all references to this role from transitions */ + update wf_transitions + set role_key = null + where workflow_key = delete_role__workflow_key + and role_key = delete_role__role_key; + + delete from wf_roles + where workflow_key = delete_role__workflow_key + and role_key = delete_role__role_key; + + return 0; +end;' language 'plpgsql'; + + +-- procedure add_transition +create function workflow__add_transition (varchar,varchar,varchar,varchar,integer,varchar) +returns integer as ' +declare + add_transition__workflow_key alias for $1; + add_transition__transition_key alias for $2; + add_transition__transition_name alias for $3; + add_transition__role_key alias for $4; + add_transition__sort_order alias for $5; + add_transition__trigger_type alias for $6; -- default ''user'' + v_sort_order integer; +begin + if add_transition__sort_order is null then + select coalesce(max(sort_order)+1, 1) + into v_sort_order + from wf_transitions + where workflow_key = add_transition__workflow_key; + else + v_sort_order := add_transition__sort_order; + end if; + insert into wf_transitions ( + workflow_key, + transition_key, + transition_name, + role_key, + sort_order, + trigger_type + ) values ( + add_transition__workflow_key, + add_transition__transition_key, + add_transition__transition_name, + add_transition__role_key, + v_sort_order, + add_transition__trigger_type + ); + + return 0; +end;' language 'plpgsql'; + + +-- procedure delete_transition +create function workflow__delete_transition (varchar,varchar) +returns integer as ' +declare + delete_transition__workflow_key alias for $1; + delete_transition__transition_key alias for $2; +begin + delete from wf_transitions + where workflow_key = delete_transition__workflow_key + and transition_key = delete_transition__transition_key; + + return 0; +end;' language 'plpgsql'; + + +-- procedure add_arc +create function workflow__add_arc (varchar,varchar,varchar,varchar,varchar,varchar,varchar) +returns integer as ' +declare + add_arc__workflow_key alias for $1; + add_arc__transition_key alias for $2; + add_arc__place_key alias for $3; + add_arc__direction alias for $4; + add_arc__guard_callback alias for $5; -- default null + add_arc__guard_custom_arg alias for $6; -- default null + add_arc__guard_description alias for $7; -- default null +begin + insert into wf_arcs (workflow_key, transition_key, place_key, direction, + guard_callback, guard_custom_arg, guard_description) + values (add_arc__workflow_key, add_arc__transition_key, add_arc__place_key, add_arc__direction, + add_arc__guard_callback, add_arc__guard_custom_arg, add_arc__guard_description); + + return 0; +end;' language 'plpgsql'; + + +-- procedure add_arc +create function workflow__add_arc (varchar,varchar,varchar,varchar,varchar,varchar) +returns integer as ' +declare + add_arc__workflow_key alias for $1; + add_arc__from_transition_key alias for $2; + add_arc__to_place_key alias for $3; + add_arc__guard_callback alias for $4; + add_arc__guard_custom_arg alias for $5; + add_arc__guard_description alias for $6; +begin + perform workflow__add_arc ( + add_arc__workflow_key, + add_arc__from_transition_key, + add_arc__to_place_key, + ''out'', + add_arc__guard_callback, + add_arc__guard_custom_arg, + add_arc__guard_description + ); + + return 0; +end;' language 'plpgsql'; + + +-- procedure add_arc +create function workflow__add_arc (varchar,varchar,varchar) +returns integer as ' +declare + add_arc__workflow_key alias for $1; + add_arc__from_place_key alias for $2; + add_arc__to_transition_key alias for $3; +begin + perform workflow__add_arc( + add_arc__workflow_key, + add_arc__to_transition_key, + add_arc__from_place_key, + ''in'', + null, + null, + null + ); + + return 0; +end;' language 'plpgsql'; + + +-- procedure delete_arc +create function workflow__delete_arc (varchar,varchar,varchar,varchar) +returns integer as ' +declare + delete_arc__workflow_key alias for $1; + delete_arc__transition_key alias for $2; + delete_arc__place_key alias for $3; + delete_arc__direction alias for $4; +begin + delete from wf_arcs + where workflow_key = delete_arc__workflow_key + and transition_key = delete_arc__transition_key + and place_key = delete_arc__place_key + and direction = delete_arc__direction; + + return 0; +end;' language 'plpgsql'; + + + +-- procedure add_trans_attribute_map +create function workflow__add_trans_attribute_map (varchar,varchar,integer,integer) +returns integer as ' +declare + p_workflow_key alias for $1; + p_transition_key alias for $2; + p_attribute_id alias for $3; + p_sort_order alias for $4; + v_num_rows integer; + v_sort_order integer; +begin + select count(*) + into v_num_rows + from wf_transition_attribute_map + where workflow_key = p_workflow_key + and transition_key = p_transition_key + and attribute_id = p_attribute_id; + + if v_num_rows > 0 then + return; + end if; + if p_sort_order is null then + select coalesce(max(sort_order)+1, 1) + into v_sort_order + from wf_transition_attribute_map + where workflow_key = p_workflow_key + and transition_key = p_transition_key; + else + v_sort_order := p_sort_order; + end if; + insert into wf_transition_attribute_map ( + workflow_key, + transition_key, + attribute_id, + sort_order + ) values ( + p_workflow_key, + p_transition_key, + p_attribute_id, + v_sort_order + ); + + return 0; + +end;' language 'plpgsql'; + + + +-- procedure add_trans_attribute_map +create function workflow__add_trans_attribute_map (varchar,varchar,varchar,integer) +returns integer as ' +declare + p_workflow_key alias for $1; + p_transition_key alias for $2; + p_attribute_name alias for $3; + p_sort_order alias for $4; + v_attribute_id integer; +begin + select attribute_id + into v_attribute_id + from acs_attributes + where object_type = p_workflow_key + and attribute_name = p_attribute_name; + + perform workflow__add_trans_attribute_map ( + p_workflow_key, + p_transition_key, + v_attribute_id, + p_sort_order + ); + + return 0; + +end;' language 'plpgsql'; + + +-- procedure delete_trans_attribute_map +create function workflow__delete_trans_attribute_map (varchar,varchar,integer) +returns integer as ' +declare + p_workflow_key alias for $1; + p_transition_key alias for $2; + p_attribute_id alias for $3; +begin + delete + from wf_transition_attribute_map + where workflow_key = p_workflow_key + and transition_key = p_transition_key + and attribute_id = p_attribute_id; + + return 0; +end;' language 'plpgsql'; + +-- procedure delete_trans_attribute_map +create function workflow__delete_trans_attribute_map (varchar,varchar,varchar) +returns integer as ' +declare + p_workflow_key alias for $1; + p_transition_key alias for $2; + p_attribute_name alias for $3; + v_attribute_id integer; +begin + select attribute_id + into v_attribute_id + from acs_attributes + where object_type = p_workflow_key + and attribute_name = p_attribute_name; + + delete + from wf_transition_attribute_map + where workflow_key = p_workflow_key + and transition_key = p_transition_key + and attribute_id = v_attribute_id; + + return 0; +end;' language 'plpgsql'; + + +-- procedure add_trans_role_assign_map +create function workflow__add_trans_role_assign_map (varchar,varchar,varchar) +returns integer as ' +declare + p_workflow_key alias for $1; + p_transition_key alias for $2; + p_assign_role_key alias for $3; + v_num_rows integer; +begin + select count(*) + into v_num_rows + from wf_transition_role_assign_map + where workflow_key = p_workflow_key + and transition_key = p_transition_key + and assign_role_key = p_assign_role_key; + + if v_num_rows = 0 then + insert into wf_transition_role_assign_map ( + workflow_key, + transition_key, + assign_role_key + ) values ( + p_workflow_key, + p_transition_key, + p_assign_role_key + ); + end if; + + return 0; +end;' language 'plpgsql'; + +-- procedure delete_trans_role_assign_map +create function workflow__delete_trans_role_assign_map (varchar,varchar,varchar) +returns integer as ' +declare + p_workflow_key alias for $1; + p_transition_key alias for $2; + p_assign_role_key alias for $3; +begin + delete + from wf_transition_role_assign_map + where workflow_key = p_workflow_key + and transition_key = p_transition_key + and assign_role_key = p_assign_role_key; + + return 0; +end;' language 'plpgsql'; + + + +create sequence workflow_session_id; + +create table previous_place_list ( + session_id integer, + rcnt integer, + constraint previous_place_list_pk + primary key (session_id, rcnt), + ky varchar(100) +); + +create table target_place_list ( + session_id integer, + rcnt integer, + constraint target_place_list_pk + primary key (session_id, rcnt), + ky varchar(100) +); + +create table guard_list ( + session_id integer, + rcnt integer, + constraint quard_list_pk + primary key (session_id, rcnt), + ky varchar(100) +); + +create function workflow__simple_p (varchar) +returns boolean as ' +declare + simple_p__workflow_key alias for $1; + v_session_id integer; + retval boolean; +begin + v_session_id := nextval(''workflow_session_id''); + retval := __workflow__simple_p(simple_p__workflow_key, v_session_id); + + delete from previous_place_list where session_id = v_session_id; + delete from target_place_list where session_id = v_session_id; + delete from guard_list where session_id = v_session_id; + + return retval; + +end;' language 'plpgsql'; + +-- function simple_p + +create function __workflow__simple_p (varchar,integer) +returns boolean as ' +declare + simple_p__workflow_key alias for $1; + v_session_id alias for $2; + -- previous_place_list t_place_table; + -- target_place_list t_place_table; + -- guard_list t_guard_table; + guard_list_1 varchar; + guard_list_2 varchar; + target_place_list_1 varchar; + target_place_list_2 varchar; + previous_place_list_i varchar; + v_row_count integer default 0; + v_count integer; + v_count2 integer; + v_place_key wf_places.place_key%TYPE; + v_end_place wf_places.place_key%TYPE; + v_transition_key wf_transitions.transition_key%TYPE; + v_rownum integer; + v_target record; +begin + + /* Let us do some simple checks first */ + + /* Places with more than one arc out */ + select count(*) into v_count + from wf_places p + where p.workflow_key = simple_p__workflow_key + and 1 < (select count(*) + from wf_arcs a + where a.workflow_key = p.workflow_key + and a.place_key = p.place_key + and direction = ''in''); + raise notice ''query 1''; + if v_count > 0 then + return ''f''; + end if; + + /* Transitions with more than one arc in */ + select count(*) into v_count + from wf_transitions t + where t.workflow_key = simple_p__workflow_key + and 1 < (select count(*) + from wf_arcs a + where a.workflow_key = t.workflow_key + and a.transition_key = t.transition_key + and direction = ''in''); + + raise notice ''query 2''; + if v_count > 0 then + return ''f''; + end if; + + /* Transitions with more than two arcs out */ + select count(*) into v_count + from wf_transitions t + where t.workflow_key = simple_p__workflow_key + and 2 < (select count(*) + from wf_arcs a + where a.workflow_key = t.workflow_key + and a.transition_key = t.transition_key + and direction = ''out''); + + raise notice ''query 3''; + if v_count > 0 then + return ''f''; + end if; + + /* Now we do the more complicated checks. + * We keep a list of visited places because I could not think + * of a nicer way that was not susceptable to infinite loops. + */ + + + v_place_key := ''start''; + v_end_place := ''end''; + + loop + exit when v_place_key = v_end_place; + + -- previous_place_list(v_row_count) := v_place_key; + insert into previous_place_list + (session_id,rcnt,ky) + values + (v_session_id,v_row_count,v_place_key); + raise notice ''query 4''; + + select distinct transition_key into v_transition_key + from wf_arcs + where workflow_key = simple_p__workflow_key + and place_key = v_place_key + and direction = ''in''; + raise notice ''query 5''; + + select count(*) into v_count + from wf_arcs + where workflow_key = simple_p__workflow_key + and transition_key = v_transition_key + and direction = ''out''; + raise notice ''query 6''; + + if v_count = 1 then + select distinct place_key into v_place_key + from wf_arcs + where workflow_key = simple_p__workflow_key + and transition_key = v_transition_key + and direction = ''out''; + raise notice ''query 7''; + + else if v_count = 0 then + /* deadend! */ + return ''f''; + + else + /* better be two based on our earlier test */ + + v_rownum := 1; + for v_target in + select place_key,guard_callback + from wf_arcs + where workflow_key = simple_p__workflow_key + and transition_key = v_transition_key + and direction = ''out'' + LOOP + -- target_place_list(v_target.rownum) := v_target.place_key; + raise notice ''query 8''; + insert into target_place_list + (session_id,rcnt,ky) + values + (v_session_id,v_rownum,v_target.place_key); + raise notice ''query 9''; + + -- guard_list(v_target.rownum) := v_target.guard_callback; + insert into guard_list + (session_id,rcnt,ky) + values + (v_session_id,v_rownum,v_target.guard_callback); + v_rownum := v_rownum + 1; + raise notice ''query 10''; + end loop; + + /* Check that the guard functions are the negation of each other + * by looking for the magic entry "#" (exactly once) + */ + select ky into guard_list_1 from guard_list + where session_id = v_session_id and rcnt = 1; + raise notice ''query 11''; + + select ky into guard_list_2 from guard_list + where session_id = v_session_id and rcnt = 2; + raise notice ''query 12''; + + if ((guard_list_1 != ''#'' and guard_list_2 != ''#'') or + (guard_list_1 = ''#'' and guard_list_2 = ''#'')) then + return ''f''; + end if; + + /* Check that exactly one of the targets is in the previous list */ + + v_count2 := 0; + select ky into target_place_list_1 from target_place_list + where session_id = v_session_id and rcnt = 1; + raise notice ''query 13''; + + select ky into target_place_list_2 from target_place_list + where session_id = v_session_id and rcnt = 2; + raise notice ''query 14''; + + for i in 0..v_row_count LOOP + select ky into previous_place_list_i + from previous_place_list where session_id = v_session_id + and rcnt = i; + if target_place_list_1 = previous_place_list_i then + v_count2 := v_count2 + 1; + v_place_key := target_place_list_2; + end if; + if target_place_list_2 = previous_place_list_i then + v_count2 := v_count2 + 1; + v_place_key := target_place_list_1; + end if; + end loop; + raise notice ''query 15''; + + if v_count2 != 1 then + return ''f''; + end if; + + end if; end if; + + v_row_count := v_row_count + 1; + + end loop; + + /* if we got here, it must be okay */ + return ''t''; + + +end;' language 'plpgsql'; + +-- show errors Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/workflow-package-head.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/workflow-package-head.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/workflow-package-head.sql 19 Nov 2001 18:20:33 -0000 1.1 @@ -0,0 +1 @@ \ No newline at end of file Index: openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/workflow-package.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/workflow-package.sql,v diff -u -r1.8 -r1.9 --- openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/workflow-package.sql 16 May 2001 00:40:41 -0000 1.8 +++ openacs-4/contrib/obsolete-packages/acs-workflow/sql/postgresql/workflow-package.sql 19 Nov 2001 18:20:33 -0000 1.9 @@ -11,688 +11,6 @@ -- @cvs-id $Id$ -- +\i workflow-package-head.sql +\i workflow-package-body.sql --- create or replace package workflow --- as --- --- /* Call this function after you have created a table */ --- function create_workflow ( --- workflow_key in varchar2, --- pretty_name in varchar2, --- pretty_plural in varchar2 default null, --- description in varchar2 default null, --- table_name in varchar2, --- id_column in varchar2 default 'case_id' --- ) return varchar2; --- --- procedure drop_workflow ( --- workflow_key in varchar2 --- ); --- --- procedure delete_cases ( --- workflow_key in varchar2 --- ); --- --- function create_attribute ( --- workflow_key in varchar2, --- attribute_name in varchar2, --- datatype in varchar2, --- pretty_name in varchar2, --- pretty_plural in varchar2 default null, --- table_name in varchar2 default null, --- column_name in varchar2 default null, --- default_value in varchar2 default null, --- min_n_values in integer default 1, --- max_n_values in integer default 1, --- sort_order in integer default null, --- storage in varchar2 default 'generic', --- wf_datatype in varchar2 default 'none' --- ) return acs_attributes.attribute_id%TYPE; --- --- procedure drop_attribute ( --- workflow_key in varchar2, --- attribute_name in varchar2 --- ); --- --- procedure add_place ( --- workflow_key in acs_object_types.object_type%TYPE, --- place_key in wf_places.place_key%TYPE, --- place_name in wf_places.place_name%TYPE, --- sort_order in wf_places.sort_order%TYPE --- ); --- --- procedure delete_place ( --- workflow_key in acs_object_types.object_type%TYPE, --- place_key in wf_places.place_key%TYPE --- ); --- --- procedure add_transition ( --- workflow_key in acs_object_types.object_type%TYPE, --- transition_key in wf_transitions.transition_key%TYPE, --- transition_name in wf_transitions.transition_name%TYPE, --- sort_order in wf_transitions.sort_order%TYPE, --- trigger_type in wf_transitions.trigger_type%TYPE default 'user' --- ); --- --- procedure delete_transition ( --- workflow_key in acs_object_types.object_type%TYPE, --- transition_key in wf_transitions.transition_key%TYPE --- ); --- --- procedure add_arc ( --- workflow_key in acs_object_types.object_type%TYPE, --- transition_key in wf_arcs.transition_key%TYPE, --- place_key in wf_arcs.place_key%TYPE, --- direction in wf_arcs.direction%TYPE, --- guard_callback in wf_arcs.guard_callback%TYPE default null, --- guard_custom_arg in wf_arcs.guard_custom_arg%TYPE default null, --- guard_description in wf_arcs.guard_description%TYPE default null --- ); --- --- procedure delete_arc ( --- workflow_key in acs_object_types.object_type%TYPE, --- transition_key in wf_arcs.transition_key%TYPE, --- place_key in wf_arcs.place_key%TYPE, --- direction in wf_arcs.direction%TYPE --- ); --- --- /* --- * A simple workflow is essentially one that we can display nicely using HTML tables. --- * More specifically, it's a workflow containing only sequential routing and --- * simple iteration, where the choice is always between moving to the next task --- * in the sequence or looping back to some prior task. --- */ --- --- function simple_p ( --- workflow_key in varchar2 --- ) return char; --- --- end workflow; - --- show errors - --- create or replace package body workflow --- function create_workflow -create function workflow__create_workflow (varchar,varchar,varchar,varchar,varchar,varchar) -returns varchar as ' -declare - create_workflow__workflow_key alias for $1; - create_workflow__pretty_name alias for $2; - create_workflow__pretty_plural alias for $3; -- default null - create_workflow__description alias for $4; -- default null - create_workflow__table_name alias for $5; - create_workflow__id_column alias for $6; -- default ''case_id'' - v_num_rows integer; - v_workflow_key varchar; -begin - select count(*) into v_num_rows - from pg_class - where relname = lower(create_workflow__table_name); - - if v_num_rows = 0 then - raise EXCEPTION ''-20000: The table "%"must be created before calling workflow.create_workflow.'', create_workflow__table_name; - end if; - - if substr(create_workflow__workflow_key, - length(create_workflow__workflow_key) - 2, 3) != ''_wf'' then - v_workflow_key := create_workflow__workflow_key || ''_wf''; - else - v_workflow_key := create_workflow__workflow_key; - end if; - - PERFORM acs_object_type__create_type( - v_workflow_key, - create_workflow__pretty_name, - create_workflow__pretty_plural, - ''workflow'', - create_workflow__table_name, - create_workflow__id_column, - null, - ''f'', - null, - null - ); - - insert into wf_workflows - (workflow_key, description) - values - (v_workflow_key, create_workflow__description); - - return v_workflow_key; - -end;' language 'plpgsql'; - - --- procedure drop_workflow -create function workflow__drop_workflow (varchar) -returns integer as ' -declare - drop_workflow__workflow_key alias for $1; - v_table_name varchar; - v_num_rows integer; - attribute_rec record; -begin - select table_name into v_table_name - from acs_object_types - where object_type = drop_workflow__workflow_key; - - select case when count(*) = 0 then 0 else 1 end into v_num_rows - from pg_class - where relname = lower(v_table_name); - - if v_num_rows > 0 then - raise EXCEPTION ''-20000: The table "%" must be dropped before calling workflow.drop_workflow.'', v_table_name; - end if; - - select case when count(*) = 0 then 0 else 1 end into v_num_rows - from wf_cases - where workflow_key = drop_workflow__workflow_key; - - if v_num_rows > 0 then - raise EXCEPTION ''-20000: You must delete all cases of workflow "%" before dropping the workflow definition.'', drop_workflow__workflow_key; - end if; - - /* Delete all the auxillary stuff */ - delete from wf_context_task_panels - where workflow_key = drop_workflow__workflow_key; - - delete from wf_context_assignments - where workflow_key = drop_workflow__workflow_key; - - delete from wf_context_transition_info - where workflow_key = drop_workflow__workflow_key; - - delete from wf_arcs - where workflow_key = drop_workflow__workflow_key; - - delete from wf_places - where workflow_key = drop_workflow__workflow_key; - - delete from wf_transition_attribute_map - where workflow_key = drop_workflow__workflow_key; - - delete from wf_transition_assignment_map - where workflow_key = drop_workflow__workflow_key; - - delete from wf_transitions - where workflow_key = drop_workflow__workflow_key; - - /* Drop all attributes */ - for attribute_rec in - select attribute_id, attribute_name - from acs_attributes - where object_type = drop_workflow__workflow_key - LOOP - /* there is no on delete cascade, so we have to manually - * delete all the values - */ - - delete from acs_attribute_values - where attribute_id = attribute_rec.attribute_id; - - PERFORM workflow__drop_attribute( - drop_workflow__workflow_key, - attribute_rec.attribute_name - ); - end loop; - - /* Delete the workflow */ - delete from wf_workflows - where workflow_key = drop_workflow__workflow_key; - - PERFORM acs_object_type__drop_type( - drop_workflow__workflow_key, - ''f'' - ); - - return 0; -end;' language 'plpgsql'; - - --- procedure delete_cases -create function workflow__delete_cases (varchar) -returns integer as ' -declare - delete_cases__workflow_key alias for $1; - case_rec record; -begin - for case_rec in - select case_id - from wf_cases - where workflow_key = delete_cases__workflow_key - LOOP - PERFORM workflow_case__delete(case_rec.case_id); - end loop; - - return 0; -end;' language 'plpgsql'; - - --- function create_attribute -create function workflow__create_attribute (varchar,varchar,varchar,varchar,varchar,varchar,varchar,varchar,integer,integer,integer,varchar,varchar) -returns integer as ' -declare - create_attribute__workflow_key alias for $1; - create_attribute__attribute_name alias for $2; - create_attribute__datatype alias for $3; - create_attribute__pretty_name alias for $4; - create_attribute__pretty_plural alias for $5; -- default null - create_attribute__table_name alias for $6; -- default null - create_attribute__column_name alias for $7; -- default null - create_attribute__default_value alias for $8; -- default null - create_attribute__min_n_values alias for $9; -- default 1 - create_attribute__max_n_values alias for $10; -- default 1 - create_attribute__sort_order alias for $11; -- default null - create_attribute__storage alias for $12; -- default ''generic'' - create_attribute__wf_datatype alias for $13; -- default ''none'' - v_attribute_id integer; -begin - v_attribute_id := acs_attribute__create_attribute( - create_attribute__workflow_key, - create_attribute__attribute_name, - create_attribute__datatype, - create_attribute__pretty_name, - create_attribute__pretty_plural, - create_attribute__table_name, - create_attribute__column_name, - create_attribute__default_value, - create_attribute__min_n_values, - create_attribute__max_n_values, - create_attribute__sort_order, - create_attribute__storage, - ''f'' - ); - - insert into wf_attribute_info - (attribute_id, wf_datatype) - values - (v_attribute_id, create_attribute__wf_datatype); - - return v_attribute_id; - -end;' language 'plpgsql'; - - --- procedure drop_attribute -create function workflow__drop_attribute (varchar,varchar) -returns integer as ' -declare - drop_attribute__workflow_key alias for $1; - drop_attribute__attribute_name alias for $2; - v_attribute_id integer; -begin - select attribute_id into v_attribute_id - from acs_attributes - where object_type = drop_attribute__workflow_key - and attribute_name = drop_attribute__attribute_name; - - delete from wf_attribute_info - where attribute_id = v_attribute_id; - - PERFORM acs_attribute__drop_attribute( - drop_attribute__workflow_key, - drop_attribute__attribute_name - ); - - return 0; -end;' language 'plpgsql'; - - --- procedure add_place -create function workflow__add_place (varchar,varchar,varchar,integer) -returns integer as ' -declare - add_place__workflow_key alias for $1; - add_place__place_key alias for $2; - add_place__place_name alias for $3; - add_place__sort_order alias for $4; -begin - insert into wf_places (workflow_key, place_key, place_name, sort_order) - values - (add_place__workflow_key, add_place__place_key,add_place__place_name, - add_place__sort_order); - - return 0; -end;' language 'plpgsql'; - - --- procedure delete_place -create function workflow__delete_place (varchar,varchar) -returns integer as ' -declare - delete_place__workflow_key alias for $1; - delete_place__place_key alias for $2; -begin - delete from wf_places - where workflow_key = delete_place__workflow_key - and place_key = delete_place__place_key; - - return 0; -end;' language 'plpgsql'; - - --- procedure add_transition -create function workflow__add_transition (varchar,varchar,varchar,integer,varchar) -returns integer as ' -declare - add_transition__workflow_key alias for $1; - add_transition__transition_key alias for $2; - add_transition__transition_name alias for $3; - add_transition__sort_order alias for $4; - add_transition__trigger_type alias for $5; -- default ''user'' -begin - insert into wf_transitions - (workflow_key, transition_key, transition_name, sort_order, trigger_type) - values - (add_transition__workflow_key, add_transition__transition_key, - add_transition__transition_name,add_transition__sort_order, - add_transition__trigger_type); - - return 0; -end;' language 'plpgsql'; - - --- procedure delete_transition -create function workflow__delete_transition (varchar,varchar) -returns integer as ' -declare - delete_transition__workflow_key alias for $1; - delete_transition__transition_key alias for $2; -begin - delete from wf_transitions - where workflow_key = delete_transition__workflow_key - and transition_key = delete_transition__transition_key; - - return 0; -end;' language 'plpgsql'; - - --- procedure add_arc -create function workflow__add_arc (varchar,varchar,varchar,varchar,varchar,varchar,varchar) -returns integer as ' -declare - add_arc__workflow_key alias for $1; - add_arc__transition_key alias for $2; - add_arc__place_key alias for $3; - add_arc__direction alias for $4; - add_arc__guard_callback alias for $5; -- default null - add_arc__guard_custom_arg alias for $6; -- default null - add_arc__guard_description alias for $7; -- default null -begin - insert into wf_arcs - (workflow_key, transition_key, place_key, direction, - guard_callback, guard_custom_arg, guard_description) - values - (add_arc__workflow_key, add_arc__transition_key, add_arc__place_key, - add_arc__direction, - add_arc__guard_callback, add_arc__guard_custom_arg, add_arc__guard_description); - - return 0; -end;' language 'plpgsql'; - - --- procedure delete_arc -create function workflow__delete_arc (varchar,varchar,varchar,varchar) -returns integer as ' -declare - delete_arc__workflow_key alias for $1; - delete_arc__transition_key alias for $2; - delete_arc__place_key alias for $3; - delete_arc__direction alias for $4; -begin - delete from wf_arcs - where workflow_key = delete_arc__workflow_key - and transition_key = delete_arc__transition_key - and place_key = delete_arc__place_key - and direction = delete_arc__direction; - - return 0; -end;' language 'plpgsql'; - -create sequence workflow_session_id; - -create table previous_place_list ( - session_id integer, - rcnt integer, - constraint previous_place_list_pk - primary key (session_id, rcnt), - ky varchar(100) -); - -create table target_place_list ( - session_id integer, - rcnt integer, - constraint target_place_list_pk - primary key (session_id, rcnt), - ky varchar(100) -); - -create table guard_list ( - session_id integer, - rcnt integer, - constraint quard_list_pk - primary key (session_id, rcnt), - ky varchar(100) -); - -create function workflow__simple_p (varchar) -returns boolean as ' -declare - simple_p__workflow_key alias for $1; - v_session_id integer; - retval boolean; -begin - v_session_id := nextval(''workflow_session_id''); - retval := __workflow__simple_p(simple_p__workflow_key, v_session_id); - - delete from previous_place_list where session_id = v_session_id; - delete from target_place_list where session_id = v_session_id; - delete from guard_list where session_id = v_session_id; - - return retval; - -end;' language 'plpgsql'; - --- function simple_p - -create function __workflow__simple_p (varchar,integer) -returns boolean as ' -declare - simple_p__workflow_key alias for $1; - v_session_id alias for $2; - -- previous_place_list t_place_table; - -- target_place_list t_place_table; - -- guard_list t_guard_table; - guard_list_1 varchar; - guard_list_2 varchar; - target_place_list_1 varchar; - target_place_list_2 varchar; - previous_place_list_i varchar; - v_row_count integer default 0; - v_count integer; - v_count2 integer; - v_place_key wf_places.place_key%TYPE; - v_end_place wf_places.place_key%TYPE; - v_transition_key wf_transitions.transition_key%TYPE; - v_rownum integer; - v_target record; -begin - - /* Let us do some simple checks first */ - - /* Places with more than one arc out */ - select count(*) into v_count - from wf_places p - where p.workflow_key = simple_p__workflow_key - and 1 < (select count(*) - from wf_arcs a - where a.workflow_key = p.workflow_key - and a.place_key = p.place_key - and direction = ''in''); - raise notice ''query 1''; - if v_count > 0 then - return ''f''; - end if; - - /* Transitions with more than one arc in */ - select count(*) into v_count - from wf_transitions t - where t.workflow_key = simple_p__workflow_key - and 1 < (select count(*) - from wf_arcs a - where a.workflow_key = t.workflow_key - and a.transition_key = t.transition_key - and direction = ''in''); - - raise notice ''query 2''; - if v_count > 0 then - return ''f''; - end if; - - /* Transitions with more than two arcs out */ - select count(*) into v_count - from wf_transitions t - where t.workflow_key = simple_p__workflow_key - and 2 < (select count(*) - from wf_arcs a - where a.workflow_key = t.workflow_key - and a.transition_key = t.transition_key - and direction = ''out''); - - raise notice ''query 3''; - if v_count > 0 then - return ''f''; - end if; - - /* Now we do the more complicated checks. - * We keep a list of visited places because I could not think - * of a nicer way that was not susceptable to infinite loops. - */ - - - v_place_key := ''start''; - v_end_place := ''end''; - - loop - exit when v_place_key = v_end_place; - - -- previous_place_list(v_row_count) := v_place_key; - insert into previous_place_list - (session_id,rcnt,ky) - values - (v_session_id,v_row_count,v_place_key); - raise notice ''query 4''; - - select distinct transition_key into v_transition_key - from wf_arcs - where workflow_key = simple_p__workflow_key - and place_key = v_place_key - and direction = ''in''; - raise notice ''query 5''; - - select count(*) into v_count - from wf_arcs - where workflow_key = simple_p__workflow_key - and transition_key = v_transition_key - and direction = ''out''; - raise notice ''query 6''; - - if v_count = 1 then - select distinct place_key into v_place_key - from wf_arcs - where workflow_key = simple_p__workflow_key - and transition_key = v_transition_key - and direction = ''out''; - raise notice ''query 7''; - - else if v_count = 0 then - /* deadend! */ - return ''f''; - - else - /* better be two based on our earlier test */ - - v_rownum := 1; - for v_target in - select place_key,guard_callback - from wf_arcs - where workflow_key = simple_p__workflow_key - and transition_key = v_transition_key - and direction = ''out'' - LOOP - -- target_place_list(v_target.rownum) := v_target.place_key; - raise notice ''query 8''; - insert into target_place_list - (session_id,rcnt,ky) - values - (v_session_id,v_rownum,v_target.place_key); - raise notice ''query 9''; - - -- guard_list(v_target.rownum) := v_target.guard_callback; - insert into guard_list - (session_id,rcnt,ky) - values - (v_session_id,v_rownum,v_target.guard_callback); - v_rownum := v_rownum + 1; - raise notice ''query 10''; - end loop; - - /* Check that the guard functions are the negation of each other - * by looking for the magic entry "#" (exactly once) - */ - select ky into guard_list_1 from guard_list - where session_id = v_session_id and rcnt = 1; - raise notice ''query 11''; - - select ky into guard_list_2 from guard_list - where session_id = v_session_id and rcnt = 2; - raise notice ''query 12''; - - if ((guard_list_1 != ''#'' and guard_list_2 != ''#'') or - (guard_list_1 = ''#'' and guard_list_2 = ''#'')) then - return ''f''; - end if; - - /* Check that exactly one of the targets is in the previous list */ - - v_count2 := 0; - select ky into target_place_list_1 from target_place_list - where session_id = v_session_id and rcnt = 1; - raise notice ''query 13''; - - select ky into target_place_list_2 from target_place_list - where session_id = v_session_id and rcnt = 2; - raise notice ''query 14''; - - for i in 0..v_row_count LOOP - select ky into previous_place_list_i - from previous_place_list where session_id = v_session_id - and rcnt = i; - if target_place_list_1 = previous_place_list_i then - v_count2 := v_count2 + 1; - v_place_key := target_place_list_2; - end if; - if target_place_list_2 = previous_place_list_i then - v_count2 := v_count2 + 1; - v_place_key := target_place_list_1; - end if; - end loop; - raise notice ''query 15''; - - if v_count2 != 1 then - return ''f''; - end if; - - end if; end if; - - v_row_count := v_row_count + 1; - - end loop; - - /* if we got here, it must be okay */ - return ''t''; - - -end;' language 'plpgsql'; - --- show errors Index: openacs-4/contrib/obsolete-packages/acs-workflow/tcl/display-procs.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/tcl/display-procs.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/tcl/display-procs.xql 19 Nov 2001 18:11:32 -0000 1.1 @@ -0,0 +1,17 @@ + + + + + + + select ca.party_id + from wf_case_assignments ca, wf_cases c + where c.case_id = :case_id + and ca.role_key = :role_key + and ca.workflow_key = c.workflow_key + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/active-tasks-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/active-tasks-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/active-tasks-oracle.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,37 @@ + + + + oracle8.1.6 + + + + + select t.task_id, + t.transition_key, + t.state, + t.case_id, + tr.transition_name, + to_char(t.enabled_date, :date_format) as enabled_date_pretty, + to_char(t.started_date, :date_format) as started_date_pretty, + to_char(t.deadline, :date_format) as deadline_pretty, + p.party_id as assignee_party_id, + p.email as assignee_email, + acs_object.name(p.party_id) as assignee_name, + '' as assignee_url, + assignee_o.object_type as assignee_object_type, + '' as reassign_url + from wf_tasks t, wf_transitions tr, wf_task_assignments tasgn, parties p, acs_objects assignee_o + where t.case_id = :case_id + and t.state in ('enabled', 'started') + and tr.workflow_key = t.workflow_key + and tr.transition_key = t.transition_key + and tasgn.task_id (+) = t.task_id + and p.party_id (+) = tasgn.party_id + and assignee_o.object_id (+) = p.party_id + order by t.enabled_date desc + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/active-tasks-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/active-tasks-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/active-tasks-postgresql.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,38 @@ + + + + postgresql7.1 + + + + + select t.task_id, + t.transition_key, + t.state, + t.case_id, + tr.transition_name, + to_char(t.enabled_date, :date_format) as enabled_date_pretty, + to_char(t.started_date, :date_format) as started_date_pretty, + to_char(t.deadline, :date_format) as deadline_pretty, + p.party_id as assignee_party_id, + p.email as assignee_email, + acs_object__name(p.party_id) as assignee_name, + '' as assignee_url, + assignee_o.object_type as assignee_object_type, + '' as reassign_url + from (((wf_tasks t LEFT OUTER JOIN wf_task_assignments tasgn + ON (t.task_id = tasgn.task_id)) LEFT OUTER JOIN parties p + ON (tasgn.party_id = p.party_id)) LEFT OUTER JOIN acs_objects assignee_o + ON (p.party_id = assignee_o.object_id)), + wf_transitions tr + where t.case_id = :case_id + and t.state in ('enabled', 'started') + and tr.workflow_key = t.workflow_key + and tr.transition_key = t.transition_key + order by t.enabled_date desc + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/active-tasks.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/active-tasks.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/active-tasks.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,66 @@ + +
+ No active tasks +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
Task NameStateActivated DateStarted DateDeadlineAssigneesAction
@active_tasks.transition_name@@active_tasks.state@@active_tasks.enabled_date_pretty@ + @active_tasks.started_date_pretty@ + not started + + @active_tasks.deadline_pretty@ +   + + + +
  • + + @active_tasks.assignee_name@ + + + @active_tasks.assignee_name@ + + + (@active_tasks.assignee_email@) + +
  • +
    +
    + + Unassigned + +
    + + (reassign) + +   +
    +
    +
    + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/active-tasks.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/active-tasks.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/active-tasks.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,51 @@ +# +# Active tasks for a case +# +# Expects: +# case_id +# date_format (optional) +# return_url (optional) +# Data sources: +# active_tasks +# +# cvs-id: $Id: active-tasks.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +# Creation date: Feb 21, 2001 +# Author: Lars Pind (lars@pinds.com) +# + +if { ![info exists date_format] } { + set date_format "Mon fmDDfm, YYYY HH24:MI:SS" +} + +db_multirow active_tasks active_tasks { + select t.task_id, + t.transition_key, + t.state, + t.case_id, + tr.transition_name, + to_char(t.enabled_date, :date_format) as enabled_date_pretty, + to_char(t.started_date, :date_format) as started_date_pretty, + to_char(t.deadline, :date_format) as deadline_pretty, + p.party_id as assignee_party_id, + p.email as assignee_email, + acs_object.name(p.party_id) as assignee_name, + '' as assignee_url, + assignee_o.object_type as assignee_object_type, + '' as reassign_url + from wf_tasks t, wf_transitions tr, wf_task_assignments tasgn, parties p, acs_objects assignee_o + where t.case_id = :case_id + and t.state in ('enabled', 'started') + and tr.workflow_key = t.workflow_key + and tr.transition_key = t.transition_key + and tasgn.task_id (+) = t.task_id + and p.party_id (+) = tasgn.party_id + and assignee_o.object_id (+) = p.party_id + order by t.enabled_date desc +} { + if { [string equal $assignee_object_type "user"] } { + set assignee_url "/shared/community-member?[export_vars -url {{user_id $assignee_party_id}}]" + } + if { [string equal $state "enabled"] } { + set reassign_url "task-assignees?[export_vars -url {task_id return_url}]" + } +} Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignment-remove-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignment-remove-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignment-remove-2.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,20 @@ +ad_page_contract { + Remove manual assignment. + + @cvs-id $Id: case-assignment-remove-2.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ + @author Lars Pind (lars@pinds.com) + @creation-date Feb 21, 2001 +} { + case_id:integer + role_key + party_id:integer + {return_url "case?[export_vars -url {case_id}]"} +} + +wf_case_remove_manual_assignment \ + -case_id $case_id \ + -role_key $role_key \ + -party_id $party_id + + +ad_returnredirect $return_url Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignment-set-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignment-set-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignment-set-2.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,26 @@ +# /packages/acs-workflow/www/case-assignment-set-2.tcl +ad_page_contract { + Set case assignments for a role. + + @author Jesse Koontz [jkoontz@arsdigita.com] + @creation-date Thu Jan 25 14:50:50 2001 + @cvs-id $Id: case-assignment-set-2.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +} { + case_id:integer + role_key + {return_url:optional "case?[export_vars -url {case_id}]"} + {assignments:multiple,integer {}} + cancel:optional +} + +if { ![info exists cancel] || [empty_string_p $cancel] } { + + # Don't update assignments if user hit cancel + + wf_case_set_manual_assignments \ + -case_id $case_id \ + -role_key $role_key \ + -party_id_list $assignments +} + +ad_returnredirect $return_url \ No newline at end of file Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignment-set-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignment-set-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignment-set-oracle.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,36 @@ + + + + oracle8.1.6 + + + + + select case_id, + acs_object.name(object_id) as object_name, + state, + workflow_key + from wf_cases + where case_id = :case_id + + + + + + + + + select p.party_id, + acs_object.name(p.party_id) as name, + case when p.email = '' then '' else '('||p.email||')' end as email + from parties p + where 0 < (select count(*) + from users u, party_approved_member_map m + where m.party_id = p.party_id + and u.user_id = m.member_id) + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignment-set-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignment-set-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignment-set-postgresql.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,36 @@ + + + + postgresql7.1 + + + + + select case_id, + acs_object__name(object_id) as object_name, + state, + workflow_key + from wf_cases + where case_id = :case_id + + + + + + + + + select p.party_id, + acs_object__name(p.party_id) as name, + case when p.email = '' then '' else '('||p.email||')' end as email + from parties p + where 0 < (select count(*) + from users u, party_approved_member_map m + where m.party_id = p.party_id + and u.user_id = m.member_id) + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignment-set.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignment-set.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignment-set.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,33 @@ + +Assign @role_name@ + +

    Assign @role_name@

    +@context_bar@ +
    + +
    +@export_vars@ + + + + + + + + + + + + + + + + +
    Role@role_name@
    Assignments@widget@
     
      + +       + +
    +
    + +
    \ No newline at end of file Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignment-set.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignment-set.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignment-set.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,68 @@ +# /packages/acs-workflow/www/case-assignment-set.tcl +ad_page_contract { + Set case assignments for a role. + + @author Jesse Koontz [jkoontz@arsdigita.com] + @creation-date Thu Jan 25 14:39:44 2001 + @cvs-id $Id: case-assignment-set.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +} { + case_id:integer + role_key + return_url:optional +} -properties { + context_bar + export_vars + widget +} + +set write_p [ad_permission_p $case_id "write"] + +db_1row case_info { + select case_id, + acs_object.name(object_id) as object_name, + state, + workflow_key + from wf_cases + where case_id = :case_id +} -column_array case + +set workflow_key $case(workflow_key) + +set role_name [db_string role_name_select " +select role_name +from wf_roles +where role_key = :role_key +and workflow_key = :workflow_key" -default ""] + +set context_bar [ad_context_bar [list "case?[export_vars -url {{case_id $case(case_id)}}]" "$case(object_name) case"] "Assign $role_name"] + +set export_vars [export_form_vars case_id role_key workflow_key return_url] + +set current_assignments [db_list assignment_select " + select party_id + from wf_case_assignments + where case_id = :case_id + and role_key = :role_key + and workflow_key = :workflow_key +"] + +set widget "" + +ad_return_template Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignment-set.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignment-set.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignment-set.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,28 @@ + + + + + + +select role_name +from wf_roles +where role_key = :role_key +and workflow_key = :workflow_key + + + + + + + + select party_id + from wf_case_assignments + where case_id = :case_id + and role_key = :role_key + and workflow_key = :workflow_key + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignments-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignments-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignments-oracle.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,20 @@ + + + + oracle8.1.6 + + + + + select case_id, + acs_object.name(object_id) as object_name, + state, + workflow_key + from wf_cases + where case_id = :case_id + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignments-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignments-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignments-postgresql.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,20 @@ + + + + postgresql7.1 + + + + + select case_id, + acs_object__name(object_id) as object_name, + state, + workflow_key + from wf_cases + where case_id = :case_id + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignments-table-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignments-table-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignments-table-oracle.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,31 @@ + + + + oracle8.1.6 + + + + + select p.party_id, + acs_object.name(p.party_id) as name, + p.email, + '' as url, + '' as remove_url, + '' as edit_url, + o.object_type, + r.role_key, + r.role_name + from wf_cases c, wf_roles r, wf_case_assignments ca, parties p, acs_objects o + where c.case_id = :case_id + and r.workflow_key = c.workflow_key + and ca.case_id (+) = :case_id + and ca.role_key (+) = r.role_key + and p.party_id (+) = ca.party_id + and o.object_id (+) = p.party_id + order by r.sort_order, r.role_key, name + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignments-table-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignments-table-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignments-table-postgresql.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,31 @@ + + + + postgresql7.1 + + + + + select p.party_id, + acs_object__name(p.party_id) as name, + p.email, + '' as url, + '' as remove_url, + '' as edit_url, + o.object_type, + r.role_key, + r.role_name + from wf_cases c, + ((wf_roles r LEFT OUTER JOIN wf_case_assignments ca + ON (r.role_key = ca.role_key and ca.case_id = :case_id)) LEFT OUTER JOIN parties p + ON (ca.party_id = p.party_id)) LEFT OUTER JOIN acs_objects o + ON (p.party_id = o.object_id) + where c.case_id = :case_id + and r.workflow_key = c.workflow_key + order by r.sort_order, r.role_key, name + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignments-table.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignments-table.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignments-table.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,48 @@ + + + + +
    + + + + + + + + + + + + + +
    RoleAssigneesAction
    @manual_assignments.role_name@ + + +
  • + + @manual_assignments.name@ + + + @manual_assignments.name@ + + + (@manual_assignments.email@) + + + (remove) + +
  • +
    +
    + + Unassigned + +
    + + (edit) + +
    +
    + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignments-table.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignments-table.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignments-table.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,40 @@ +# +# Table of manual assignments for a case +# +# Expects: +# case_id +# return_url (optional) +# Data sources: +# manual_assignments +# +# cvs-id: $Id: case-assignments-table.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +# Creation date: Feb 21, 2001 +# Author: Lars Pind (lars@pinds.com) +# + +db_multirow manual_assignments manual_assignments { + select p.party_id, + acs_object.name(p.party_id) as name, + p.email, + '' as url, + '' as remove_url, + '' as edit_url, + o.object_type, + r.role_key, + r.role_name + from wf_cases c, wf_roles r, wf_case_assignments ca, parties p, acs_objects o + where c.case_id = :case_id + and r.workflow_key = c.workflow_key + and ca.case_id (+) = :case_id + and ca.role_key (+) = r.role_key + and p.party_id (+) = ca.party_id + and o.object_id (+) = p.party_id + order by r.sort_order, r.role_key, name +} { + if { [string equal $object_type "user"] } { + set url "/shared/community-member?[export_vars -url { { user_id $party_id }}]" + } + set remove_url "case-assignment-remove-2?[export_vars -url {case_id role_key party_id return_url}]" + set edit_url "case-assignment-set?[export_vars -url {case_id role_key return_url}]" +} + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignments.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignments.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignments.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,23 @@ + +Assignments for @case.object_name@ case +

    Assignments for @case.object_name@ case

    +@context_bar@ +
    + +
    + +
    + + + + @done_export_vars@ + + + + +
    + +
    + +
    + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignments.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignments.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-assignments.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,36 @@ +# /packages/acs-workflow/www/case-assignments.tcl +ad_page_contract { + View/change role assignments for a case. + + @author Jesse Koontz [jkoontz@arsdigita.com] + @creation-date Thu Jan 25 14:23:36 2001 + @cvs-id $Id: case-assignments.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +} { + case_id:integer,notnull +} -properties { + case:onerow + context_bar + case_id + return_url + done_export_vars +} + +db_1row case_info { + select case_id, + acs_object.name(object_id) as object_name, + state, + workflow_key + from wf_cases + where case_id = :case_id +} -column_array case + +set workflow_key $case(workflow_key) + +set return_url "case-assignments?[export_vars -url {{case_id $case(case_id)}}]" + +set context_bar [ad_context_bar [list "case?case_id=$case_id" "$case(object_name) case"] "Assignments"] + +set done_export_vars [export_vars -form {{case_id $case(case_id)}}] + + +ad_return_template Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-attributes-table-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-attributes-table-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-attributes-table-oracle.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,26 @@ + + + + oracle8.1.6 + + + + + select a.attribute_id, + a.sort_order, + a.attribute_name, + a.pretty_name, + a.datatype, + '' as edit_url, + workflow_case.get_attribute_value(:case_id, a.attribute_name) as value, + '' as value_pretty + from acs_attributes a, wf_cases c + where c.case_id = :case_id + and a.object_type = c.workflow_key + order by a.sort_order + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-attributes-table-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-attributes-table-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-attributes-table-postgresql.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,26 @@ + + + + postgresql7.1 + + + + + select a.attribute_id, + a.sort_order, + a.attribute_name, + a.pretty_name, + a.datatype, + '' as edit_url, + workflow_case__get_attribute_value (:case_id, a.attribute_name) as value, + '' as value_pretty + from acs_attributes a, wf_cases c + where c.case_id = :case_id + and a.object_type = c.workflow_key + order by a.sort_order + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-attributes-table.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-attributes-table.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-attributes-table.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,28 @@ + + + + +
    + + + + + + + + + + + + + +
    AttributeCurrent Value
    @attributes.pretty_name@@attributes.value_pretty@
    +
    + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-attributes-table.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-attributes-table.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-attributes-table.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,30 @@ +# +# Table of attributes for a case. +# +# Expects: +# case_id +# Data sources: +# attributes +# +# cvs-id: $Id: case-attributes-table.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +# Creation date: Feb 21, 2001 +# Author: Lars Pind (lars@pinds.com) +# + +db_multirow attributes attributes { + select a.attribute_id, + a.sort_order, + a.attribute_name, + a.pretty_name, + a.datatype, + '' as edit_url, + workflow_case.get_attribute_value(:case_id, a.attribute_name) as value, + '' as value_pretty + from acs_attributes a, wf_cases c + where c.case_id = :case_id + and a.object_type = c.workflow_key + order by a.sort_order +} { + # set edit_url "case-attribute-edit?[export_vars -url {case_id attribute_name}]" + set value_pretty [wf_attribute_value_pretty [list datatype $datatype value $value]] +} Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadline-remove-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadline-remove-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadline-remove-2.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,18 @@ +# /packages/acs-workflow/www/case-deadline-remove-2.tcl +ad_page_contract { + Sets deadline for case transition. + + @author Lars Pind (lars@pinds.com) + @creation-date Feb 21, 2001 + @cvs-id $Id: case-deadline-remove-2.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +} { + case_id:integer + transition_key + {return_url:optional "case?[export_vars -url {case_id}]"} +} + +wf_case_remove_case_deadline \ + -case_id $case_id \ + -transition_key $transition_key + +ad_returnredirect $return_url Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadline-set-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadline-set-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadline-set-2.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,26 @@ +# /packages/acs-workflow/www/case-deadline-set-2.tcl +ad_page_contract { + Sets deadline for case transition. + + @author Jesse Koontz [jkoontz@arsdigita.com] + @creation-date Mon Jan 15 10:11:07 2001 + @cvs-id $Id: case-deadline-set-2.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +} { + case_id:integer + transition_key + {return_url:optional "case?[export_vars -url {case_id}]"} + deadline:array,date + cancel:optional +} + +if { ![info exists cancel] || [empty_string_p $cancel] } { + + # Only set deadline if the user didn't hit cancel + + wf_case_set_case_deadline \ + -case_id $case_id \ + -transition_key $transition_key \ + -deadline $deadline(date) +} + +ad_returnredirect $return_url Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadline-set-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadline-set-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadline-set-oracle.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,27 @@ + + + + oracle8.1.6 + + + + + select case_id, + acs_object.name(object_id) as object_name, + state, + workflow_key + from wf_cases + where case_id = :case_id + + + + + + + + select sysdate+7 from dual + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadline-set-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadline-set-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadline-set-postgresql.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,27 @@ + + + + postgresql7.1 + + + + + select case_id, + acs_object__name(object_id) as object_name, + state, + workflow_key + from wf_cases + where case_id = :case_id + + + + + + + + select current_timestamp+7 + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadline-set.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadline-set.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadline-set.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,33 @@ + +Set Deadline + +

    Set Deadline

    +@context_bar@ +
    + +
    +@export_vars@ + + + + + + + + + + + + + + + + +
    Task@transition_name@
    Deadline@date_widget@
     
      + +     + +
    +
    + +
    \ No newline at end of file Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadline-set.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadline-set.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadline-set.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,56 @@ +# /packages/acs-workflow/www/case-deadline-set.tcl +ad_page_contract { + Set the deadline for a transition in a case. + + @author Jesse Koontz [jkoontz@arsdigita.com] + @creation-date Mon Jan 15 10:05:21 2001 + @cvs-id $Id: case-deadline-set.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +} { + case_id:integer + transition_key + return_url:optional +} -properties { + context_bar + export_vars + date_widget +} + +set write_p [ad_permission_p $case_id "write"] + +db_1row case_info { + select case_id, + acs_object.name(object_id) as object_name, + state, + workflow_key + from wf_cases + where case_id = :case_id +} -column_array case + +set workflow_key $case(workflow_key) + +set transition_name [db_string transition_name_select " +select transition_name +from wf_transitions +where transition_key = :transition_key + and workflow_key = :workflow_key" -default ""] + +set context_bar [ad_context_bar [list "case?[export_vars -url {{case_id $case(case_id)}}]" "$case(object_name) case"] "Deadline for $transition_name "] + +set export_vars [export_form_vars case_id transition_key workflow_key return_url] + +set deadline [db_string deadline_select " + select deadline + from wf_case_deadlines + where case_id = :case_id + and transition_key = :transition_key + and workflow_key = :workflow_key +" -default [db_string a_week_from_now "select sysdate+7 from dual"]] + + +set date_widget [ad_dateentrywidget deadline $deadline] + +ad_return_template + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadline-set.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadline-set.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadline-set.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,28 @@ + + + + + + +select transition_name +from wf_transitions +where transition_key = :transition_key + and workflow_key = :workflow_key + + + + + + + + select deadline + from wf_case_deadlines + where case_id = :case_id + and transition_key = :transition_key + and workflow_key = :workflow_key + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadlines-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadlines-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadlines-oracle.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,20 @@ + + + + oracle8.1.6 + + + + + select case_id, + acs_object.name(object_id) as object_name, + state, + workflow_key + from wf_cases + where case_id = :case_id + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadlines-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadlines-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadlines-postgresql.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,20 @@ + + + + postgresql7.1 + + + + + select case_id, + acs_object__name(object_id) as object_name, + state, + workflow_key + from wf_cases + where case_id = :case_id + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadlines-table-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadlines-table-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadlines-table-oracle.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,26 @@ + + + + oracle8.1.6 + + + + + select tr.transition_name, + tr.transition_key, + to_char(cd.deadline, :date_format) as deadline_pretty, + '' as edit_url, + '' as remove_url + from (select c.case_id, tr.sort_order, tr.transition_name, tr.transition_key, tr.workflow_key from wf_cases c, wf_transitions tr + where c.case_id = :case_id and c.workflow_key = tr.workflow_key) tr, + wf_case_deadlines cd + where tr.case_id = cd.case_id(+) + and tr.transition_key = cd.transition_key(+) + and tr.workflow_key = cd.workflow_key(+) + order by tr.sort_order + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadlines-table-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadlines-table-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadlines-table-postgresql.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,31 @@ + + + + postgresql7.1 + + + + + select tr.transition_name, + tr.transition_key, + to_char(cd.deadline, :date_format) as deadline_pretty, + '' as edit_url, + '' as remove_url + from (select c.case_id, + tr.sort_order, + tr.transition_name, + tr.transition_key, + tr.workflow_key + from wf_cases c, wf_transitions tr + where c.case_id = :case_id + and c.workflow_key = tr.workflow_key) tr LEFT OUTER JOIN wf_case_deadlines cd + ON (tr.case_id = cd.case_id and + tr.transition_key = cd.transition_key and + tr.workflow_key = cd.workflow_key) + order by tr.sort_order + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadlines-table.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadlines-table.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadlines-table.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,48 @@ + + + + +
    + + + + + + + + + + + + + + + + + + + + +
    TaskDeadlineRemoveEdit
    + @deadlines.transition_name@ + + + @deadlines.deadline_pretty@ + + + no deadline + + + + (remove) + +   + + + (edit) + +   +
    + No transitions +
    +
    Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadlines-table.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadlines-table.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadlines-table.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,41 @@ +# +# Display deadlines for a case +# +# Expects: +# case_id +# date_format (optional) +# return_url (optional) +# Data sources: +# deadlines +# +# Cvs-id $Id: case-deadlines-table.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +# Author: Lars Pind (lars@pinds.com) +# Creation-date: Feb 21, 2001 +# + +if { ![info exists date_format] } { + set date_format "Mon fmDDfm, YYYY HH24:MI:SS" +} + + + +db_multirow deadlines deadlines { + select tr.transition_name, + tr.transition_key, + to_char(cd.deadline, :date_format) as deadline_pretty, + '' as edit_url, + '' as remove_url + from (select c.case_id, tr.sort_order, tr.transition_name, tr.transition_key, tr.workflow_key from wf_cases c, wf_transitions tr + where c.case_id = :case_id and c.workflow_key = tr.workflow_key) tr, + wf_case_deadlines cd + where tr.case_id = cd.case_id(+) + and tr.transition_key = cd.transition_key(+) + and tr.workflow_key = cd.workflow_key(+) + order by tr.sort_order +} { + set edit_url "case-deadline-set?[export_vars -url {case_id transition_key return_url}]" + if { ![empty_string_p $deadline_pretty] } { + set remove_url "case-deadline-remove-2?[export_vars -url {case_id transition_key return_url}]" + } +} + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadlines.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadlines.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadlines.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,24 @@ + +@case.object_name@ Deadlines +

    @case.object_name@ Deadlines

    +@context_bar@ +
    + +
    + +
    + + + + @done_export_vars@ + + + + +
    + +
    + +
    + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadlines.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadlines.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-deadlines.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,36 @@ +ad_page_contract { + Displays deadlines set for a case. + + @author Jesse Koontz (jkoontz@arsdigita.com) + @creation-date 11 January 2001 + @cvs-id $Id: case-deadlines.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +} { + case_id:integer,notnull +} -properties { + case:onerow + context_bar + return_url + done_export_vars +} + +db_1row case_info { + select case_id, + acs_object.name(object_id) as object_name, + state, + workflow_key + from wf_cases + where case_id = :case_id +} -column_array case + +set workflow_key $case(workflow_key) + +set return_url "case-deadlines?[export_vars -url {{case_id $case(case_id)}}]" + +set context_bar [ad_context_bar [list "case?case_id=$case_id" "$case(object_name) case"] "Deadlines"] + +set done_export_vars [export_vars -form {{case_id $case(case_id)}}] + +ad_return_template + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-state-graph-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-state-graph-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-state-graph-oracle.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,23 @@ + + + + oracle8.1.6 + + + + + select tok.token_id, + tok.place_key, + tok.locked_task_id, + ta.transition_key + from wf_tokens tok, + wf_tasks ta + where tok.case_id = :case_id + and ta.task_id (+) = tok.locked_task_id + and tok.state in ('free', 'locked') + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-state-graph.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-state-graph.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-state-graph.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1 @@ +@workflow_img_tag@ Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-state-graph.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-state-graph.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-state-graph.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,92 @@ +# +# Display the state of a case graphically +# +# Expects: +# case_id +# size (optional) +# Data sources +# workflow_img_tag +# + +##### +# +# Add marking to the graph +# +##### + +set workflow_key [db_string workflow_key_from_case_id { select workflow_key from wf_cases where case_id = :case_id }] + +set workflow_info [wf_get_workflow_net $workflow_key] +array set workflow $workflow_info +wf_decorate_workflow workflow + +foreach place_key $workflow(places) { + set workflow(place,$place_key,num_tokens) 0 +} +foreach transition_key $workflow(transitions) { + set workflow(transition,$transition_key,num_tokens) 0 +} + +db_foreach tokens { + select tok.token_id, + tok.place_key, + tok.locked_task_id, + ta.transition_key + from wf_tokens tok, + wf_tasks ta + where tok.case_id = :case_id + and ta.task_id (+) = tok.locked_task_id + and tok.state in ('free', 'locked') +} { + if { [empty_string_p $transition_key] } { + incr workflow(place,$place_key,num_tokens) + } else { + incr workflow(transition,$transition_key,num_tokens) + } +} + +foreach place_key $workflow(places) { + if { $workflow(place,$place_key,num_tokens) > 0 } { + append workflow(place,$place_key,place_name) "\\n[string repeat "*" $workflow(place,$place_key,num_tokens)]" + lappend workflow(selected_place_key) $place_key + } +} +foreach transition_key $workflow(transitions) { + if { $workflow(transition,$transition_key,num_tokens) > 0 } { + append workflow(transition,$transition_key,transition_name) "\\n[string repeat "*" $workflow(transition,$transition_key,num_tokens)]" + lappend workflow(selected_transition_key) $transition_key + } +} + +db_release_unused_handles + +##### +# +# Create the workflow gif +# +##### + +if { [wf_graphviz_installed_p] } { + + if { ![info exists size] } { + set size {} + } + + set dot_text [wf_generate_dot_representation -size $size workflow] + + set tmpfile [wf_graphviz_dot_exec -to_file -output gif $dot_text] + + set width_and_height "" + if { ![catch { set image_size [ns_gifsize $tmpfile] } error] } { + if { ![empty_string_p $image_size] } { + set width_and_height "width=[lindex $image_size 0] height=[lindex $image_size 1]" + } + } + + ad_set_client_property wf wf_net_tmpfile $tmpfile + + set workflow_img_tag "\"Graphical" +} else { + set workflow_img_tag "" +} + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/case-state-graph.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/case-state-graph.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/case-state-graph.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,26 @@ + + + + + + select workflow_key from wf_cases where case_id = :case_id + + + + + + + + select tok.token_id, + tok.place_key, + tok.locked_task_id, + ta.transition_key + from wf_tokens tok left outer join wf_tasks ta on (ta.task_id = tok.locked_task_id) + where tok.case_id = :case_id + and tok.state in ('free', 'locked') + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/finished-tasks-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/finished-tasks-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/finished-tasks-oracle.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,36 @@ + + + + oracle8.1.6 + + + + + select t.task_id, + t.transition_key, + t.state, + t.case_id, + tr.transition_name, + to_char(t.enabled_date, :date_format) as enabled_date_pretty, + to_char(t.started_date, :date_format) as started_date_pretty, + to_char(t.canceled_date, :date_format) as canceled_date_pretty, + to_char(t.overridden_date, :date_format) as overridden_date_pretty, + to_char(t.finished_date, :date_format) as finished_date_pretty, + to_char(nvl(t.finished_date, nvl(t.canceled_date, t.overridden_date)), :date_format) as done_date_pretty, + p.party_id as done_by_party_id, + '' as done_by_url, + acs_object.name(p.party_id) as done_by_name, + p.email as done_by_email + from wf_tasks t, wf_transitions tr, parties p + where t.case_id = :case_id + and t.state not in ('enabled', 'started') + and tr.workflow_key = t.workflow_key + and tr.transition_key = t.transition_key + and p.party_id (+) = t.holding_user + order by t.enabled_date desc + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/finished-tasks-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/finished-tasks-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/finished-tasks-postgresql.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,35 @@ + + + + postgresql7.1 + + + + + select t.task_id, + t.transition_key, + t.state, + t.case_id, + tr.transition_name, + to_char(t.enabled_date, :date_format) as enabled_date_pretty, + to_char(t.started_date, :date_format) as started_date_pretty, + to_char(t.canceled_date, :date_format) as canceled_date_pretty, + to_char(t.overridden_date, :date_format) as overridden_date_pretty, + to_char(t.finished_date, :date_format) as finished_date_pretty, + to_char(coalesce(t.finished_date, coalesce(t.canceled_date, t.overridden_date)), :date_format) as done_date_pretty, + p.party_id as done_by_party_id, + '' as done_by_url, + acs_object__name(p.party_id) as done_by_name, + p.email as done_by_email + from wf_transitions tr, wf_tasks t LEFT OUTER JOIN parties p ON (t.holding_user = p.party_id) + where t.case_id = :case_id + and t.state not in ('enabled', 'started') + and tr.workflow_key = t.workflow_key + and tr.transition_key = t.transition_key + order by t.enabled_date desc + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/finished-tasks.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/finished-tasks.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/finished-tasks.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,45 @@ + +
    + No tasks have finished yet. +
    +
    + + + + + +
    + + + + + + + + + + + + + + + + + +
    Task NameStateActivated DateDone DateDone By
    @finished_tasks.transition_name@@finished_tasks.state@@finished_tasks.enabled_date_pretty@ + @finished_tasks.done_date_pretty@ +   + + + + @finished_tasks.done_by_name@ + + @finished_tasks.done_by_name + + (@finished_tasks.done_by_email@) + + +   +
    +
    +
    Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/finished-tasks.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/finished-tasks.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/finished-tasks.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,44 @@ +# +# Finished tasks for a case +# +# Expects: +# case_id +# date_format (optional) +# Data sources: +# finished_tasks +# +# cvs-id: $Id: finished-tasks.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +# Creation date: Feb 21, 2001 +# Author: Lars Pind (lars@pinds.com) +# + +if { ![info exists date_format] } { + set date_format "Mon fmDDfm, YYYY HH24:MI:SS" +} + +db_multirow finished_tasks finished_tasks { + select t.task_id, + t.transition_key, + t.state, + t.case_id, + tr.transition_name, + to_char(t.enabled_date, :date_format) as enabled_date_pretty, + to_char(t.started_date, :date_format) as started_date_pretty, + to_char(t.canceled_date, :date_format) as canceled_date_pretty, + to_char(t.overridden_date, :date_format) as overridden_date_pretty, + to_char(t.finished_date, :date_format) as finished_date_pretty, + to_char(nvl(t.finished_date, nvl(t.canceled_date, t.overridden_date)), :date_format) as done_date_pretty, + p.party_id done_by_party_id, + '' as done_by_url, + acs_object.name(p.party_id) as done_by_name, + p.email as done_by_email + from wf_tasks t, wf_transitions tr, parties p + where t.case_id = :case_id + and t.state not in ('enabled', 'started') + and tr.workflow_key = t.workflow_key + and tr.transition_key = t.transition_key + and p.party_id (+) = t.holding_user + order by t.enabled_date desc +} { + set done_by_url "/shared/community-member?[export_vars -url {{user_id $done_by_party_id}}]" +} Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/task-deadline-set-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/task-deadline-set-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/task-deadline-set-2.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,20 @@ +# /packages/acs-workflow/www/task-deadline-set-2.tcl +ad_page_contract { + Update deadline for a task + + @author Jesse Koontz [jkoontz@arsdigita.com] + @creation-date Wed Jan 10 16:28:05 2001 + @cvs-id $Id: task-deadline-set-2.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +} { + task_id:integer + return_url:optional + deadline:array,date +} + +set deadline_date $deadline(date) + +db_dml deadline_update " +update wf_tasks set deadline = :deadline_date +where task_id = :task_id" + +ad_returnredirect $return_url \ No newline at end of file Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/task-deadline-set-2.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/task-deadline-set-2.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/task-deadline-set-2.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,13 @@ + + + + + + +update wf_tasks set deadline = :deadline_date +where task_id = :task_id + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/task-deadline-set.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/task-deadline-set.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/task-deadline-set.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,17 @@ + +Set Deadline + +

    Set Deadline

    +@context_bar@ +
    + +
    +@export_vars@ + + + + +
    Task@task.task_name@
    Deadline@date_widget@
    +
    + +
    \ No newline at end of file Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/task-deadline-set.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/task-deadline-set.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/task-deadline-set.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,34 @@ +# /packages/acs-workflow/www/task-deadline-set.tcl +ad_page_contract { + Set the deadline for a task + + @author Jesse Koontz [jkoontz@arsdigita.com] + @creation-date Wed Jan 10 16:18:17 2001 + @cvs-id $Id: task-deadline-set.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +} { + task_id:integer + return_url:optional +} -properties { + context_bar + export_vars + date_widget +} + +set write_p [ad_permission_p $task_id "write"] + +array set task [wf_task_info $task_id] + +set context_bar [ad_context_bar [list "case?case_idf=$task(case_id)" "Case \"$task(object_name)\""] [list "task?[export_url_vars task_id]" "Task \"$task(task_name)\""] "Set deadline"] + +set export_vars [export_form_vars task_id return_url] + +set deadline [db_string deadline_select " +select deadline +from wf_tasks +where task_id = :task_id" -default ""] + +set date_widget [ad_dateentrywidget deadline $deadline] + +ad_return_template + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/task-deadline-set.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/task-deadline-set.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/task-deadline-set.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,14 @@ + + + + + + +select deadline +from wf_tasks +where task_id = :task_id + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/task-instructions.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/task-instructions.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/task-instructions.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,7 @@ + + + + + + +
    @task.instructions@
    \ No newline at end of file Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/task-instructions.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/task-instructions.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/task-instructions.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,6 @@ +# This template expects the following properties: +# task:onerow + +ad_return_template + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/test-display.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/test-display.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/test-display.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,18 @@ +set case_id 2002 +set workflow_key [db_string workflow_key_from_case_id { select workflow_key from wf_cases where case_id = :case_id }] + + +set workflow_info [wf_get_workflow_net $workflow_key] + + +doc_return 200 text/html " + + +test + +workflow_key : $workflow_key

    +workflow_info :$workflow_info

    + + + +" \ No newline at end of file Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/test-display.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/test-display.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/test-display.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,11 @@ + + + + + + select workflow_key from wf_cases where case_id = :case_id + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/assign-transition-role-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/assign-transition-role-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/assign-transition-role-2.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,41 @@ +# /packages/acs-workflow/www/admin/assign-transition-role-2.tcl +ad_page_contract { + Add assignment of a transition to a role. + + @author Jesse Koontz [jkoontz@arsdigita.com] + @creation-date Thu Jan 25 11:16:04 2001 + @cvs-id $Id: assign-transition-role-2.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +} { + workflow_key:notnull + role_key:notnull + transition_key:notnull +} -properties { + workflow:onerow + role:onerow + available_transitions:multirow + export_form_vars +} -validate { + workflow_exists -requires {workflow_key} { + if { 0 == [db_string workflow_exists " + select count(*) from wf_workflows + where workflow_key = :workflow_key"] } { + ad_complain "You seem to have specified a nonexistent workflow." + } + } + role_exists -requires {role_key} { + if { 0 == [db_string role_exists " + select count(*) from wf_roles + where workflow_key = :workflow_key + and role_key = :role_key"] } { + ad_complain "You seem to have specified a nonexistent role." + } + } +} + +db_dml assign_transition_role { + update wf_transitions set role_key = :role_key + where workflow_key = :workflow_key + and transition_key = :transition_key +} + +ad_returnredirect "workflow-roles?[export_vars -url {workflow_key}]" Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/assign-transition-role-2.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/assign-transition-role-2.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/assign-transition-role-2.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,34 @@ + + + + + + + select count(*) from wf_workflows + where workflow_key = :workflow_key + + + + + + + + select count(*) from wf_roles + where workflow_key = :workflow_key + and role_key = :role_key + + + + + + + + update wf_transitions set role_key = :role_key + where workflow_key = :workflow_key + and transition_key = :transition_key + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/assign-transition-role.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/assign-transition-role.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/assign-transition-role.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,35 @@ + +Assign Transition to @role.role_name@ + +

    Assign Transition to @role.role_name@

    +@context_bar@ + +
    + +
    +@export_form_vars@ + + + + + + + + + + + + + + + + +
    Workflow@workflow.pretty_name@
    Role@role.role_name@
    Transition +
    +
    + + \ No newline at end of file Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/assign-transition-role.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/assign-transition-role.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/assign-transition-role.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,64 @@ +# /packages/acs-workflow/www/admin/assign-transition-role.tcl +ad_page_contract { + Sets a transition's role. + + @author Jesse Koontz [jkoontz@arsdigita.com] + @creation-date Thu Jan 25 10:31:34 2001 + @cvs-id $Id: assign-transition-role.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +} { + workflow_key:notnull + role_key:notnull +} -properties { + workflow:onerow + role:onerow + available_transitions:multirow + export_form_vars +} -validate { + workflow_exists -requires {workflow_key} { + if { 0 == [db_string workflow_exists " + select count(*) from wf_workflows + where workflow_key = :workflow_key"] } { + ad_complain "You seem to have specified a nonexistent workflow." + } + } + role_exists -requires {role_key} { + if { 0 == [db_string role_exists " + select count(*) from wf_roles + where workflow_key = :workflow_key + and role_key = :role_key"] } { + ad_complain "You seem to have specified a nonexistent role." + } + } +} + +db_1row workflow { + select w.workflow_key, + t.pretty_name + from wf_workflows w, + acs_object_types t + where w.workflow_key = :workflow_key + and w.workflow_key = t.object_type +} -column_array workflow + +db_1row role { + select role_name + from wf_roles + where workflow_key = :workflow_key + and role_key = :role_key +} -column_array role + +set context_bar [ad_context_bar [list "workflow?[export_vars -url {workflow_key}]" "$workflow(pretty_name)"] [list "workflow-roles?[export_vars -url {workflow_key}]" "Workflow Roles"] "Assign transition to $role(role_name)"] + +db_multirow available_transitions workflow_transitions { + select transition_name, + transition_key + from wf_transitions + where workflow_key = :workflow_key + and role_key is null + order by sort_order +} { +} + +set export_form_vars [export_vars -form {workflow_key role_key}] + +ad_return_template Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/assign-transition-role.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/assign-transition-role.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/assign-transition-role.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,63 @@ + + + + + + + select count(*) from wf_workflows + where workflow_key = :workflow_key + + + + + + + + select count(*) from wf_roles + where workflow_key = :workflow_key + and role_key = :role_key + + + + + + + + select w.workflow_key, + t.pretty_name + from wf_workflows w, + acs_object_types t + where w.workflow_key = :workflow_key + and w.workflow_key = t.object_type + + + + + + + + + select role_name + from wf_roles + where workflow_key = :workflow_key + and role_key = :role_key + + + + + + + + + select transition_name, + transition_key + from wf_transitions + where workflow_key = :workflow_key + and role_key is null + order by sort_order + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/attributes-table.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/attributes-table.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/attributes-table.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,52 @@ + +
    + No attributes defined +
    +
    + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    No.Attribute nameDatatypeUsedAction
    + No attributes +
    @attributes.rownum@.@attributes.pretty_name@@attributes.datatype@ + Yes + No + + + (edit) + + + (delete) + +
    +
    +
    + +(add attribute) Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/attributes-table.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/attributes-table.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/attributes-table.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,45 @@ +# +# Attributes table. +# +# Input: +# workflow_key +# return_url (optional) +# modifiable_p (optional) +# +# Data sources: +# attributes +# add_url +# +# Author: Lars Pind (lars@pinds.com) +# Creation-date: Feb 26, 2001 +# Cvs-id: $Id: attributes-table.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +# + +if { ![info exists modifiable_p] } { + set modifiable_p 1 +} + +db_multirow attributes attributes { + select a.attribute_id, + a.sort_order, + a.attribute_name, + a.pretty_name, + a.datatype, + '' as delete_url, + (select count(*) from wf_transition_attribute_map m + where m.workflow_key = a.object_type + and m.attribute_id = a.attribute_id) as used_p + from acs_attributes a + where a.object_type = :workflow_key + order by sort_order +} { + if { $modifiable_p } { + set delete_url "attribute-delete?[export_vars -url {workflow_key attribute_id return_url}]" + } +} + +set add_url "attribute-add?[export_vars -url {workflow_key return_url}]" + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/attributes-table.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/attributes-table.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/attributes-table.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,24 @@ + + + + + + + select a.attribute_id, + a.sort_order, + a.attribute_name, + a.pretty_name, + a.datatype, + '' as delete_url, + (select count(*) from wf_transition_attribute_map m + where m.workflow_key = a.object_type + and m.attribute_id = a.attribute_id) as used_p + from acs_attributes a + where a.object_type = :workflow_key + order by sort_order + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/down.gif =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/down.gif,v diff -u Binary files differ Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-add-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-add-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-add-2.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,32 @@ +# /packages/acs-workflow/www/admin/role-add-2.tcl +ad_page_contract { + Adds a role + + @author Jesse Koontz [jkoontz@arsdigita.com] + @creation-date Thu Jan 25 09:32:52 2001 + @cvs-id $Id: role-add-2.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +} { + workflow_key:notnull + role_name:notnull + {return_url "workflow-roles?[expolrt_vars -url {workflow_key}]"} +} -validate { + role_name_unique -requires { workflow_key:notnull role_name:notnull } { + set num_rows [db_string num_roles { + select count(*) + from wf_roles + where workflow_key = :workflow_key + and role_name = :role_name + }] + + if { $num_rows > 0 } { + ad_complain "There is already a role with this name" + } + } +} + +wf_add_role \ + -workflow_key $workflow_key \ + -role_name $role_name + +ad_returnredirect $return_url + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-add-2.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-add-2.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-add-2.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,16 @@ + + + + + + + select count(*) + from wf_roles + where workflow_key = :workflow_key + and role_name = :role_name + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-add.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-add.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-add.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,29 @@ + +Add Role +role.role_name + +

    Add Role

    + +
    +@export_vars@ + + + + + + + + + + + + +
    Role name
    + +
    + +
    + +
    Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-add.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-add.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-add.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,27 @@ +# /packages/acs-workflow/www/admin/role-add.tcl +ad_page_contract { + Adds a role to a workflow + + @author Jesse Koontz [jkoontz@arsdigita.com] + @creation-date Thu Jan 25 09:29:57 2001 + @cvs-id $Id: role-add.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +} { + workflow_key:notnull + return_url:optional +} -properties { + context_bar + export_vars +} + +db_1row workflow_info { + select ot.pretty_name as workflow_name + from acs_object_types ot + where ot.object_type = :workflow_key +} + +set context_bar [ad_context_bar [list "workflow?[export_vars -url {workflow_key {tab roles}}]" "$workflow_name"] "Add role"] + +set export_vars [export_vars -form {workflow_key return_url}] + +ad_return_template + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-add.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-add.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-add.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,15 @@ + + + + + + + select ot.pretty_name as workflow_name + from acs_object_types ot + where ot.object_type = :workflow_key + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-delete.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-delete.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-delete.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,18 @@ +ad_page_contract { + Delete role. + + @author Lars Pind (lars@pinds.com) + @creation-date Sep 2000 + @cvs-id $Id: role-delete.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +} { + workflow_key + role_key + {return_url "define?[export_url_vars workflow_key]"} +} + +wf_delete_role \ + -workflow_key $workflow_key \ + -role_key $role_key + +ad_returnredirect $return_url + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-edit-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-edit-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-edit-2.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,40 @@ +# /packages/acs-workflow/www/admin/role-edit-2.tcl +ad_page_contract { + Edits a role + + @author Lars Pind (lars@pinds.com) + @creation-date Feb 27, 2001 + @cvs-id $Id: role-edit-2.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +} { + workflow_key:notnull + role_key:notnull + role_name:notnull + {return_url "workflow-roles?[expolrt_vars -url {workflow_key}]"} + cancel:optional +} -validate { + role_name_unique -requires { workflow_key:notnull role_name:notnull role_key:notnull } { + set num_rows [db_string num_roles { + select count(*) + from wf_roles + where workflow_key = :workflow_key + and role_name = :role_name + and role_key != :role_key + }] + + if { $num_rows > 0 } { + ad_complain "There is already another role with this name" + } + } +} + +if { ![info exists cancel] || [empty_string_p $cancel] } { + db_dml edit_role { + update wf_roles + set role_name = :role_name + where workflow_key = :workflow_key + and role_key = :role_key + } +} + +ad_returnredirect $return_url + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-edit-2.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-edit-2.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-edit-2.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,29 @@ + + + + + + + select count(*) + from wf_roles + where workflow_key = :workflow_key + and role_name = :role_name + and role_key != :role_key + + + + + + + + + update wf_roles + set role_name = :role_name + where workflow_key = :workflow_key + and role_key = :role_key + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-edit.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-edit.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-edit.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,32 @@ + +Edit @role_name@ role +role.role_name + +

    Edit @role_name@ role

    +@context_bar@ +
    + +
    +@export_vars@ + + + + + + + + + +
    + Role name + + +
    + +       + +
    + +
    + +
    \ No newline at end of file Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-edit.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-edit.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-edit.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,38 @@ +# /packages/acs-workflow/www/admin/role-edit.tcl +ad_page_contract { + Edit a role. + + @author Lars Pind (lars@pinds.com) + @creation-date Feb 27, 2001 + @cvs-id $Id: role-edit.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +} { + workflow_key:notnull + role_key:notnull + return_url:optional +} -properties { + context_bar + export_vars + role_key + role_name +} + +db_1row workflow_info { + select ot.pretty_name as workflow_name + from acs_object_types ot + where ot.object_type = :workflow_key +} + +set context_bar [ad_context_bar [list "workflow?[export_vars -url {workflow_key {tab roles}}]" "$workflow_name"] "Edit role"] + +set export_vars [export_vars -form {workflow_key role_key return_url}] + +db_1row role_info { + select role_key, + role_name + from wf_roles + where workflow_key = :workflow_key + and role_key = :role_key +} + +ad_return_template + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-edit.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-edit.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-edit.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,28 @@ + + + + + + + select ot.pretty_name as workflow_name + from acs_object_types ot + where ot.object_type = :workflow_key + + + + + + + + + select role_key, + role_name + from wf_roles + where workflow_key = :workflow_key + and role_key = :role_key + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-manual-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-manual-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-manual-2.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,23 @@ +ad_page_contract { + Make role manually assigned. + + @author Lars Pind (lars@pinds.com) + @creation-date Feb 27, 2001 + @cvs-id $Id: role-manual-2.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +} { + workflow_key:notnull + role_key:notnull + transition_key:notnull + {return_url "workflow?[export_vars -url {workflow_key {tab roles}}]"} + cancel:optional +} + + + +wf_add_trans_role_assign_map \ + -workflow_key $workflow_key \ + -transition_key $transition_key \ + -assign_role_key $role_key + +ad_returnredirect $return_url + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-manual.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-manual.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-manual.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,41 @@ + +Manually Assign @role_name@ +manual_form.transition_key + +

    Manually Assign @role_name@

    +@context_bar@ +
    + + +

    + +

    +@export_vars@ + + + + + + + + + + + +
    + Select the task that you want to assign the @role_name@ role: +
    + +
    + +       + +
    + +
    + +
    Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-manual.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-manual.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-manual.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,51 @@ +# /packages/acs-workflow/www/admin/role-manual.tcl +ad_page_contract { + Makes a role manually assigned + + @author Lars Pind (lars@pinds.com) + @creation-date Feb 27, 2001 + @cvs-id $Id: role-manual.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +} { + workflow_key:notnull + role_key:notnull + {return_url "workflow?[export_vars -url {workflow_key {tab roles}}]"} +} -properties { + context_bar + export_vars + transitions + role_name +} + +db_1row workflow_info { + select ot.pretty_name as workflow_name + from acs_object_types ot + where ot.object_type = :workflow_key +} + +db_1row role_info { + select role_name + from wf_roles + where workflow_key = :workflow_key + and role_key = :role_key +} + +set context_bar [ad_context_bar [list "$return_url" "$workflow_name"] "Manually Assign $role_name"] + +set export_vars [export_vars -form {workflow_key role_key return_url}] + +db_multirow transitions transitions { + select t.transition_key, + t.transition_name + from wf_transitions t + where t.workflow_key = :workflow_key + and not exists (select 1 + from wf_transition_role_assign_map m + where m.workflow_key = t.workflow_key + and m.transition_key = t.transition_key + and m.assign_role_key = :role_key) + order by t.sort_order +} + + +ad_return_template + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-manual.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-manual.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-manual.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,45 @@ + + + + + + + select ot.pretty_name as workflow_name + from acs_object_types ot + where ot.object_type = :workflow_key + + + + + + + + + select role_name + from wf_roles + where workflow_key = :workflow_key + and role_key = :role_key + + + + + + + + + select t.transition_key, + t.transition_name + from wf_transitions t + where t.workflow_key = :workflow_key + and not exists (select 1 + from wf_transition_role_assign_map m + where m.workflow_key = t.workflow_key + and m.transition_key = t.transition_key + and m.assign_role_key = :role_key) + order by t.sort_order + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-move-down.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-move-down.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-move-down.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,18 @@ +ad_page_contract { + Move role down. + + @author Lars Pind (lars@pinds.com) + @creation-date Feb 27, 2001 + @cvs-id $Id: role-move-down.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +} { + workflow_key:notnull + role_key:notnull + {return_url "workflow?[export_vars -url {workflow_key {tab roles}}]"} +} + +wf_move_role_down \ + -workflow_key $workflow_key \ + -role_key $role_key + +ad_returnredirect $return_url + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-move-up.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-move-up.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/role-move-up.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,18 @@ +ad_page_contract { + Move role up. + + @author Lars Pind (lars@pinds.com) + @creation-date Feb 27, 2001 + @cvs-id $Id: role-move-up.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +} { + workflow_key:notnull + role_key:notnull + {return_url "workflow?[export_vars -url {workflow_key {tab roles}}]"} +} + +wf_move_role_up \ + -workflow_key $workflow_key \ + -role_key $role_key + +ad_returnredirect $return_url + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/roles-assignment-table-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/roles-assignment-table-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/roles-assignment-table-oracle.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,37 @@ + + + + oracle8.1.6 + + + + + select r.sort_order, + r.role_key, + r.role_name, + '' as delete_url, + '' as edit_url, + '' as static_url, + '' as manual_url, + '' as programmatic_url, + 0 as is_static_p, + cri.assignment_callback, + cri.assignment_custom_arg, + map.transition_key as assigning_transition_key, + t.transition_name as assigning_transition_name + from wf_roles r, wf_context_role_info cri, wf_transition_role_assign_map map, wf_transitions t + where r.workflow_key = :workflow_key + and cri.context_key (+) = :context_key + and cri.workflow_key (+) = r.workflow_key + and cri.role_key (+) = r.role_key + and map.workflow_key (+) = r.workflow_key + and map.assign_role_key (+) = r.role_key + and t.workflow_key (+) = map.workflow_key + and t.transition_key (+) = map.transition_key + order by r.sort_order + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/roles-assignment-table.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/roles-assignment-table.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/roles-assignment-table.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,70 @@ + +
    + No roles defined +
    +
    + + + + + +
    + + + + + + + + + + + + + + + + + + + + +
    No.RoleActionStatic AssignmentManual AssignmentProgrammatic Assignment
    @roles.rownum@.@roles.role_name@ + + (delete) + +   + + + Static + + +   + + + +
    (change to manual)
    +
    + +
    + Manual +
    Assigned by these transitions: +
    + +
  • @roles.assigning_transition_name@
  • +
    +
    (assign by another transition) +
    +
    + + (change to programmatic) + + + @roles.assignment_callback@ + +
    +
    +
    +(add role) + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/roles-assignment-table.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/roles-assignment-table.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/roles-assignment-table.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,60 @@ +# +# Display roles for a process. +# +# Input: +# workflow_key +# return_url (optional) +# context (optional) +# +# Data sources: +# roles +# role_add_url +# +# Author: Lars Pind (lars@pinds.com) +# Creation-date: Feb 26, 2001 +# Cvs-id: $Id: roles-assignment-table.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ + +if { ![info exists context_key] } { + set context_key "default" +} + +db_multirow roles roles { + select r.sort_order, + r.role_key, + r.role_name, + '' as delete_url, + '' as edit_url, + '' as static_url, + '' as manual_url, + '' as programmatic_url, + 0 as is_static_p, + cri.assignment_callback, + cri.assignment_custom_arg, + map.transition_key as assigning_transition_key, + t.transition_name as assigning_transition_name + from wf_roles r, wf_context_role_info cri, wf_transition_role_assign_map map, wf_transitions t + where r.workflow_key = :workflow_key + and cri.context_key (+) = :context_key + and cri.workflow_key (+) = r.workflow_key + and cri.role_key (+) = r.role_key + and map.workflow_key (+) = r.workflow_key + and map.assign_role_key (+) = r.role_key + and t.workflow_key (+) = map.workflow_key + and t.transition_key (+) = map.transition_key + order by r.sort_order +} { + set delete_url "role-delete?[export_vars -url {workflow_key role_key return_url}]" + set edit_url "role-edit?[export_vars -url {workflow_key role_key return_url}]" + set static_url "role-static?[export_vars -url {workflow_key role_key return_url}]" + set manual_url "role-manual?[export_vars -url {workflow_key role_key return_url}]" + set programmatic_url "role-programmatic?[export_vars -url {workflow_key role_key return_url}]" + if { [empty_string_p $assignment_callback] && [empty_string_p $assigning_transition_key] } { + set is_static_p 1 + } +} + +set role_add_url "role-add?[export_vars -url {workflow_key return_url}]" + +ad_return_template + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/roles-assignment-table.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/roles-assignment-table.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/roles-assignment-table.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,30 @@ + + + + + + + select r.sort_order, + r.role_key, + r.role_name, + '' as delete_url, + '' as edit_url, + '' as static_url, + '' as manual_url, + '' as programmatic_url, + 0 as is_static_p, + cri.assignment_callback, + cri.assignment_custom_arg, + map.transition_key as assigning_transition_key, + t.transition_name as assigning_transition_name + from ((wf_roles r LEFT OUTER JOIN wf_context_role_info cri + ON (r.workflow_key = cri.workflow_key and cri.context_key = :context_key and cri.role_key = r.role_key)) LEFT OUTER JOIN wf_transition_role_assign_map map + ON (r.workflow_key = map.workflow_key and r.role_key = map.assign_role_key)) LEFT OUTER JOIN wf_transitions t ON (map.workflow_key = t.workflow_key and map.transition_key = t.transition_key) + where r.workflow_key = :workflow_key + order by r.sort_order + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/roles-table-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/roles-table-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/roles-table-oracle.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,30 @@ + + + + oracle8.1.6 + + + + + select r.sort_order, + r.role_key, + r.role_name, + '' as delete_url, + '' as edit_url, + '' as move_up_url, + '' as move_down_url, + 0 as role_no, + t.transition_key, + t.transition_name, + '' as transition_edit_url + from wf_roles r, wf_transitions t + where r.workflow_key = :workflow_key + and t.workflow_key (+) = r.workflow_key + and t.role_key (+) = r.role_key + order by r.sort_order, t.sort_order + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/roles-table.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/roles-table.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/roles-table.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,61 @@ + +
    + No roles defined +
    +
    + + + + + +
    + + + + + + + + + + + + + + + + + + + + +
      No.RoleActionTransitions
    + + Move up + +   + + + Move down + +   + @roles.role_no@.@roles.role_name@ + + (delete) + +   + + + +
  • @roles.transition_name@
  • +
    +
    + + No transitions belong to this role + +
    +
    +
    +(add role) + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/roles-table.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/roles-table.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/roles-table.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,77 @@ +# +# Display roles for a process. +# +# Input: +# workflow_key +# return_url (optional) +# context (optional) +# modifiable_p (optional) +# +# Data sources: +# roles +# role_add_url +# +# Author: Lars Pind (lars@pinds.com) +# Creation-date: Feb 26, 2001 +# Cvs-id: $Id: roles-table.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ + +if { ![info exists context_key] } { + set context_key "default" +} + +if { ![info exists modifiable_p] } { + set modifiable_p 1 +} + +set row_count 0 +set role_count 0 +set last_role_key {} +db_multirow roles roles { + select r.sort_order, + r.role_key, + r.role_name, + '' as delete_url, + '' as edit_url, + '' as move_up_url, + '' as move_down_url, + 0 as role_no, + t.transition_key, + t.transition_name, + '' as transition_edit_url + from wf_roles r, wf_transitions t + where r.workflow_key = :workflow_key + and t.workflow_key (+) = r.workflow_key + and t.role_key (+) = r.role_key + order by r.sort_order, t.sort_order +} { + incr row_count + if { ![string equal $role_key $last_role_key] } { + incr role_count + set last_role_key $role_key + } + # For some reason we seem to need to ns_urlencode the whole thing again, when using it in javascript + if { $modifiable_p } { + set delete_url [ad_quotehtml "javascript:if(confirm('Are you sure you want to delete this role?'))location.href='role-delete?[export_vars -url {workflow_key role_key return_url}]'"] + } + +# set delete_url "role-delete?[export_vars -url {workflow_key role_key return_url}]" + set edit_url "role-edit?[export_vars -url {workflow_key role_key return_url}]" + if { $row_count > 1 } { + set move_up_url "role-move-up?[export_vars -url {workflow_key role_key return_url}]" + } + set move_down_url "role-move-down?[export_vars -url {workflow_key role_key return_url}]" + set role_no $role_count + if { ![empty_string_p $transition_key] } { + set transition_edit_url "task-edit?[export_vars -url {workflow_key transition_key return_url context_key}]" + } +} + +for { set i $row_count } { $i > 0 && [string equal [template::multirow get roles $i role_key] $last_role_key] } { incr i -1 } { + template::multirow set roles $i move_down_url "" +} + +set role_add_url "role-add?[export_vars -url {workflow_key return_url}]" + +ad_return_template + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/roles-table.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/roles-table.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/roles-table.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,26 @@ + + + + + + + select r.sort_order, + r.role_key, + r.role_name, + '' as delete_url, + '' as edit_url, + '' as move_up_url, + '' as move_down_url, + 0 as role_no, + t.transition_key, + t.transition_name, + '' as transition_edit_url + from wf_roles r left outer join wf_transitions t on (t.workflow_key = r.workflow_key and t.role_key = r.role_key) + where r.workflow_key = :workflow_key + order by r.sort_order, t.sort_order + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/static-assignments-table-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/static-assignments-table-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/static-assignments-table-oracle.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,48 @@ + + + + oracle8.1.6 + + + + + select r.role_key, + r.role_name, + p.party_id, + acs_object.name(p.party_id) as party_name, + p.email as party_email, + '' as user_select_widget, + '' as add_export_vars, + '' as remove_url + from wf_roles r, + wf_context_assignments ca, + parties p + where r.workflow_key = :workflow_key + and ca.context_key (+) = :context_key + and ca.role_key (+) = r.role_key + and p.party_id (+) = ca.party_id + order by r.sort_order, r.role_key + + + + + + + + + select p.party_id as sel_party_id, + acs_object.name(p.party_id) as sel_name, + p.email as sel_email + from parties p + where p.party_id not in + (select ca.party_id + from wf_context_assignments ca + where ca.workflow_key = :workflow_key + and ca.context_key = :context_key + and ca.role_key = :role_key) + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/static-assignments-table-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/static-assignments-table-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/static-assignments-table-postgresql.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,49 @@ + + + + postgresql7.1 + + + + + select r.role_key, + r.role_name, + p.party_id, + acs_object__name(p.party_id) as party_name, + p.email as party_email, + '' as user_select_widget, + '' as add_export_vars, + '' as remove_url + from wf_roles r + left outer join + wf_context_assignments ca + on (ca.context_key = :context_key and ca.role_key = r.role_key) + left outer join + parties p + using (party_id) + where r.workflow_key = :workflow_key + order by r.sort_order, r.role_key + + + + + + + + + select p.party_id as sel_party_id, + acs_object__name(p.party_id) as sel_name, + p.email as sel_email + from parties p + where p.party_id not in + (select ca.party_id + from wf_context_assignments ca + where ca.workflow_key = :workflow_key + and ca.context_key = :context_key + and ca.role_key = :role_key) + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/static-assignments-table.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/static-assignments-table.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/static-assignments-table.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,57 @@ + +
    + No roles defined +
    +
    + + + + + +
    + + + + + + + + + + + + +
    + @roles.add_export_vars@ +
    + + + + + + + +
    RoleAssignmentsAction
    @roles.role_name@ + + +
  • + @roles.party_name@ + + (@roles.party_email@) + + (remove) +
  • +
    + + Unassigned + +
    +
    + @roles.user_select_widget@ + +  
    +
    +
    + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/static-assignments-table.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/static-assignments-table.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/static-assignments-table.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,74 @@ +# +# Display transitions for a process. +# +# Input: +# workflow_key +# return_url (optional) +# context (optional) +# +# Data sources: +# roles +# +# Author: Lars Pind (lars@pinds.com) +# Creation-date: Feb 26, 2001 +# Cvs-id: $Id: static-assignments-table.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ + +if { ![info exists context_key] } { + set context_key "default" +} + +set last_role_key {} +db_multirow roles roles { + select r.role_key, + r.role_name, + p.party_id, + acs_object.name(p.party_id) as party_name, + p.email as party_email, + '' as user_select_widget, + '' as add_export_vars, + '' as remove_url + from wf_roles r, + wf_context_assignments ca, + parties p + where r.workflow_key = :workflow_key + and ca.context_key (+) = :context_key + and ca.role_key (+) = r.role_key + and p.party_id (+) = ca.party_id + order by r.sort_order, r.role_key +} { + if { ![string equal $role_key $last_role_key] } { + set counter 0 + set user_select_widget "" + if { $counter == 0 } { + set user_select_widget "" + } + set last_user_select_widget $user_select_widget + set last_role_key $role_key + } else { + set user_select_widget $last_user_select_widget + } + set add_export_vars [export_vars -form {workflow_key context_key role_key return_url}] + if { ![empty_string_p $party_id] } { + set remove_url "static-assignment-delete?[export_vars -url { workflow_key context_key role_key party_id return_url }]" + } +} + +ad_return_template + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/task-attribute-add-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/task-attribute-add-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/task-attribute-add-oracle.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,19 @@ + + + + oracle8.1.6 + + + + + insert into wf_transition_attribute_map (workflow_key, transition_key, sort_order, attribute_id) + select :workflow_key, :transition_key, nvl(max(sort_order)+1,1), :attribute_id + from wf_transition_attribute_map + where workflow_key = :workflow_key + and transition_key = :transition_key + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/task-panel-add-2-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/task-panel-add-2-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/task-panel-add-2-oracle.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,21 @@ + + + + oracle8.1.6 + + + + + insert into wf_context_task_panels + (workflow_key, transition_key, context_key, sort_order, header, template_url) + select :workflow_key, :transition_key, :context_key, nvl(max(sort_order)+1,1), :header, :template_url + from wf_context_task_panels + where workflow_key = :workflow_key + and transition_key = :transition_key + and context_key = :context_key + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/transition-panels-table-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/transition-panels-table-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/transition-panels-table-oracle.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,34 @@ + + + + oracle8.1.6 + + + + + select t.transition_key, + t.transition_name, + '' as transition_edit_url, + '' as panel_add_url, + pan.sort_order, + 0 as panel_no, + pan.header, + pan.template_url, + pan.template_url as template_url_pretty, + pan.overrides_action_p, + pan.only_display_when_started_p, + 0 as rowspan, + '' as panel_edit_url, + '' as panel_delete_url + from wf_transitions t, wf_context_task_panels pan + where t.workflow_key = :workflow_key + and pan.workflow_key (+) = t.workflow_key + and pan.context_key (+) = :context_key + and pan.transition_key (+) = t.transition_key + order by t.sort_order, pan.sort_order + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/transition-panels-table.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/transition-panels-table.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/transition-panels-table.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,75 @@ + +
    + No transitions defined +
    +
    + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    TransitionAddNo.HeaderAction
    + @panels.transition_name@ + + (add panel) + + + @panels.panel_no@. + +   + + + @panels.header@ + +   + + (delete) +
    +
    +
    + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/transition-panels-table.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/transition-panels-table.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/transition-panels-table.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,81 @@ +# +# Display panels for a process +# +# Input: +# workflow_key +# return_url (optional) +# context (optional) +# +# Data sources: +# transitions +# transition_add_url +# +# Author: Lars Pind (lars@pinds.com) +# Creation-date: Feb 27, 2001 +# Cvs-id: $Id: transition-panels-table.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ + +if { ![info exists context_key] } { + set context_key "default" +} + +set row_count 0 +set panel_count 0 +set last_transition_key {} +db_multirow panels panels { + select t.transition_key, + t.transition_name, + '' as transition_edit_url, + '' as panel_add_url, + pan.sort_order, + 0 as panel_no, + pan.header, + pan.template_url, + pan.template_url as template_url_pretty, + pan.overrides_action_p, + pan.only_display_when_started_p, + 0 as rowspan, + '' as panel_edit_url, + '' as panel_delete_url + from wf_transitions t, wf_context_task_panels pan + where t.workflow_key = :workflow_key + and pan.workflow_key (+) = t.workflow_key + and pan.context_key (+) = :context_key + and pan.transition_key (+) = t.transition_key + order by t.sort_order, pan.sort_order +} { + incr row_count + if { ![string equal $transition_key $last_transition_key] } { + set panel_count 0 + set last_transition_key $transition_key + } + incr panel_count + # For some reason we seem to need to ns_urlencode the whole thing again when we use it in a javascript thing +# set delete_url + + set panel_add_url "task-panel-add?[export_vars -url {workflow_key transition_key context_key return_url}]" + set panel_edit_url "task-panel-edit?[export_vars -url {sort_order workflow_key transition_key context_key return_url}]" + set panel_delete_url [ad_quotehtml "javascript:if(confirm('Are you sure you want to delete this panel?'))location.href='task-panel-delete?[export_vars -url {sort_order workflow_key transition_key context_key return_url}]'"] + + set transition_edit_url "task-edit?[export_vars -url {workflow_key transition_key return_url}]" + set panel_no $panel_count + if { [string length $template_url] > 30 } { + set len [string length $template_url] + set slash [string first "/" $template_url [expr { $len - 30 }]] + if { $slash == -1 } { + set slash [string last "/" $template_url [expr { $len - 30 }]] + } + set template_url_pretty "...[string range $template_url $slash end]" + } +} + +for { set i $row_count } { $i > 0 } { incr i -1 } { + set panel_no [template::multirow get panels $i panel_no] + incr i [expr -$panel_no + 1] + template::multirow set panels $i rowspan $panel_no +} + +#set transition_add_url "task-add?[export_vars -url {workflow_key return_url}]" + +ad_return_template + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/transition-panels-table.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/transition-panels-table.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/transition-panels-table.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,32 @@ + + + + + + + select t.transition_key, + t.transition_name, + '' as transition_edit_url, + '' as panel_add_url, + pan.sort_order, + 0 as panel_no, + pan.header, + pan.template_url, + pan.template_url as template_url_pretty, + pan.overrides_action_p, + pan.only_display_when_started_p, + 0 as rowspan, + '' as panel_edit_url, + '' as panel_delete_url + from wf_transitions t left outer join wf_context_task_panels pan on + (pan.workflow_key = t.workflow_key + and pan.context_key = :context_key + and pan.transition_key = t.transition_key) + where t.workflow_key = :workflow_key + order by t.sort_order, pan.sort_order + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/transitions-table-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/transitions-table-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/transitions-table-oracle.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,29 @@ + + + + oracle8.1.6 + + + + + select t.sort_order, + t.transition_key, + t.transition_name, + t.trigger_type, + '' as trigger_type_pretty, + t.role_key, + r.role_name, + '' as delete_url, + '' as edit_url, + '' as role_edit_url + from wf_transitions t, wf_roles r + where t.workflow_key = :workflow_key + and r.workflow_key (+) = t.workflow_key + and r.role_key (+) = t.role_key + order by t.sort_order + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/transitions-table.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/transitions-table.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/transitions-table.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,53 @@ + +
    + No transitions defined +
    +
    + + + + + +
    + + + + + + + + + + + + + + + + + + +
    No.TransitionTriggerActionBy Role
    @transitions.rownum@.@transitions.transition_name@@transitions.trigger_type_pretty@ + + (delete) + +   + + + @transitions.role_name@ + + + + Not associated with any role (edit) + + +   + + +
    +
    +
    +(add transition) + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/transitions-table.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/transitions-table.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/transitions-table.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,63 @@ +# +# Display transitions for a process. +# +# Input: +# workflow_key +# return_url (optional) +# context (optional) +# modifiable_p (optional) +# +# Data sources: +# transitions +# transition_add_url +# +# Author: Lars Pind (lars@pinds.com) +# Creation-date: Feb 26, 2001 +# Cvs-id: $Id: transitions-table.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ + +if { ![info exists context_key] } { + set context_key "default" +} + +if { ![info exists modifiable_p] } { + set modifiable_p 1 +} + +array set trigger_type_pretty_array { + user "" + automatic Auto + message Message + time Time +} + +db_multirow transitions transtitions { + select t.sort_order, + t.transition_key, + t.transition_name, + t.trigger_type, + '' as trigger_type_pretty, + t.role_key, + r.role_name, + '' as delete_url, + '' as edit_url, + '' as role_edit_url + from wf_transitions t, wf_roles r + where t.workflow_key = :workflow_key + and r.workflow_key (+) = t.workflow_key + and r.role_key (+) = t.role_key + order by t.sort_order +} { + # For some reason we seem to need to ns_urlencode the whole thing again when we use it in a javascript thing + if { $modifiable_p } { + set delete_url [ad_quotehtml "javascript:if(confirm('Are you sure you want to delete this transition?'))location.href='task-delete?[export_vars -url {workflow_key transition_key return_url}]'"] + } + set edit_url "task-edit?[export_vars -url {workflow_key transition_key return_url}]" + set role_edit_url "role-edit?[export_vars -url {workflow_key role_key return_url}]" + set trigger_type_pretty $trigger_type_pretty_array($trigger_type) +} + +set transition_add_url "task-add?[export_vars -url {workflow_key return_url}]" + +ad_return_template + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/transitions-table.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/transitions-table.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/transitions-table.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,25 @@ + + + + + + + select t.sort_order, + t.transition_key, + t.transition_name, + t.trigger_type, + '' as trigger_type_pretty, + t.role_key, + r.role_name, + '' as delete_url, + '' as edit_url, + '' as role_edit_url + from wf_transitions t left outer join wf_roles r on (r.workflow_key = t.workflow_key and r.role_key = t.role_key) + where t.workflow_key = :workflow_key + order by t.sort_order + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/up.gif =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/up.gif,v diff -u Binary files differ Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/workflow-graph.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/workflow-graph.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/workflow-graph.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1 @@ +@workflow_img_tag@ Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/workflow-graph.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/workflow-graph.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/workflow-graph.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,52 @@ +# +# Display the workflow process graphically +# +# Expects: +# workflow_key +# size (optional) +# Data sources +# workflow_img_tag +# + +##### +# +# Add marking to the graph +# +##### + +set workflow_info [wf_get_workflow_net $workflow_key] +array set workflow $workflow_info +wf_decorate_workflow workflow + +db_release_unused_handles + +##### +# +# Create the workflow gif +# +##### + +if { [wf_graphviz_installed_p] } { + + if { ![info exists size] } { + set size {} + } + + set dot_text [wf_generate_dot_representation -size $size workflow] + + set tmpfile [wf_graphviz_dot_exec -to_file -output gif $dot_text] + + set width_and_height "" + if { ![catch { set image_size [ns_gifsize $tmpfile] } error] } { + if { ![empty_string_p $image_size] } { + set width_and_height "width=[lindex $image_size 0] height=[lindex $image_size 1]" + } + } + + ad_set_client_property wf wf_net_tmpfile $tmpfile + + set workflow_img_tag "\"Graphical" +} else { + set workflow_img_tag "" +} + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/workflow-roles.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/workflow-roles.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/workflow-roles.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,11 @@ + +@workflow.pretty_name@ + +

    @workflow.pretty_name@ Roles

    +@context_bar@ + +
    + + + +
    Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/workflow-roles.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/workflow-roles.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/workflow-roles.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,37 @@ +# /packages/acs-workflow/www/admin/workflow-roles.tcl +ad_page_contract { + Display roles for a workflow + + @author Jesse Koontz [jkoontz@arsdigita.com] + @creation-date Thu Jan 25 09:38:08 2001 + @cvs-id $Id: workflow-roles.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +} { + workflow_key:notnull +} -properties { + workflow:onerow + context_bar + workflow_roles:multirow +} -validate { + workflow_exists -requires {workflow_key} { + if { 0 == [db_string workflow_exists " + select count(*) from wf_workflows + where workflow_key = :workflow_key"] } { + ad_complain "You seem to have specified a nonexistent workflow." + } + } +} + +set return_url "[ns_conn url]?[export_vars -url {workflow_key}]" + +db_1row workflow { + select w.workflow_key, + t.pretty_name + from wf_workflows w, + acs_object_types t + where w.workflow_key = :workflow_key + and w.workflow_key = t.object_type +} -column_array workflow + +set context_bar [ad_context_bar [list "workflow?[export_vars -url {workflow_key}]" "$workflow(pretty_name)"] "Workflow Roles"] + +ad_return_template Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/workflow-roles.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/workflow-roles.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/workflow-roles.xql 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,27 @@ + + + + + + + select count(*) from wf_workflows + where workflow_key = :workflow_key + + + + + + + + select w.workflow_key, + t.pretty_name + from wf_workflows w, + acs_object_types t + where w.workflow_key = :workflow_key + and w.workflow_key = t.object_type + + + + + + Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/workflow-tabs.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/workflow-tabs.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/workflow-tabs.adp 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + +
      @tabs.name@  @tabs.name@  
    + + + + +
    +
    +
    Index: openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/workflow-tabs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/workflow-tabs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/acs-workflow/www/admin/workflow-tabs.tcl 19 Nov 2001 18:11:03 -0000 1.1 @@ -0,0 +1,30 @@ +# +# Tabs for workflow-page +# +# Input: +# tab +# workflow_key +# +# Data sources: +# tabs:multirow name url +# +# Author: Lars Pind (lars@pinds.com) +# Creation-date: Feb 26, 2001 +# Cvs-id: $Id: workflow-tabs.tcl,v 1.1 2001/11/19 18:11:03 neophytosd Exp $ +# + +template::multirow create tabs name key url +foreach loop_tab { + { Home home } + { Transitions process } + { Attributes attributes } + { Roles roles } + { Panels panels } + { Assignments assignments } +} { + template::multirow append tabs [lindex $loop_tab 0] [lindex $loop_tab 1] "workflow?[export_vars -url {workflow_key {tab {[lindex $loop_tab 1]}}}]" +} + +# { Timing timing } +# { Actions actions } +