From a91e4b0ae7b1087419e42266ab237556d52669e7 Mon Sep 17 00:00:00 2001 From: Om Jadiye Date: Thu, 15 Oct 2026 14:24:58 +0000 Subject: [PATCH] Add smart-csv-org-loader example (Integration App) --- README.md | 1 + examples/smart-csv-org-loader/README.md | 50 + .../smart-csv-org-loader/appManifest.json | 4 + examples/smart-csv-org-loader/example.json | 22 + .../model/OrgAssignmentLoadRow.businessobject | 124 + .../model/SmartOrgLoaderDomain.securitydomain | 6 + .../processOrgAssignmentLoad.orchestration | 2581 +++++++++++++++++ .../presentation/errorPage.pmd | 22 + .../scripts/csvParserAndValidator.script | 140 + .../presentation/smartCsvOrgLoader.amd | 34 + .../presentation/smartCsvOrgLoader.smd | 22 + .../presentation/uploadAndValidateOrgCsv.pmd | 260 ++ .../presentation/viewLoadBatchHistory.pmd | 130 + .../samples/assign_org_sample_template.csv | 6 + 14 files changed, 3402 insertions(+) create mode 100644 examples/smart-csv-org-loader/README.md create mode 100644 examples/smart-csv-org-loader/appManifest.json create mode 100644 examples/smart-csv-org-loader/example.json create mode 100644 examples/smart-csv-org-loader/model/OrgAssignmentLoadRow.businessobject create mode 100644 examples/smart-csv-org-loader/model/SmartOrgLoaderDomain.securitydomain create mode 100644 examples/smart-csv-org-loader/orchestration/processOrgAssignmentLoad.orchestration create mode 100644 examples/smart-csv-org-loader/presentation/errorPage.pmd create mode 100644 examples/smart-csv-org-loader/presentation/scripts/csvParserAndValidator.script create mode 100644 examples/smart-csv-org-loader/presentation/smartCsvOrgLoader.amd create mode 100644 examples/smart-csv-org-loader/presentation/smartCsvOrgLoader.smd create mode 100644 examples/smart-csv-org-loader/presentation/uploadAndValidateOrgCsv.pmd create mode 100644 examples/smart-csv-org-loader/presentation/viewLoadBatchHistory.pmd create mode 100755 examples/smart-csv-org-loader/samples/assign_org_sample_template.csv diff --git a/README.md b/README.md index c0f0120..f0e77f9 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,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 | | [`peer-kudos-home-card`](examples/peer-kudos-home-card) | An Extend app with a Home page card, custom business object, and orchestration that lets employees celebrate peer contributions and notifies managers. | Extend App | | [`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 | +| [`smart-csv-org-loader`](examples/smart-csv-org-loader) | An Extend app and async orchestration that replaces multi-row Assign Organization EIB spreadsheets with a flat one-row-per-worker CSV: WQL pre-validation of workers and positions, Staffing Change_Organization_Assignments SOAP calls in the background, and per-row status write-back. | Integration App | | [`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 | | [`workday-ai-gateway-skill`](examples/workday-ai-gateway-skill) | A markdown skill that reviews an AI Gateway or AWS starter call and keeps secrets out of the page. | Agent Skill | | [`workday-apis-skill`](examples/workday-apis-skill) | A markdown skill that chooses and reviews a Workday Graph, WQL, REST, or SOAP call. | Agent Skill | diff --git a/examples/smart-csv-org-loader/README.md b/examples/smart-csv-org-loader/README.md new file mode 100644 index 0000000..96e9765 --- /dev/null +++ b/examples/smart-csv-org-loader/README.md @@ -0,0 +1,50 @@ +# Smart CSV Org Assignment Loader + +## What it is + +An Extend app and orchestration for Workday admins who change organization assignments in bulk. The Assign Organization EIB expects one parent row per worker plus a child row per custom organization, and a single inactive or misspelled Reference ID fails the row with a SOAP fault. This example takes a flat CSV instead, one row per worker, checks each worker and position against the tenant with WQL before anything is written, and then loads the valid rows through the Staffing `Change_Organization_Assignments` web service (v42.0), writing each row's result back so you can see what succeeded. + +## What's inside + +- `presentation/uploadAndValidateOrgCsv.pmd`: paste the CSV, click **Validate**, review the results grid, then **Load valid rows**. Rows marked ERROR are skipped; only VALID rows are staged and loaded. +- `presentation/scripts/csvParserAndValidator.script`: parses the CSV, builds WQL queries that fetch only the IDs in the file, validates each row, and builds the SOAP request body. Blank organization columns are left out of the request, so Workday keeps the existing assignment. +- `presentation/viewLoadBatchHistory.pmd`: every staged row with its status (`STAGED`, `COMPLETED`, `SOAP_FAULT`) and message. +- `model/OrgAssignmentLoadRow.businessobject` and `model/SmartOrgLoaderDomain.securitydomain`: the staging business object and its security domain. +- `orchestration/processOrgAssignmentLoad.orchestration`: an **asynchronous** orchestration, launched once by the page with the `batchId` and every valid row. For each row it creates a `STAGED` record in the business object, sends one SOAP call, and patches the record with `COMPLETED` or the SOAP fault text. +- `samples/assign_org_sample_template.csv`: five rows, three valid and two with deliberate errors. + +### What the validation catches + +| Check | Example message | +| --- | --- | +| Employee isn't an active worker | `Employee_ID 'EMP_99999' is not an active worker` | +| Position isn't held by that worker | `Position 'P-00999' isn't held by EMP_21001` | +| Date format | `Effective_Date '11/01/2026' must be YYYY-MM-DD` | +| Same worker twice for one date | `Duplicate of row 2: one change per worker per effective date` | +| Quoted cells | `Remove quotes: Reference IDs never contain commas` | + +Up to three custom organizations per row (`Custom_Org_1` to `Custom_Org_3`). Blank cells keep the worker's existing assignment. + +Organization Reference IDs (unknown IDs, wrong type for the column, types not allowed on positions) and business-process conflicts (e.g. pending actions on the worker) are checked by Workday itself at load. Each row's result, including Workday's exact fault text, appears in **Batch history** as `COMPLETED` or `SOAP_FAULT`. Rows marked `ERROR` in pre-validation are skipped, never sent. + +## How to use it + +1. Deploy the app source to your development tenant (App Builder, the IDE plugins, or the WDCLI), then install it. +2. Import `orchestration/processOrgAssignmentLoad.orchestration` in Orchestration Builder and deploy it to the same app. +3. Map `SmartOrgLoaderDomain` to a security group that may change organization assignments. +4. Open **Smart CSV Org Assignment Loader**, paste `samples/assign_org_sample_template.csv` with your own tenant's IDs, and click **Validate**. +5. Fix rows in red (or let them be skipped), then click **Load valid rows**. The load runs in the background, so the page returns straight away, even for hundreds of rows. Open **Batch history** to watch progress: rows appear as `STAGED` and turn `COMPLETED` or `SOAP_FAULT` as Workday processes them. Refresh the page until no `STAGED` rows remain. + +**Auto-complete** is off by default, so each change goes through your normal business process approvals. Turn it on only when you mean to skip them. + +## Before you deploy + +- **App reference id**: the orchestration builds its business object path from `context.appReferenceId()`, so it follows whatever reference id Workday generates for your app. +- **WQL field names**: the worker query uses `employeeID` and `positionID` on `workersForHCMReporting`. Confirm them in your tenant (the `wql` catalog app helps) and adjust the script if they differ. Organization IDs aren't pre-checked with WQL; Workday validates them at load. +- **Organization type names**: the type check compares against `Cost Center`, `Company` and `Region`. Change these if your tenant names the types differently. +- **Load size**: the whole file goes in one asynchronous launch, so loads aren't bound by the synchronous request timeout. Each row's SOAP request travels in the launch body (about 1 KB a row). **Batch history** shows the latest 100 rows. +- **Web service version**: the request uses Staffing v42.0. Update the version in the script and the orchestration's SOAP path together. + +### Tested so far + +Run end to end in a Workday development tenant (October 2026): CSV parsing, blank cells, bad dates, duplicate worker/date rows and unknown positions are caught before load; valid rows complete and show up in Worker History as Assign Organizations events; invalid organization IDs and pending-action conflicts come back as `SOAP_FAULT` with Workday's message. A 47-row file loaded in one background launch and finished in about a minute. Not yet observed: a change that routes to approval (the test user's changes auto-completed) and a successful custom organization assignment. diff --git a/examples/smart-csv-org-loader/appManifest.json b/examples/smart-csv-org-loader/appManifest.json new file mode 100644 index 0000000..a45fc2d --- /dev/null +++ b/examples/smart-csv-org-loader/appManifest.json @@ -0,0 +1,4 @@ +{ + "referenceId": "smartCsvOrgLoader", + "name": "Smart CSV Org Assignment Loader" +} \ No newline at end of file diff --git a/examples/smart-csv-org-loader/example.json b/examples/smart-csv-org-loader/example.json new file mode 100644 index 0000000..f322821 --- /dev/null +++ b/examples/smart-csv-org-loader/example.json @@ -0,0 +1,22 @@ +{ + "title": "Smart CSV Org Assignment Loader", + "description": "An Extend app and async orchestration that replaces multi-row Assign Organization EIB spreadsheets with a flat one-row-per-worker CSV: WQL pre-validation of workers and positions, Staffing Change_Organization_Assignments SOAP calls in the background, and per-row status write-back.", + "type": "Integration App", + "components": [ + "Presentation", + "Model", + "Orchestration", + "WQL" + ], + "products": [ + "Workday Extend", + "Workday Orchestrate", + "Workday SOAP API", + "Workday HCM" + ], + "authors": [ + "jadiyeom" + ], + "tutorial": "", + "source": "community" +} diff --git a/examples/smart-csv-org-loader/model/OrgAssignmentLoadRow.businessobject b/examples/smart-csv-org-loader/model/OrgAssignmentLoadRow.businessobject new file mode 100644 index 0000000..9a9afe8 --- /dev/null +++ b/examples/smart-csv-org-loader/model/OrgAssignmentLoadRow.businessobject @@ -0,0 +1,124 @@ +{ + "id": 1, + "name": "OrgAssignmentLoadRow", + "label": "Org Assignment Load Row", + "defaultSecurityDomains": [ + "SmartOrgLoaderDomain" + ], + "defaultCollection": { + "name": "orgAssignmentLoadRows", + "label": "Org Assignment Load Rows" + }, + "fields": [ + { + "id": 1, + "name": "batchId", + "type": "TEXT", + "isReferenceId": false, + "useForDisplay": false, + "isPurgeable": false, + "enableIndex": true, + "enableSearch": false + }, + { + "id": 2, + "name": "employeeId", + "type": "TEXT", + "isReferenceId": false, + "useForDisplay": true, + "isPurgeable": false, + "enableIndex": false, + "enableSearch": false + }, + { + "id": 3, + "name": "positionId", + "type": "TEXT", + "isReferenceId": false, + "useForDisplay": false, + "isPurgeable": false, + "enableIndex": false, + "enableSearch": false + }, + { + "id": 4, + "name": "effectiveDate", + "type": "TEXT", + "isReferenceId": false, + "useForDisplay": false, + "isPurgeable": false, + "enableIndex": false, + "enableSearch": false + }, + { + "id": 5, + "name": "costCenterRefId", + "type": "TEXT", + "isReferenceId": false, + "useForDisplay": false, + "isPurgeable": false, + "enableIndex": false, + "enableSearch": false + }, + { + "id": 6, + "name": "companyRefId", + "type": "TEXT", + "isReferenceId": false, + "useForDisplay": false, + "isPurgeable": false, + "enableIndex": false, + "enableSearch": false + }, + { + "id": 7, + "name": "regionRefId", + "type": "TEXT", + "isReferenceId": false, + "useForDisplay": false, + "isPurgeable": false, + "enableIndex": false, + "enableSearch": false + }, + { + "id": 8, + "name": "customOrgsPipeDelimited", + "type": "TEXT", + "isReferenceId": false, + "useForDisplay": false, + "isPurgeable": false, + "enableIndex": false, + "enableSearch": false + }, + { + "id": 9, + "name": "soapRequestXml", + "type": "TEXT", + "isReferenceId": false, + "useForDisplay": false, + "isPurgeable": false, + "enableIndex": false, + "enableSearch": false + }, + { + "id": 10, + "name": "validationStatus", + "type": "TEXT", + "isReferenceId": false, + "useForDisplay": false, + "isPurgeable": false, + "enableIndex": false, + "enableSearch": false + }, + { + "id": 11, + "name": "validationMessage", + "type": "TEXT", + "isReferenceId": false, + "useForDisplay": false, + "isPurgeable": false, + "enableIndex": false, + "enableSearch": false + } + ] +} \ No newline at end of file diff --git a/examples/smart-csv-org-loader/model/SmartOrgLoaderDomain.securitydomain b/examples/smart-csv-org-loader/model/SmartOrgLoaderDomain.securitydomain new file mode 100644 index 0000000..dcb03f9 --- /dev/null +++ b/examples/smart-csv-org-loader/model/SmartOrgLoaderDomain.securitydomain @@ -0,0 +1,6 @@ +{ + "id": 1, + "name": "SmartOrgLoaderDomain", + "enabledForPageSecurity": true, + "enabledForOrchestrationSecurity": true +} \ No newline at end of file diff --git a/examples/smart-csv-org-loader/orchestration/processOrgAssignmentLoad.orchestration b/examples/smart-csv-org-loader/orchestration/processOrgAssignmentLoad.orchestration new file mode 100644 index 0000000..7a2d400 --- /dev/null +++ b/examples/smart-csv-org-loader/orchestration/processOrgAssignmentLoad.orchestration @@ -0,0 +1,2581 @@ +{ + "flowVersion": "3.2.0", + "_type": "Flow", + "_value": { + "id": { + "_type": "String", + "_value": "554d9678cd4f42e0b129fbe30f8db42e" + }, + "name": { + "_type": "Identifier", + "_value": "processOrgAssignmentLoad" + }, + "type": { + "_type": "FlowType", + "_value": ".maya.FlowAsync" + }, + "start": { + "_type": "StartAsync", + "_value": { + "structuredRequest": { + "_type": [ + "Opt", + "RequestStructure" + ], + "_value": null + }, + "notes": { + "_type": [ + "List", + "Note" + ], + "_value": [ + { + "_type": "Note", + "_value": { + "key": { + "_type": "String", + "_value": "description" + }, + "value": { + "_type": "String", + "_value": "Async launch from the Extend page: body is {batchId, rows:[...]}. Returns immediately; per-row results land in the orgAssignmentLoadRows business object." + } + } + } + ] + } + } + }, + "end": { + "_type": "EndEmptyMaya", + "_value": { + "notes": { + "_type": [ + "List", + "Note" + ], + "_value": [] + } + } + }, + "nodes": { + "_type": [ + "List", + "Node" + ], + "_value": [ + { + "_type": "CreateValues", + "_value": { + "name": { + "_type": "Identifier", + "_value": "ParseRequest" + }, + "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": "batchId" + }, + "type": { + "_type": "Type", + "_value": "String" + }, + "default": { + "_type": [ + "Opt", + "Any" + ], + "_value": null + } + } + }, + "expr": { + "_type": [ + "Expr", + "String" + ], + "_value": { + "type": { + "_type": "Type", + "_value": "String" + }, + "source": { + "_type": "String", + "_value": "data(\"start\", \"request\").asJSON().stringAtJsonPath(\"$.batchId\")" + }, + "isAuto": { + "_type": "Boolean", + "_value": false + } + } + } + } + } + ] + }, + "notes": { + "_type": [ + "List", + "Note" + ], + "_value": [ + { + "_type": "Note", + "_value": { + "key": { + "_type": "String", + "_value": "description" + }, + "value": { + "_type": "String", + "_value": "Read the batchId the Extend page sent when it launched this orchestration" + } + } + } + ] + } + } + }, + { + "_type": "SendWorkdayApiRequest", + "_value": { + "name": { + "_type": "Identifier", + "_value": "GetStagedRows" + }, + "isDisabled": { + "_type": "Boolean", + "_value": true + }, + "errorHandler": { + "_type": [ + "Opt", + "ErrorHandler" + ], + "_value": null + }, + "body": { + "_type": [ + "Opt", + "DataRefBody" + ], + "_value": null + }, + "path": { + "_type": [ + "Expr", + "String" + ], + "_value": { + "type": { + "_type": "Type", + "_value": "String" + }, + "source": { + "_type": "String", + "_value": "s\"${\"/apps/\"}${context.appReferenceId()}${\"/v1/orgAssignmentLoadRows?limit=100\"}\"" + }, + "isAuto": { + "_type": "Boolean", + "_value": false + } + } + }, + "queryParams": { + "_type": [ + "List", + "QueryParam" + ], + "_value": [] + }, + "method": { + "_type": "HttpMethod", + "_value": "GET" + }, + "headers": { + "_type": [ + "List", + "Header" + ], + "_value": [] + }, + "auth": { + "_type": "WorkdayCredentialRef", + "_value": { + "resourceName": { + "_type": "String", + "_value": "_DEFAULT_WORKDAY_CREDENTIAL" + } + } + }, + "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" + }, + "notes": { + "_type": [ + "List", + "Note" + ], + "_value": [ + { + "_type": "Note", + "_value": { + "key": { + "_type": "String", + "_value": "description" + }, + "value": { + "_type": "String", + "_value": "Read staged rows from the app's business object (filtered to this batch in the loop)" + } + } + } + ] + } + } + }, + { + "_type": "Loop", + "_value": { + "name": { + "_type": "Identifier", + "_value": "Loop" + }, + "isDisabled": { + "_type": "Boolean", + "_value": false + }, + "errorHandler": { + "_type": [ + "Opt", + "ErrorHandler" + ], + "_value": null + }, + "inputData": { + "_type": [ + "Expr", + [ + "Iterator", + [ + "Opt", + "Any" + ] + ] + ], + "_value": { + "type": { + "_type": "Type", + "_value": [ + "Iterator", + [ + "Json", + { + "_type": [ + "Opt", + "JsonSchemaRef" + ], + "_value": null + } + ] + ] + }, + "source": { + "_type": "String", + "_value": "data(\"start\", \"request\").asJSON().iterator(\"$.rows[*]\")" + }, + "isAuto": { + "_type": "Boolean", + "_value": false + } + } + }, + "filter": { + "_type": [ + "Opt", + [ + "Expr", + "Boolean" + ] + ], + "_value": { + "_type": [ + "Expr", + "Boolean" + ], + "_value": { + "type": { + "_type": "Type", + "_value": "Boolean" + }, + "source": { + "_type": "String", + "_value": "data.Loop.item.stringAtJsonPath(\"$.batchId\") == data.ParseRequest.batchId" + }, + "isAuto": { + "_type": "Boolean", + "_value": false + } + } + } + }, + "aggregateNode": { + "_type": [ + "Opt", + "Aggregate" + ], + "_value": null + }, + "earlyStopCondition": { + "_type": [ + "Opt", + "EarlyStopCondition" + ], + "_value": null + }, + "sorts": { + "_type": [ + "List", + "SortedBy" + ], + "_value": [] + }, + "locale": { + "_type": [ + "Opt", + "Locale" + ], + "_value": null + }, + "group": { + "_type": "ImplicitGroup", + "_value": { + "name": { + "_type": "Identifier", + "_value": "_group_Loop" + }, + "isDisabled": { + "_type": "Boolean", + "_value": false + }, + "errorHandler": { + "_type": [ + "Opt", + "ErrorHandler" + ], + "_value": { + "_type": "ErrorHandler", + "_value": { + "name": { + "_type": "Identifier", + "_value": "_errorHandler_group_Loop" + }, + "isDisabled": { + "_type": "Boolean", + "_value": false + }, + "strategy": { + "_type": "ErrorHandlerStrategy", + "_value": "ConditionalOutputs" + }, + "nodes": { + "_type": [ + "List", + "Node" + ], + "_value": [ + { + "_type": "Log", + "_value": { + "name": { + "_type": "Identifier", + "_value": "LogRowError" + }, + "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": "\"\"\"Row failed; see the load history task for details\"\"\"" + }, + "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": [ + { + "_type": "Note", + "_value": { + "key": { + "_type": "String", + "_value": "description" + }, + "value": { + "_type": "String", + "_value": "Log the row error and continue with the next row" + } + } + } + ] + } + } + } + ] + }, + "notes": { + "_type": [ + "List", + "Note" + ], + "_value": [ + { + "_type": "Note", + "_value": { + "key": { + "_type": "String", + "_value": "description" + }, + "value": { + "_type": "String", + "_value": "" + } + } + } + ] + } + } + } + }, + "nodes": { + "_type": [ + "List", + "Node" + ], + "_value": [ + { + "_type": "CreateValues", + "_value": { + "name": { + "_type": "Identifier", + "_value": "RowFields" + }, + "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": "batchId" + }, + "type": { + "_type": "Type", + "_value": "String" + }, + "default": { + "_type": [ + "Opt", + "Any" + ], + "_value": null + } + } + }, + "expr": { + "_type": [ + "Expr", + "String" + ], + "_value": { + "type": { + "_type": "Type", + "_value": "String" + }, + "source": { + "_type": "String", + "_value": "data.Loop.item.stringAtJsonPath(\"$.batchId\")" + }, + "isAuto": { + "_type": "Boolean", + "_value": false + } + } + } + } + }, + { + "_type": "Assignment", + "_value": { + "param": { + "_type": "Parameter", + "_value": { + "name": { + "_type": "Identifier", + "_value": "employeeId" + }, + "type": { + "_type": "Type", + "_value": "String" + }, + "default": { + "_type": [ + "Opt", + "Any" + ], + "_value": null + } + } + }, + "expr": { + "_type": [ + "Expr", + "String" + ], + "_value": { + "type": { + "_type": "Type", + "_value": "String" + }, + "source": { + "_type": "String", + "_value": "data.Loop.item.stringAtJsonPath(\"$.employeeId\")" + }, + "isAuto": { + "_type": "Boolean", + "_value": false + } + } + } + } + }, + { + "_type": "Assignment", + "_value": { + "param": { + "_type": "Parameter", + "_value": { + "name": { + "_type": "Identifier", + "_value": "soapRequestXml" + }, + "type": { + "_type": "Type", + "_value": "String" + }, + "default": { + "_type": [ + "Opt", + "Any" + ], + "_value": null + } + } + }, + "expr": { + "_type": [ + "Expr", + "String" + ], + "_value": { + "type": { + "_type": "Type", + "_value": "String" + }, + "source": { + "_type": "String", + "_value": "data.Loop.item.stringAtJsonPath(\"$.soapRequestXml\")" + }, + "isAuto": { + "_type": "Boolean", + "_value": false + } + } + } + } + }, + { + "_type": "Assignment", + "_value": { + "param": { + "_type": "Parameter", + "_value": { + "name": { + "_type": "Identifier", + "_value": "positionId" + }, + "type": { + "_type": "Type", + "_value": "String" + }, + "default": { + "_type": [ + "Opt", + "Any" + ], + "_value": null + } + } + }, + "expr": { + "_type": [ + "Expr", + "String" + ], + "_value": { + "type": { + "_type": "Type", + "_value": "String" + }, + "source": { + "_type": "String", + "_value": "data.Loop.item.stringAtJsonPath(\"$.positionId\")" + }, + "isAuto": { + "_type": "Boolean", + "_value": false + } + } + } + } + }, + { + "_type": "Assignment", + "_value": { + "param": { + "_type": "Parameter", + "_value": { + "name": { + "_type": "Identifier", + "_value": "effectiveDate" + }, + "type": { + "_type": "Type", + "_value": "String" + }, + "default": { + "_type": [ + "Opt", + "Any" + ], + "_value": null + } + } + }, + "expr": { + "_type": [ + "Expr", + "String" + ], + "_value": { + "type": { + "_type": "Type", + "_value": "String" + }, + "source": { + "_type": "String", + "_value": "data.Loop.item.stringAtJsonPath(\"$.effectiveDate\")" + }, + "isAuto": { + "_type": "Boolean", + "_value": false + } + } + } + } + }, + { + "_type": "Assignment", + "_value": { + "param": { + "_type": "Parameter", + "_value": { + "name": { + "_type": "Identifier", + "_value": "costCenterRefId" + }, + "type": { + "_type": "Type", + "_value": "String" + }, + "default": { + "_type": [ + "Opt", + "Any" + ], + "_value": null + } + } + }, + "expr": { + "_type": [ + "Expr", + "String" + ], + "_value": { + "type": { + "_type": "Type", + "_value": "String" + }, + "source": { + "_type": "String", + "_value": "data.Loop.item.stringAtJsonPath(\"$.costCenterRefId\")" + }, + "isAuto": { + "_type": "Boolean", + "_value": false + } + } + } + } + }, + { + "_type": "Assignment", + "_value": { + "param": { + "_type": "Parameter", + "_value": { + "name": { + "_type": "Identifier", + "_value": "companyRefId" + }, + "type": { + "_type": "Type", + "_value": "String" + }, + "default": { + "_type": [ + "Opt", + "Any" + ], + "_value": null + } + } + }, + "expr": { + "_type": [ + "Expr", + "String" + ], + "_value": { + "type": { + "_type": "Type", + "_value": "String" + }, + "source": { + "_type": "String", + "_value": "data.Loop.item.stringAtJsonPath(\"$.companyRefId\")" + }, + "isAuto": { + "_type": "Boolean", + "_value": false + } + } + } + } + }, + { + "_type": "Assignment", + "_value": { + "param": { + "_type": "Parameter", + "_value": { + "name": { + "_type": "Identifier", + "_value": "regionRefId" + }, + "type": { + "_type": "Type", + "_value": "String" + }, + "default": { + "_type": [ + "Opt", + "Any" + ], + "_value": null + } + } + }, + "expr": { + "_type": [ + "Expr", + "String" + ], + "_value": { + "type": { + "_type": "Type", + "_value": "String" + }, + "source": { + "_type": "String", + "_value": "data.Loop.item.stringAtJsonPath(\"$.regionRefId\")" + }, + "isAuto": { + "_type": "Boolean", + "_value": false + } + } + } + } + }, + { + "_type": "Assignment", + "_value": { + "param": { + "_type": "Parameter", + "_value": { + "name": { + "_type": "Identifier", + "_value": "customOrgsPipeDelimited" + }, + "type": { + "_type": "Type", + "_value": "String" + }, + "default": { + "_type": [ + "Opt", + "Any" + ], + "_value": null + } + } + }, + "expr": { + "_type": [ + "Expr", + "String" + ], + "_value": { + "type": { + "_type": "Type", + "_value": "String" + }, + "source": { + "_type": "String", + "_value": "data.Loop.item.stringAtJsonPath(\"$.customOrgsPipeDelimited\")" + }, + "isAuto": { + "_type": "Boolean", + "_value": false + } + } + } + } + } + ] + }, + "notes": { + "_type": [ + "List", + "Note" + ], + "_value": [ + { + "_type": "Note", + "_value": { + "key": { + "_type": "String", + "_value": "description" + }, + "value": { + "_type": "String", + "_value": "Fields for this staged row" + } + } + } + ] + } + } + }, + { + "_type": "CreateTextTemplate", + "_value": { + "name": { + "_type": "Identifier", + "_value": "CreateRowBody" + }, + "isDisabled": { + "_type": "Boolean", + "_value": false + }, + "errorHandler": { + "_type": [ + "Opt", + "ErrorHandler" + ], + "_value": null + }, + "message": { + "_type": "TextTemplate", + "_value": "{\"batchId\": \"{{data.RowFields.batchId}}\", \"employeeId\": \"{{data.RowFields.employeeId}}\", \"positionId\": \"{{data.RowFields.positionId}}\", \"effectiveDate\": \"{{data.RowFields.effectiveDate}}\", \"costCenterRefId\": \"{{data.RowFields.costCenterRefId}}\", \"companyRefId\": \"{{data.RowFields.companyRefId}}\", \"regionRefId\": \"{{data.RowFields.regionRefId}}\", \"customOrgsPipeDelimited\": \"{{data.RowFields.customOrgsPipeDelimited}}\", \"validationStatus\": \"STAGED\", \"validationMessage\": \"Passed pre-validation\"}" + }, + "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": "" + } + } + } + ] + } + } + }, + { + "_type": "SendWorkdayApiRequest", + "_value": { + "name": { + "_type": "Identifier", + "_value": "CreateRow" + }, + "isDisabled": { + "_type": "Boolean", + "_value": false + }, + "errorHandler": { + "_type": [ + "Opt", + "ErrorHandler" + ], + "_value": null + }, + "body": { + "_type": [ + "Opt", + "DataRefBody" + ], + "_value": { + "_type": "DataRefBody", + "_value": { + "dataRef": { + "_type": [ + "Expr", + "Data" + ], + "_value": { + "type": { + "_type": "Type", + "_value": "Data" + }, + "source": { + "_type": "String", + "_value": "data.CreateRowBody.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": "s\"${\"/apps/\"}${context.appReferenceId()}${\"/v1/orgAssignmentLoadRows\"}\"" + }, + "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" + } + } + }, + "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" + }, + "notes": { + "_type": [ + "List", + "Note" + ], + "_value": [ + { + "_type": "Note", + "_value": { + "key": { + "_type": "String", + "_value": "description" + }, + "value": { + "_type": "String", + "_value": "Mark the row completed" + } + } + } + ] + } + } + }, + { + "_type": "CreateValues", + "_value": { + "name": { + "_type": "Identifier", + "_value": "CreatedRow" + }, + "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": "rowId" + }, + "type": { + "_type": "Type", + "_value": "String" + }, + "default": { + "_type": [ + "Opt", + "Any" + ], + "_value": null + } + } + }, + "expr": { + "_type": [ + "Expr", + "String" + ], + "_value": { + "type": { + "_type": "Type", + "_value": "String" + }, + "source": { + "_type": "String", + "_value": "data.CreateRow.response.asJSON().stringAtJsonPath(\"$.id\")" + }, + "isAuto": { + "_type": "Boolean", + "_value": false + } + } + } + } + } + ] + }, + "notes": { + "_type": [ + "List", + "Note" + ], + "_value": [ + { + "_type": "Note", + "_value": { + "key": { + "_type": "String", + "_value": "description" + }, + "value": { + "_type": "String", + "_value": "Fields for this staged row" + } + } + } + ] + } + } + }, + { + "_type": "CreateTextTemplate", + "_value": { + "name": { + "_type": "Identifier", + "_value": "ChangeOrgAssignmentsRequest" + }, + "isDisabled": { + "_type": "Boolean", + "_value": false + }, + "errorHandler": { + "_type": [ + "Opt", + "ErrorHandler" + ], + "_value": null + }, + "message": { + "_type": "TextTemplate", + "_value": "{{data.RowFields.soapRequestXml}}" + }, + "contentType": { + "_type": "String", + "_value": "application/xml" + }, + "formatRef": { + "_type": [ + "Opt", + "TextFormatRef" + ], + "_value": null + }, + "notes": { + "_type": [ + "List", + "Note" + ], + "_value": [ + { + "_type": "Note", + "_value": { + "key": { + "_type": "String", + "_value": "description" + }, + "value": { + "_type": "String", + "_value": "Change_Organization_Assignments_Request body, prebuilt and validated by the Extend page (blank org columns are omitted there)" + } + } + } + ] + } + } + }, + { + "_type": "SendWorkdayApiRequest", + "_value": { + "name": { + "_type": "Identifier", + "_value": "SOAP_Call" + }, + "isDisabled": { + "_type": "Boolean", + "_value": false + }, + "errorHandler": { + "_type": [ + "Opt", + "ErrorHandler" + ], + "_value": null + }, + "body": { + "_type": [ + "Opt", + "DataRefBody" + ], + "_value": { + "_type": "DataRefBody", + "_value": { + "dataRef": { + "_type": [ + "Expr", + "Data" + ], + "_value": { + "type": { + "_type": "Type", + "_value": "Data" + }, + "source": { + "_type": "String", + "_value": "data.ChangeOrgAssignmentsRequest.message.wrapSoapV11()" + }, + "isAuto": { + "_type": "Boolean", + "_value": false + } + } + }, + "contentType": { + "_type": [ + "Opt", + "String" + ], + "_value": null + } + } + } + }, + "path": { + "_type": [ + "Expr", + "String" + ], + "_value": { + "type": { + "_type": "Type", + "_value": "String" + }, + "source": { + "_type": "String", + "_value": "\"/soap/v42.0/Staffing\"" + }, + "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" + } + } + }, + "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" + }, + "notes": { + "_type": [ + "List", + "Note" + ], + "_value": [ + { + "_type": "Note", + "_value": { + "key": { + "_type": "String", + "_value": "description" + }, + "value": { + "_type": "String", + "_value": "Staffing v42.0 Change_Organization_Assignments" + } + } + } + ] + } + } + }, + { + "_type": "CreateValues", + "_value": { + "name": { + "_type": "Identifier", + "_value": "ResponseValues" + }, + "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": "response" + }, + "type": { + "_type": "Type", + "_value": "Data" + }, + "default": { + "_type": [ + "Opt", + "Any" + ], + "_value": null + } + } + }, + "expr": { + "_type": [ + "Expr", + "Data" + ], + "_value": { + "type": { + "_type": "Type", + "_value": "Data" + }, + "source": { + "_type": "String", + "_value": "data.SOAP_Call.response" + }, + "isAuto": { + "_type": "Boolean", + "_value": false + } + } + } + } + }, + { + "_type": "Assignment", + "_value": { + "param": { + "_type": "Parameter", + "_value": { + "name": { + "_type": "Identifier", + "_value": "resStatusCode" + }, + "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.SOAP_Call.responseStatusCode" + }, + "isAuto": { + "_type": "Boolean", + "_value": false + } + } + } + } + }, + { + "_type": "Assignment", + "_value": { + "param": { + "_type": "Parameter", + "_value": { + "name": { + "_type": "Identifier", + "_value": "isError" + }, + "type": { + "_type": "Type", + "_value": "Boolean" + }, + "default": { + "_type": [ + "Opt", + "Any" + ], + "_value": null + } + } + }, + "expr": { + "_type": [ + "Expr", + "Boolean" + ], + "_value": { + "type": { + "_type": "Type", + "_value": "Boolean" + }, + "source": { + "_type": "String", + "_value": "data.ResponseValues.resStatusCode.is2xxStatusCode().not().or(data.ResponseValues.response.isSoapFault())" + }, + "isAuto": { + "_type": "Boolean", + "_value": false + } + } + } + } + } + ] + }, + "notes": { + "_type": [ + "List", + "Note" + ], + "_value": [ + { + "_type": "Note", + "_value": { + "key": { + "_type": "String", + "_value": "description" + }, + "value": { + "_type": "String", + "_value": "" + } + } + } + ] + } + } + }, + { + "_type": "BranchOnConditions", + "_value": { + "name": { + "_type": "Identifier", + "_value": "WriteBackStatus" + }, + "isDisabled": { + "_type": "Boolean", + "_value": false + }, + "errorHandler": { + "_type": [ + "Opt", + "ErrorHandler" + ], + "_value": null + }, + "ifBranches": { + "_type": [ + "List", + "WhenBranch" + ], + "_value": [ + { + "_type": "WhenBranch", + "_value": { + "name": { + "_type": "Identifier", + "_value": "IF" + }, + "condition": { + "_type": [ + "Expr", + "Boolean" + ], + "_value": { + "type": { + "_type": "Type", + "_value": "Boolean" + }, + "source": { + "_type": "String", + "_value": "data.ResponseValues.isError" + }, + "isAuto": { + "_type": "Boolean", + "_value": false + } + } + }, + "group": { + "_type": "ImplicitGroup", + "_value": { + "name": { + "_type": "Identifier", + "_value": "_group_IF_BranchonConditions" + }, + "isDisabled": { + "_type": "Boolean", + "_value": false + }, + "errorHandler": { + "_type": [ + "Opt", + "ErrorHandler" + ], + "_value": null + }, + "nodes": { + "_type": [ + "List", + "Node" + ], + "_value": [ + { + "_type": "CreateValues", + "_value": { + "name": { + "_type": "Identifier", + "_value": "FaultText" + }, + "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": "message" + }, + "type": { + "_type": "Type", + "_value": "String" + }, + "default": { + "_type": [ + "Opt", + "Any" + ], + "_value": null + } + } + }, + "expr": { + "_type": [ + "Expr", + "String" + ], + "_value": { + "type": { + "_type": "Type", + "_value": "String" + }, + "source": { + "_type": "String", + "_value": "data.SOAP_Call.response.asXML().stringAtXPath(\"/*/*/*/faultstring\")" + }, + "isAuto": { + "_type": "Boolean", + "_value": false + } + } + } + } + } + ] + }, + "notes": { + "_type": [ + "List", + "Note" + ], + "_value": [ + { + "_type": "Note", + "_value": { + "key": { + "_type": "String", + "_value": "description" + }, + "value": { + "_type": "String", + "_value": "" + } + } + } + ] + } + } + }, + { + "_type": "CreateTextTemplate", + "_value": { + "name": { + "_type": "Identifier", + "_value": "FaultPatchBody" + }, + "isDisabled": { + "_type": "Boolean", + "_value": false + }, + "errorHandler": { + "_type": [ + "Opt", + "ErrorHandler" + ], + "_value": null + }, + "message": { + "_type": "TextTemplate", + "_value": "{\"validationStatus\": \"SOAP_FAULT\", \"validationMessage\": \"{{data.FaultText.message}}\"}" + }, + "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": "" + } + } + } + ] + } + } + }, + { + "_type": "SendWorkdayApiRequest", + "_value": { + "name": { + "_type": "Identifier", + "_value": "PatchRowFault" + }, + "isDisabled": { + "_type": "Boolean", + "_value": false + }, + "errorHandler": { + "_type": [ + "Opt", + "ErrorHandler" + ], + "_value": null + }, + "body": { + "_type": [ + "Opt", + "DataRefBody" + ], + "_value": { + "_type": "DataRefBody", + "_value": { + "dataRef": { + "_type": [ + "Expr", + "Data" + ], + "_value": { + "type": { + "_type": "Type", + "_value": "Data" + }, + "source": { + "_type": "String", + "_value": "data.FaultPatchBody.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": "s\"${\"/apps/\"}${context.appReferenceId()}${\"/v1/orgAssignmentLoadRows/\"}${data.CreatedRow.rowId}\"" + }, + "isAuto": { + "_type": "Boolean", + "_value": false + } + } + }, + "queryParams": { + "_type": [ + "List", + "QueryParam" + ], + "_value": [] + }, + "method": { + "_type": "HttpMethod", + "_value": "PATCH" + }, + "headers": { + "_type": [ + "List", + "Header" + ], + "_value": [] + }, + "auth": { + "_type": "WorkdayCredentialRef", + "_value": { + "resourceName": { + "_type": "String", + "_value": "_DEFAULT_WORKDAY_CREDENTIAL" + } + } + }, + "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" + }, + "notes": { + "_type": [ + "List", + "Note" + ], + "_value": [ + { + "_type": "Note", + "_value": { + "key": { + "_type": "String", + "_value": "description" + }, + "value": { + "_type": "String", + "_value": "Write the SOAP fault back to the row" + } + } + } + ] + } + } + } + ] + }, + "notes": { + "_type": [ + "List", + "Note" + ], + "_value": [] + } + } + } + } + } + ] + }, + "elseBranch": { + "_type": "ImplicitGroup", + "_value": { + "name": { + "_type": "Identifier", + "_value": "_else_BranchonConditions" + }, + "isDisabled": { + "_type": "Boolean", + "_value": false + }, + "errorHandler": { + "_type": [ + "Opt", + "ErrorHandler" + ], + "_value": null + }, + "nodes": { + "_type": [ + "List", + "Node" + ], + "_value": [ + { + "_type": "CreateTextTemplate", + "_value": { + "name": { + "_type": "Identifier", + "_value": "SuccessPatchBody" + }, + "isDisabled": { + "_type": "Boolean", + "_value": false + }, + "errorHandler": { + "_type": [ + "Opt", + "ErrorHandler" + ], + "_value": null + }, + "message": { + "_type": "TextTemplate", + "_value": "{\"validationStatus\": \"COMPLETED\", \"validationMessage\": \"Change_Organization_Assignments succeeded\"}" + }, + "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": "" + } + } + } + ] + } + } + }, + { + "_type": "SendWorkdayApiRequest", + "_value": { + "name": { + "_type": "Identifier", + "_value": "PatchRowSuccess" + }, + "isDisabled": { + "_type": "Boolean", + "_value": false + }, + "errorHandler": { + "_type": [ + "Opt", + "ErrorHandler" + ], + "_value": null + }, + "body": { + "_type": [ + "Opt", + "DataRefBody" + ], + "_value": { + "_type": "DataRefBody", + "_value": { + "dataRef": { + "_type": [ + "Expr", + "Data" + ], + "_value": { + "type": { + "_type": "Type", + "_value": "Data" + }, + "source": { + "_type": "String", + "_value": "data.SuccessPatchBody.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": "s\"${\"/apps/\"}${context.appReferenceId()}${\"/v1/orgAssignmentLoadRows/\"}${data.CreatedRow.rowId}\"" + }, + "isAuto": { + "_type": "Boolean", + "_value": false + } + } + }, + "queryParams": { + "_type": [ + "List", + "QueryParam" + ], + "_value": [] + }, + "method": { + "_type": "HttpMethod", + "_value": "PATCH" + }, + "headers": { + "_type": [ + "List", + "Header" + ], + "_value": [] + }, + "auth": { + "_type": "WorkdayCredentialRef", + "_value": { + "resourceName": { + "_type": "String", + "_value": "_DEFAULT_WORKDAY_CREDENTIAL" + } + } + }, + "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" + }, + "notes": { + "_type": [ + "List", + "Note" + ], + "_value": [ + { + "_type": "Note", + "_value": { + "key": { + "_type": "String", + "_value": "description" + }, + "value": { + "_type": "String", + "_value": "Mark the row completed" + } + } + } + ] + } + } + } + ] + }, + "notes": { + "_type": [ + "List", + "Note" + ], + "_value": [] + } + } + }, + "exceptionMessage": { + "_type": "String", + "_value": "None of the conditions are matched" + }, + "exceptionIfNoBranchMatched": { + "_type": "Boolean", + "_value": false + }, + "enableOutputs": { + "_type": "Boolean", + "_value": false + }, + "notes": { + "_type": [ + "List", + "Note" + ], + "_value": [ + { + "_type": "Note", + "_value": { + "key": { + "_type": "String", + "_value": "description" + }, + "value": { + "_type": "String", + "_value": "" + } + } + } + ] + } + } + } + ] + }, + "notes": { + "_type": [ + "List", + "Note" + ], + "_value": [] + } + } + }, + "notes": { + "_type": [ + "List", + "Note" + ], + "_value": [ + { + "_type": "Note", + "_value": { + "key": { + "_type": "String", + "_value": "description" + }, + "value": { + "_type": "String", + "_value": "One SOAP call per staged row; an error handler on the group logs and continues" + } + } + } + ] + } + } + } + ] + }, + "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.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": { + "_type": [ + "List", + "String" + ], + "_value": [ + { + "_type": "String", + "_value": "SmartOrgLoaderDomain" + } + ] + } + } + } +} \ No newline at end of file diff --git a/examples/smart-csv-org-loader/presentation/errorPage.pmd b/examples/smart-csv-org-loader/presentation/errorPage.pmd new file mode 100644 index 0000000..abc2080 --- /dev/null +++ b/examples/smart-csv-org-loader/presentation/errorPage.pmd @@ -0,0 +1,22 @@ +{ + "id": "errorPage", + "presentation": { + "title": { + "type": "title", + "id": "errTitle", + "label": "Something went wrong" + }, + "body": { + "type": "section", + "id": "errSection", + "children": [ + { + "type": "text", + "id": "errText", + "enabled": false, + "value": "The loader couldn't reach Workday. Try again, or check the integration event for details." + } + ] + } + } +} \ No newline at end of file diff --git a/examples/smart-csv-org-loader/presentation/scripts/csvParserAndValidator.script b/examples/smart-csv-org-loader/presentation/scripts/csvParserAndValidator.script new file mode 100644 index 0000000..a76ca0a --- /dev/null +++ b/examples/smart-csv-org-loader/presentation/scripts/csvParserAndValidator.script @@ -0,0 +1,140 @@ +/* + * Flat CSV -> validated rows -> Change_Organization_Assignments SOAP body. + * Columns: Employee_ID,Position_ID,Effective_Date,Cost_Center_ID,Company_ID,Region_ID,Custom_Org_1,Custom_Org_2,Custom_Org_3 + * Reference IDs never contain commas, so quoted cells are rejected with a clear message instead of parsed. + */ + +var cell = function(cols, i) { + return cols.size() > i ? string:trim(cols.get(i).replace('~', '')) : ''; +}; + +// string:split drops empty tokens, which would shift columns left when a cell is blank +// (e.g. a blank Company_ID would push Region_ID into the Company column). Wrapping every +// cell in '~' keeps each one non-empty; cell() strips the marker again. +var splitCells = function(line) { + return string:split('~' + line.replace('~', '').replace(',', '~,~') + '~', ','); +}; + +// Step 1: split the CSV into raw rows (no tenant calls yet) +var parseCsv = function(rawCsvText) { + var rows = []; + if (!string:isBlank(rawCsvText)) { + var lines = string:split(string:trim(rawCsvText), '\n'); + var lineNo = 0; + for (var rawLine : lines) { + lineNo = lineNo + 1; + var line = string:trim(rawLine); + if (lineNo > 1 && !string:isBlank(line)) { + var cols = splitCells(line); + list:add(rows, { + 'rowNumber': lineNo - 1, + 'hasQuotes': line.contains('"'), + 'employeeId': cell(cols, 0), 'positionId': cell(cols, 1), 'effectiveDate': cell(cols, 2), + 'costCenterRefId': cell(cols, 3), 'companyRefId': cell(cols, 4), 'regionRefId': cell(cols, 5), + 'customOrgs': list:filter([cell(cols, 6), cell(cols, 7), cell(cols, 8)], c => !string:isBlank(c)) + }); + } + } + } + return rows; +}; + +// Step 2: build WHERE ... IN lists so WQL only fetches the IDs in this file +var quoteList = function(ids) { + return list:distinct(list:filter(ids, i => !string:isBlank(i))).map(i => { "'" + i + "'" }).join(', '); +}; +var workerQuery = function(rows) { + return 'SELECT employeeID, positionID FROM workersForHCMReporting (dataSourceFilter = allActiveWorkers) WHERE employeeID IN (' + quoteList(rows.map(r => { r.employeeId })) + ')'; +}; +var orgQuery = function(rows) { + var ids = []; + for (var r : rows) { + list:add(ids, r.costCenterRefId); list:add(ids, r.companyRefId); list:add(ids, r.regionRefId); + for (var c : r.customOrgs) { list:add(ids, c); } + } + return 'SELECT referenceID, organizationType, inactive FROM organizations WHERE referenceID IN (' + quoteList(ids) + ')'; +}; + +var xmlEscape = function(s) { + return s.replace('&', '&').replace('<', '<').replace('>', '>'); +}; +var ref = function(element, idType, value) { + return '' + xmlEscape(value) + ''; +}; + +// Matches Staffing v42.0 Change_Organization_Assignments_Request. Blank columns are omitted, +// which tells Workday to keep the existing assignment. +var buildSoap = function(r, autoComplete) { + var orgs = ''; + if (!string:isBlank(r.companyRefId)) { orgs += ref('Company_Assignments_Reference', 'Company_Reference_ID', r.companyRefId); } + if (!string:isBlank(r.costCenterRefId)) { orgs += ref('Cost_Center_Assignments_Reference', 'Cost_Center_Reference_ID', r.costCenterRefId); } + if (!string:isBlank(r.regionRefId)) { orgs += ref('Region_Assignments_Reference', 'Region_Reference_ID', r.regionRefId); } + for (var c : r.customOrgs) { + orgs += '' + ref('Custom_Organization_Assignment_Reference', 'Custom_Organization_Reference_ID', c) + ''; + } + return '' + + '' + (autoComplete ? 'true' : 'false') + 'true' + + '' + + ref('Position_Reference', 'Position_ID', r.positionId) + + ref('Worker_Reference', 'Employee_ID', r.employeeId) + + '' + orgs + '' + + ''; +}; + +var checkOrg = function(orgMap, id, expectedType, errors) { + if (!string:isBlank(id)) { + if (!map:containsKey(orgMap, id)) { + list:add(errors, "Org Ref ID '" + id + "' does not exist"); + } else { + var org = map:get(orgMap, id); + if (org.inactive == true) { list:add(errors, "Org Ref ID '" + id + "' is inactive"); } + if (!empty expectedType && org.organizationType.descriptor != expectedType) { + list:add(errors, "'" + id + "' is a " + org.organizationType.descriptor + ", not a " + expectedType); + } + } + } +}; + +// Step 3: validate rows against the WQL results and attach the SOAP body to valid rows +var validateRows = function(rows, workers, orgs, autoComplete) { + var workerMap = {:}; + for (var w : list:nonNull(workers)) { map:put(workerMap, w.employeeID, w); } + var orgMap = {:}; + for (var o : list:nonNull(orgs)) { map:put(orgMap, o.referenceID, o); } + + var seen = {:}; + for (var r : rows) { + var errors = []; + var dupKey = r.employeeId + '|' + r.effectiveDate; + if (map:containsKey(seen, dupKey)) { list:add(errors, 'Duplicate of row ' + map:get(seen, dupKey) + ': one change per worker per effective date'); } + else { map:put(seen, dupKey, r.rowNumber); } + if (r.hasQuotes) { list:add(errors, 'Remove quotes: Reference IDs never contain commas'); } + if (string:isBlank(r.employeeId)) { list:add(errors, 'Missing Employee_ID'); } + else if (!map:containsKey(workerMap, r.employeeId)) { list:add(errors, "Employee_ID '" + r.employeeId + "' is not an active worker"); } + else if (!string:isBlank(r.positionId) && map:get(workerMap, r.employeeId).positionID != r.positionId) { + list:add(errors, "Position '" + r.positionId + "' isn't held by " + r.employeeId); + } + if (string:isBlank(r.positionId)) { list:add(errors, 'Missing Position_ID'); } + if (!validate:match('^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$', r.effectiveDate)) { list:add(errors, "Effective_Date '" + r.effectiveDate + "' must be YYYY-MM-DD"); } + if (orgs != null) { + checkOrg(orgMap, r.costCenterRefId, 'Cost Center', errors); + checkOrg(orgMap, r.companyRefId, 'Company', errors); + checkOrg(orgMap, r.regionRefId, 'Region', errors); + for (var c : r.customOrgs) { checkOrg(orgMap, c, '', errors); } + } + + r.customOrgsPipeDelimited = r.customOrgs.join('|'); + r.validationStatus = list:isEmpty(errors) ? 'VALID' : 'ERROR'; + r.validationMessage = list:isEmpty(errors) ? (orgs != null ? 'Ready to load' : 'Ready to load (organization IDs will be checked by Workday at load)') : errors.join('; '); + r.soapRequestXml = list:isEmpty(errors) ? buildSoap(r, autoComplete) : ''; + } + return rows; +}; + +/* Export all functions */ +{ + "parseCsv": parseCsv, + "workerQuery": workerQuery, + "orgQuery": orgQuery, + "validateRows": validateRows +} diff --git a/examples/smart-csv-org-loader/presentation/smartCsvOrgLoader.amd b/examples/smart-csv-org-loader/presentation/smartCsvOrgLoader.amd new file mode 100644 index 0000000..a187e5d --- /dev/null +++ b/examples/smart-csv-org-loader/presentation/smartCsvOrgLoader.amd @@ -0,0 +1,34 @@ +{ + "appProperties": [], + "tasks": [ + { + "id": "uploadAndValidateOrgCsv", + "routingPattern": "/", + "page": { + "id": "uploadAndValidateOrgCsv" + } + }, + { + "id": "viewLoadBatchHistory", + "routingPattern": "/history", + "page": { + "id": "viewLoadBatchHistory" + } + } + ], + "applicationId": "smartCsvOrgLoader", + "dataProviders": [ + { + "key": "workday-wql", + "value": "<% apiGatewayEndpoint + '/wql/v1/' %>" + }, + { + "key": "workday-app", + "value": "<% apiGatewayEndpoint + '/apps/' + site.applicationId + '/v1/' %>" + }, + { + "key": "orchestration", + "value": "<% apiGatewayEndpoint + '/orchestrate/v1/apps/' + site.applicationId + '/orchestrations/' %>" + } + ] +} \ No newline at end of file diff --git a/examples/smart-csv-org-loader/presentation/smartCsvOrgLoader.smd b/examples/smart-csv-org-loader/presentation/smartCsvOrgLoader.smd new file mode 100644 index 0000000..8aecb49 --- /dev/null +++ b/examples/smart-csv-org-loader/presentation/smartCsvOrgLoader.smd @@ -0,0 +1,22 @@ +{ + "id": "smartCsvOrgLoader", + "applicationId": "smartCsvOrgLoader", + "siteId": "smartCsvOrgLoader", + "languages": [ + { + "code": "en-US", + "description": "English" + } + ], + "siteAuth": { + "authTypes": [ + { + "scheme": "SSO", + "id": "sso" + } + ] + }, + "errorPage": { + "pageId": "errorPage" + } +} \ No newline at end of file diff --git a/examples/smart-csv-org-loader/presentation/uploadAndValidateOrgCsv.pmd b/examples/smart-csv-org-loader/presentation/uploadAndValidateOrgCsv.pmd new file mode 100644 index 0000000..39c4696 --- /dev/null +++ b/examples/smart-csv-org-loader/presentation/uploadAndValidateOrgCsv.pmd @@ -0,0 +1,260 @@ +{ + "id": "uploadAndValidateOrgCsv", + "securityDomains": [ + "SmartOrgLoaderDomain" + ], + "include": [ + "csvParserAndValidator.script" + ], + "endPoints": [ + { + "name": "workersWql", + "baseUrlType": "workday-wql", + "url": "data", + "httpMethod": "POST", + "authType": "sso", + "deferred": true, + "onSend": "<% self.data = {:}; self.data.query = pageVariables.workerQuery; self.data; %>", + "failOnStatusCodes": [ + { + "code": 400 + }, + { + "code": 403 + }, + { + "code": 500 + } + ] + }, + { + "name": "orgsWql", + "baseUrlType": "workday-wql", + "url": "data", + "httpMethod": "POST", + "authType": "sso", + "deferred": true, + "onSend": "<% self.data = {:}; self.data.query = pageVariables.orgQuery; self.data; %>", + "failOnStatusCodes": [ + { + "code": 403 + }, + { + "code": 500 + } + ] + }, + { + "name": "launchLoad", + "baseUrlType": "orchestration", + "url": "processOrgAssignmentLoad/launch", + "httpMethod": "POST", + "authType": "sso", + "deferred": true, + "onSend": "<% self.data = {'batchId': pageVariables.batchId, 'rows': pageVariables.launchRows}; self.data; %>", + "failOnStatusCodes": [ + { + "code": 400 + }, + { + "code": 403 + }, + { + "code": 500 + } + ] + } + ], + "presentation": { + "title": { + "type": "title", + "id": "pageTitle", + "label": "Smart CSV Org Assignment Loader" + }, + "body": { + "type": "section", + "id": "mainSection", + "children": [ + { + "type": "button", + "id": "historyLink", + "action": "LINK", + "label": "Batch history", + "taskReference": { + "taskId": "viewLoadBatchHistory" + } + }, + { + "type": "text", + "id": "intro", + "enabled": false, + "value": "Paste one row per worker. Every Employee, Position and Organization Reference ID is checked against your tenant before anything is loaded." + }, + { + "type": "textArea", + "id": "csvInput", + "label": "CSV (one row per worker)", + "value": "Employee_ID,Position_ID,Effective_Date,Cost_Center_ID,Company_ID,Region_ID,Custom_Org_1,Custom_Org_2,Custom_Org_3" + }, + { + "type": "checkBox", + "id": "autoComplete", + "label": "Auto-complete the business process (skips approvals)", + "value": false + }, + { + "type": "pageActionButton", + "id": "validateButton", + "label": "Validate", + "onClick": "<% var rows = csvParserAndValidator.parseCsv(csvInput.value); if (rows.isEmpty()) { pageVariables.rows = []; validationGrid.setRows([]); loadStatus.setValue('Paste at least one data row under the header, then click Validate.'); } else { pageVariables.workerQuery = csvParserAndValidator.workerQuery(rows); pageVariables.orgQuery = csvParserAndValidator.orgQuery(rows); var workers = workersWql.invoke().data; var orgResp = orgsWql.invoke(); var orgs = (orgResp != null && orgResp.data != null) ? orgResp.data : null; pageVariables.rows = csvParserAndValidator.validateRows(rows, workers, orgs, autoComplete.value); validationGrid.setRows(pageVariables.rows); loadStatus.setValue(''); } %>" + }, + { + "type": "grid", + "id": "validationGrid", + "label": "Pre-validation results", + "rows": "<% pageVariables.rows ?? [] %>", + "rowVariableName": "r", + "columns": [ + { + "type": "column", + "columnId": "rowCol", + "label": "Row", + "cellTemplate": { + "type": "text", + "id": "rowColCell", + "enabled": false, + "value": "<% r.rowNumber %>" + } + }, + { + "type": "column", + "columnId": "empCol", + "label": "Employee ID", + "cellTemplate": { + "type": "text", + "id": "empColCell", + "enabled": false, + "value": "<% r.employeeId %>" + } + }, + { + "type": "column", + "columnId": "posCol", + "label": "Position ID", + "cellTemplate": { + "type": "text", + "id": "posColCell", + "enabled": false, + "value": "<% r.positionId %>" + } + }, + { + "type": "column", + "columnId": "dateCol", + "label": "Effective Date", + "cellTemplate": { + "type": "text", + "id": "dateColCell", + "enabled": false, + "value": "<% r.effectiveDate %>" + } + }, + { + "type": "column", + "columnId": "ccCol", + "label": "Cost Center", + "cellTemplate": { + "type": "text", + "id": "ccColCell", + "enabled": false, + "value": "<% r.costCenterRefId %>" + } + }, + { + "type": "column", + "columnId": "compCol", + "label": "Company", + "cellTemplate": { + "type": "text", + "id": "compColCell", + "enabled": false, + "value": "<% r.companyRefId %>" + } + }, + { + "type": "column", + "columnId": "regCol", + "label": "Region", + "cellTemplate": { + "type": "text", + "id": "regColCell", + "enabled": false, + "value": "<% r.regionRefId %>" + } + }, + { + "type": "column", + "columnId": "custCol", + "label": "Custom Orgs", + "cellTemplate": { + "type": "text", + "id": "custColCell", + "enabled": false, + "value": "<% r.customOrgsPipeDelimited %>" + } + }, + { + "type": "column", + "columnId": "statusCol", + "label": "Status", + "cellTemplate": { + "type": "text", + "id": "statusColCell", + "enabled": false, + "value": "<% r.validationStatus %>" + } + }, + { + "type": "column", + "columnId": "msgCol", + "label": "Message", + "cellTemplate": { + "type": "text", + "id": "msgColCell", + "enabled": false, + "value": "<% r.validationMessage %>" + } + } + ] + }, + { + "type": "pageActionButton", + "id": "loadButton", + "label": "Load valid rows", + "onClick": "<% var validRows = empty pageVariables.rows ? [] : pageVariables.rows.filter(x => x.validationStatus == 'VALID'); if (validRows.isEmpty()) { loadStatus.setValue('Nothing to load: validate the CSV and fix at least one row first.'); } else { pageVariables.batchId = string:uuid(); var launchRows = []; for (var r : validRows) { launchRows.add({'batchId': pageVariables.batchId, 'employeeId': r.employeeId, 'positionId': empty r.positionId ? '' : r.positionId, 'effectiveDate': empty r.effectiveDate ? '' : r.effectiveDate, 'costCenterRefId': empty r.costCenterRefId ? '' : r.costCenterRefId, 'companyRefId': empty r.companyRefId ? '' : r.companyRefId, 'regionRefId': empty r.regionRefId ? '' : r.regionRefId, 'customOrgsPipeDelimited': empty r.customOrgsPipeDelimited ? '' : r.customOrgsPipeDelimited, 'soapRequestXml': r.soapRequestXml}); } pageVariables.launchRows = launchRows; launchLoad.invoke(); loadStatus.setValue('Load started in the background for ' + validRows.size() + ' valid row(s); rows marked ERROR were skipped. Batch ' + pageVariables.batchId + '. Open Batch history to watch progress: rows appear as STAGED, then COMPLETED or SOAP_FAULT.'); } %>" + }, + { + "type": "text", + "id": "loadStatus", + "label": "Load status", + "enabled": false, + "value": "" + } + ] + }, + "footer": { + "type": "footer", + "id": "pageFooter", + "children": [ + { + "type": "richText", + "id": "footerNote", + "enabled": false, + "value": "Workday Developer Program community example" + } + ] + }, + "pageType": "EDIT", + "standardEditButtonsHidden": true + } +} \ No newline at end of file diff --git a/examples/smart-csv-org-loader/presentation/viewLoadBatchHistory.pmd b/examples/smart-csv-org-loader/presentation/viewLoadBatchHistory.pmd new file mode 100644 index 0000000..75b22b5 --- /dev/null +++ b/examples/smart-csv-org-loader/presentation/viewLoadBatchHistory.pmd @@ -0,0 +1,130 @@ +{ + "id": "viewLoadBatchHistory", + "securityDomains": [ + "SmartOrgLoaderDomain" + ], + "endPoints": [ + { + "name": "countRows", + "baseUrlType": "workday-app", + "url": "orgAssignmentLoadRows?limit=1", + "authType": "sso", + "failOnStatusCodes": [ + { + "code": 400 + }, + { + "code": 403 + }, + { + "code": 500 + } + ] + }, + { + "name": "loadRows", + "baseUrlType": "workday-app", + "url": "<% 'orgAssignmentLoadRows?limit=100&offset=' + ((countRows.total != null && countRows.total > 100) ? (countRows.total - 100) : 0) %>", + "authType": "sso", + "failOnStatusCodes": [ + { + "code": 400 + }, + { + "code": 403 + }, + { + "code": 500 + } + ] + } + ], + "presentation": { + "title": { + "type": "title", + "id": "histTitle", + "label": "Org Assignment Batch History" + }, + "body": { + "type": "section", + "id": "histSection", + "children": [ + { + "type": "grid", + "id": "historyGrid", + "label": "Loaded rows (latest 100)", + "rows": "<% loadRows.data %>", + "rowVariableName": "h", + "columns": [ + { + "type": "column", + "columnId": "hBatch", + "label": "Batch", + "cellTemplate": { + "type": "text", + "id": "hBatchCell", + "enabled": false, + "value": "<% h.batchId %>" + } + }, + { + "type": "column", + "columnId": "hEmp", + "label": "Employee ID", + "cellTemplate": { + "type": "text", + "id": "hEmpCell", + "enabled": false, + "value": "<% h.employeeId %>" + } + }, + { + "type": "column", + "columnId": "hPos", + "label": "Position ID", + "cellTemplate": { + "type": "text", + "id": "hPosCell", + "enabled": false, + "value": "<% h.positionId %>" + } + }, + { + "type": "column", + "columnId": "hDate", + "label": "Effective Date", + "cellTemplate": { + "type": "text", + "id": "hDateCell", + "enabled": false, + "value": "<% h.effectiveDate %>" + } + }, + { + "type": "column", + "columnId": "hStatus", + "label": "Status", + "cellTemplate": { + "type": "text", + "id": "hStatusCell", + "enabled": false, + "value": "<% h.validationStatus %>" + } + }, + { + "type": "column", + "columnId": "hMsg", + "label": "Message", + "cellTemplate": { + "type": "text", + "id": "hMsgCell", + "enabled": false, + "value": "<% h.validationMessage %>" + } + } + ] + } + ] + } + } +} \ No newline at end of file diff --git a/examples/smart-csv-org-loader/samples/assign_org_sample_template.csv b/examples/smart-csv-org-loader/samples/assign_org_sample_template.csv new file mode 100755 index 0000000..6580c81 --- /dev/null +++ b/examples/smart-csv-org-loader/samples/assign_org_sample_template.csv @@ -0,0 +1,6 @@ +Employee_ID,Position_ID,Effective_Date,Cost_Center_ID,Company_ID,Region_ID,Custom_Org_1,Custom_Org_2,Custom_Org_3 +EMP_21001,P-00104,2026-11-01,CC_410_ENG,COMP_GLOBAL_US,REG_AMER_WEST,CUST_PROJ_APOLLO,CUST_SEC_CLOUD,CUST_SQUAD_CORE +EMP_21002,P-00108,2026-11-01,CC_420_PROD,COMP_GLOBAL_US,REG_AMER_EAST,CUST_PROJ_APOLLO,CUST_SEC_DATA, +EMP_21003,P-00115,2026-11-01,CC_510_FIN,COMP_EMEA_UK,REG_EMEA_NORTH,CUST_PROJ_HORIZON,, +EMP_99999,P-00999,2026-11-01,CC_INVALID_99,COMP_GLOBAL_US,REG_AMER_WEST,CUST_UNKNOWN_ORG,, +EMP_21004,P-00122,11/01/2026,CC_410_ENG,COMP_INACTIVE_01,REG_APAC_IN,CUST_PROJ_APOLLO,CUST_SEC_AI,