I often go through the Agile PLM SDK group in LinkedIn. On a recent visit, someone was having an issue with obsolete parts showing on the BOM of an item on a change order. To be clear, the issue is not that parts on the change were obsolete, it is that parts on the BOM of the affected items of a change were obsolete. A process extension (PX) was proposed by another group member to remedy this business rule. This blog illustrates the implementation of that process extension.
2. Introduction/Background
I was reviewing the Agile PLM SDK group in LinkedIn
Someone was having an issue with obsolete parts
showing on the BOM of an item on a change order
The issue is not that parts on the change were
obsolete, it is that parts on the BOM of the affected
items of a change were obsolete
A process extension (PX) was proposed by another
group member to remedy this business rule
This presentation illustrates the implementation of that
process extension.
3. Agile PLM Change Order
Agile PLM Change Order containing part 140002 (not obsolete) and its BOM.
4. Agile PLM Part
Here is the title page of the item (140001) that was on the BOM of the
affected item (140002)
5. Problem Decomposition
Here is the functional decomposition of what needs to happen in the Agile
PLM process extension (PX) to get the desired results:
Pull the affected items table for the change order passed into the process
extension
– For each item on the change
• Get the underlying Agile item from the referenced affected item
– Get the BOM of the affected item
» Look at the title page lifecycle attribute for each item on the
BOM
• If we find an obsolete part, we need to demote
If we need to demote
– Get the workflow status’
– Make sure we are not at the beginning of the workflow – if we are, do nothing
– Demote to the prior workflow state and add a history item
7. Source Code (page 1)
package com.vestalsgap.px;
import com.agile.api.*;
import com.agile.px.ActionResult;
import java.util.*;
import org.apache.log4j.Logger;
public class EcoDemoter extends AbstractPX {
/*
* Process Extension Functionality
*
* Configure a Process Extension which can run on workflow change status to get Items on
* Change Order and check all of its BOM for Obselete part if its failing, Dont release the
* Change Order.
*
*/
// consider a history message that mentions the actual affected items that are in violation
// and a format string read from configuration rather than hard coded - this is only an example
String history = "The change order was demoted because the BOM of one or more affected items contained an obsolete item";
// again this should be a configuration setting
String invalidLifecycles = ",Obsolete,";
public ActionResult doAction(IAgileSession session, INode actionNode, IDataObject affectedObject) {
// only process change orders
ActionResult outcome = new ActionResult();
if ( !(affectedObject instanceof IChange) ) return outcome;
IChange change = (IChange) affectedObject;
9. Source Code (page 3)
private void demote(IChange change, String reason) throws Exception {
IStatus[] states = change.getWorkflow().getStates();
IStatus status = change.getStatus();
// a change cannot be demoted if it is already at the beginning of the workflow
if (states[0] == status) {
logger.info(change.getName() + " is already at the first workflow step ... cannot demote.");
return;
}
for (int i=0; i<states.length; i++) {
if (states[i] == status && i>0) {
status = states[i-1];
break;
}
}
Object[] approvers = change.getApproversEx(status);
Object[] observers = change.getObserversEx(status);
change.changeStatus(status, false, reason, true, false, new IUser[0], approvers, observers, false);
}
10. Source Code (page 4)
private boolean hasValidBOM(IItem parent) throws Exception {
ITable items = parent.getTable(ItemConstants.TABLE_BOM);
Iterator<IRow> rows = items.iterator();
IRow row;
String lifecycle = "";
IItem item;
while(rows.hasNext()) {
row = rows.next();
// This should be a configuration parameter to check against a list of phases
lifecycle = row.getReferent().getValue(ItemConstants.ATT_TITLE_BLOCK_LIFECYCLE_PHASE).toString();
if (lifecycle != null && invalidLifecycles.indexOf(lifecycle) > -1) return false;
}
return true;
}
}
11. About Us
PLM Mechanic specializes in the technical
aspects of Oracle’s Agile PLM solution
We offer the following service:
– Agile PLM installations and upgrades
– Agile PLM maintenance and help desk functions
– Agile PLM hosting
– Customization
PLM Mechanic also has several product
offerings
Title: Agile Process Extensions - (Agile PX)Subtitle: Demoting a Change Order
Introduction/BackgroundI was reviewing the Agile PLM SDK group in LinkedInSomeone was having an issue with obsolete parts showing on the BOM of an item on a change orderThe issue is not that parts on the change were obsolete, it is that parts on the BOM of the affected items of a change were obsoleteA process extension (PX) was proposed by another group member to remedy this business ruleThis presentation illustrates the implementation of that process extension.
This is a picture of the Agile PLM Change Order containing part 140002 (not obsolete) and its BOM.
Here is a picture of the title page of the item (140001) that was on the BOM of the affected item (140002)
Here is the functional decomposition of what needs to happen in the Agile PLM process extension (PX) to get the desired results:Pull the affected items table for the change order passed into the process extensionFor each item on the changeGet the underlying Agile item from the referenced affected itemGet the BOM of the affected itemLook at the title page lifecycle attribute for each item on the BOMIf we find an obsolete part, we need to demoteIf we need to demoteGet the workflow status’Make sure we are not at the beginning of the workflow – if we are, do nothingDemote to the prior workflow state and add a history item
Here is the aftermath the process extension fires
Source Code for the process extensionpackage com.vestalsgap.px;import com.agile.api.*;import com.agile.px.ActionResult;import java.util.*;import org.apache.log4j.Logger;public class EcoDemoter extends AbstractPX { /* * Process Extension Functionality * * Configure a Process Extension which can run on workflow change status to get Items on * Change Order and check all of its BOM for Obselete part if its failing, Dont release the * Change Order. * */ // consider a history message that mentions the actual affected items that are in violation // and a format string read from configuration rather than hard coded - this is only an example String history = "The change order was demoted because the BOM of one or more affected items contained an obsolete item"; // again this should be a configuration setting String invalidLifecycles = ",Obsolete,"; public ActionResultdoAction(IAgileSession session, INodeactionNode, IDataObjectaffectedObject) { // only process change ordersActionResult outcome = new ActionResult(); if ( !(affectedObjectinstanceofIChange) ) return outcome; IChange change = (IChange) affectedObject; try {ITableaffectedItems = change.getTable(ChangeConstants.TABLE_AFFECTEDITEMS); Iterator<IRow> rows = affectedItems.iterator();IRow row;IItemaffectedItem = null; while(rows.hasNext()) { // get the affected item row = (IRow) (rows.next());affectedItem = (IItem) row.getReferent(); if ( !hasValidBOM(affectedItem) ) { outcome = new ActionResult(ActionResult.STRING, history); demote(change, history); break; } } return outcome; } catch (Throwableth) {logger.error("Error: " + th.getMessage()); return new ActionResult(ActionResult.EXCEPTION, th); } } private void demote(IChange change, String reason) throws Exception {IStatus[] states = change.getWorkflow().getStates();IStatus status = change.getStatus(); // a change cannot be demoted if it is already at the beginning of the workflow if (states[0] == status) { logger.info(change.getName() + " is already at the first workflow step ... cannot demote."); return; } for (inti=0; i<states.length; i++) { if (states[i] == status && i>0) { status = states[i-1]; break; } } Object[] approvers = change.getApproversEx(status); Object[] observers = change.getObserversEx(status);change.changeStatus(status, false, reason, true, false, new IUser[0], approvers, observers, false); } private booleanhasValidBOM(IItem parent) throws Exception {ITable items = parent.getTable(ItemConstants.TABLE_BOM); Iterator<IRow> rows = items.iterator();IRow row; String lifecycle = "";IItem item; while(rows.hasNext()) { row = rows.next(); // This should be a configuration parameter to check against a list of phases lifecycle = row.getReferent().getValue(ItemConstants.ATT_TITLE_BLOCK_LIFECYCLE_PHASE).toString(); if (lifecycle != null && invalidLifecycles.indexOf(lifecycle) > -1) return false; } return true; }}
About UsPLM Mechanic specializes in the technical aspects of Oracle’s Agile PLM solutionWe offer the following service:Agile PLM installations and upgradesAgile PLM maintenance and help desk functionsAgile PLM hostingCustomizationPLM Mechanic also has several product offerings