create or replace package library_workflow as function new_workflow_case ( p_object_id in sn_objects.object_id%TYPE, p_creation_date in acs_objects.creation_date%TYPE default sysdate, p_creation_user in acs_objects.creation_user%TYPE, p_creation_ip in acs_objects.creation_ip%TYPE default null, p_publisher_id in sn_objects.publisher_id%TYPE default null ) return integer; procedure delete_workflow_case ( object_id in sn_objects.object_id%TYPE ); function workflow_url ( absolute_p in char default 't' ) return varchar2; function notification_sender ( package_id in apm_packages.package_id%TYPE ) return users.user_id%TYPE; end library_workflow; / show errors create or replace package body library_workflow as function new_workflow_case ( p_object_id in sn_objects.object_id%TYPE, p_creation_date in acs_objects.creation_date%TYPE default sysdate, p_creation_user in acs_objects.creation_user%TYPE, p_creation_ip in acs_objects.creation_ip%TYPE default null, p_publisher_id in sn_objects.publisher_id%TYPE default null ) return integer is v_case_id wf_cases.case_id%TYPE; begin -- create a new case v_case_id := workflow_case.new ( workflow_key => 'library_approval_wf', object_id => p_object_id, creation_user => p_creation_user, creation_ip => p_creation_ip ); -- start the case workflow_case.start_case ( case_id => v_case_id, creation_user => p_creation_user, creation_ip => p_creation_ip ); -- now automatically assign the task to the coordinator. The workflow -- package requires static assignment otherwise. return v_case_id; end new_workflow_case ; procedure delete_workflow_case ( object_id in sn_objects.object_id%TYPE ) is cursor case_cur is select case_id from wf_cases where object_id = object_id; case_rec case_cur%ROWTYPE; begin open case_cur; fetch case_cur into case_rec; -- delete the workflow case that's associated with this object if case_cur%FOUND then workflow_case.delete(case_rec.case_id); end if; close case_cur; end delete_workflow_case ; function workflow_url ( absolute_p in char default 't' ) return varchar2 is v_system_url apm_parameter_values.attr_value%TYPE; cursor node_cur is select sn.node_id from site_nodes sn, apm_packages ap where ap.package_key = 'acs-workflow' and sn.object_id = ap.package_id; node_rec node_cur%ROWTYPE; begin -- try to get the id of the site node that contains acs workflow open node_cur; fetch node_cur into node_rec; if node_cur%NOTFOUND then close node_cur; raise_application_error(-20000, 'ACS Workflow must be mounted'); end if; close node_cur; -- if only relative url is needed if absolute_p <> 't' then return site_node.url(node_rec.node_id); end if; -- since there's only 1 instance of the kernel -- it's ok to use select.. into.. select apv.attr_value into v_system_url from apm_parameter_values apv, apm_parameters ap where ap.package_key = 'acs-kernel' and ap.parameter_name = 'SystemURL' and ap.parameter_id = apv.parameter_id; return v_system_url||site_node.url(node_rec.node_id); end workflow_url; function notification_sender ( package_id in apm_packages.package_id%TYPE ) return users.user_id%TYPE is v_result users.user_id%TYPE; begin select nvl(apm.get_value(notification_sender.package_id,'NotificationSender'),-1) into v_result from dual; return v_result; end notification_sender; end library_workflow; / show errors create or replace package library_callback as procedure assign_task_to_submitter ( task_id in number, custom_arg in varchar2 ); procedure assign_task_to_assignee ( task_id in number, custom_arg in varchar2 ); procedure publish_fire ( case_id in number, transition_key in varchar2, custom_arg in varchar2 ); procedure clarify_fire ( case_id in number, transition_key in varchar2, custom_arg in varchar2 ); procedure review_fire ( case_id in number, transition_key in varchar2, custom_arg in varchar2 ); procedure notification ( 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, sent_p in out char ); procedure notify_admin ( task_id in number, custom_arg in varchar2 ) ; end library_callback; / show errors create or replace package body library_callback as procedure assign_task_to_assignee ( task_id in number, custom_arg in varchar2 ) is v_publisher_id users.user_id%TYPE; v_case_id wf_tasks.case_id%TYPE; v_transition_key wf_tasks.transition_key%TYPE; begin begin -- let's look up the last publisher. select o.publisher_id, wt.case_id, wt.transition_key into v_publisher_id, v_case_id, v_transition_key from sn_objects o, wf_tasks wt, wf_cases wc where wt.task_id = assign_task_to_assignee.task_id and wt.case_id = wc.case_id and wc.object_id = o.object_id and o.publisher_id is not null and (acs_permission.permission_p(o.object_id, o.publisher_id , 'km_publish'))='t'; workflow_case.add_task_assignment(assign_task_to_assignee.task_id, v_publisher_id); workflow_case.add_manual_assignment ( case_id => v_case_id, transition_key => v_transition_key, party_id => v_publisher_id ); exception when no_data_found then -- find the default assignees for this community for v_approval_coordinators in ( select ac.coordinator_id, wt.case_id, wt.transition_key from acs_objects ao, wf_tasks wt,wf_cases wc, approval_coordinators ac where wt.task_id = assign_task_to_assignee.task_id and wt.case_id = wc.case_id and wc.object_id = ao.object_id and ac.package_id = ao.context_id ) loop workflow_case.add_task_assignment(assign_task_to_assignee.task_id, v_approval_coordinators.coordinator_id); workflow_case.add_manual_assignment ( case_id => v_approval_coordinators.case_id, transition_key => v_approval_coordinators.transition_key, party_id => v_approval_coordinators.coordinator_id ); end loop; end; end assign_task_to_assignee; procedure assign_task_to_submitter ( task_id in number, custom_arg in varchar2 ) is cursor object_cur is select ao.creation_user, wt.case_id, wt.transition_key from acs_objects ao, wf_tasks wt,wf_cases wc where wt.task_id = assign_task_to_submitter.task_id and wt.case_id = wc.case_id and wc.object_id = ao.object_id; object_rec object_cur%ROWTYPE; begin -- find the creation user of the object (submitter) open object_cur; fetch object_cur into object_rec; close object_cur; -- assign the task to the object submitter workflow_case.add_task_assignment(assign_task_to_submitter.task_id, object_rec.creation_user); workflow_case.add_manual_assignment ( case_id => object_rec.case_id, transition_key => object_rec.transition_key, party_id => object_rec.creation_user ); end assign_task_to_submitter; procedure publish_fire ( case_id in number, transition_key in varchar2, custom_arg in varchar2 ) is v_journal_id journal_entries.journal_id%TYPE; v_task_id wf_tasks.task_id%TYPE; v_party_from users.user_id%TYPE; v_party_to users.user_id%TYPE; v_author_id users.user_id%TYPE; v_subject varchar2(4000); v_body varchar2(4000); v_request_id integer; v_sent_p char(1); begin select distinct(task_id) into v_task_id from wf_tasks t where case_id = publish_fire.case_id and rownum = 1 order by task_id desc; select ao.creation_user, so.original_author_id into v_party_to, v_author_id from acs_objects ao, wf_cases c, sn_objects so where ao.object_id = c.case_id and c.case_id = publish_fire.case_id and so.object_id = c.object_id; v_party_from := -1; v_subject := 'default'; v_body := 'default'; v_sent_p := 'f'; library_callback.notification ( task_id => v_task_id, custom_arg => 'library_published', party_to => v_party_to, party_from => v_party_from, subject => v_subject, body => v_body, sent_p => v_sent_p ); if v_party_to != v_author_id then library_callback.notification ( task_id => v_task_id, custom_arg => 'library_published', party_to => v_author_id, party_from => v_party_from, subject => v_subject, body => v_body, sent_p => v_sent_p ); end if; v_journal_id := journal_entry.new ( object_id => case_id, action => 'modify', action_pretty => 'Attribute Change', msg => 'Automatic action by the workflow process' ); workflow_case.set_attribute_value ( journal_id => v_journal_id, attribute_name => 'library_object_published', value => 't' ); end publish_fire; procedure clarify_fire ( case_id in number, transition_key in varchar2, custom_arg in varchar2 ) is v_journal_id journal_entries.journal_id%TYPE; begin v_journal_id := journal_entry.new ( object_id => case_id, action => 'modify', action_pretty => 'Attribute Change', msg => 'Automatic action by the workflow process' ); workflow_case.set_attribute_value ( journal_id => v_journal_id, attribute_name => 'library_object_needs_clarification', value => 'f' ); end clarify_fire; procedure review_fire ( case_id in number, transition_key in varchar2, custom_arg in varchar2 ) is v_journal_id journal_entries.journal_id%TYPE; begin v_journal_id := journal_entry.new ( object_id => case_id, action => 'modify', action_pretty => 'Attribute Change', msg => 'Automatic action by the workflow process' ); workflow_case.set_attribute_value ( journal_id => v_journal_id, attribute_name => 'verified', value => 't' ); end review_fire; procedure notification ( 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, sent_p in out char ) is begin select o.creation_user, j.msg into notification.party_from, notification.body from acs_objects o, journal_entries j where o.object_id = j.journal_id and j.journal_id = (select max(j2.journal_id) from journal_entries j2, wf_tasks t, acs_objects o2 where t.case_id = j2.object_id and t.task_id = notification.task_id and o2.object_id = j2.journal_id and o2.creation_user is not null); insert into wf_library_notifications (task_id, template_key, recipient_id, sender_id, body) values (notification.task_id, notification.custom_arg, notification.party_to, notification.party_from, notification.body); sent_p := 't'; end notification; procedure notify_admin ( task_id in number, custom_arg in varchar2 ) is -- uses 2 separate queries to find out who has 'admin' privilege on this package -- because we don't want to join any table with acs_object_party_privilege_map -- unless we absolutely have to (in this case, users table) -- the first query is only used to gather object info and package id cursor object_cur is select o.object_id, o.one_line_description, o.context_id as package_id from sn_objects o, wf_cases wc, wf_tasks wt where wt.task_id = notify_admin.task_id and wc.case_id = wt.case_id and wc.object_id = o.object_id; object_rec object_cur%ROWTYPE; cursor admin_cur is select u.user_id from users u, acs_object_party_privilege_map m where m.object_id = object_rec.package_id and m.party_id = u.user_id and m.privilege = 'admin'; v_request_id integer; begin open object_cur; fetch object_cur into object_rec; close object_cur; for admin_rec in admin_cur loop v_request_id := nt.post_request ( party_from => library_workflow.notification_sender(object_rec.package_id), party_to => admin_rec.user_id, expand_group => 'f', subject => 'Object #'||object_rec.object_id||' -- '||'Assign Object', message => 'Subject: '||object_rec.one_line_description||'To do: '||'Assign Object Manage via: '||library_workflow.workflow_url||'task?task_id='||task_id, max_retries => 3 ); end loop; end notify_admin; end library_callback; / show errors