PL2758-P Autodesk® PLM 360 Automation Solutions with Scripting Jared Sund Autodesk PLM 360 Product Manager
Class summary In this class, we explore several advanced automation examples using scripting in Autodesk PLM 360 cloud-based product lifecycle software. The scripting capabilities in Autodesk PLM 360 offer you the tools to take your Autodesk PLM 360 solutions to next level. We explore advanced solutions in workflow for approvals and routings, part number generation, automated relationship creation, HTML email controls, HTML mash-ups, and connecting to external web services. We examine scripting solutions, not the scripts themselves—so you don’t need to be a developer to attend this class.
Key learning objectives At the end of this class, you will be able to: Explain how scripting is used to create advanced workflow approval solutions Describe how scripting is used to create advanced part numbering solutions Describe how scripting is used to create rich HTML email solutions
Explain how scripting is used to create automated relationships between items
PLM 360 Scripting Basics PL2760-L Autodesk® PLM 360 Developer's Delight: A Hands-on PLM 360 Scripting Overview
Server-Side JavaScript
aka: Mocha, LiveScript, Jscript, ECMAScrip
JavaScript 1.5 (Standard ECMA-262 3rd edition) NOT JAVA C construct language Not Strongly Typed
Server Side No Access to client side DOM (document object model) • • • •
navigator event window document
No client side functions
such as: navigator.userAgent such as: event.button() such as: window.navigate() such as: document.getElementsByName().value such as: alert(), document.write()
http://w3schools.com/js/default.asp
JavaScript Basics Comments
//Single line comment
Variables
/* Multiple line comments Multiple line comments */ var instructor = ‘Jared Sund’; var qty = 7; var price = 3.25; var subTotal = qty * price;
Array
Conditions
Loops
var students = []; students[0] = ‘Tom’; students[1] = ‘Jane’; If(subTotal > 150) { tax = .05; } for(var i =0; i < students.lengh; i++){ println(students[i]); }
Comments are a great way to document your scripts and are ignored by the scripting engine A multiline or block comment is great for creating a header at the top of your script. Everything inside /* …… */ is ignored by the scripting engine The variable instructor contains the string – Jared Sund The variable qty holds the integer number 7 The variable price hold the decimal number 3.25 The variable subTotal holds the decimal number 22.75 (7*3.25) An array is a list of items
Conditions are questions. When the question is true (the value in the variable subTotal is greater than the number 150), perform the instructions with the body ( { …… } ) Loops are used to iterate through arrays (lists), or can be used to iterate until a condition (question) is true (see while loops)
PLM 360 Script Management
Single location to manage all your PLM 360 scripts
Administration System Configuration Scripting
Create New Edit Existing Delete Existing Where Used
PLM 360 Script Editor Script Management Unique Name Description Imports
Code Embedded editor
Tools
Save Close Testing Error Log
PLM 360 Script Debugging/Errors Syntactic Errors (design time) In editor warnings On save messaging
Semantic Errors (run time) Testing Execution
Debugging Errors Script Log print() and println()
PLM 360 Script Types and Events
PLM 360 Script Types Condition Validation Action Library
– – – –
returns true/false (boolean) returns a list (array) – empty or populated does not return a value holds one or more JavaScript functions or objects
PLM 360 Script Events
Scripts DO NOT maintain PLM 360 permissions
Workflow Transitions
Precondition
Validation
Script Type: Condition (boolean) Hide or show WF Actions based on the outcome of a condition script Script Type: Validation (array) Validates requirements before allowing transition to the next state
Action
Script Type: Action Performs some action, sends an email
Workspace Behaviors (action scripts)
Add item
Performs some action, sets the value of a default field
Edit item details
Performs some action, calculates the total of values
PLM 360 Scripting Object and Functions
PLM 360 API item object The item object is prepopulated from the workspace item associated with the script Property
Description
descriptor
Properties for the item object (meta-fields)
fields
Read/write access to custom fields added to item details or the grid tab
grid
Read/write access to the rows and columns of a grid[row][column]
Examples • item.descriptor.workflowState • item.descriptor.ownerID • item.TITLE • item.QTY • item.grid[1].QTY • item.grid[2].TITLE • item.grid.addRow(row) • item.grid[1].remove()
• • • attachments Read access to items in the attachments tab • Read only access to workflow actions history (first is the most • workflowActions • recent) • • functions Additional operations that can be performed on an item • milestones
Read/write access to items in the milestones tab
item.milestones[1].progress item.milestones[1].milestoneDate item.attachments[1].fileStatus item.attachments[1].fileSize item.workflowActions[0].userID item.workflowActions[0].timeStamp item.performWorkflowTransition item.addMilestone item.deleteItem
See Scripting Reference for a complete list: http://help.autodesk.com/view/PLM/ENU
PLM 360 API functions PLM 360 API functions outside of the item object function createItem getPrintView loadItem
security
Description Creates a new record in a given workspace Returns the rendered html body of an Advanced Print View Returns an existing item by dmsID A set of functions to return user/group/role information
Email
Create and send emails from scripts
print/println
Used when testing scripts, writes the debug section
Logger
Writes to the item’s Change Log
XMLHttpRequest
Access external web services
Example • var newItem = createItem(workspace ID); • var body = getPrintView(APV name); • • • • • • • •
var relatedItem = loadItem(dmsID); var user = Security.loadUser(userID); var inGroup = Security.inGroup(group name); var email = new Email(); email.to = ‘
[email protected]’; email.subject = ‘This is a test email’; email.body = getPrintView(‘Item Details’); email.send();
•
println(item.descriptor.workflowState);
•
Logger.log(‘Owned by: ‘ + item.descriptor.ownerID);
See Scripting Reference for a complete list: http://help.autodesk.com/view/PLM/ENU
Advanced Workflow Approval Solutions
Standard Approval Board Solution Workflow Actions and Workflow States Basics Workflow Actions (transitions) are directed paths between Workflow States Access to perform Workflow Actions are permission based
A single permitted user can perform a Workflow Action A Workflow Action can move from State A to State B A Workflow Action can exit and enter the same State
Standard Approval Board Solution Features: N number of approvers to move state Approvers set by record Approval Lists – predefined sets of approvers Reject – requires all approvers to re-approve
Standard Approval Board Solution Roles Author
Transition
Condition
Michelle Sally Sam Roger JoePurchasing Manufacturing Engineer Author Quality Submit to CCB
False True N/A
Approve
True False N/A
Reject
False True N/A
Final Approval
False True N/A
Approvers
Standard Approval Board Solution //condition return value var userCanApprove = false; //start by getting the first and last name of the usr and check with the multi-select var usr = Security.loadUser(userID); var usrName = usr.lastName + ", " + usr.firstName;
Sam Engineer
var wfSteps = item.workflowActions; //generate a list of approvers from APPROVAL_LISTS and APPROVALS_REQUIRED var approvers = getApprovers(); //main program starts here if (approvers.length > 1){ //more than one approver is needed if (inArray(approvers,usrName) === true){ //current user is in list of approvers if (userAlreadyApproved(wfSteps,userID) === false){ //current user hasn't already approved if (requiresMoreApprovals(wfSteps, approvers.length,false) === true){ //still needs more approvals userCanApprove = true; //ok for the current user to approve } } } } returnValue(userCanApprove);
Standard Approval Board Solution //condition return value var userCanApprove = false; //start by getting the first and last name of the usr and check with the multi-select var usr = Security.loadUser(userID); var usrName = usr.lastName + ", " + usr.firstName;
Sally Purchasing
var wfSteps = item.workflowActions; //generate a list of approvers from APPROVAL_LISTS and APPROVALS_REQUIRED var approvers = getApprovers(); //main program starts here if (inArray(approvers,usrName) === true){ //current user is in list of approvers if (userAlreadyApproved(wfSteps,userID) === false){ //current user hasn't already approved if (requiresMoreApprovals(wfSteps, approvers.length, true) === true){ //still needs more approvals userCanApprove = true; //ok for the current user to approve } } } returnValue(userCanApprove);
Required and Optional AB Solution Features: N number of approvers to move state Approvers set by record Approval Lists – predefined sets of approvers Reject – requires all approvers to re-approve Required and Optional Approvers
Required and Optional AB Solution Roles Author
Transition
Condition
Michelle Sally Sam Roger JoePurchasing Manufacturing Engineer Author Quality Submit to CCB
False True N/A
Approve
N/A True False
Reject
N/A False True
Final Approval
N/A False True
Approvers
Required and Optional AB Solution (Condition) var allowTransition = false; var usr = Security.loadUser(userID); var currentUser = usr.lastName + ", " + usr.firstName;
Sam Engineer
switch(customTransID){ case 'CCBAPPROVE': allowTransition = ((item.REMAINING_REQUIRED.length > 1 && item.REMAINING_REQUIRED.contains(currentUser) === true) || item.REMAINING_OPTIONAL.contains(currentUser)); break; case 'FINAL_APPROVE': allowTransition = ((item.REMAINING_REQUIRED.length === 1 && item.REMAINING_REQUIRED.contains(currentUser) === true)); break; case 'REJECT_APPROVAL': allowTransition = (item.REMAINING_REQUIRED.contains(currentUser) === true || item.REMAINING_OPTIONAL.contains(currentUser)); break; } returnValue(allowTransition);
Required and Optional AB Solution (Action) var usr = Security.loadUser(userID); var currentUser = usr.lastName + ", " + usr.firstName; switch(customTransID){
Sam Engineer
case 'CCBAPPROVE':
if(item.REMAINING_REQUIRED.contains(currentUser) === true){ item.APPROVED_REQUIRED.add(currentUser); item.REMAINING_REQUIRED.remove(currentUser); } if(item.REMAINING_OPTIONAL.contains(currentUser) === true){ item.APPROVED_OPTIONAL.add(currentUser); item.REMAINING_OPTIONAL.remove(currentUser); } …
Related Item Approval Boards
Advanced Part Numbering Solutions
General Sequencer Solution function nextSeqNumber(SEQID){ var seqGenerator = loadItem(SEQID); if(seqGenerator === null){return null;} var prefix = seqGenerator.PREFIX; var sufix = seqGenerator.SUFIX; var stepSize = seqGenerator.STEP_SIZE; var includePadding = seqGenerator.ZEROPAD_AUTOGENERATED_SEQUENCE; var sequenceNo = parseFloat(seqGenerator.CURRENT_SEQUENCE_NUMBER); //update the project's next available number seqGenerator.CURRENT_SEQUENCE_NUMBER = ''+(sequenceNo+stepSize); var adjustedNo = ''; if(includePadding === true){ adjustedNo = '' + zeroFill(sequenceNo,padding, '0'); } else{ adjustedNo = '' + sequenceNo; }
if(prefix !== null){adjustedNo = prefix + adjustedNo;} if(sufix !== null){adjustedNo = adjustedNo + sufix;} return adjustedNo; }
Classification Sequencer if(item.NUMBER === null) //New Record setNewPartNumber(); else //Clone of existing Record roleExistingPN(existingPN); function setNewPartNumber(){ var classNumber = (item.CLASS_NUMBER !== null) ? item.CLASS_NUMBER : '000'; if(item.LINKED_CLASS !== null){ var newItemNumber = item.LINKED_CLASS.CURRENT_VALUE; newItemNumber = zeroFill(newItemNumber, 4, '0'); //increment the sequencer item.LINKED_CLASS.CURRENT_VALUE = item.LINKED_CLASS.CURRENT_VALUE + 1; item.NUMBER = classNumber + '-' + newItemNumber + '-000';
} } function roleExistingPN(existingPN){ var classNumber = (item.CLASS_NUMBER !== null) ? item.CLASS_NUMBER : '000'; var pnParts = existingPN.split('-'); var rollNumber = zeroFill((parseInt(pnParts[2], 10)+1),3,0); item.NUMBER = classNumber + '-' + pnParts[1]+ '-' + rollNumber; }
External Sequencer (PLM 360 Connect)
Legacy System
Returned Item
PN Request
Create New Item
New PN PN Request
1. 2. 3. 4. 5.
PLM 360 item created PLM 360 requests new PN from Jitterbit Jitterbit creates new item in target system Target system returns item to Jitterbit Jitterbit updates PLM 360 item
Returned Item
External Sequencer (PLM 360 Connect) Behavior: Script to run at item creation
• • • • •
XMLHttpRequest only supports synchronous Action script have a 5000ms timeout Sending the items dmsID to the Jitterbit Operation Jitterbit “GET” item details from the REST API Jitterbit “PUT” item updates from the REST API
//create a temp PN from the standard seqGen item.PART_NUMBER = nextSeqNumber('2928');
//kick off Jitterbit process to request new PN var url = 'http://JitterbitServer/PNG?dmsid=' + dmsID;
Jitterbit Request
xhr = new XMLHttpRequest(); xhr.open('GET', url); xhr.setRequestHeader('Content-Type', 'text/html'); xhr.setRequestHeader('Accept', 'text/html'); xhr.send();
Jitterbit Response
Rich HTML Email Solutions
Notifications Workflow Notifications Workflow Actions Reminders On Escalation
Scripting Email Objects Workflow Actions Escalation Behaviors
var email = new Email(); email.to = '
[email protected],
[email protected]'; //comma separated list email.cc = '
[email protected]'; //optional - comma separated list email.bcc = '
[email protected]'; //optional - comma separated list email.subject = email subject goes here'; email.body = ‘email body goes here’; email.send();
Advanced Print Views Email Bodies var emailAddress = {}; var emailToAddresses = ''; //get all additional owners email addresses emailAddress[item.master.owner.email] =1; //get additional owners for(var i = 0; i< item.master.additionalOwners.length; i++) emailAddress[item.master.additionalOwners[i].email] =1; //get additional owners groups for(var i = 0; i < item.master.groupAdditionalOwners.length; i++ ){ //get emails from each user in the group var users = Security.listUsersInGroup(item.master.groupAdditionalOwners[i]); for(var user in users){ emailAddress[users[user].email] = 1;} }
for(var userEmail in emailAddress) emailToAddresses += (emailToAddresses === '') ? userEmail : ',' + userEmail; //Send email from advanced print view var email = new Email(); email.to = emailToAddresses; //comma separated list email.subject = 'PLM 360 Change Order Completed [' + item.NUMBER + ']'; email.body = getPrintView('BasicChangeLog'); email.send();
Full HTML Email Bodies
function emailHTML(passedAsset){ var BODY = passedAsset.BODY; for(var gridRow in passedAsset.grid){ re = new RegExp(passedAsset.grid[gridRow].REPLACE_STRING, "g"); BODY = BODY.replace(re, passedAsset.grid[gridRow].FIELD_ID); } var email = new Email(); email.to = getEmailFromPicklist(passedAsset.USERS); email.subject = passedAsset.SUBJECT; email.body = BODY; email.send(); }
Automated Relationships
performWorkflowTransitionByCustomID('CUSTOM_ID', 'COMMENTS') if(item.CHANGE_REQUEST !== null) { item.CHANGE_REQUEST.performWorkflowTransitionByCustomID('ECO_COMPLETED', ‘CO Complete') }
item.CHANGE_REQUEST
Autodesk is a registered trademark of Autodesk, Inc., and/or its subsidiaries and/or affiliates in the USA and/or other countries. All other brand names, product names, or trademarks belong to their respective holders. Autodesk reserves the right to alter product and services offerings, and specifications and pricing at any time without notice, and is not responsible for typographical or graphical errors that may appear in this document. © 2013 Autodesk, Inc. All rights reserved.