Index: openacs-4/packages/workflow/workflow.info
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/workflow.info,v
diff -u -N -r1.1 -r1.2
--- openacs-4/packages/workflow/workflow.info 10 Jan 2003 13:37:46 -0000 1.1
+++ openacs-4/packages/workflow/workflow.info 14 Jan 2003 15:08:54 -0000 1.2
@@ -30,12 +30,17 @@
+
+
+
+
+
Index: openacs-4/packages/workflow/sql/postgresql/workflow-procedural-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/sql/postgresql/workflow-procedural-create.sql,v
diff -u -N -r1.1 -r1.2
--- openacs-4/packages/workflow/sql/postgresql/workflow-procedural-create.sql 10 Jan 2003 13:38:15 -0000 1.1
+++ openacs-4/packages/workflow/sql/postgresql/workflow-procedural-create.sql 14 Jan 2003 15:09:07 -0000 1.2
@@ -11,13 +11,24 @@
-- Workflow level, Generic Model
---------------------------------
+create function workflow__delete (integer)
+returns integer as '
+declare
+ delete_workflow_id alias for $1;
+begin
+ select acs_object__delete(delete_workflow_id);
+
+ return 0;
+end;' language 'plpgsql';
+
+
-- Function for creating a workflow
create function workflow__new (varchar, -- short_name
varchar, -- pretty_name
integer, -- object_id
varchar, -- object_type
integer, -- creation_user
- integer, -- creation_ip
+ varchar, -- creation_ip
integer -- context_id
)
returns integer as '
@@ -34,7 +45,7 @@
begin
-- Instantiate the ACS Object super type with auditing info
v_workflow_id := acs_object__new(null,
- ''workflow_new'',
+ ''workflow_lite'',
now(),
p_creation_user,
p_creation_ip,
@@ -45,7 +56,9 @@
insert into workflows
(workflow_id, short_name, pretty_name, object_id, object_type)
values
- (v_workflow_id, p_short_name, p_pretty_name, p_object_id, p_object_type)
+ (v_workflow_id, p_short_name, p_pretty_name, p_object_id, p_object_type);
+
+ return v_workflow_id;
end;
' language 'plpgsql';
Index: openacs-4/packages/workflow/sql/postgresql/workflow-procedural-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/sql/postgresql/workflow-procedural-drop.sql,v
diff -u -N -r1.1 -r1.2
--- openacs-4/packages/workflow/sql/postgresql/workflow-procedural-drop.sql 10 Jan 2003 13:38:15 -0000 1.1
+++ openacs-4/packages/workflow/sql/postgresql/workflow-procedural-drop.sql 14 Jan 2003 15:09:07 -0000 1.2
@@ -12,11 +12,12 @@
---------------------------------
-- Drop all functions
-drop function workflow__new (varchar, -- short_name
+drop function workflow__delete (integer);
+drop function workflow__new (varchar, -- short_name
varchar, -- pretty_name
integer, -- object_id
varchar, -- object_type
integer, -- creation_user
- integer, -- creation_ip
+ varchar, -- creation_ip
integer -- context_id
);
Index: openacs-4/packages/workflow/sql/postgresql/workflow-service-contracts-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/sql/postgresql/workflow-service-contracts-create.sql,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/workflow/sql/postgresql/workflow-service-contracts-create.sql 14 Jan 2003 15:09:07 -0000 1.1
@@ -0,0 +1,70 @@
+--
+-- Workflow Service Contracts
+--
+-- @author Lars Pind (lars@collaboraid.biz)
+-- @version $Id: workflow-service-contracts-create.sql,v 1.1 2003/01/14 15:09:07 peterm Exp $
+--
+-- GNU GPL v2
+--
+
+--
+-- The service contract for workflows
+--
+
+create function inline_1()
+returns integer as '
+DECLARE
+BEGIN
+ PERFORM acs_sc_contract__new (
+ ''NotificationType'',
+ ''Notification Type''
+ );
+
+ PERFORM acs_sc_msg_type__new (
+ ''NotificationType.GetURL.InputType'',
+ ''object_id:integer''
+ );
+
+ PERFORM acs_sc_msg_type__new (
+ ''NotificationType.GetURL.OutputType'',
+ ''url:string''
+ );
+
+ PERFORM acs_sc_operation__new (
+ ''NotificationType'',
+ ''GetURL'',
+ ''gets the URL for an object in this notification type'',
+ ''f'',
+ 1,
+ ''NotificationType.GetURL.InputType'',
+ ''NotificationType.GetURL.OutputType''
+ );
+
+ PERFORM acs_sc_msg_type__new (
+ ''NotificationType.ProcessReply.InputType'',
+ ''reply_id:integer''
+ );
+
+ PERFORM acs_sc_msg_type__new (
+ ''NotificationType.ProcessReply.OutputType'',
+ ''success_p:boolean''
+ );
+
+ PERFORM acs_sc_operation__new (
+ ''NotificationType'',
+ ''ProcessReply'',
+ ''Process a single reply'',
+ ''f'',
+ 1,
+ ''NotificationType.ProcessReply.InputType'',
+ ''NotificationType.ProcessReply.OutputType''
+ );
+
+ return (0);
+
+END;
+' language 'plpgsql';
+
+select inline_1();
+drop function inline_1();
+
Index: openacs-4/packages/workflow/sql/postgresql/workflow-tables-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/sql/postgresql/workflow-tables-create.sql,v
diff -u -N -r1.1 -r1.2
--- openacs-4/packages/workflow/sql/postgresql/workflow-tables-create.sql 10 Jan 2003 13:38:15 -0000 1.1
+++ openacs-4/packages/workflow/sql/postgresql/workflow-tables-create.sql 14 Jan 2003 15:09:07 -0000 1.2
@@ -14,15 +14,15 @@
---------------------------------
-- Create the workflow object type
--- We use workflow_new rather than just workflow
+-- We use workflow_lite rather than just workflow
-- to avoid a clash with the old workflow package acs-workflow
create function inline_0 ()
returns integer as '
begin
PERFORM acs_object_type__create_type (
- ''workflow_new'',
- ''New Workflow'',
- ''New Workflows'',
+ ''workflow_lite'',
+ ''Workflow Lite'',
+ ''Workflow Lites'',
''acs_object'',
''workflows'',
''workflow_id'',
@@ -37,6 +37,11 @@
select inline_0 ();
drop function inline_0 ();
+-- A generic table for any kind of workflow implementation
+-- Currently, the table only holds FSM workflows but when
+-- other types of workflows are added we will add a table
+-- to hold workflow_types and reference that table from
+-- this workflows table.
create table workflows (
workflow_id integer
constraint workflows_pk
@@ -108,9 +113,7 @@
not null
);
-create sequence t_wf_workflow_roles_seq;
-create view wf_workflow_roles_seq as
-select nextval('t_wf_workflow_roles_seq') as nextval;
+create sequence workflow_roles_seq;
-- Static role-party map
create table workflow_role_default_parties (
@@ -195,12 +198,11 @@
assigned_role integer
constraint workflow_actions_assigned_role_fk
references workflow_roles(role_id)
- on delete set null
+ on delete set null,
+ always_enabled_p bool default 'f'
);
-create sequence t_wf_workflow_actions_seq;
-create view wf_workflow_actions_seq as
-select nextval('t_wf_workflow_actions_seq') as nextval;
+create sequence workflow_actions_seq;
-- Determines which roles are allowed to take certain actions
create table workflow_action_allowed_roles (
@@ -261,6 +263,20 @@
primary key (action_id, acs_sc_impl_id)
);
+create table workflow_initial_action (
+ workflow_id integer
+ constraint workflow_initial_action_pk
+ primary key
+ constraint workflow_initial_action_wf_fk
+ references workflows(workflow_id)
+ on delete cascade,
+ action_id integer
+ constraint workflow_initial_action_act_fk
+ references workflow_actions(action_id)
+ on delete cascade
+);
+
+
---------------------------------
-- Workflow level, Finite State Machine Model
---------------------------------
@@ -278,6 +294,7 @@
sort_order integer
constraint workflow_fsm_states_sort_order_nn
not null,
+ -- The state with the lowest sort order is the initial state
short_name varchar(100)
constraint workflow_fsm_states_short_name_nn
not null,
@@ -286,24 +303,21 @@
not null
);
-create sequence t_wf_workflow_fsm_states_seq;
-create view wf_workflow_fsm_states_seq as
-select nextval('t_wf_workflow_fsm_states_seq') as nextval;
+create sequence workflow_fsm_states_seq;
create table workflow_fsm_actions (
action_id integer
constraint workflow_fsm_actions_pk
- primary key
- constraint workflow_fsm_actions_action_id_fk
- references workflow_actions(action_id)
- on delete cascade,
+ primary key,
new_state integer
constraint workflow_fsm_actions_new_state_fk
references workflow_fsm_states(state_id)
on delete set null
-- can be null
);
+-- If an action is enabled in all states it won't have any entries in this table
+-- it is enabled in all states
create table workflow_fsm_action_enabled_in_states (
action_id integer
constraint workflow_fsm_action_enabled_in_states_action_id_nn
@@ -319,24 +333,12 @@
on delete cascade
);
-create table workflow_fsm (
- workflow_id integer
- constraint workflow_fsm_pk
- primary key
- constraint workflow_fsm_workflow_id_fk
- references workflows(workflow_id)
- on delete cascade,
- initial_state integer
- constraint workflow_fsm_initial_state_nn
- not null
- constraint workflow_fsm_initial_state_fk
- references workflow_fsm_states(state_id)
-);
-
---------------------------------
-- Case level, Generic Model
---------------------------------
+create sequence workflow_cases_seq;
+
create table workflow_cases (
case_id integer
constraint workflow_cases_pk
@@ -361,6 +363,8 @@
-- the object which this case is about, e.g. the acs-object for a bug-tracker bug
);
+create sequence workflow_case_log_seq;
+
create table workflow_case_log (
entry_id integer
constraint workflow_case_log_pk
@@ -435,8 +439,6 @@
references workflow_cases(case_id)
on delete cascade,
current_state integer
- constraint workflow_case_fsm_state_id_nn
- not null
constraint workflow_case_fsm_state_id_fk
references workflow_fsm_states(state_id)
on delete cascade
Index: openacs-4/packages/workflow/sql/postgresql/workflow-tables-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/sql/postgresql/workflow-tables-drop.sql,v
diff -u -N -r1.1 -r1.2
--- openacs-4/packages/workflow/sql/postgresql/workflow-tables-drop.sql 10 Jan 2003 13:38:15 -0000 1.1
+++ openacs-4/packages/workflow/sql/postgresql/workflow-tables-drop.sql 14 Jan 2003 15:09:07 -0000 1.2
@@ -17,7 +17,7 @@
row record;
begin
for row in select object_id from acs_objects
- where object_type = ''workflow_new''
+ where object_type = ''workflow_lite''
loop
perform acs_object__delete(row.object_id);
end loop;
@@ -31,7 +31,7 @@
create function inline_0 ()
returns integer as '
begin
- perform acs_object_type__drop_type(''workflow_new'', ''t'');
+ perform acs_object_type__drop_type(''workflow_lite'', ''t'');
return 1;
end;' language 'plpgsql';
@@ -44,9 +44,9 @@
drop table workflow_case_log_data;
drop table workflow_case_log;
drop table workflow_cases;
-drop table workflow_fsm;
drop table workflow_fsm_action_enabled_in_states;
drop table workflow_fsm_actions;
+drop table workflow_initial_action;
drop table workflow_fsm_states;
drop table workflow_action_side_effects;
drop table workflow_action_privileges;
@@ -59,10 +59,9 @@
drop table workflow_side_effects;
drop table workflows;
--- Drop all sequences and their views
-drop sequence t_wf_workflow_roles_seq;
-drop view wf_workflow_roles_seq;
-drop sequence t_wf_workflow_actions_seq;
-drop view wf_workflow_actions_seq;
-drop sequence t_wf_workflow_fsm_states_seq;
-drop view wf_workflow_fsm_states_seq;
+-- Drop sequences
+drop sequence workflow_roles_seq;
+drop sequence workflow_actions_seq;
+drop sequence workflow_fsm_states_seq;
+drop sequence workflow_cases_seq;
+drop sequence workflow_case_log_seq;
Index: openacs-4/packages/workflow/tcl/action-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/tcl/action-procs.tcl,v
diff -u -N -r1.1 -r1.2
--- openacs-4/packages/workflow/tcl/action-procs.tcl 10 Jan 2003 13:38:37 -0000 1.1
+++ openacs-4/packages/workflow/tcl/action-procs.tcl 14 Jan 2003 15:09:16 -0000 1.2
@@ -7,29 +7,41 @@
@cvs-id $Id$
}
-namespace eval ::workflow::action {}
+namespace eval workflow::action {}
+namespace eval workflow:::action::fsm {}
-ad_proc -public ::workflow::action::add {
+#####
+#
+# workflow::action namespace
+#
+#####
+
+ad_proc -public workflow::action::add {
{-workflow_id:required}
+ {-sort_order {}}
{-short_name:required}
{-pretty_name:required}
{-pretty_past_tense {}}
{-assigned_role {}}
{-allowed_roles {}}
{-privileges {}}
+ {-always_enabled_p f}
} {
- This procedure should never be invoked from application code. Instead use
+ This procedure is normally not invoked from application code. Instead
a procedure for a certain workflow implementation, such as for example
- workflow::fsm::action::add for Finite State Machine workflows.
+ workflow::fsm::action::add (for Finite State Machine workflows), is used.
@param workflow_id The id of the FSM workflow to add the action to
@param short_name Short name of the action for use in source code.
Should be on Tcl variable syntax.
@param pretty_name Human readable name of the action for use in UI.
@param pretty_past_tense Past tense of pretty name
- @param assigned_role Users in this role are expected (obliged) to take
+ @param assigned_role The name of an assigned role. Users in this
+ role are expected (obliged) to take
the action.
- @param allowed_roles Users in these roles are allowed to take the action.
+ @param allowed_roles A list of role names. Users in these roles are
+ allowed to take the action.
+
@param privileges Users with these privileges on the object
treated by the workflow (i.e. a bug in the
Bug Tracker) will be allowed to take this
@@ -43,7 +55,16 @@
} {
db_transaction {
# Insert basic action info
- set action_id [db_nextval "wf_workflow_fsm_actions_seq"]
+ if { [empty_string_p $sort_order] } {
+ set sort_order [workflow::default_sort_order -workflow_id $workflow_id workflow_actions]
+ }
+ set action_id [db_nextval "workflow_actions_seq"]
+ if { [empty_string_p $assigned_role] } {
+ set assigned_role_id [db_null]
+ } else {
+ set assigned_role_id [workflow::role::get_id -workflow_id $workflow_id \
+ -short_name $assigned_role]
+ }
db_dml insert_action {}
# Record which roles are allowed to take action
@@ -59,3 +80,64 @@
return $action_id
}
+
+ad_proc -public workflow::action::get_assigned_role {
+ {-action_id:required}
+} {
+ Return the assigned role of the given action
+ @param action_id The action_id of the action.
+ @return role_id of the assigned role.
+} {
+ return [db_string select_assigned_role {}]
+}
+
+ad_proc -public workflow::action::get_allowed_roles {
+ {-action_id:required}
+} {
+ Return the assigned role of the given action
+ @param action_id The action_id of the action.
+ @return List of role_id of the allowed roles
+} {
+ return [db_list select_allowed_roles {}]
+}
+
+ad_proc -public workflow::action::get_privileges {
+ {-action_id:required}
+} {
+ Return the assigned role of the given action
+ @param action_id The action_id of the action.
+ @return List of privileges that give permission to do this action
+} {
+ return [db_list select_privileges {}]
+}
+
+ad_proc -public workflow::action::get_id {
+ {-workflow_id:required}
+ {-short_name:required}
+} {
+ Return the action_id of the action with the given short_name in the given workflow.
+
+ @param workflow_id The ID of the workflow
+ @param short_name The short_name of the action
+ @return action_id of the desired action, or the empty string if it can't be found.
+} {
+ return [db_string select_action_id {} -default {}]
+}
+
+
+
+#####
+#
+# workflow::action::fsm
+#
+#####
+
+ad_proc -public workflow::action::fsm::get_new_state {
+ {-action_id:required}
+} {
+ Return the new state for an action
+ @param action_id The action_id of the action.
+ @return The new state after executing this action, or the empty string if the action doesn't change the state.
+} {
+ return [db_string select_new_state {} -default {}]
+}
Index: openacs-4/packages/workflow/tcl/action-procs.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/tcl/action-procs.xql,v
diff -u -N -r1.1 -r1.2
--- openacs-4/packages/workflow/tcl/action-procs.xql 10 Jan 2003 13:38:37 -0000 1.1
+++ openacs-4/packages/workflow/tcl/action-procs.xql 14 Jan 2003 15:09:16 -0000 1.2
@@ -1,30 +1,78 @@
-
+
- insert into workflow_actions
- (action_id, workflow_id, sort_order, short_name,
- pretty_name, pretty_past_tense, assigned_role)
- values (:action_id, :workflow_id, :sort_order, :short_name,
- :pretty_name, :pretty_past_tense, :assigned_role)
-
-
-
-
-
insert into workflow_action_allowed_roles
- (action_id, role_id)
- values (:action_id, :allowed_role)
+ select :action_id,
+ (select role_id
+ from workflow_roles
+ where workflow_id = :workflow_id
+ and short_name = :allowed_role) as role_id
-
+
insert into workflow_action_privileges
(action_id, privilege)
values (:action_id, :privilege)
+
+
+ select assigned_role
+ from workflow_actions
+ where action_id = :action_id
+
+
+
+
+
+ select role_id
+ from workflow_action_allowed_roles
+ where action_id = :action_id
+
+
+
+
+
+ select privilege
+ from workflow_action_privileges
+ where action_id = :action_id
+
+
+
+
+
+ select action_id
+ from workflow_actions
+ where workflow_id = :workflow_id
+ and short_name = :short_name
+
+
+
+
+
+ insert into workflow_actions
+ select :action_id,
+ :workflow_id,
+ :sort_order,
+ :short_name,
+ :pretty_name,
+ :pretty_past_tense,
+ :assigned_role_id,
+ :always_enabled_p
+
+
+
+
+
+ select new_state
+ from workflow_fsm_actions a
+ where action_id = :action_id
+
+
+
Index: openacs-4/packages/workflow/tcl/case-procs-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/tcl/case-procs-postgresql.xql,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/workflow/tcl/case-procs-postgresql.xql 14 Jan 2003 15:09:16 -0000 1.1
@@ -0,0 +1,15 @@
+
+
+ postgresql7.2
+
+
+
+ select state_id
+ from workflow_fsm_states
+ where workflow_id = :workflow_id
+ order by sort_order
+ limit 1
+
+
+
+
Index: openacs-4/packages/workflow/tcl/case-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/tcl/case-procs.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/workflow/tcl/case-procs.tcl 14 Jan 2003 15:09:16 -0000 1.1
@@ -0,0 +1,474 @@
+ad_library {
+ Procedures in the case namespace.
+
+ @creation-date 13 January 2003
+ @author Lars Pind (lars@collaboraid.biz)
+ @author Peter Marklund (peter@collaboraid.biz)
+ @cvs-id $Id: case-procs.tcl,v 1.1 2003/01/14 15:09:16 peterm Exp $
+}
+
+namespace eval workflow::case {}
+namespace eval workflow::case::fsm {}
+namespace eval workflow::case::action {}
+namespace eval workflow::case::action::fsm {}
+
+#####
+#
+# workflow::case
+#
+#####
+
+ad_proc -public workflow::case::insert {
+ {-workflow_id:required}
+ {-object_id:required}
+} {
+ Start a new case for this workflow and object
+
+ @param case_object_id The object_id which the case is about
+ @param workflow_short_name The short_name of the workflow.
+ @return The case_id of the case. Returns the empty string if no case could be found.
+
+ @author Lars Pind (lars@collaboraid.biz)
+} {
+ set case_id [db_nextval "workflow_cases_seq"]
+
+ db_transaction {
+ # Create the case
+ db_dml insert_case {}
+
+ # Initialize the FSM state to NULL
+ db_dml insert_case_fsm {}
+ }
+
+ return $case_id
+}
+
+ad_proc -public workflow::case::new {
+ {-workflow_id:required}
+ {-object_id:required}
+ {-comment:required}
+ {-comment_format:required}
+ {-user_id}
+} {
+ Start a new case for this workflow and object
+
+ @param case_object_id The object_id which the case is about
+ @param workflow_short_name The short_name of the workflow.
+ @return The case_id of the case. Returns the empty string if no case could be found.
+
+ @author Lars Pind (lars@collaboraid.biz)
+} {
+ if { ![exists_and_not_null user_id] } {
+ set user_id [ad_conn user_id]
+ }
+
+ db_transaction {
+ # Insert the case
+ set case_id [insert -workflow_id $workflow_id -object_id $object_id]
+
+ # Execute the initial action
+ workflow::case::action::execute \
+ -case_id $case_id \
+ -action_id [get_initial_action -workflow_id $workflow_id] \
+ -comment $comment \
+ -comment_format $comment_format \
+ -user_id $user_id \
+ -no_check
+ }
+
+ return $case_id
+}
+
+ad_proc -public workflow::case::get_case_id {
+ {-case_object_id:required}
+ {-workflow_short_name:required}
+} {
+ Gets the case_id from the object_id which the case is about,
+ along with the short_name of the workflow.
+
+ @param case_object_id The object_id which the case is about
+ @param workflow_short_name The short_name of the workflow.
+ @return The case_id of the case. Returns the empty string if no case could be found.
+
+ @author Lars Pind (lars@collaboraid.biz)
+} {
+ set found_p [db_0or1row select_case_id {}]
+ if { $found_p } {
+ return $case_id
+ } else {
+ return {}
+ }
+}
+
+ad_proc -public workflow::case::get_object_id {
+ {-case_id:required}
+} {
+ Gets the object_id from the case.
+
+ @param case_id The case_id.
+ @return The object_id of the case.
+
+ @author Lars Pind (lars@collaboraid.biz)
+} {
+ return [db_string select_object_id {}]
+}
+
+ad_proc -public workflow::case::get_user_roles {
+ {-case_id:required}
+ -user_id
+} {
+ Get the roles which this user is assigned to
+of
+ @param case_id The ID of the case.
+ @param user_id The user_id of the user for which you want to know the roles.
+ @return A list of role_id's of the roles which the user is assigned to in this case.
+
+ @author Lars Pind (lars@collaboraid.biz)
+} {
+ if { ![exists_and_not_null user_id] } {
+ set user_id [ad_conn user_id]
+ }
+ return [db_list select_user_roles {}]
+}
+
+ad_proc -public workflow::case::get_enabled_actions {
+ {-case_id:required}
+} {
+ Get the currently enabled actions, based on the state of the case
+
+ @param case_id The ID of the case.
+ @return A list of action_id's of the actions which are currently enabled
+
+ @author Lars Pind (lars@collaboraid.biz)
+} {
+ set action_ids [db_list select_enabled_actions {}]
+ return $action_ids
+}
+
+ad_proc -public workflow::case::get_user_actions {
+ {-case_id:required}
+ -user_id
+} {
+ Get the currently enabled actions, which the user has permission
+ to execute.
+
+ @param case_id The ID of the case.
+ @return A list of action_id's of the actions which are currently enabled
+
+ @author Lars Pind (lars@collaboraid.biz)
+} {
+ if { ![exists_and_not_null user_id] } {
+ set user_id [ad_conn user_id]
+ }
+
+ set action_ids [list]
+
+ foreach action_id [get_enabled_actions -case_id $case_id] {
+ if { [workflow::case::action::permission_p -case_id $case_id -action_id $action_id -user_id $user_id] } {
+ lappend action_ids $action_id
+ }
+ }
+
+ return $action_ids
+}
+
+ad_proc -public workflow::case::assign_roles {
+ {-case_id:required}
+} {
+ Find out which roles are assigned to currently enabled actions.
+ If any of these currently have zero assignees, run the default
+ assignment process.
+
+ @param case_id the ID of the case.
+
+ @author Lars Pind (lars@collaboraid.biz)
+} {
+ set role_id_list [list]
+
+ foreach action_id [get_enabled_actions -case_id $case_id] {
+ set role_id [workflow::action::get_assigned_role -action_id $action_id]
+ if { [lsearch $role_id_list $role_id] == -1 } {
+ lappend role_id_list $role_id
+ }
+ }
+
+ foreach role_id $role_id_list {
+ set num_assignees [db_string select_num_assignees {}]
+
+ if { $num_assignees == 0 } {
+ workflow::case::role::set_default_assignees -case_id $case_id -role_id $role_id
+ }
+ }
+}
+
+
+
+
+
+#####
+#
+# workflow::case::role namespace
+#
+#####
+
+ad_proc -public workflow::case::role::set_default_assignees {
+ {-case_id:required}
+ {-role_id:required}
+} {
+ Find the default assignee for this role.
+
+ @param case_id the ID of the case.
+ @param role_id the ID of the role to assign.
+
+ @author Lars Pind (lars@collaboraid.biz)
+} {
+ set contract_name [workflow::service_contract::role_default_assignee]
+
+ set object_id [workflow::case::get_object_id -case_id $case_id]
+
+ db_foreach select_assignment_rules {} {
+
+ # Run the service contract
+ set party_id_list [acs_sc_call $contract_name "GetAssignees" [list $case_id $object_id $role_id] $impl_name]
+
+ if { [llength $party_id_list] != 0 } {
+ foreach party_id $party_id_list {
+ assignee_insert -case_id $case_id -role_id $role_id -party_id $party_id
+ }
+ # We stop when the first callback returned something
+ break
+ }
+ }
+}
+
+ad_proc -public workflow::case::role::assignee_insert {
+ {-case_id:required}
+ {-role_id:required}
+ {-party_id:required}
+} {
+ Insert a new assignee for this role
+
+ @param case_id the ID of the case.
+ @param role_id the ID of the role to assign.
+ @param party_id the ID of party to assign to this role
+
+ @author Lars Pind (lars@collaboraid.biz)
+} {
+ if { [catch {
+ db_dml insert_assignee {}
+ } errMsg] } {
+ set already_assigned_p [db_string already_assigned_p {}]
+ if { !$already_assigned_p } {
+ global errorInfo errorCode
+ error $errMsg $errorInfo $errorCode
+ }
+ }
+}
+
+
+
+#####
+#
+# workflow::case::fsm
+#
+#####
+
+ad_proc -public workflow::case::fsm::get_current_state {
+ {-case_id:required}
+} {
+ Gets the current state_id of this case.
+
+ @param case_id The case_id.
+ @return The state_id of the state which this case is in
+
+ @author Lars Pind (lars@collaboraid.biz)
+} {
+ return [db_string select_current_state {}]
+}
+
+
+
+
+
+#####
+#
+# workflow::case::action
+#
+#####
+
+ad_proc -public workflow::case::action::permission_p {
+ {-case_id:required}
+ {-action_id:required}
+ {-user_id}
+} {
+ Does the user have permission to perform this action. Doesn't
+ check whether the action is enabled.
+
+ @param case_id The ID of the case.
+ @param action_id The ID of the action
+ @param user_id The user.
+ @return true or false.
+
+ @author Lars Pind (lars@collaboraid.biz)
+} {
+ if { ![exists_and_not_null user_id] } {
+ set user_id [ad_conn user_id]
+ }
+
+ set object_id [get_object_id -case_id $case_id]
+ set user_role_ids [get_user_roles -case_id $case_id -user_id $user_id]
+
+ set permission_p 0
+
+ foreach role_id $user_role_ids {
+
+ # Is this an assigned role for this action?
+ set assigned_role [workflow::action::get_assigned_role -action_id $action_id]
+ if { $assigned_role == $role_id } {
+ set permission_p 1
+ break
+ }
+
+ # Is this an allowed role for this action?
+ set allowed_roles [workflow::action::get_allowed_roles -action_id $action_id]
+ if { [lsearch $allowed_roles $role_id] != -1 } {
+ set permission_p 1
+ break
+ }
+ }
+
+ if { !$permission_p } {
+ set privileges [workflow::action::get_privileges -action_id $action_id]
+ foreach privilege $privileges {
+ if { [permission::permission_p -object_id $object_id -privilege $privilege] } {
+ set permission_p 1
+ break
+ }
+ }
+ }
+
+ return $permission_p
+}
+
+ad_proc -public workflow::case::action::enabled_p {
+ {-case_id:required}
+ {-action_id:required}
+} {
+ Is this action currently enabled.
+
+ @param case_id The ID of the case.
+ @param action_id The ID of the action
+ @return true or false.
+
+ @author Lars Pind (lars@collaboraid.biz)
+} {
+ return [db_string select_enabled_p {} -default 0]
+}
+
+ad_proc -public workflow::case::action::available_p {
+ {-case_id:required}
+ {-action_id:required}
+ {-user_id}
+} {
+ Is this action currently enabled and does the user have permission to perform it?
+
+ @param case_id The ID of the case.
+ @param action_id The ID of the action
+ @param user_id The user.
+ @return true or false.
+
+ @author Lars Pind (lars@collaboraid.biz)
+} {
+ if { ![exists_and_not_null user_id] } {
+ set user_id [ad_conn user_id]
+ }
+
+ if {
+ [enabled_p -case_id $case_id -action_id $action_id]
+ &&
+ [permission_p -case_id $case_id -action_id $action_id -user_id $user_id]
+ } {
+ return 1
+ } else {
+ return 0
+ }
+}
+
+ad_proc -public workflow::case::action::execute {
+ {-case_id:required}
+ {-action_id:required}
+ {-comment:required}
+ {-comment_format:required}
+ {-user_id}
+ {-no_check:boolean}
+} {
+ Execute the action
+
+ @param case_id The ID of the case.
+ @param action_id The ID of the action
+ @param comment Comment for the case activity log
+ @param comment_format Format of the comment, according to OpenACS standard text formatting (HM!)
+ @param user_id User_id
+
+ @author Lars Pind (lars@collaboraid.biz)
+} {
+ if { ![exists_and_not_null user_id] } {
+ set user_id [ad_conn user_id]
+ }
+
+ if { !$no_check_p } {
+ if { ![available_p -case_id $case_id -action_id $action_id -user_id $user_id] } {
+ error "This user is not allowed to perform this action at this time."
+ }
+ }
+
+ set new_state [workflow::action::fsm::get_new_state -action_id $action_id]
+
+ db_transaction {
+
+ # Update the workflow state
+ if { ![empty_string_p $new_state] } {
+ db_dml update_fsm_state {}
+ }
+
+ # Insert activity log entry
+ set entry_id [db_nextval "workflow_case_log_seq"]
+ db_dml insert_log_entry {}
+
+ # Assign new enabled roles, if currently unassigned
+ workflow::case::assign_roles -case_id $case_id
+
+ # Fire side-effects, both action ones and workflow ones
+ # ... TODO ...
+
+ # Notifications
+ # ... TODO ...
+ }
+}
+
+
+#####
+#
+# workflow::case::action::fsm
+#
+#####
+
+ad_proc -public workflow::case::action::fsm::new_state {
+ {-case_id:required}
+ {-action_id:required}
+} {
+ The new state which the workflow will be in after this action.
+
+ @param case_id The ID of the case.
+ @param action_id The ID of the action
+ @return The state_id of the new state which the workflow will be in after this action
+
+ @author Lars Pind (lars@collaboraid.biz)
+} {
+ set new_state [workflow::action::fsm::get_new_state -action_id $action_id]
+ if { [empty_string_p $new_state] } {
+ set new_state [workflow::case::fsm::get_current_state -case_id $case_id]
+ }
+ return $new_state
+}
+
Index: openacs-4/packages/workflow/tcl/case-procs.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/tcl/case-procs.xql,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/workflow/tcl/case-procs.xql 14 Jan 2003 15:09:16 -0000 1.1
@@ -0,0 +1,161 @@
+
+
+
+
+
+ insert into workflow_cases (
+ case_id, workflow_id, object_id
+ ) values (
+ :case_id, :workflow_id, :object_id
+ )
+
+
+
+
+
+ insert into workflow_case_fsm (
+ case_id, current_state
+ ) values (
+ :case_id, null
+ )
+
+
+
+
+
+ select case_id
+ from workflow_cases c,
+ workflows w
+ where c.object_id = :case_object_id
+ and w.workflow_id = c.workflow_id
+ and w.short_name = :workflow_short_name
+
+
+
+
+
+ select object_id
+ from workflow_cases c
+ where c.case_id = :case_id
+
+
+
+
+
+ select distinct rpm.role_id
+ from workflow_case_role_party_map rpm,
+ party_approved_member_map pmm
+ where rpm.case_id = :case_id
+ and rpm.party_id = pmm.party_id
+ and pmm.member_id = :user_id
+
+
+
+
+
+ select distinct action_id
+ from (select waeis.action_id
+ from workflow_cases c,
+ workflow_case_fsm cfsm,
+ workflow_fsm_action_enabled_in_states waeis
+ where c.case_id = :case_id
+ and cfsm.case_id = c.case_id
+ and waeis.state_id = cfsm.state_id
+
+ union
+
+ select a.action_id
+ from workflow_cases c,
+ workflow_actions a
+ where c.case_id = :case_id
+ and a.workflow_id = c.workflow_id
+ and a.always_enabled_p = 't'
+ )
+
+
+
+
+
+ select count(*)
+ from workflow_case_role_party_map
+ where case_id = :case_id
+ and role_id = :role_id
+
+
+
+
+
+ select impl.impl_name
+ from workflow_role_assignment_rules r,
+ acs_sc_impls impl,
+ acs_sc_bindings bind,
+ acs_sc_contracts ctr
+ where r.role_id = :role_id
+ and impl.impl_id = r.acs_sc_impl_id
+ and impl.impl_id = bind.impl_id
+ and bind.contract_id = ctr.contract_id
+ and ctr.contract_name = :contract_name
+ order by r.sort_order
+
+
+
+
+
+ insert into workflow_case_role_party_map
+ (case_id, role_id, party_id)
+ values
+ (:case_id, :role_id, :party_id)
+
+
+
+
+
+ select count(*)
+ from workflow_case_role_party_map
+ where case_id = :case_id
+ and role_id = :role_id
+ and party_id = :party_id
+
+
+
+
+
+ select current_state
+ from workflow_case_fsm c
+ where c.case_id = :case_id
+
+
+
+
+
+ select 1
+ from workflow_actions a
+ where a.action_id = :action_id
+ and a.always_enabled_p = 't' or
+ exists (select 1
+ from workflow_actions_enabled_in_states waeis,
+ workflow_cases_fsm c_fsm,
+ where waeis.action_id = a.action_id
+ and c_fsm.case_id = :case_id
+ and waeis.state_id = c_fsm.current_state)
+
+
+
+
+
+ update workflow_case_fsm
+ set current_state = :new_state
+ where case_id = :case_id
+
+
+
+
+
+ insert into workflow_case_log
+ (entry_id, case_id, action_id, user_id, comment, comment_format)
+ values
+ (:entry_id, :case_id, :action_id, :user_id, :comment, :comment_format)
+
+
+
+
Index: openacs-4/packages/workflow/tcl/fsm-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/tcl/Attic/fsm-procs.tcl,v
diff -u -N -r1.1 -r1.2
--- openacs-4/packages/workflow/tcl/fsm-procs.tcl 10 Jan 2003 13:38:37 -0000 1.1
+++ openacs-4/packages/workflow/tcl/fsm-procs.tcl 14 Jan 2003 15:09:16 -0000 1.2
@@ -8,26 +8,36 @@
@cvs-id $Id$
}
-namespace eval ::workflow::fsm {}
+namespace eval workflow::fsm {}
+namespace eval workflow::fsm::state {}
+namespace eval workflow::fsm::action {}
+
+#####
+#
+# workflow::fsm namespace
+#
+#####
-ad_proc -public ::workflow::fsm::set_initial_state {
+ad_proc -public workflow::fsm::delete {
{-workflow_id:required}
- {-initial_state:required}
} {
- Set the initial state of an FSM (Finite State Machine) workflow.
+ Delete an FSM workflow and all data attached to it (states, actions etc.).
- @param workflow_id The id of the workflow to set initial state for.
- @param initial_state The id of the initial state of the workflow
+ @param workflow_id The id of the FSM workflow to delete.
@author Peter Marklund
} {
- db_dml do_insert {}
+ # All FSM data hangs on the generic workflow data and will be deleted on cascade
+ workflow::delete $workflow_id
}
+#####
+#
+# workflow::fsm::state namespace
+#
+#####
-namespace eval ::workflow::fsm::state {}
-
-ad_proc -public ::workflow::fsm::state::add {
+ad_proc -public workflow::fsm::state::add {
{-workflow_id:required}
{-short_name:required}
{-pretty_name:required}
@@ -41,26 +51,36 @@
@author Peter Marklund
} {
- set state_id [db_nextval "wf_workflow_fsm_states_seq"]
+ set state_id [db_nextval "workflow_fsm_states_seq"]
+ if { [empty_string_p $sort_order] } {
+ set sort_order [workflow::default_sort_order -workflow_id $workflow_id workflow_fsm_states]
+ }
+
db_dml do_insert {}
}
-ad_proc -public ::workflow::fsm::state::id_from_short_name {
- short_name
+ad_proc -public workflow::fsm::state::get_id {
+ {-workflow_id:required}
+ {-short_name:required}
} {
Return the id of the state with given short name
+ @param workflow_id The id of the workflow the state belongs to.
@param short_name The name of the state to return the id for.
@author Peter Marklund
} {
- return [db_string id_from_name {}]
+ return [db_string select_id {}]
}
-namespace eval ::workflow::fsm::action {}
+#####
+#
+# workflow::fsm::action namespace
+#
+#####
-ad_proc -public ::workflow::fsm::action::add {
+ad_proc -public workflow::fsm::action::add {
{-workflow_id:required}
{-short_name:required}
{-pretty_name:required}
@@ -78,7 +98,7 @@
@param enabled_states The short names of states in which the
action is enabled.
- @param new_state The state that a workflow case moves to
+ @param new_state The name of the state that a workflow case moves to
when the action is taken. Optional.
@see workflow::action::add
@@ -88,22 +108,29 @@
db_transaction {
# Generic workflow data:
- set action_id [workflow::action::add -workflow_id $workflow_id
- -short_name $short_name
- -pretty_name $pretty_name
- -pretty_past_tense $pretty_past_tense
- -allowed_roles $allowed_roles
- -assigned_role $assigned_role
+ set action_id [workflow::action::add -workflow_id $workflow_id \
+ -short_name $short_name \
+ -pretty_name $pretty_name \
+ -pretty_past_tense $pretty_past_tense \
+ -allowed_roles $allowed_roles \
+ -assigned_role $assigned_role \
-privileges $privileges]
# FSM specific data:
# Record whether the action changes state
+ if { ![empty_string_p $new_state] } {
+ set new_state_id [workflow::fsm::state::get_id -workflow_id $workflow_id \
+ -short_name $new_state]
+ } else {
+ set new_state_id [db_null]
+ }
db_dml insert_fsm_action {}
# Record in which states the action is enabled
foreach state_short_name $enabled_states {
- set enabled_state_id [workflow::fsm::state::id_from_short_name $state_short_name]
+ set enabled_state_id [workflow::fsm::state::get_id -workflow_id $workflow_id \
+ -short_name $state_short_name]
db_dml insert_enabled_state {}
}
}
Index: openacs-4/packages/workflow/tcl/fsm-procs.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/tcl/Attic/fsm-procs.xql,v
diff -u -N -r1.1 -r1.2
--- openacs-4/packages/workflow/tcl/fsm-procs.xql 10 Jan 2003 13:38:37 -0000 1.1
+++ openacs-4/packages/workflow/tcl/fsm-procs.xql 14 Jan 2003 15:09:16 -0000 1.2
@@ -1,14 +1,6 @@
-
-
- insert into workflow_fsm
- (workflow_id, initial_state)
- values (:workflow_id, :initial_state)
-
-
-
insert into workflow_fsm_states
@@ -17,20 +9,21 @@
-
+
select state_id
- from workflow workflow_fsm_states
+ from workflow_fsm_states
where short_name = :short_name
+ and workflow_id = :workflow_id
- insert info workflow_fsm_actions
+ insert into workflow_fsm_actions
(action_id, new_state)
values
- (:action_id, :new_state)
+ (:action_id, :new_state_id)
Index: openacs-4/packages/workflow/tcl/install-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/tcl/install-procs.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/workflow/tcl/install-procs.tcl 14 Jan 2003 15:09:16 -0000 1.1
@@ -0,0 +1,199 @@
+
+ # Array-list with list of lists style
+
+ set operations {
+ GetObjectType {
+ {operation_desc "Get the object type for which this operation is valid."}
+ {inputspec {}}
+ {outputspec {object_type:string}}
+ {nargs 0}
+ {iscachable_p "t"}
+ }
+ GetPrettyName {
+ {operation_desc "Get the pretty name. May contain #...#, so should be localized."}
+ {inputspec {}}
+ {outputspec {pretty_name:string}}
+ {nargs 0}
+ {iscachable_p "t"}
+ }
+ GetAssignees {
+ {operation_desc "Get the assignees as a Tcl list of party_ids, of the default assignees for this case, object, role"}
+ {inputspec {case_id:integer,object_id:integer,role_id:integer}}
+ {outputspec {party_ids:[integer]}}
+ {nargs 3}
+ {iscachable_p "f"}
+ }
+ }
+
+
+
+#####
+#
+# Style one: Lists of lists of lists with potentially unclear semantics
+#
+#####
+
+ad_proc -private workflow::install::create_service_contracts {} {
+
+ # Array-list style
+
+acs_sc::contract::new \
+ -contract_name [workflow::service_contract::role_default_assignee] \
+ -contract_desc "Service contract to get the default assignees for a role from parameters case_id, object_id and role_id" \
+ -operations {
+
+ GetObjectType {
+ operation_desc "Get the object type for which this operation is valid."
+ inputspec {}
+ outputspec {object_type:string}
+ nargs 0
+ iscachable_p "t"
+ }
+
+ GetPrettyName {
+ operation_desc "Get the pretty name. May contain #...#, so should be localized."
+ inputspec {}
+ outputspec {pretty_name:string}
+ nargs 0
+ iscachable_p "t"
+ }
+
+ GetAssignees {
+ operation_desc "Get the assignees as a Tcl list of party_ids, of the default assignees for this case, object, role"
+ inputspec {case_id:integer,object_id:integer,role_id:integer}
+ outputspec {party_ids:[integer]}
+ nargs 3
+ iscachable_p "f"
+ }
+}
+
+}
+
+#####
+#
+# Style two: Using procs in procs with global variables
+#
+#####
+
+ad_proc -private workflow::install::create_service_contracts {} {
+
+acs_sc::contract::new \
+ -contract_name [workflow::service_contract::role_default_assignee] \
+ -contract_desc "Service contract to get the default assignees for a role from parameters case_id, object_id and role_id" \
+ -operations {
+
+ operation \
+ -operation_name GetObjectType \
+ -operation_desc "Get the object type for which this operation is valid." \
+ -inputspec {} \
+ -outputspec {object_type:string} \
+ -nargs 0 \
+ -iscachable_p "t"
+
+ operation \
+ -operation_name GetPrettyName \
+ -operation_desc "Get the pretty name. May contain #...#, so should be localized." \
+ -inputspec {} \
+ -outputspec {pretty_name:string} \
+ -nargs 0 \
+ -iscachable_p "t"
+
+ operation \
+ -operation_name GetAssignees \
+ -operation_desc "Get the assignees as a Tcl list of party_ids, of the default assignees for this case, object, role" \
+ -inputspec {case_id:integer,object_id:integer,role_id:integer} \
+ -outputspec {party_ids:[integer]} \
+ -nargs 3 \
+ -iscachable_p "f"
+}
+
+}
+
+#
+# Corresponding Service Contract Definition API
+#
+
+ad_proc -public acs_sc::contract::new {
+ {-contract_name:required}
+ {-contract_dec {}}
+ {-oprations}
+} {
+ insert -contract_name $contract_name -contract_desc $contract_desc
+
+ if { [exists_and_not_null operations] } {
+
+ namespace eval ::acs_sc::contract::define variable contract_name $contract_name
+
+ namespace eval ::acs_sc::contract::define $operations
+ }
+}
+
+ad_proc -public acs_sc::contract::define::operation {
+ {-operation_name:required}
+ {-operation_desc {}}
+ {-inputspec {}}
+ {-outputspec {}}
+ {-nargs 0}
+ {-iscachable_p "f"}
+} {
+ variable contract_name
+
+ set inputtype "${contract_name}.${operatoin_name}.InputType"
+
+ acs_sc::msg_type::insert \
+ -msg_type_name $inputtype \
+ -msg_type_spec $inputspec
+
+ set outputtype "${contract_name}.${operation_name}.OutputType"
+
+ acs_sc::msg_type::insert \
+ -msg_type_name $outputtype \
+ -msg_type_spec $outputspec
+
+ acs_sc::operation::insert \
+ -contract_name $contract_name \
+ -operation_desc $operation_desc \
+ -inputtype $inputtype \
+ -outputtype $outputtype \
+ -nargs $nargs \
+ -iscachable_p $iscachable_p
+}
+
+
+
+
+#############################################################
+
+
+proc create_service_contracts {} {
+ acs_sc::contract::new DefaultAssignees {
+ operation GetObjectType
+ operation GetPrettyName
+ operation GetAssignees
+ }
+ acs_sc::contract::new SideEffect {
+ operation GetObjectType
+ operation GetPrettyName
+ operation DoSideEffect
+ }
+}
+
+namespace eval acs_sc::contract {}
+namespace eval acs_sc::contract::define {}
+
+proc acs_sc::contract::new { contract_name {operations {}} } {
+ puts "New Contract: $contract_name"
+ if { ![string equal $operations ""] } {
+ puts "Operations:"
+ namespace eval ::acs_sc::contract::define variable contract_name $contract_name
+ namespace eval ::acs_sc::contract::define $operations
+ }
+}
+
+proc acs_sc::contract::define::operation { operation_name } {
+ variable contract_name
+ puts "Operation: ${contract_name}.${operation_name}"
+}
+
+create_service_contracts
+
Index: openacs-4/packages/workflow/tcl/role-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/tcl/role-procs.tcl,v
diff -u -N -r1.1 -r1.2
--- openacs-4/packages/workflow/tcl/role-procs.tcl 10 Jan 2003 13:38:37 -0000 1.1
+++ openacs-4/packages/workflow/tcl/role-procs.tcl 14 Jan 2003 15:09:16 -0000 1.2
@@ -7,23 +7,41 @@
@cvs-id $Id$
}
-namespace eval workflow::role {
+namespace eval workflow::role {}
- ad_proc -public add {
- {-workflow_id:required}
- {-short_name:required}
- {-pretty_name:required}
- } {
- Creates a new role for a certain workflow.
-
- @param workflow_id
- @param short_name
- @param pretty_name
-
- @author Peter Marklund
- } {
- set role_id [db_nextval "wf_workflow_roles_seq"]
+#####
+#
+# workflow::role namespace
+#
+#####
- db_dml do_insert {}
- }
+ad_proc -public workflow::role::add {
+ {-workflow_id:required}
+ {-short_name:required}
+ {-pretty_name:required}
+} {
+ Creates a new role for a certain workflow.
+
+ @param workflow_id
+ @param short_name
+ @param pretty_name
+
+ @author Peter Marklund
+} {
+ set role_id [db_nextval "workflow_roles_seq"]
+
+ db_dml do_insert {}
}
+
+ad_proc -public workflow::role::get_id {
+ {-workflow_id:required}
+ {-short_name:required}
+} {
+ Return the role_id of the role with the given short_name in the given workflow.
+
+ @param workflow_id The ID of the workflow
+ @param short_name The short_name of the role
+ @return role_id of the desired role, or the empty string if it can't be found.
+} {
+ return [db_string select_role_id {} -default {}]
+}
Index: openacs-4/packages/workflow/tcl/role-procs.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/tcl/role-procs.xql,v
diff -u -N -r1.1 -r1.2
--- openacs-4/packages/workflow/tcl/role-procs.xql 10 Jan 2003 13:38:37 -0000 1.1
+++ openacs-4/packages/workflow/tcl/role-procs.xql 14 Jan 2003 15:09:16 -0000 1.2
@@ -10,4 +10,13 @@
+
+
+ select role_id
+ from workflow_roles
+ where workflow_id = :workflow_id
+ and short_name = :short_name
+
+
+
Index: openacs-4/packages/workflow/tcl/workflow-procs-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/tcl/workflow-procs-postgresql.xql,v
diff -u -N -r1.1 -r1.2
--- openacs-4/packages/workflow/tcl/workflow-procs-postgresql.xql 10 Jan 2003 13:38:37 -0000 1.1
+++ openacs-4/packages/workflow/tcl/workflow-procs-postgresql.xql 14 Jan 2003 15:09:16 -0000 1.2
@@ -16,4 +16,10 @@
+
+
+ select acs_object__delete(:workflow_id);
+
+
+
Index: openacs-4/packages/workflow/tcl/workflow-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/tcl/workflow-procs.tcl,v
diff -u -N -r1.1 -r1.2
--- openacs-4/packages/workflow/tcl/workflow-procs.tcl 10 Jan 2003 13:38:37 -0000 1.1
+++ openacs-4/packages/workflow/tcl/workflow-procs.tcl 14 Jan 2003 15:09:16 -0000 1.2
@@ -7,9 +7,20 @@
@cvs-id $Id$
}
-namespace eval ::workflow {}
+namespace eval workflow {}
+namespace eval workflow::service_contract {}
-ad_proc -public ::workflow::add {
+#####
+#
+# workflow namespace
+#
+#####
+
+ad_proc -public workflow::package_key {} {
+ return "workflow"
+}
+
+ad_proc -public workflow::add {
{-short_name:required}
{-pretty_name:required}
{-object_id:required}
@@ -42,5 +53,92 @@
# that sets the scope of the workflow
set context_id $object_id
- db_dml do_insert {}
+ return [db_string do_insert {}]
}
+
+ad_proc -public workflow::delete {
+ {-workflow_id:required}
+} {
+ Delete a generic workflow and all data attached to it (states, actions etc.).
+
+ @param workflow_id The id of the workflow to delete.
+
+ @author Peter Marklund
+} {
+ return [db_string do_delete {}]
+}
+
+ad_proc -public workflow::get_id {
+ {-object_id:required}
+ {-short_name:required}
+} {
+ Get workflow_id by short_name and object_id.
+
+ @param object_id The ID of the object the workflow's for (typically a package instance)
+ @param short_name the short name of the workflow you want
+
+ @author Lars Pind (lars@collaboraid.biz)
+} {
+ return [db_string select_workflow_id {} -default {}]
+}
+
+ad_proc -public workflow::action::get_initial_action {
+ {-workflow_id:required}
+} {
+ Get the action_id of the special 'open' action of a workflow.
+
+ @param workflow_id The ID of the workflow
+ @return action_id of the magic 'open' action
+
+ @author Lars Pind (lars@collaboraid.biz)
+} {
+ return [db_string select_initial_action {}]
+}
+
+ad_proc -private workflow::default_sort_order {
+ {-workflow_id:required}
+ table_name
+} {
+ By default the sort_order will be the highest current sort order plus 1.
+ This reflects the order in which states and actions are added to the
+ workflow starting with 1
+
+ @author Peter Marklund
+} {
+ set sort_order_current \
+ [db_string max_sort_order "select max(sort_order) \
+ from $table_name \
+ where workflow_id = $workflow_id" \
+ -default 0]
+
+ set sort_order [expr $sort_order_current + 1]
+
+ return $sort_order
+}
+
+#####
+#
+# workflow::service_contract
+#
+#####
+
+ad_proc -public workflow::service_contract::role_default_assignee {} {
+ return "Role_DefaultAssignees"
+}
+
+ad_proc -public workflow::service_contract::role_assignee_pick_list {} {
+ return "Role_AssigneePickList"
+}
+
+ad_proc -public workflow::service_contract::role_assignee_subquery {} {
+ return "Role_AssigneeSubQuery"
+}
+
+ad_proc -public workflow::service_contract::action_side_effect {} {
+ return "Action_SideEffect"
+}
+
+ad_proc -public workflow::service_contract::activity_log_format_title {} {
+ return "ActivityLog_FormatTitle"
+}
+
Index: openacs-4/packages/workflow/tcl/workflow-procs.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/tcl/workflow-procs.xql,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/workflow/tcl/workflow-procs.xql 14 Jan 2003 15:09:16 -0000 1.1
@@ -0,0 +1,21 @@
+
+
+
+
+
+ select workflow_id
+ from workflows
+ where object_id = :object_id
+ and short_name = :short_name
+
+
+
+
+
+ select action_id
+ from workflow_initial_action
+ where workflow_id = :workflow_id
+
+
+
+
Index: openacs-4/packages/workflow/tcl/test/workflow-test-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/workflow/tcl/test/workflow-test-procs.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/workflow/tcl/test/workflow-test-procs.tcl 14 Jan 2003 15:09:27 -0000 1.1
@@ -0,0 +1,165 @@
+ad_library {
+ Test cases for the Tcl API of the workflow package. The test cases are based
+ on the acs-automated-testing package.
+
+ @author Peter Marklund
+ @creation-date 10 January 2003
+ @cvs-id $Id: workflow-test-procs.tcl,v 1.1 2003/01/14 15:09:27 peterm Exp $
+}
+
+namespace eval workflow::test {}
+
+ad_proc workflow::test::bug_workflow_name {} {
+ The short name used for the Bug Tracker Bug test
+ workflow. It is assumed this short name will not be
+ present in the system.
+} {
+ return "bug_test"
+}
+
+ad_proc workflow::test::bug_workflow_object_id {} {
+
+} {
+ return [db_string main_site_package_id {select object_id
+ from site_nodes
+ where parent_id is null}]
+}
+
+ad_proc workflow::test::workflow_setup {} {
+ Create a test workflow for the Bug Tracker
+ Bug use case.
+} {
+ #####
+ #
+ # Workflow
+ #
+ #####
+
+ set main_site_package_id [workflow::test::bug_workflow_object_id]
+ # Cannot use bt_bug as we cannot assume Bug Tracker to be installed
+ # TODO: test side_effects?
+ # -side_effects { bug-tracker.FormatLogTitle }
+ set workflow_id [workflow::add \
+ -short_name [workflow::test::bug_workflow_name] \
+ -pretty_name "Bug Test" \
+ -object_id $main_site_package_id \
+ -object_type "acs_object"]
+
+ #####
+ #
+ # Roles
+ #
+ #####
+
+ # TODO: add assignment rules?
+ # -assignment_rules { workflow.CreationUser }
+ workflow::role::add -workflow_id $workflow_id \
+ -short_name "submitter" \
+ -pretty_name "Submitter"
+
+ # TODO: add assignment rules?
+ # -assignment_rules {
+ # bug-tracker.ComponentMaintainer
+ # bug-tracker.ProjectMaintainer
+ # }
+ workflow::role::add -workflow_id $workflow_id \
+ -short_name "assignee" \
+ -pretty_name "Assignee"
+
+ #####
+ #
+ # States
+ #
+ #####
+
+ workflow::fsm::state::add -workflow_id $workflow_id \
+ -short_name "open" \
+ -pretty_name "Open"
+
+ workflow::fsm::state::add -workflow_id $workflow_id \
+ -short_name "resolved" \
+ -pretty_name "Resolved"
+
+ workflow::fsm::state::add -workflow_id $workflow_id \
+ -short_name "closed" \
+ -pretty_name "Closed"
+
+ #####
+ #
+ # Actions
+ #
+ #####
+
+ workflow::fsm::action::add -workflow_id $workflow_id \
+ -short_name "comment" \
+ -pretty_name "Comment" \
+ -pretty_past_tense "Commented" \
+ -allowed_roles { submitter assignee } \
+ -privileges { read }
+
+ workflow::fsm::action::add -workflow_id $workflow_id \
+ -short_name "edit" \
+ -pretty_name "Edit" \
+ -pretty_past_tense "Edited" \
+ -allowed_roles { submitter assignee } \
+ -privileges { write }
+
+ # TODO add side effects?
+ # -side_effects { bug-tracker.CaptureResolutionCode }
+ workflow::fsm::action::add -workflow_id $workflow_id \
+ -short_name "resolve" \
+ -pretty_name "Resolve" \
+ -pretty_past_tense "Resolved" \
+ -assigned_role { assignee } \
+ -enabled_states { open resolved } \
+ -new_state "resolved" \
+ -privileges { write }
+
+ workflow::fsm::action::add -workflow_id $workflow_id \
+ -short_name "close" \
+ -pretty_name "Close" \
+ -pretty_past_tense "Closed" \
+ -assigned_role { submitter } \
+ -enabled_states { resolved } \
+ -new_state "closed" \
+ -privileges { write }
+
+ workflow::fsm::action::add -workflow_id $workflow_id \
+ -short_name "reopen" \
+ -pretty_name "Reopen" \
+ -pretty_past_tense "Closed" \
+ -allowed_roles { submitter } \
+ -enabled_states { resolved closed } \
+ -new_state "open" \
+ -privileges { write }
+}
+
+ad_proc workflow::test::workflow_teardown {} {
+ Delete the Bug Tracker Bug test workflow.
+} {
+ set workflow_id [workflow::get_id -object_id [workflow::test::bug_workflow_object_id] \
+ -short_name [workflow::test::bug_workflow_name]]
+
+ workflow::delete -workflow_id $workflow_id
+}
+
+aa_register_case bugtracker_workflow_create {
+ Test creation and teardown of an FSM workflow.
+
+ @author Peter Marklund
+ @creation-date 10 January 2003
+} {
+ # Make sure to run the teardown proc even if there is an error
+ #set error_p [catch workflow::test::workflow_setup error]
+ workflow::test::workflow_setup
+
+ # Any assertions here?
+
+ workflow::test::workflow_teardown
+
+ # Any assertions here?
+
+ # Report any errors from the setup proc
+ #global errorInfo
+ #aa_false "error during setup: $error - $errorInfo" $error_p
+}