Skip Headers

Agile Product Lifecycle Management SDK Developer Guide - Using APIs Release 9.3.3 E39307-01 |
| Contents

Previous | Next |

# 15 Managing Workflow

Agile has electronic routing, Notification, and signoff capabilities, thus automating the change control process and providing a simplified but powerful Workflow mechanism. With these Workflow features, you can

- Route changes automatically to the users who need to approve or observe the change.

- Send email alerts automatically to approvers and observers to notify them that a change has been routed to them.

- Approve or reject changes online.

- Attach comments to changes.

## 15.1 The Change Control Process

The change control process can vary for each Workflow defined for a routable object. The table below lists the sequences for the default Workflows for each type of routable object. For changes the first four steps in the sequence are identical and only the final step is different.

Workflow | Default sequence
--- | ---
Default Activities | Not Started > In Process > Complete
Default Attachments | Review
Default Audits | Prepared > Initiated > Audited > Issued > Corrected > Validated > Closed
Default CAPAs | Identified > Acknowledged > Investigated > Implemented > Validated > Closed
Default Change Orders | Pending > Submitted > CCB > Released > Implemented
Default Change Requests | Pending > Submitted > CCB > Released > Closed
Default CTOs | Pending> Review > Released > Complete
Default Declarations | Pending > Open to Supplier > Submit to Manager > Review > Released > Implemented
Default Deviations | Pending > Submitted > CCB > Released > Expired
Default Gates | Closed > In Review > Open
Default Manufacturer Orders | Pending > Submitted > CCB > Released > First Article Complete
Default Non-Conformance Reports | Pending > Submitted > Review > Released > Closed
Default Packages | Pending > Submitted > Review > Accepted > Closed
Default Price Change Orders | Pending > Submitted > Price Review > Released > Implemented
Default Problem Reports | Pending > Submitted > Review > Released > Closed
Default Sites Change Orders | Pending > Submitted > CCB > Released > Implemented
Default Stop Ships | Pending > Submitted > CCB > Released > Resumed

## 15.2 Dynamics of Workflow Functionality

The Workflow functionality available to each user for a particular routable object depends on the status of the routable object and the user's privileges. Your Agile API program should take these Workflow dynamics into account and, where possible, adjust your program accordingly.

### 15.2.1 How the Status of a Change Affects Workflow Functionality

The Workflow actions available for a pending change are different from those for a released change. To check the status of a change to determine whether it's pending or released, use the IRoutable.getStatus() method. The getStatus() method returns an IStatus object for the Workflow status. IStatus extends the INode interface and provides helpful methods for working with status nodes. The following example shows how to use getStatus() to determine whether a change is released.

Example: Getting the status of a change object

    private static boolean isReleased(IChange change) throws APIException {
    // Check if the user can change status
    }

return (change.getStatus().getStatusType().equals(StatusConstants.TYPE_RELEASED);

### 15.2.2 How User Privileges Affect Workflow Functionality

Agile privileges determine the types of Workflow actions a user can perform on a change. The Agile system administrator assigns roles and privileges to each user. The table below lists privileges needed to perform Workflow actions.

Privilege | Related API
--- | ---
Change Status | IRoutable.changeStatus()
Comment | IRoutable.comment()
Send | DataObject.send()

To determine at run time whether a user has the appropriate privileges to perform an action, use the IUser.hasPrivilege() method. You can adjust your program's UI based on the user's privileges. The following example shows how to check whether a user has the privilege to change the status of a change before calling the IRoutable.changeStatus() method.

Example: Checking the privileges of a user before changing the status of a change

    private void goToNextStatus(IChange change, IUser user) throws APIException {

if(user.hasPrivilege(UserConstants.PRIV_CHANGESTATUS, change)) {

IUser[] approvers = new IUser[] { user };

IStatus nextStatus = change.getDefaultNextStatus();

change.changeStatus(nextStatus, true, "", true, true, null, approvers, null, false);

} else {

System.out.println("Insufficient privileges to change status.");

}

    }
    // Get an Admin instance

## 15.3 Selecting a Workflow

When you create a new change, package, product service request, or quality change order, you must select a Workflow. Otherwise, the object is in an unassigned state and cannot progress through a Workflow process. Your Agile system can have multiple Workflows defined for each type of routable object. To retrieve the valid Workflows for an object, use the IRoutable.getWorkflows() method. If a routable object has not been assigned a Workflow yet, you can use the IRoutable.getWorkflows() method to select a Workflow.

As long as a change is in the Pending status, you can select a different Workflow. Once a change moves beyond the Pending status, you can't change the Workflow.

Example: Selecting a Workflow

    private IChange createECO(IAgileSession session) throws APIException {

IAdmin admin = session.getAdminInstance();

    // Create a change
    // since the Workflow has not been set yet)

IAgileClass ecoClass = admin.getAgileClass(ChangeConstants.CLASS_ECO);

IAutoNumber[] autoNumbersPart = ecoClass.getAutoNumberSources();

IChange change = (IChange)m_session.createObject(ecoClass, autoNumbersPart[0]);

    // Get the current Workflow (a null object,

IWorkflow wf = change.getWorkflow();

    // Get all available Workflows
    //(There can be multiple exceptions for each data cell.)
    // Set the change to use the first Workflow

IWorkflow[] wfs = change.getWorkflows();

change.setWorkflow(wfs[0]);

    // Set the change to use the second Workflow

change.setWorkflow(wfs[1]);

return change;

    }

If a change is still in the Pending status type, you can deselect a Workflow to make the change "unassigned." To make a change unassigned, use the IRoutable.setWorkflow() method and specify null for the Workflow parameter.

Example: Making a change unassigned

    private void unassign(IChange change) throws APIException {
    }

change.setWorkflow(null);

## 15.4 Adding and Removing Approvers

After a change is routed and the online approval process is initiated, it is sometimes necessary to add or remove people from the list of approvers or observers. To add or remove approvers or observers, a user must have the Route privilege.

You don't need to load the Workflow table to modify the list of approvers. Once you have a routable object, such as an ECO, you can modify its list of approvers using the IRoutable.addApprovers() and IRoutable.removeApprovers() methods. When you use addApprovers() or removeApprovers(), you specify the lists of approvers and observers, whether the Notification is urgent, and an optional comment. The Agile API provides overloaded addApprovers() and removeApprovers() methods for adding or removing a user or a user group from the list of approvers. For more information, refer to the API Reference files at Oracle® E-Cloud Web site (`http://edelivery.oracle.com/`).

If any users you select as approvers or observers do not have appropriate privileges to view a change, your program throws an APIException. To avoid the possible exception, check the privileges of each user before adding him to the approvers or observers list.

The following example shows how to add and remove approvers for a change.

Example: Adding and removing approvers and observers

    public void modifyApprovers(IChange change) {

    // Get current approvers for the change

try {

IDataObject[] currApprovers = change.getApproversEx(change.getStatus());

    // Get current observers for the change
    // Add hhawkes to approvers

IDataObject[] currObservers = change.getObserversEx(change.getStatus());

IUser user = (IUser)m_session.getObject(IUser.OBJECT_TYPE, "hhawkes");

IUser[] approvers = new IUser[]{user};

    // Add flang to observers

user = (IUser)m_session.getObject(IUser.OBJECT_TYPE, "flang");

IUser[] observers = new IUser[]{user};

    // Add approvers and observers

change.addApprovers(change.getStatus(), approvers, observers, true,

"Adding hhawkes to approvers and flang to observers");

    // Add skubrick to approvers

user = (IUser)m_session.getObject(IUser.OBJECT_TYPE, "skubrick");

approvers[0] = user;

    // Add kwong to observers

user = (IUser)m_session.getObject(IUser.OBJECT_TYPE, "kwong");

observers[0] = user;

    // Remove skubrick from approvers and kwong from observers

change.removeApprovers(change.getStatus(), approvers, observers,

"Removing skubrick from approvers and kwong from observers");

} catch (APIException ex) {

System.out.println(ex);

}

    }

If you want to modify only the list of approvers or the list of observers for a change, you can pass a null value for the parameter you don't want to change. The following example shows how to add the current user to the approvers list without changing the list of observers.

Example: Adding approvers without changing observers

    public void addMeToApprovers(IChange change) {

    // Get the current user

try {

IUser user = m_session.getCurrentUser();

    // Add the current user to the approvers list for the change

IUser[] approvers = new IUser[]{user};

change.addApprovers(change.getStatus(), approvers, null, true,

"Adding current user to approvers list");

} catch (APIException ex) {

System.out.println(ex);

}

    }

### 15.4.1 Approving or Rejecting Change

After a change is routed to a group of approvers, the online approval process begins. Users listed in the Workflow table for a change can approve or reject the change.

When you approve a change, the Agile system records the approval on the Workflow table. When all approvers have approved the change, the system sends an email Notification to the change analyst or component engineer indicating that the change is ready to be released.

Note: To approve or reject a change, users must have the correct privileges. For more information, refer to Agile PLM Administrator Guide.

When you use the IRoutable.approve() method, you specify the user's approval password and an optional comment. approve() methods allow you to specify a Notification list and a collection of user groups for which you're approving; refer to the API Reference files at Oracle® E-Cloud Web site (`http://edelivery.oracle.com/`) for details.

The following paragraphs document approving or rejecting a given routable object. The APIs that support approving or rejecting a change object when a second signature is required are described in detail in Setting the "Signoff User Dual Identification" Preference.

The following example shows how to approve a change.

Example: Approving a change

    public void approveChange(IChange change) {

try {

change.approve("agile", "Looks good to me");

} catch (APIException ex) {

System.out.println(ex);

}

    }

If a change has a fundamental flaw, users listed on the Workflow table may reject it. When you reject a change, the system records the rejection on the Workflow tab for the change and sends an email Notification to the change analyst or component engineer. The change analyst or component engineer may decide to return the rejected change to the originator, thus reverting its status to Pending.

When you use the IRoutable.reject() method, you must specify the userNotifications approval password and optional comments. An overloaded reject() method allows you to specify a Notification list and a collection of user groups for which you're approving; refer to the API Reference files at Oracle® E-Cloud Web site (`http://edelivery.oracle.com/`) for more information.

The following example shows how to reject a change.

Example: Rejecting a change

    public void rejectChange(IChange change) {

try {

change.reject("agile", "Incorrect replacement part!");

} catch (APIException ex) {

System.out.println(ex);

}

    }

### 15.4.2 Approving or Rejecting a Change Without Password

Agile PLM's Java Client provides the option to configure Workflow Settings to enable the approval or rejection of a change with or without typing a password. Users with the Administrator role and privileges configure this option by selecting the Yes or No option in the Password Required field shown in the following illustration.

Figure 15-1 Configuring workflow settings without a password

The following example uses the Agile SDK to programmatically configure this requirement.

Example: Approving or rejecting change without a password

    // Workflow settings - Password Required

Iadmin admin = session.getAdminInstance();

INode root = admin.getNode(NodeConstants.NODE_AGILE_WORKFLOWS);

INode CCBStatus = (INode)root.getChildNode("Default Change Orders/Status List/CCB/Status Properties");

IProperty PwdReq = CCBStatus.getProperty(PropertyConstants.PROP_WORKFLOW_PASSWORD_REQUIRED);

PwdReq.setValue("No");

    // Approve change without passing password

change.approve(null, null, "Approve", null, null, null, null, true);

### 15.4.3 Commenting a Change

When you comment a change, you send a comment to other CCB reviewers during the online approval process. In addition to the comment, you can specify whether to notify the originator, the change analyst, and the change control board. An overloaded comment() method allows you to specify a Notification list. For more information, refer to the API Reference files at Oracle® E-Cloud Web site (`http://edelivery.oracle.com/`).

The following example shows how to comment a change.

Example: Commenting a change

    public void commentChange(IChange change) {

try {

change.comment(true, true, true, "Change flagged for transfer to ERP.");

} catch (APIException ex) {

System.out.println(ex);

}

    }

### 15.4.4 Auditing a Change

At any point in a change's workflow, you can audit it to determine if any required entry cells are not completed or if the change violates any Agile SmartRules. When you use the IRoutable.audit() method, the method returns a Map object containing ICell objects as keys and a List of APIException objects as values. The ICell key can be null if there are no problems with the change. The APIException object describes a problem with the associated entry cell.

The Map object returned by the audit() method may also contain null objects as keys. The APIException object associated with a null object describes a problem unrelated to data cells.

The following example shows how to audit a change.

Example: Auditing a change

    public void auditChange(IChange change) {
    // Audit the release

try {

Map results = change.audit();

    // Get the set view of the map
    // Get an iterator for the set

Set set = results.entrySet();

Iterator it = set.iterator();

    // Iterate through the cells and print each cell name and exception

while (it.hasNext()) {

Map.Entry entry = (Map.Entry)it.next();

ICell cell = (ICell)entry.getKey();

if(cell != null) {

System.out.println("Cell : " + cell.getName());

} else {

System.out.println("Cell : No associated data cell");

}

    //Iterate through exceptions for each map entry.

Iterator jt = ((Collection)entry.getValue()).iterator();

while (jt.hasNext()) {

APIException e = (APIException)jt.next();

System.out.println("Exception : " + e.getMessage());

}

}

} catch (APIException ex) {

System.out.println(ex);

}

    }
    // Get the next status of the change

### 15.4.5 Changing the Workflow Status of an Object

The IRouteable.changeStatus() method is a general purpose method for changing the status of an Agile object. For example, you can use changeStatus() to submit, release, or cancel a change. In instances such as failed audits, it throws the compound exception ExceptionConstants.API_SEE_MULTIPLE_ROOT_CAUSES. You can disable this exception by modifying the code that caught the exception. See the example below.

Example: Throwing compound exception s

    while (true) {

try {

change.changeStatus(

wf.getStates(expectStatus)[0],

false,

"comment",

false,

false,

null,

null,

null,

false

);

} catch (APIException ae) {

try {

if

(ae.getErrorCode().equals(ExceptionConstants.API_SEE_MULTIPLE_ROOT_CAUSES)){

Throwable[] causes = ae.getRootCauses();

for (int i = 0; i < causes.length; i++) {

m_session.disableWarning(

(Integer)((APIException)causes[i]).getErrorCode());

}

} else {

m_session.disableWarning((Integer)ae.getErrorCode());

}

} catch (Exception e) {

throw ae;

}

continue;

}

break;

    }

In general, you release a change after it is signed off by CCB members. In addition to modifying the status of a change, you can also use changeStatus() to specify a Notification list, optional comments, and whether to notify the originator and change control board.

Depending on the overloaded changeStatus() method you use, the notifyList parameter is an array of IUser or IUserGroup objects that should be notified about the change in status; refer to the API Reference files at Oracle® E-Cloud Web site (`http://edelivery.oracle.com/`) for details. To use the default Notification list for the Workflow status, specify a null value. To indicate that no users should be notified, specify an empty array.

For both the approvers and observers parameters of the changeStatus() method, you must explicitly pass an array of users or user groups. If you pass null, no approvers or observers are used. To get the default approvers and observers for a particular Workflow status, use getApproversEx() and getObserversEx(), respectively.

The following example shows how to check the Workflow status of a change.

Example: Checking the status of a change

    void checkStatus(IChange change) {
    // Get current workflow status (an IStatus object)

try {

IStatus status = change.getStatus();

System.out.println("Status name = " + status.getName());

    // Get next available Workflow statuses

IStatus[] nextStatuses = change.getNextStatuses();

for (int i = 0; i < nextStatuses.length; i++) {

System.out.println("nextStatuses[" + i +"] = " +

nextStatuses[i].getName());

}

// Get next default Workflow status

IStatus nextDefStatus = change.getDefaultNextStatus();

System.out.println("Next default status = " + nextDefStatus.getName());

} catch (APIException ex) {

System.out.println(ex);

}

    }

The following example shows how to change the status of a change.

Example: Changing the status of a change

    public void nextStatus(IChange change, IUser[] notifyList,

IUser[] approvers, IUser[] observers) {

try {

// Check if the user has privileges to change to the next status

IStatus nextStatus = change.getDefaultNextStatus();

if (nextStatus == null) {

System.out.println("Insufficient privileges to change status.");

return;

}

// Change to the next status

else {

change.changeStatus(nextStatus, true, "", true, true, notifyList, approvers, observers, false);

}

} catch (APIException ex) {

System.out.println(ex);

}

    }

The following example shows how to use the default approvers and observers when you change the status of a routable object.

Example: Changing the status and routing to the default approvers and observers

    public void changeToDefaultNextStatus(IChange change) throws APIException {

IStatus nextStatus = change.getDefaultNextStatus();

    // Get default approvers for the next status
    Funcational Teams is a class under User Group Base Class having out of the box sub class 'Functional Team'. Creating Functional Team object is similar to creating any Agile object as detailed below:
    // Get default observers for the next status

IDataObject[] defaultApprovers = change.getApproversEx(nextStatus);

IDataObject[] defaultObservers = change.getObserversEx(nextStatus);

    // Change to the next status

    }

change.changeStatus(nextStatus, false, "", false, false, null, defaultApprovers, defaultObservers, false);

### 15.4.6 Sending an Agile Object to Selected Users

You can send any Agile object to a selected group of users. When you send an object, such as an ECO, there is no signoff required. The selected recipients receive an email message with an attached link to the object. When you use the IDataObject.send() method, you can specify an array of Agile users and an optional comment. Unlike other Workflow commands, the send() method is not limited to routable objects. You can use it to send any type of Agile dataobject, including an item.

The following example shows how to send an object to all users.

Example: Sending an Agile object to selected users

    public void sendToAll(IDataObject object) {
    // Get all users

try {

IQuery q = (IQuery)m_session.createObject(IQuery.OBJECT_TYPE, "select * from [Users]");

ArrayList userList = new ArrayList();

Iterator i = q.execute().getReferentIterator();

while (i.hasNext()) {

userList.add(i.next());

}

IUser[] users = new IUser[userList.size()];

System.arraycopy(userList.toArray(), 0, users, 0, userList.size());

    // Send the object to all users

object.send(users, "Please read this important document.");

} catch (APIException ex) {

System.out.println(ex);

}

    }

### 15.4.7 Sending an Agile Object to User Groups

You can send an Agile change object or an item object to a user group. When you send an object, such as an ECO, there is no signoff required. The selected recipients receive an email message with an attached link to the object. When you use the IDataObject.send(IDataObject[] to, String Comment) method, you can specify an array of Agile User Groups and an optional comment. The IDataObject parent interface represents the IUserGroup Agile object. Unlike other Workflow commands, the send() method is not limited to routable objects. You can use it to send any type of Agile dataobject, including an item.

The following example shows how to send an object to all User Groups.

Example: Sending an Agile object to selected user groups

    public void sendToAll(IDataObject[] object) {

    // Get all user groups

try {

IQuery q = (IQuery)m_session.createObject(IQuery.OBJECT_TYPE, "select * from [UserGroup]");

ArrayList usergroupList = new ArrayList();

Iterator i = q.execute().getReferentIterator();

while (i.hasNext()) {

usergroupList.add(i.next());

}

IUserGroup[] group = (IUserGroup[])(usergroupList.toArray());

    // Send the object to all user groups

object.send(usergroups, "Please read this important document.");

} catch (APIException ex) {

System.out.println(ex);

}

    }

## 15.5 Managing Functional Teams

The Functional Team feature streamlines the approval process by eliminating the need to update the list and roles of workflow approvers (the approval "criteria"). This is achieved by enabling the workflow process to create a Workflow Template and assign users to workflow actions. Users are then linked to the job functions they perform. Job functions and users are linked together to form the Functional Teams. These Functional Teams are added to routable objects and when they are routed through the workflow, the combination of Functional Team, Workflow Criteria, and the Approval Template determine which user performs the required workflow action.

### 15.5.1 Job Functions, Functional Teams, and Workflow Actions

You can use the SDK to eliminate updating the approval criteria in the event of a change in the approval criteria by defining the following Workflow-related objects and attributes:

- Job Function - The job performed by a user. Examples are product manager, product marketing manager, development lead, development manager, and so on.

- Functional Team - Group of users and/or user groups who work as a team to perform specific job functions. Logically, a Functional Team is a Job Function and not a User, because a Job Function can be associated with a Functional Team without any Users, but a User can not be added to a Functional Team without an assigned Job Function.

- Reviewers - Based on the role, a Reviewer can be an Approver, an Acknowledger, or an Observer. A user can have more than one Reviewer role.

  Note: Users can have more than one Reviewer role, but they cannot be Acknowledgers, Observers and/or Approvers.

  - Observers - A workflow action that requires the notified users to signoff when notified. Observers can be Users, User Groups or Functional Teams.

  - Acknowledgers - A workflow action that requires the notified users to signoff the change they have approved. This is different from an approval signoff. Acknowledgers can be Users, User Groups or Functional Teams.

  - Approvers - Approvers can sign -off for multiple job functions. Approvers can be Users, User Groups or Functional Teams.

### 15.5.2 Creating a Functional Team

Functional Teams are uniquely identified by name and they are a class under the User Group Base Class with the Functional Team as the default sub class. Creating a Functional Team object is similar to creating any Agile object. To create a Functional Team, use the IAgileSession.createObject method, specifying both the class and the name of the Team.

All users cannot create a Functional Team. Only users who have the Create privilege for this object can create Functional Teams.

Example: Creating a Functional Team

IAgileClass ft_class = session.getAdminInstance().getAgileClass("Functional Team");

HashMap map = new HashMap();

//Put values into map // map.put(UserGroupConstants.ATT_GENERAL_INFO_NAME, "PGC");

map.put(UserGroupConstants.ATT_GENERAL_INFO_DESCRIPTION, "PGC Functional Team");

IDataObject FtObj = (IDataObject) (session.getObject(UserGroupConstants.CLASS_FUNCTIONAL_TEAM, map));

if (FtObj==null){

// Create Functional Team with this Map //

FtObj = (IDataObject) session.createObject(ft_class, map);

}

    //Exmple to Create Functional Team
                IAgileClass ft_class = session.getAdminInstance().getAgileClass("Functional Team");
                HashMap map = new HashMap();
                //Put values into map // map.put(UserGroupConstants.ATT_GENERAL_INFO_NAME, "PGC");
                map.put(UserGroupConstants.ATT_GENERAL_INFO_DESCRIPTION, "PGC Functional Team");
                IDataObject FtObj = (IDataObject) (session.getObject(UserGroupConstants.CLASS_FUNCTIONAL_TEAM, map));
                if (FtObj==null){
                    //   Create Functional Team with this Map     //
                    FtObj = (IDataObject) session.createObject(ft_class, map);
                }

### 15.5.3 Managing Timesheets

PPM has the capability to manage the following Timesheet-related functions from the Web Client. The SDK enables performing the functions programmatically, by exposing the ITimesheetManager.

- Retrieving tasks a user can report time against - This feature enables retrieving the Web Client's Timesheet view and the list of tasks the user can report time against programmatically.

- Logging or modifying time reported for a user on a task - Similar to the Web Client, this feature supports logging or modifying time by day or activity for the user.

- Retrieving hours for a user or activity - This feature enables searching and retrieving hours for a user, an activity, a project, the date in between, and Canceled and Soft-Deleted activities. Results are provided as CSV or XLS similar to the UI

Important: As the SDK developer, you must have the proper privileges to perform Timesheet-related tasks.

#### 15.5.3.1 Retrieving Tasks Users Can Log Time Against

As the SDK developer with proper privileges, you can retrieve Timesheet records that display activities against which users can log time worked. The ITimesheetManager API returns the Timesheet table listing input dates for the week as shown the following example.

Example: Retrieving Timesheet table with week's input dates

Function: ITimesheetManager:: retrieveTimesheet(Date selectedDate)

//connect to Agile Server

IAgileSession ses = connect();

ITimesheetManager timesheetManager = (ITimesheetManager) ses.getManager(ITimesheetManager.class);

Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));

cal.set(Calendar.YEAR, 2013);

cal.set(Calendar.MONTH, 2);

cal.set(Calendar.DAY_OF_MONTH, 27);

// Retrieve a list of tasks the user can report time against

ITable result = timesheetManager.retrieveTimesheet(cal);

#### 15.5.3.2 Logging or Modifying the Reported Time for a User on a Task

After retrieving a Timesheet, the user can log or modify hours for the activity in the returned Timesheet records.

Function: ITimesheetManager:: logOrChangeTimesheet(ITable tsTable)

Sample Code

//connect to Agile Server

IAgileSession ses = connect();

ITimesheetManager timesheetManager = (ITimesheetManager) ses.getManager(ITimesheetManager.class);

Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));

cal.set(Calendar.YEAR, <YEAR>);

cal.set(Calendar.MONTH, <MONTH>);

cal.set(Calendar.DAY_OF_MONTH, <Day of Month>);

// Retrieve a list of tasks the user can report time against

ITable result = timesheetManager.retrieveTimesheet(cal);

ITwoWayIterator it = result.getTableIterator();

while (it.hasNext()) {

// Use row to set values on every cell

IRow row = (IRow)it.next();

ap sets = new HashMap();

sets.put(TimesheetConstants.ATTR_MONDAY, "1");

sets.put(TimesheetConstants.ATTR_SATURDAY, "1");

...

row.setValues(sets);

}

// Log or change time on the retrieved timesheet

timesheetManager.logOrChangeTimesheet(result);

#### 15.5.3.3 Retrieving Hours for a Given User or Activity

This API enables searching the Timesheet by User, Project, Date Between, as well as Canceled and Soft-Deleted Activities. The search result table is exported as a CSV or XLS file to the specified device.

Function:ITimesheetManager:: exportSearchedTimesheet (Map params)

Sample Code

//connect to Agile Server

IAgileSession ses = connect();

ITimesheetManager timesheetManager = (ITimesheetManager) ses.getManager(ITimesheetManager.class);

HashMap params = new HashMap();

Calendar fromDate = new GregorianCalendar(TimeZone.getTimeZone("GMT"));

fromDate.set(2013, 02, 25);

Calendar toDate = new GregorianCalendar(TimeZone.getTimeZone("GMT"));

toDate.set(<YEAR>,<MONTH>,<DAY>);

String[] users = {"admin"}; params.put(TimesheetConstants.TIMESHEET_SEARCH_USERS, users);

String[] progs = {"ph001"};

params.put(TimesheetConstants.TIMESHEET_SEARCH_PROGRAMS, progs);

params.put(TimesheetConstants.TIMESHEET_SEARCH_FROM_DATE, fromDate);

params.put(TimesheetConstants.TIMESHEET_SEARCH_TO_DATE, toDate);

params.put(TimesheetConstants.TIMESHEET_SEARCH_INCLUDE_CHECKBOX, true);

params.put(TimesheetConstants.TIMESHEET_SEARCH_EXPORTED_FILETYPE, TimesheetConstants.EXPORT_TYPE_XLS);

params.put(TimesheetConstants.TIMESHEET_SEARCH_EXPORTED_FILEPATH, "D:\\test");

params.put(TimesheetConstants.TIMESHEET_SEARCH_EXPORTED_FILENAME, "exportResult4");

//Retrive hours for a given user or activity and export the retrieved table as a CVS or XLS file.

String fullFileName = timesheetManager.exportSearchedTimesheet(params);

### 15.5.4 Creating a Job Functions Table

A Functional Team object contains a valid Job function and associated members such as users, user groups, and so on, in its Job Functions Table.

Example: Creating a Job Functions Table

    //get Job Functions Table of the Functional Team Object

ITable jobFuncTbl=FtObj.getTable(UserGroupConstants.TABLE_JOBFUNCTION);

IDataObject usr0 = (IDataObject) session.getObject(UserConstants.CLASS_USER, "usr01");

IDataObject usr1 = (IDataObject) session.getObject(UserConstants.CLASS_USER, "usr02");

IDataObject uGp0 = (IDataObject) session.getObject(UserGroupConstants.CLASS_USER_GROUP, "usrGroup01");

IRow ft_jf_row;

try{

map.clear();

map.put(UserGroupConstants.ATT_JOB_FUNCTION_NAME, "Developer"); //a valid value from 'Job Functioins' list

map.put(UserGroupConstants.ATT_JOB_FUNCTION_USERS_USERGROUPS, new Object[] {usr0, usr1, uGp0});

ft_jf_row = jobFuncTbl.createRow(map);

map.clear();

map.put(UserGroupConstants.ATT_JOB_FUNCTION_NAME, "Product Manager"); //a valid value from 'Job Functioins' list

map.put(UserGroupConstants.ATT_JOB_FUNCTION_USERS_USERGROUPS, new Object[] {usr1, uGp0});

ft_jf_row = jobFuncTbl.createRow(map);

}catch(APIException e){

System.out.println(e.getRootCause());

}

### 15.5.5 Adding a Discussion to a Functional Team

Discussions are integrated into the Product Portfolio Management solution, and are also applicable to the Product Cost Management solution. Discussions are created similar to other Agile PLM objects. Discussions are always viewed in the Web Client. To access a discussion while using Java Client, you can search to locate an existing discussion and open the object, which will open the Web Client. Also, you can open the Web Client and proceed from there to create a discussions.

Note: Discussions, Action Items, and News is a subset of Activity-specific subscription events that only apply to Product Portfolio Management and users can subscribe to actions related to Discussions, Action Items, and News.

The following example shows how to add a Discussion to a Functional Team.

Example: Adding a discussion to Functional Team

ITable ft_dc_tbl = (ITable)FtObj.getTable(UserGroupConstants.TABLE_DISCUSSIONS);

//Create a New discussion and add it to Functional Team.Discussion Table

IAgileClass discClass = session.getAdminInstance().getAgileClass(DiscussionConstants.CLASS_DISCUSSION);

String discNmbr = "D00003";

map.put(DiscussionConstants.ATT_COVER_PAGE_NUMBER, discNmbr);

map.put(DiscussionConstants.ATT_COVER_PAGE_SUBJECT, "Testing Func Team: "+discNmbr );

IDiscussion disc = (IDiscussion)session.getObject(DiscussionConstants.CLASS_DISCUSSION, map);

if (disc == null){

disc = (IDiscussion)session.createObject(DiscussionConstants.CLASS_DISCUSSION, map);

}

//Add Discussion to FunctionalTeam.Discussions Table

map.clear();

//map.put(UserGroupConstants.ATT_DISCUSSIONS_NUMBER, disc.getName());

map.put(UserGroupConstants.ATT_DISCUSSIONS_NUMBER, disc);

IRow newRow = ft_dc_tbl.createRow(map);

#### 15.5.5.1 Assigning Actions Items to Functional Teams

Action items are routable objects that require an action by the assigned user or user group. They inform the assigned users of a request for an action or activity. For a list and description of potential users, see Functional Team, Reviewers, and Observers in Job Functions, Functional Teams, and Workflow Actions on page 238. The following example shows how to assign action item using the SDK and the various fields such as dates, assignee, the action, and so on.

Note In Agile Web Client, Action Items is a sub-level tab of the Discussions tab.

Example: Assigning Action items to Functional Teams

//Get FunctionalTeam.ActionItems Table

ITable ft_ai_tbl = FtObj.getTable(UserGroupConstants.TABLE_ACTION_ITEMS);

//Add an Action Item to Functional Team.ActionItems Table SimpleDateFormat df = new SimpleDateFormat("MM/dd/yyyy");

Date dueDate = df.parse((String) "11/18/2011");

map.clear();

IDataObject usr0 = (IDataObject) session.getObject(UserConstants.CLASS_USER, "usr0");

map.put(UserGroupConstants.ATT_ACTIONITEM_SUBJECT, " ActItm for: "+usr0.getName());

map.put(UserGroupConstants.ATT_ACTIONITEMS_ASSIGNEDTO, usr0);

map.put(UserGroupConstants.ATT_ACTIONITEM_DUEDATE, dueDate);

IRow newRow1 = ft_ai_tbl.createRow(map);

IDataObject usr1 = (IDataObject) session.getObject(UserConstants.CLASS_USER, "usr1");

map.put(UserGroupConstants.ATT_ACTIONITEM_SUBJECT, " ActItm for: "+usr.getName());

map.put(UserGroupConstants.ATT_ACTIONITEMS_ASSIGNEDTO, usr1);

IRow newRow2 = ft_ai_tbl.createRow(map);

#### 15.5.5.2 Updating a Functional Team's News Table

As information passes through the Agile system, users receive news of status changes, requests, and notifications. Similar to Action Items, News is a sub-level tab of the Discussions tab, described earlier in the Note in Adding a Discussion to a Functional Team on page 243. The following example shows the various fields and how to use the SDK to update the applicable data elements.

Example: Updating a Functional Teams' News Table

//Get the Functional Team.News Table

ITable ft_ns_tbl = FtObj.getTable(UserGroupConstants.TABLE_NEWS);

//Add new News to Functional Team.News Table

IAgileList newsTypeLst = session.getAdminInstance().getListLibrary().getAdminList(AdminListConstants.LIST_NEWS_TYPE).getValues();

newsTypeLst.setSelection(new Object[]{"Information"});

map.clear();

map.put(UserGroupConstants.ATT_NEWS_TYPE, newsTypeLst);

map.put(UserGroupConstants.ATT_NEWS_TITLE, "Publishing News Title ");

map.put(UserGroupConstants.ATT_NEWS_NEWS, "This is testing the news publishing feature" + System.currentTimeMillis());

ft_ns_tbl.createRow(map);