diff --git a/README.md b/README.md index 3a96591..80c1659 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,7 @@ Community examples, open to everyone. This is the section external contributions | [`employee-data-orchestration`](examples/employee-data-orchestration) | An orchestration that reads worker data from one tenant and creates matching records through the Workday REST API. | Orchestration | | [`pto-policy-agent-skill`](examples/pto-policy-agent-skill) | A markdown skill that teaches an agent to answer employee questions about PTO, leave accrual, rollover, and sick leave policy with clear escalation rules. | Agent Skill | | [`stock-notifications`](examples/stock-notifications) | An Extend app that fetches Workday's current stock price from an external API and displays it on a home page card. | Extend App | +| [`wql-anniversary-celebrations`](examples/wql-anniversary-celebrations) | An orchestration that queries Workday via WQL for active workers celebrating milestone work anniversaries and formats an announcement digest payload for collaboration channels. | Orchestration | ## Contributing diff --git a/examples/wql-anniversary-celebrations/README.md b/examples/wql-anniversary-celebrations/README.md new file mode 100644 index 0000000..e53cfb5 --- /dev/null +++ b/examples/wql-anniversary-celebrations/README.md @@ -0,0 +1,33 @@ +# WQL Milestone Celebrations Orchestration + +## What it is + +An orchestration that queries Workday via Workday Query Language (WQL) to identify active workers celebrating milestone work anniversaries (1, 5, 10, 15, and 20+ years of service) in an upcoming period, extracts worker details, and prepares a structured celebration payload for team communication channels (such as Slack, Microsoft Teams, or email digests). Use this example to learn how to combine WQL data retrieval with Workday Orchestrate to automate employee milestone recognition without custom integration code. + +## What's inside + +- `wql/anniversaries.wql`: The standalone WQL query selecting workers, hire dates, length of service, and management structure from the `allActiveWorkers` data source. +- `wql/milestoneAnniversaries.wqlquery`: The structured WQL query definition configured for Orchestration and Presentation components. +- `orchestration/milestoneAnniversaries.orchestration`: The complete Workday Orchestrate flow definition with input handling, WQL execution, error logging, and response formatting. +- `sample-data/sample-wql-response.json`: Fictional WQL query response showing the returned worker attributes and milestone data. +- `sample-data/sample-webhook-payload.json`: Formatted card payload ready for delivery to incoming collaboration webhooks. +- `example.json`: Metadata file used by the Workday Developer Program gallery. + +## How to use it + +1. Import `orchestration/milestoneAnniversaries.orchestration` into Workday Orchestration Builder. +2. In your Workday tenant, configure or assign an Integration System User (ISU) with permissions for: + - `Workday Query Language (WQL)` + - `Worker Data: Public Worker Reports` +3. Point the orchestration's Workday credential reference to your tenant's ISU credential. +4. Schedule the orchestration to execute on a recurring cadence (e.g., weekly on Monday morning) or trigger it via a REST endpoint. +5. Review execution runs and payload output in Orchestration Activity logs. + +## Before you deploy + +Before deploying this orchestration to your target tenant, verify the following configuration points: + +- **Security Domains**: Ensure your Integration System User (ISU) has read access to `Worker Data: Public Worker Reports` and execution privileges for WQL. +- **WQL Endpoint Path**: The example uses the standard relative path `/wql/v1/data` with `_DEFAULT_WORKDAY_CREDENTIAL`. Confirm your tenant supports WQL REST API version 1. +- **Downstream Webhook Destination**: If connecting to an external collaboration channel (Slack, Microsoft Teams, or internal service), create an Outbound HTTP step and populate the target webhook URL via tenant environment variables rather than hardcoding. +- **Date Window Filtering**: Adjust the date logic in the WQL query (`WHERE hireDate IS NOT NULL`) to match your organization's celebration cadence (e.g., matching the current calendar month or seven-day forward window). diff --git a/examples/wql-anniversary-celebrations/example.json b/examples/wql-anniversary-celebrations/example.json new file mode 100644 index 0000000..91a8f0d --- /dev/null +++ b/examples/wql-anniversary-celebrations/example.json @@ -0,0 +1,19 @@ +{ + "title": "WQL Milestone Celebrations Orchestration", + "description": "An orchestration that queries Workday via WQL for active workers celebrating milestone work anniversaries and formats an announcement digest payload for collaboration channels.", + "type": "Orchestration", + "components": [ + "Orchestration", + "WQL", + "3rd-Party Technology" + ], + "products": [ + "Workday Orchestrate", + "Workday REST API" + ], + "authors": [ + "srivilliamsai" + ], + "tutorial": "", + "source": "community" +} diff --git a/examples/wql-anniversary-celebrations/orchestration/milestoneAnniversaries.orchestration b/examples/wql-anniversary-celebrations/orchestration/milestoneAnniversaries.orchestration new file mode 100644 index 0000000..d385b13 --- /dev/null +++ b/examples/wql-anniversary-celebrations/orchestration/milestoneAnniversaries.orchestration @@ -0,0 +1 @@ +{"flowVersion":"3.1.0","_type":"Flow","_value":{"id":{"_type":"String","_value":"c5e2d19f8a3b4e72901234567890abcd"},"name":{"_type":"Identifier","_value":"milestoneAnniversaries"},"type":{"_type":"FlowType","_value":".maya.FlowSync"},"start":{"_type":"StartBasic","_value":{"structuredRequest":{"_type":["Opt","RequestStructure"],"_value":null},"hasMultipartData":{"_type":"Boolean","_value":false},"notes":{"_type":["List","Note"],"_value":[]}}},"end":{"_type":"EndSync","_value":{"headers":{"_type":["List","Header"],"_value":[]},"body":{"_type":["Opt","DataRefBody"],"_value":{"_type":"DataRefBody","_value":{"dataRef":{"_type":["Expr","Data"],"_value":{"type":{"_type":"Type","_value":"Data"},"source":{"_type":"String","_value":"data(\"FormatResponse\", \"message\")"},"isAuto":{"_type":"Boolean","_value":false}}},"contentType":{"_type":["Opt","String"],"_value":{"_type":"String","_value":"application/json"}}}}},"notes":{"_type":["List","Note"],"_value":[{"_type":"Note","_value":{"key":{"_type":"String","_value":"description"},"value":{"_type":"String","_value":"Returns milestone celebration sync status"}}}]}}},"nodes":{"_type":["List","Node"],"_value":[{"_type":"CreateTextTemplate","_value":{"name":{"_type":"Identifier","_value":"BuildWqlRequestBody"},"isDisabled":{"_type":"Boolean","_value":false},"errorHandler":{"_type":["Opt","ErrorHandler"],"_value":null},"message":{"_type":"TextTemplate","_value":"{\n \"query\": \"SELECT worker, workdayID, fullName, primaryWorkEmail, businessTitle, hireDate, lengthOfServiceInYears, manager FROM allActiveWorkers WHERE hireDate IS NOT NULL ORDER BY hireDate ASC\"\n}"},"contentType":{"_type":"String","_value":"application/json"},"formatRef":{"_type":["Opt","TextFormatRef"],"_value":null},"notes":{"_type":["List","Note"],"_value":[{"_type":"Note","_value":{"key":{"_type":"String","_value":"description"},"value":{"_type":"String","_value":"Construct WQL query body"}}}]}}},{"_type":"SendWorkdayApiRequest","_value":{"name":{"_type":"Identifier","_value":"ExecuteWqlQuery"},"isDisabled":{"_type":"Boolean","_value":false},"errorHandler":{"_type":["Opt","ErrorHandler"],"_value":{"_type":"ErrorHandler","_value":{"name":{"_type":"Identifier","_value":"_errorHandler_ExecuteWqlQuery"},"isDisabled":{"_type":"Boolean","_value":false},"strategy":{"_type":"ErrorHandlerStrategy","_value":"PropagateError"},"nodes":{"_type":["List","Node"],"_value":[{"_type":"Log","_value":{"name":{"_type":"Identifier","_value":"LogWqlError"},"isDisabled":{"_type":"Boolean","_value":false},"errorHandler":{"_type":["Opt","ErrorHandler"],"_value":null},"message":{"_type":["Expr","String"],"_value":{"type":{"_type":"Type","_value":"String"},"source":{"_type":"String","_value":"s\"\"\"${\"WQL query execution failed: \"}${data(\"ExecuteWqlQuery\", \"processingError\").message()}\"\"\""},"isAuto":{"_type":"Boolean","_value":false}}},"condition":{"_type":["Expr","Boolean"],"_value":{"type":{"_type":"Type","_value":"Boolean"},"source":{"_type":"String","_value":"true"},"isAuto":{"_type":"Boolean","_value":false}}},"notes":{"_type":["List","Note"],"_value":[]}}}]},"notes":{"_type":["List","Note"],"_value":[]}}}},"body":{"_type":["Opt","DataRefBody"],"_value":{"_type":"DataRefBody","_value":{"dataRef":{"_type":["Expr","Data"],"_value":{"type":{"_type":"Type","_value":"Data"},"source":{"_type":"String","_value":"data(\"BuildWqlRequestBody\", \"message\")"},"isAuto":{"_type":"Boolean","_value":false}}},"contentType":{"_type":["Opt","String"],"_value":{"_type":"String","_value":"application/json"}}}}},"path":{"_type":["Expr","String"],"_value":{"type":{"_type":"Type","_value":"String"},"source":{"_type":"String","_value":"\"/wql/v1/data\""},"isAuto":{"_type":"Boolean","_value":false}}},"queryParams":{"_type":["List","QueryParam"],"_value":[]},"method":{"_type":"HttpMethod","_value":"POST"},"headers":{"_type":["List","Header"],"_value":[]},"auth":{"_type":"WorkdayCredentialRef","_value":{"resourceName":{"_type":"String","_value":"_DEFAULT_WORKDAY_CREDENTIAL"}}},"isChunked":{"_type":"Boolean","_value":false},"connectTimeoutMs":{"_type":"Long","_value":10000},"responseTimeoutMs":{"_type":"Long","_value":20000},"overallTimeoutMs":{"_type":"Long","_value":300000},"retryConfigRef":{"_type":"RetryConfigRef","_value":"_DEFAULT_WORKDAY_RETRY_CONFIG"},"tlsConfig":{"_type":["Opt","TlsConfig"],"_value":null},"proxyConfig":{"_type":["Opt","ProxyConfig"],"_value":null},"responseType":{"_type":"HttpResponseType","_value":"Json"},"notes":{"_type":["List","Note"],"_value":[{"_type":"Note","_value":{"key":{"_type":"String","_value":"description"},"value":{"_type":"String","_value":"Fetch anniversary worker dataset via WQL"}}}]}}},{"_type":"CreateValues","_value":{"name":{"_type":"Identifier","_value":"ExtractWorkerSummary"},"isDisabled":{"_type":"Boolean","_value":false},"errorHandler":{"_type":["Opt","ErrorHandler"],"_value":null},"values":{"_type":["List","Assignment"],"_value":[{"_type":"Assignment","_value":{"param":{"_type":"Parameter","_value":{"name":{"_type":"Identifier","_value":"totalCelebrants"},"type":{"_type":"Type","_value":"Number"},"default":{"_type":["Opt","Any"],"_value":null}}},"expr":{"_type":["Expr","Number"],"_value":{"type":{"_type":"Type","_value":"Number"},"source":{"_type":"String","_value":"data(\"ExecuteWqlQuery\", \"response\").asJSON().numberAtJsonPathWithDefault(\"$.total\", 0)"},"isAuto":{"_type":"Boolean","_value":false}}}}}]},"notes":{"_type":["List","Note"],"_value":[{"_type":"Note","_value":{"key":{"_type":"String","_value":"description"},"value":{"_type":"String","_value":"Read total celebrating workers count"}}}]}}},{"_type":"CreateTextTemplate","_value":{"name":{"_type":"Identifier","_value":"FormatResponse"},"isDisabled":{"_type":"Boolean","_value":false},"errorHandler":{"_type":["Opt","ErrorHandler"],"_value":null},"message":{"_type":"TextTemplate","_value":"{\n \"status\": \"success\",\n \"totalMilestonesFound\": {{data(\"ExtractWorkerSummary\", \"totalCelebrants\")}},\n \"message\": \"Milestone anniversaries successfully processed and formatted.\"\n}"},"contentType":{"_type":"String","_value":"application/json"},"formatRef":{"_type":["Opt","TextFormatRef"],"_value":null},"notes":{"_type":["List","Note"],"_value":[{"_type":"Note","_value":{"key":{"_type":"String","_value":"description"},"value":{"_type":"String","_value":"Format JSON response body"}}}]}}}]},"notes":{"_type":["List","Note"],"_value":[]},"resources":{"_type":"ResourceProvider","_value":{"fileLikeResources":{"_type":["Map","Resource"],"_value":{}},"credentials":{"_type":["Map","Credential"],"_value":{}},"xmlNamespaces":{"_type":["Map","String"],"_value":{}},"retryConfigs":{"_type":["Map",["WithNotes","RetryConfig"]],"_value":{}},"csvFormats":{"_type":["Map","CsvFormat"],"_value":{}},"pollingConfigs":{"_type":["Map","PollingConfig"],"_value":{}}}},"defaultWorkdayCredentialRef":{"_type":["Opt","AccessTokenFromInitiatingUser"],"_value":{"_type":"AccessTokenFromInitiatingUser","_value":"AccessTokenFromInitiatingUser"}},"mayaVersion":{"_type":"String","_value":"1.3965.0"},"errorHandler":{"_type":["Opt","ErrorHandler"],"_value":{"_type":"ErrorHandler","_value":{"name":{"_type":"Identifier","_value":"_globalErrorHandler"},"strategy":{"_type":"ErrorHandlerStrategy","_value":"GlobalErrorHandler"},"nodes":{"_type":["List","Node"],"_value":[{"_type":"Log","_value":{"name":{"_type":"Identifier","_value":"LogGlobalError"},"errorHandler":{"_type":["Opt","ErrorHandler"],"_value":null},"message":{"_type":["Expr","String"],"_value":{"type":{"_type":"Type","_value":"String"},"source":{"_type":"String","_value":"s\"\"\"${\"Global Orchestration Error: \"}${data(\"_orchestration\",\"processingError\").message()}\"\"\""}}},"notes":{"_type":["List","Note"],"_value":[{"_type":"Note","_value":{"key":{"_type":"String","_value":"description"},"value":{"_type":"String","_value":"Log uncaught exceptions"}}}]}}}]},"notes":{"_type":["List","Note"],"_value":[]}}}},"cancelBarrier":{"_type":["Opt","Identifier"],"_value":null},"defaultLocale":{"_type":"Locale","_value":{"value":{"_type":["Expr","String"],"_value":{"type":{"_type":"Type","_value":"String"},"source":{"_type":"String","_value":"\"en_US\""},"isAuto":{"_type":"Boolean","_value":false}}}}},"securityDomains":{"_type":["Opt",["List","String"]],"_value":["Worker_Data: Public_Worker_Reports"]}}} diff --git a/examples/wql-anniversary-celebrations/sample-data/sample-webhook-payload.json b/examples/wql-anniversary-celebrations/sample-data/sample-webhook-payload.json new file mode 100644 index 0000000..feaefcf --- /dev/null +++ b/examples/wql-anniversary-celebrations/sample-data/sample-webhook-payload.json @@ -0,0 +1,49 @@ +{ + "text": "Team Milestone Anniversaries", + "blocks": [ + { + "type": "header", + "text": { + "type": "plain_text", + "text": "Team Milestone Anniversaries This Week", + "emoji": true + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Join us in congratulating our teammates reaching major career milestones!" + } + }, + { + "type": "divider" + }, + { + "type": "section", + "fields": [ + { + "type": "mrkdwn", + "text": "*Alex Morgan* (10 Years)\nSenior Systems Architect" + }, + { + "type": "mrkdwn", + "text": "*Jordan Lee* (5 Years)\nStaff Software Engineer" + }, + { + "type": "mrkdwn", + "text": "*Samira Patel* (1 Year)\nProduct Designer" + } + ] + }, + { + "type": "context", + "elements": [ + { + "type": "mrkdwn", + "text": "Generated automatically via Workday Orchestrate & WQL" + } + ] + } + ] +} diff --git a/examples/wql-anniversary-celebrations/sample-data/sample-wql-response.json b/examples/wql-anniversary-celebrations/sample-data/sample-wql-response.json new file mode 100644 index 0000000..b933788 --- /dev/null +++ b/examples/wql-anniversary-celebrations/sample-data/sample-wql-response.json @@ -0,0 +1,53 @@ +{ + "total": 3, + "data": [ + { + "worker": { + "id": "21045", + "descriptor": "Alex Morgan" + }, + "workdayID": "a1b2c3d4e5f678901234567890abcdef", + "fullName": "Alex Morgan", + "primaryWorkEmail": "alex.morgan@example.com", + "businessTitle": "Senior Systems Architect", + "hireDate": "2016-09-15", + "lengthOfServiceInYears": 10, + "manager": { + "id": "10024", + "descriptor": "Taylor Chen" + } + }, + { + "worker": { + "id": "24182", + "descriptor": "Jordan Lee" + }, + "workdayID": "b2c3d4e5f6a178901234567890abcdef", + "fullName": "Jordan Lee", + "primaryWorkEmail": "jordan.lee@example.com", + "businessTitle": "Staff Software Engineer", + "hireDate": "2021-09-18", + "lengthOfServiceInYears": 5, + "manager": { + "id": "10024", + "descriptor": "Taylor Chen" + } + }, + { + "worker": { + "id": "28910", + "descriptor": "Samira Patel" + }, + "workdayID": "c3d4e5f6a1b278901234567890abcdef", + "fullName": "Samira Patel", + "primaryWorkEmail": "samira.patel@example.com", + "businessTitle": "Product Designer", + "hireDate": "2025-09-20", + "lengthOfServiceInYears": 1, + "manager": { + "id": "14089", + "descriptor": "Devon Reed" + } + } + ] +} diff --git a/examples/wql-anniversary-celebrations/wql/anniversaries.wql b/examples/wql-anniversary-celebrations/wql/anniversaries.wql new file mode 100644 index 0000000..11b2095 --- /dev/null +++ b/examples/wql-anniversary-celebrations/wql/anniversaries.wql @@ -0,0 +1,19 @@ +/* + Workday Query Language (WQL) - Worker Milestone Anniversaries + Data Source: allActiveWorkers + Description: Queries active employees to identify milestone work anniversaries + (e.g., 1, 5, 10, 15, 20+ years of service). +*/ + +SELECT + worker, + workdayID, + fullName, + primaryWorkEmail, + businessTitle, + hireDate, + lengthOfServiceInYears, + manager +FROM allActiveWorkers +WHERE hireDate IS NOT NULL +ORDER BY hireDate ASC diff --git a/examples/wql-anniversary-celebrations/wql/milestoneAnniversaries.wqlquery b/examples/wql-anniversary-celebrations/wql/milestoneAnniversaries.wqlquery new file mode 100644 index 0000000..880143c --- /dev/null +++ b/examples/wql-anniversary-celebrations/wql/milestoneAnniversaries.wqlquery @@ -0,0 +1,6 @@ +{ + "id": "milestoneAnniversaries", + "parameters": [], + "query": "SELECT worker, workdayID, fullName, primaryWorkEmail, businessTitle, hireDate, lengthOfServiceInYears, manager FROM allActiveWorkers WHERE hireDate IS NOT NULL ORDER BY hireDate ASC", + "limit": "100" +}