From bfdd519a5695cc40e2c58ffed3b0eed4d06a9139 Mon Sep 17 00:00:00 2001 From: tony-gilfillan Date: Fri, 31 Jul 2026 11:23:32 -0400 Subject: [PATCH] Add stock-notifications example Extend app that displays Workday's current stock price on a home page card, backed by an orchestration that fetches the quote from an external API and writes it to a StockInfo business object. Co-Authored-By: Claude Sonnet 5 --- examples/stock-notifications/README.md | 20 +++++++++ examples/stock-notifications/appManifest.json | 8 ++++ .../cards/stockInfo.carddefinition | 16 +++++++ examples/stock-notifications/example.json | 20 +++++++++ .../model/StockInfo.businessobject | 44 +++++++++++++++++++ .../model/StockSecurityDomain.securitydomain | 6 +++ .../StockRetrieval.orchestration | 1 + .../stocknotifications_svfbfp.amd | 13 ++++++ .../stocknotifications_svfbfp.smd | 19 ++++++++ 9 files changed, 147 insertions(+) create mode 100644 examples/stock-notifications/README.md create mode 100644 examples/stock-notifications/appManifest.json create mode 100644 examples/stock-notifications/cards/stockInfo.carddefinition create mode 100644 examples/stock-notifications/example.json create mode 100644 examples/stock-notifications/model/StockInfo.businessobject create mode 100644 examples/stock-notifications/model/StockSecurityDomain.securitydomain create mode 100644 examples/stock-notifications/orchestration/StockRetrieval.orchestration create mode 100644 examples/stock-notifications/presentation/stocknotifications_svfbfp.amd create mode 100644 examples/stock-notifications/presentation/stocknotifications_svfbfp.smd diff --git a/examples/stock-notifications/README.md b/examples/stock-notifications/README.md new file mode 100644 index 0000000..1439ee8 --- /dev/null +++ b/examples/stock-notifications/README.md @@ -0,0 +1,20 @@ +# Stock Notifications + +## What it is + +An Extend app that shows Workday's current stock price (WDAY) on a home page card. An orchestration calls an external stock quote API, then writes the ticker, price, and timestamp into a Workday business object through the Workday REST API so the card can render the latest value. + +## What's inside + +- `appManifest.json`, `presentation/` — the Extend app shell (site and app manifest) +- `cards/stockInfo.carddefinition` — the home page card that displays the stock price +- `model/StockInfo.businessobject` and `model/StockSecurityDomain.securitydomain` — the business object that stores the ticker, price, and last-updated fields +- `orchestration/StockRetrieval.orchestration` — fetches the quote from an external API and posts it into the `StockInfo` business object via the Workday API + +## How to use it + +1. Deploy the app source to your WCP development tenant (App Builder, the IDE plugins, or the WDCLI), then install and launch it. +2. Import `orchestration/StockRetrieval.orchestration` in Orchestration Builder and update the `SendHTTPRequest` node's URL to point at your own stock quote API. +3. The orchestration authenticates to that external API with a Basic Auth credential named `onrender`. Replace the placeholder `YOUR_USERNAME` / `YOUR_PASSWORD` values with your own credential — never commit real ones. +4. Deploy the orchestration to your tenant, then run it (or schedule it) to keep the `StockInfo` record fresh. +5. Launch the app; the `stockInfo` card reads from the `StockInfo` business object and shows the latest price. diff --git a/examples/stock-notifications/appManifest.json b/examples/stock-notifications/appManifest.json new file mode 100644 index 0000000..8fd4e99 --- /dev/null +++ b/examples/stock-notifications/appManifest.json @@ -0,0 +1,8 @@ +{ + "id": "6f4026e444f4f3f37ac1d53d4a63a298", + "referenceId": "stocknotifications_svfbfp", + "name": "StockNotifications", + "description": "", + "latestVersion": "eaa00627e15388b48397b7c8974413f4", + "organizationId": "9ff68ed1-68e4-4225-9f3d-68dbf554c38b" +} \ No newline at end of file diff --git a/examples/stock-notifications/cards/stockInfo.carddefinition b/examples/stock-notifications/cards/stockInfo.carddefinition new file mode 100644 index 0000000..404b93d --- /dev/null +++ b/examples/stock-notifications/cards/stockInfo.carddefinition @@ -0,0 +1,16 @@ +{ + "id": "stockInfo", + "presentation": { + "type": "inlineCard", + "header": { + "type": "cardHeader", + "title": "Workday Stock Price", + "subtitle": "current price", + "icon": "wd-accent-chart-bar-arrow" + }, + "body": { + "type": "simpleCard", + "value": "My Simple Card Body" + } + } +} \ No newline at end of file diff --git a/examples/stock-notifications/example.json b/examples/stock-notifications/example.json new file mode 100644 index 0000000..acc40d0 --- /dev/null +++ b/examples/stock-notifications/example.json @@ -0,0 +1,20 @@ +{ + "title": "Stock Notifications", + "description": "An Extend app that fetches Workday's current stock price from an external API and displays it on a home page card.", + "type": "Extend App", + "components": [ + "Presentation", + "Card", + "Model", + "Orchestration" + ], + "products": [ + "Workday Extend", + "Workday Orchestrate" + ], + "authors": [ + "tony-gilfillan" + ], + "tutorial": "", + "source": "community" +} diff --git a/examples/stock-notifications/model/StockInfo.businessobject b/examples/stock-notifications/model/StockInfo.businessobject new file mode 100644 index 0000000..59c995d --- /dev/null +++ b/examples/stock-notifications/model/StockInfo.businessobject @@ -0,0 +1,44 @@ +{ + "id": 1, + "name": "StockInfo", + "label": "Stock Info", + "defaultSecurityDomains": [ + "StockSecurityDomain" + ], + "defaultCollection": { + "name": "stockInfos", + "label": "Stock Infos" + }, + "fields": [ + { + "id": 1, + "name": "stockTicker", + "type": "TEXT", + "isReferenceId": false, + "useForDisplay": true, + "isPurgeable": false, + "enableIndex": false, + "enableSearch": false + }, + { + "id": 2, + "name": "currentPrice", + "type": "TEXT", + "isReferenceId": false, + "useForDisplay": false, + "isPurgeable": false, + "enableIndex": false, + "enableSearch": false + }, + { + "id": 3, + "name": "lastUpdated", + "type": "TEXT", + "isReferenceId": false, + "useForDisplay": false, + "isPurgeable": false, + "enableIndex": false, + "enableSearch": false + } + ] +} \ No newline at end of file diff --git a/examples/stock-notifications/model/StockSecurityDomain.securitydomain b/examples/stock-notifications/model/StockSecurityDomain.securitydomain new file mode 100644 index 0000000..b4d7530 --- /dev/null +++ b/examples/stock-notifications/model/StockSecurityDomain.securitydomain @@ -0,0 +1,6 @@ +{ + "id": 1, + "name": "StockSecurityDomain", + "enabledForPageSecurity": false, + "enabledForOrchestrationSecurity": false +} \ No newline at end of file diff --git a/examples/stock-notifications/orchestration/StockRetrieval.orchestration b/examples/stock-notifications/orchestration/StockRetrieval.orchestration new file mode 100644 index 0000000..95a0175 --- /dev/null +++ b/examples/stock-notifications/orchestration/StockRetrieval.orchestration @@ -0,0 +1 @@ +{"flowVersion":"3.2.0","_type":"Flow","_value":{"id":{"_type":"String","_value":"5b8fa91937ce46d7a6ee41f4691099ef"},"name":{"_type":"Identifier","_value":"StockRetrieval"},"type":{"_type":"FlowType","_value":".maya.FlowSync"},"start":{"_type":"StartBasic","_value":{"structuredRequest":{"_type":["Opt","RequestStructure"],"_value":null},"hasMultipartData":{"_type":"Boolean","_value":false},"mcpToolConfig":{"_type":["Opt","MCPToolInputConfig"],"_value":null},"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.SendWorkdayAPIRequest.response"},"isAuto":{"_type":"Boolean","_value":false}}},"contentType":{"_type":["Opt","String"],"_value":null}}}},"mcpToolConfig":{"_type":["Opt","MCPToolOutputConfig"],"_value":null},"notes":{"_type":["List","Note"],"_value":[]}}},"nodes":{"_type":["List","Node"],"_value":[{"_type":"SendHttpRequest","_value":{"name":{"_type":"Identifier","_value":"SendHTTPRequest"},"isDisabled":{"_type":"Boolean","_value":false},"errorHandler":{"_type":["Opt","ErrorHandler"],"_value":null},"body":{"_type":["Opt","HttpBody"],"_value":null},"url":{"_type":["Expr","Url"],"_value":{"type":{"_type":"Type","_value":"Url"},"source":{"_type":"String","_value":"\"https://stockinfo-a6k3.onrender.com/api/stock\""},"isAuto":{"_type":"Boolean","_value":false}}},"queryParams":{"_type":["List","QueryParam"],"_value":[]},"method":{"_type":"HttpMethod","_value":"GET"},"headers":{"_type":["List","Header"],"_value":[]},"auth":{"_type":["Opt","ExternalAuthRef"],"_value":{"_type":"ExternalAuthRef","_value":{"resourceName":{"_type":"String","_value":"QnIDDPyQ"}}}},"isChunked":{"_type":"Boolean","_value":false},"connectTimeoutMs":{"_type":"Long","_value":10000},"responseTimeoutMs":{"_type":"Long","_value":20000},"overallTimeoutMs":{"_type":"Long","_value":300000},"retryConfigRef":{"_type":"RetryConfigRef","_value":"2n6B1rWL"},"tlsConfig":{"_type":["Opt","TlsConfig"],"_value":null},"proxyConfig":{"_type":["Opt","ProxyConfig"],"_value":null},"responseType":{"_type":"HttpResponseType","_value":"Any"},"pollingConfigRef":{"_type":["Opt","PollingConfigRef"],"_value":null},"notes":{"_type":["List","Note"],"_value":[]}}},{"_type":"SendWorkdayApiRequest","_value":{"name":{"_type":"Identifier","_value":"SendWorkdayAPIRequest"},"isDisabled":{"_type":"Boolean","_value":false},"errorHandler":{"_type":["Opt","ErrorHandler"],"_value":null},"body":{"_type":["Opt","CreateTextTemplateBody"],"_value":{"_type":"CreateTextTemplateBody","_value":{"message":{"_type":"TextTemplate","_value":"{\n \"stockTicker\": \"WDAY\",\n \"currentPrice\": {{data.SendHTTPRequest.response.asJSON().jsonDataAtJsonPath(\"$.data.c\")}},\n \"lastUpdated\": {{data.SendHTTPRequest.response.asJSON().jsonDataAtJsonPath(\"$.lastUpdated\")}}\n }"},"contentType":{"_type":"String","_value":"application/json"}}}},"path":{"_type":["Expr","String"],"_value":{"type":{"_type":"Type","_value":"String"},"source":{"_type":"String","_value":"\"apps/stocknotifications_svfbfp/v1/stockInfos\""},"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":"Any"},"longRunningRequest":{"_type":"Boolean","_value":false},"notes":{"_type":["List","Note"],"_value":[]}}}]},"notes":{"_type":["List","Note"],"_value":[]},"resources":{"_type":"ResourceProvider","_value":{"fileLikeResources":{"_type":["Map","Resource"],"_value":{}},"credentials":{"_type":["Map","Credential"],"_value":{"QnIDDPyQ":{"_type":"BasicCredential","_value":{"name":{"_type":"String","_value":"onrender"},"username":{"_type":["Expr","String"],"_value":{"type":{"_type":"Type","_value":"String"},"source":{"_type":"String","_value":"\"YOUR_USERNAME\""},"isAuto":{"_type":"Boolean","_value":false}}},"password":{"_type":["Expr","String"],"_value":{"type":{"_type":"Type","_value":"String"},"source":{"_type":"String","_value":"\"YOUR_PASSWORD\""},"isAuto":{"_type":"Boolean","_value":false}}}}}}},"xmlNamespaces":{"_type":["Map","String"],"_value":{}},"retryConfigs":{"_type":["Map",["WithNotes","RetryConfig"]],"_value":{"2n6B1rWL":{"_type":["WithNotes","RetryConfig"],"_value":{"value":{"_type":"RetryConfig","_value":{"name":{"_type":"String","_value":"OnRender"},"maxTotalRetries":{"_type":"Int","_value":6},"successResponseCodeRanges":{"_type":["List","ResponseCodeRange"],"_value":[]},"defaultBackOff":{"_type":"BackOff","_value":{"intervalMs":{"_type":"Long","_value":10000},"factor":{"_type":"Decimal","_value":1.0},"maxBackOffMs":{"_type":"Long","_value":300000}}},"retryPolicies":{"_type":["List","RetryPolicy"],"_value":[]}}},"notes":{"_type":["List","Note"],"_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.4072.0"},"errorHandler":{"_type":["Opt","ErrorHandler"],"_value":null},"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":null}}} \ No newline at end of file diff --git a/examples/stock-notifications/presentation/stocknotifications_svfbfp.amd b/examples/stock-notifications/presentation/stocknotifications_svfbfp.amd new file mode 100644 index 0000000..10f8acc --- /dev/null +++ b/examples/stock-notifications/presentation/stocknotifications_svfbfp.amd @@ -0,0 +1,13 @@ +{ + "appProperties": [], + "tasks": [ + { + "id": "stockInfo", + "routingPattern": "/stockInfo", + "page": { + "id": "stockInfo" + } + } + ], + "applicationId": "stocknotifications_svfbfp" +} \ No newline at end of file diff --git a/examples/stock-notifications/presentation/stocknotifications_svfbfp.smd b/examples/stock-notifications/presentation/stocknotifications_svfbfp.smd new file mode 100644 index 0000000..acb47ea --- /dev/null +++ b/examples/stock-notifications/presentation/stocknotifications_svfbfp.smd @@ -0,0 +1,19 @@ +{ + "id": "stocknotifications_svfbfp", + "applicationId": "stocknotifications_svfbfp", + "siteId": "stocknotifications_svfbfp", + "languages": [ + { + "code": "en-US", + "description": "English" + } + ], + "siteAuth": { + "authTypes": [ + { + "scheme": "SSO", + "id": "sso" + } + ] + } +} \ No newline at end of file