25.1.9.1.4.4 Accounting for Vacations or Absences

Use a vacation rule procedure to add alternate task participants for absent users.

Sometimes, stakeholders involved in task assignments are out of the office. Your task definition can use a vacation rule procedure to run custom business logic after the APEX engine determines participants using your original Participants configuration. The rule affects both initial task participant assignment, as well as task delegation.

You can also specify a vacation rule procedure at application level. If you do that, a task uses it unless it specifies a more specific rule of its own. You can optionally create the procedure in a PL/SQL package. It needs the following signature using exactly the indicated parameter names, modes, and types, in the given order:
procedure your_vacation_rule (
  p_param    in apex_human_task.t_vacation_rule_input,
  p_result  out apex_human_task.t_vacation_rule_result )

To process the list of existing participants, access the original_participants list from the p_param input record. If any alternative assignees are needed, populate the participant_changes list in the output record. For each participant change you populate the original username, the username who replaces them, and a reason explaining why that is recorded in the task history. The participant changes you return automatically become additional participants on the task.

Tip:

The participant changed reason is logged in the PARTICIPANT_CHANGED_REASON column of the APEX_TASK_HISTORY view and is available among the result columns returned by the GET_TASK_HISTORY function in the APEX_HUMAN_TASK package. This information is not included by default in a generated Task Details page, but is straightforward to add when required.

When configuring an out-of-office assignment handler, specify either:
  • your_vacation_proc, or
  • yourpackage.your_vacation_proc

as the value of the Vacation Procedure property. The following example vacation rule procedure adds SUSAN as an additional approver for DAVID due to some personal time off. In your application, you can read absence assignments from a table, but this code illustrates the fundamentals.

procedure handle_absences(
    p_param   in apex_human_task.t_vacation_rule_input,
    p_result out apex_human_task.t_vacation_rule_result )
is
    l_participant apex_human_task.t_task_participant;
    l_change      apex_human_task.t_task_participant_change;
    --------------------------------------------------------
    function potential_owner(
        p_username in varchar2)
        return apex_human_task.t_task_participant
    is
    begin
        return apex_human_task.t_task_participant(
                apex_human_task.c_task_potential_owner,
                apex_human_task.c_task_identity_type_user,
                p_username);
    end potential_owner;
    --------------------------------------------------------
    function absent_user_cover(
        p_original_username in varchar2,
        p_covering_username in varchar2,
        p_reason            in varchar2)
        return apex_human_task.t_task_participant_change
    is
    begin
        return apex_human_task.t_task_participant_change(
            potential_owner(p_original_username),
            potential_owner(p_covering_username),
            p_reason);
    end absent_user_cover;
begin
    -- Loop over original participants
    for j in 1..p_param.original_participants.count loop
        l_participant := p_param.original_participants(j);
        -- If the participant is DAVID as a potential owner
        if     l_participant.type  = apex_human_task.c_task_potential_owner
           and l_participant.value = 'DAVID'
        then
            -- Add participant change: SUSAN covers for DAVID's personal time off
            p_result.participant_changes(p_result.participant_changes.count + 1) :=
                absent_user_cover('DAVID','SUSAN','Personal Time Off');
            p_result.has_participant_changes := true;
        end if;
    end loop;
end handle_absences;

Caution:

Participant usernames are case-sensitive. If :APP_USER returns DAVID, then use DAVID.