Here is a Standard Operating Procedure (SOP) document summarizing the interaction, configuration, and execution of the INT6001 and INT6002 Accounting Journals Outbound integrations.
This document is designed for the HRIS/Financial Systems team responsible for maintaining property mappings and scheduling these integrations.
INT6001 and INT6002 are duplicate Workday Studio integrations designed to extract General Ledger (GL) activity and ending balances for ingestion into the ProfitSword (BRAINS) system.
While the integrations share identical source code and logic, they function as two distinct "pipelines" to allow for:
Segmentation: Splitting the processing load between two different lists of properties (Companies).
Scheduling Flexibility: Delivering data for specific groups of hotels at different times of the day/month.
Output Separation: Producing distinct output files for each group to streamline ingestion on the ProfitSword side.
Both integrations follow the exact same execution path. The only variable is the input list of companies, which is defined by an Integration Attribute.
Launch & Parameters: The integration is launched (manually or scheduled) with a specific Fiscal Period and Time Period.
Property Selection: The integration looks up the specific Integration Attribute configured for that system (INT6001 or INT6002) to determine which companies to process1111.
+1
Iterative Processing: The integration loops through every selected company one by one.
It retrieves Journal Lines (Activity and Ending Balance) for that specific company.
It retrieves Translation Codes (BRAINS codes) to map Workday "Outlet" values to ProfitSword codes.
Transformation:
GL Balance: Aggregates totals by Ledger Account, Cost Center, and Spend Category.
GL Detail: extracting granular journal line details (Invoice #, Supplier, etc.).
Aggregation & Output: All individual company data is combined into two final CSV files per integration run:
GL_Balances_YYYYMMDDHHMMSS.csv
GL_Detail_YYYYMMDDHHMMSS.csv
This is the most critical step for the team. A company must only be mapped to ONE integration at a time to avoid duplicate data in ProfitSword.
To assign a hotel/entity to a specific integration pipeline:
Search for Configure Integration Attributes in Workday.
Select the specific integration system:
Choose INT6001 Accounting Journals Outbound for Group A (e.g., Managed Hotels).
Choose INT6002 Accounting Journals Outbound for Group B (e.g., Franchised/Other).
Locate the attribute: "Companies / Company Hierarchies"6666.
+1
Action: Add or Remove Company Reference IDs from this list.
Note: Ensure the company is not listed in both integrations.
Since both integrations query the exact same Journal Lines data source, they can compete for system resources if run simultaneously.
Recommendation: Offset the schedules by at least 30–60 minutes.
Example: Schedule INT6001 to run at 2:00 AM and INT6002 to run at 3:00 AM.
SFTP Delivery: Both integrations will deliver files to the configured SFTP server. The filenames will differ only by the timestamp and the content (based on the mapped companies).
"Missing Data" in ProfitSword:
Cause: The company was created in Workday but not added to the Integration Attribute list for either INT6001 or INT6002.
Fix: Follow the steps in Section 3 to add the new company to the correct integration map.
Duplicate Data:
Cause: A company was added to both INT6001 and INT6002 attributes.
Fix: Audit both attribute lists and remove the duplicate.
Timeout / Performance Failures:
Cause: If one integration is overloaded (e.g., INT6001 has 200 companies and INT6002 has 10), INT6001 may time out.
Fix: Balance the load by moving some companies from the "heavy" integration to the "light" one using the Attribute settings.
INT6002 Creation: Cloned from INT6001 to allow parallel processing of distinct property groups.
Codebase: Both integrations utilize the same GLBalance.xsl and GLDetail.xsl transformations. Any code changes (XSLT updates) must be applied to both integrations to maintain consistency.
Purpose The INT6001 integration automates the extraction of financial data from Workday for ProfitSword, a business intelligence and data management platform used in the hospitality industry. It bridges the gap between Workday Financials and ProfitSword by delivering accurate General Ledger (GL) data in a specific format required for financial reporting and forecasting.
Key Capabilities
Dual-Level Reporting: It generates two distinct output files simultaneously:
GL Balances: A high-level summary of ending balances and activity totals for the period.
GL Details: A granular, transaction-level log of every journal entry, invoice, and payment.
Intelligent Mapping: The system automatically translates internal Workday "Outlet" IDs into ProfitSword "Translation Codes" using a dynamic lookup, eliminating the need for manual cross-referencing.
Scalable Architecture: It uses a "Split-and-Aggregate" technical design. This allows it to process multiple companies sequentially without running out of memory, while still delivering a single, unified file for the end-user.
Workflow Overview
Launch: A user or schedule triggers the integration for a specific Fiscal Period (e.g., Nov 2024).
Process: The system identifies all relevant companies, extracts their financial activity and balance data, and applies complex formatting rules (XSLT).
Deliver: The final output is two CSV files (GL_Balances_....csv and GL_Detail_....csv) attached to the integration event record in Workday.
Business Value
Automation: Replaces manual report running and Excel manipulation with a single-click or scheduled process.
Auditability: By providing both summary and detail files from the same source snapshot, it ensures that financial reports in ProfitSword can be easily reconciled back to Workday.
Reliability: Technical safeguards (error handling and memory management) ensure the integration runs successfully even during high-volume period-close cycles.
Document ID: SOP-INT6001-001
Integration Type: Workday Studio Custom Integration
System ID: INT6001
Version: 2024.11
This integration extracts General Ledger (GL) data from Workday for consumption by the ProfitSword system. It processes financial data for specific companies and periods, aggregating the results into two distinct CSV output files:
GL Balances: Summary level data including ending balances and activity amounts.
GL Details: Transactional level details for the journals.
The integration runs a "Split-and-Aggregate" pattern: it splits processing by Company, fetches data via Report-as-a-Service (RaaS), transforms the data using XSLT, and aggregates the results into single batch files.
When launching this integration, the following parameters are required:
Note: The integration also utilizes an Attribute Map named Companies / Company Hierarchies to determine which Companies to process. This is configured on the Integration System, not selected at runtime.
Parameter Retrieval: The integration captures the Period and Time Period WIDs.
Company Selection: It retrieves the list of companies from the Companies / Company Hierarchies attribute.
Translation Codes: It calls a specific RaaS (OutletTranslationCode) to fetch mapping data that links "Outlets" to "Translation Codes." This data is cached in memory variable v.TRACodes for later use.
The integration iterates through every Company found in the attribute map. For each company, the following steps occur:
Fetch Activity: Calls the JournalLines RaaS filtering by Amount_Type = 'ACTIVITY'.
Fetch Ending Balance: Calls the JournalLines RaaS filtering by Amount_Type = 'END_BALANCE'.
Data Consolidation:
Merges Activity Data, Ending Balance Data, and the cached Translation Codes into a single XML structure.
Applies XSLT GenerateActivityTotalsXML.xsl to calculate totals.
Snapshot: Saves an intermediate XML file WD_Data_@{Company}.xml to the event documents (useful for debugging).
Transformation:
Balance Data: Applies GLBalance.xsl to format the data for the Balance CSV.
Detail Data: Applies GLDetail.xsl to format the data for the Detail CSV.
Aggregation: The transformed lines are sent to two separate aggregators (DetailGLAggregator and BalanceGLAggregator) to be held until all companies are processed.
Once all companies are processed:
Batch Processing: The aggregators release the combined data.
Header Generation:
A CSV header is prepended to the Balance data.
A CSV header is prepended to the Detail data.
File Naming: Files are named using the pattern:
GL_Balances_YYYYMMDDHHMMSS.csv
GL_Detail_YYYYMMDDHHMMSS.csv
Delivery: The files are attached to the Integration Event via PutIntegrationMessage and marked as deliverable.
OutletTranslationCode: Used to map internal Outlet IDs to external Translation Codes.
JournalLines: The primary data source. It accepts parameters for Company, Amount Type, Period, and Time Period.
GenerateActivityTotalsXML.xsl: Calculates math/totals within the XML before CSV conversion.
GLBalance.xsl: Transforms the XML XML data into the CSV structure for the Balances file.
GLDetail.xsl: Transforms the XML data into the CSV structure for the Details file.
Columns: Period, Company, Ledger Account, Cost Center, Spend Code, Revenue Code, Job Title, Outlet, Meal Period, Hotel Lot and Unit, Bank Account, Intercompany Affiliate, Translation Code, Ending_Balance_Amount, Activity_Amount
Columns: Accounting_Journal_ID, Journal_Entry_Status_ID, Period, Ledger_Reference_ID, Journal_Number, Journal_Source_ID, Currency_ID, Company, Ledger Account, Revenue Code, Cost Center, Spend Code, Job Title, Outlet, Meal Period, Hotel Lot and Unit, Bank Account, Intercompany Affiliate, Translation Code, Accounting_Date, DESCRIPTION, Debit_Amount, Credit_Amount, Supplier_Invoice_ID, Invoice_Number, Document_Status_ID, Supplier_ID, Invoice_Date, Payment Number, Date Paid, Invoice WID
If data looks incorrect in the final CSV, look at the Integration Attachments. The integration saves a file named WD_Data_[CompanyID].xml for every company processed. Download this file to see the raw data before it was converted to CSV.
Here are the templates for the two XSLT files required by your integration (GLBalance.xsl and GLDetail.xsl).
Important Configuration Note:
Since I do not have the exact XML Schema (XSD) of your specific Workday Reports (JournalLines and OutletTranslationCode), I have used standard Workday RaaS namespaces (urn:com.workday/bsvc) and logical field names. You must replace the specific XPath field names (e.g., wd:Ledger_Account/wd:ID) with the actual field names from your specific RaaS output.
This stylesheet generates the summarized balance data. It iterates through the <ending_balance> section of your aggregated data and performs a lookup for the Translation Code.
XML
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:wd="urn:com.workday/bsvc"
exclude-result-prefixes="wd">
<xsl:output method="text" indent="no" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:key name="TraCodeKey" match="TRACodes/wd:Report_Data/wd:Report_Entry" use="wd:Outlet_ID"/>
<xsl:template match="/">
<xsl:apply-templates select="data/ending_balance/wd:Report_Data/wd:Report_Entry"/>
</xsl:template>
<xsl:template match="wd:Report_Entry">
<xsl:variable name="outletID" select="wd:Outlet/wd:ID[@wd:type='Outlet_ID']"/>
<xsl:variable name="translationCode">
<xsl:for-each select="/data">
<xsl:value-of select="key('TraCodeKey', $outletID)/wd:Translation_Code"/>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="wd:Fiscal_Period/wd:Descriptor"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Company/wd:ID[@wd:type='Company_Reference_ID']"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Ledger_Account/wd:ID[@wd:type='Ledger_Account_ID']"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Cost_Center/wd:ID[@wd:type='Cost_Center_Reference_ID']"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Spend_Category/wd:ID[@wd:type='Spend_Category_ID']"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Revenue_Category/wd:ID[@wd:type='Revenue_Category_ID']"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Job_Profile/wd:Descriptor"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="$outletID"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Meal_Period"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Hotel_Lot_Unit"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Bank_Account"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Intercompany_Affiliate"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="$translationCode"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Ending_Balance_Amount"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Activity_Amount"/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
This stylesheet generates the transaction level details. It likely iterates through the <activity> section of your data (or wherever the journal lines are stored) and maps fields to the larger detail CSV specification.
XML
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:wd="urn:com.workday/bsvc"
exclude-result-prefixes="wd">
<xsl:output method="text" indent="no" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:key name="TraCodeKey" match="TRACodes/wd:Report_Data/wd:Report_Entry" use="wd:Outlet_ID"/>
<xsl:template match="/">
<xsl:apply-templates select="data/activity/wd:Report_Data/wd:Report_Entry"/>
</xsl:template>
<xsl:template match="wd:Report_Entry">
<xsl:variable name="outletID" select="wd:Outlet/wd:ID[@wd:type='Outlet_ID']"/>
<xsl:variable name="translationCode">
<xsl:for-each select="/data">
<xsl:value-of select="key('TraCodeKey', $outletID)/wd:Translation_Code"/>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="wd:Accounting_Journal_ID"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Journal_Status_ID"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Fiscal_Period/wd:Descriptor"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Ledger/wd:ID[@wd:type='Ledger_Reference_ID']"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Journal_Number"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Journal_Source_ID"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Currency/wd:ID[@wd:type='Currency_ID']"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Company/wd:ID[@wd:type='Company_Reference_ID']"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Ledger_Account/wd:ID[@wd:type='Ledger_Account_ID']"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Revenue_Category/wd:ID[@wd:type='Revenue_Category_ID']"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Cost_Center/wd:ID[@wd:type='Cost_Center_Reference_ID']"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Spend_Category/wd:ID[@wd:type='Spend_Category_ID']"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Job_Profile/wd:Descriptor"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="$outletID"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Meal_Period"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Hotel_Lot_Unit"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Bank_Account"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Intercompany_Affiliate"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="$translationCode"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Accounting_Date"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="replace(wd:Description, ',', ' ')"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Debit_Amount"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Credit_Amount"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Supplier_Invoice_ID"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Invoice_Number"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Document_Status_ID"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Supplier/wd:ID[@wd:type='Supplier_ID']"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Invoice_Date"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Payment_Number"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Date_Paid"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="wd:Invoice_WID"/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
Pipeline Name: Workday to ProfitSword GL Extract
Pipeline Type: Batch / Scheduled
Source System: Workday Financials (GL)
Target System: ProfitSword (via CSV file exchange)
Middleware: Workday Studio
The pipeline utilizes a "Split-Extract-Aggregate" pattern. To avoid timeouts and memory issues common with large financial data sets, the integration splits the request by Company, extracts data for each company individually, and then re-aggregates the results into a single payload for delivery.
Trigger: Scheduled or Ad-hoc Manual Launch.
Scope Definition:
Time: Determined by Launch Parameters (Period, Time Period).
Entity: Determined by Integration Attribute (Companies / Company Hierarchies).
The pipeline extracts data from three distinct internal Workday Report-as-a-Service (RaaS) endpoints:
Reference Caching: SRC_01 is called once at the start. The output is stored in a global variable (v.TRACodes) to allow for O(1) lookup speeds during transformation, preventing repeated API calls.
Company Iteration: The pipeline iterates through the list of companies provided in the Attribute Map.
Dual-Pass Extraction: For each company:
Pass 1: Call SRC_02 (Activity).
Pass 2: Call SRC_03 (Balance).
This pipeline performs complex transformations including data merging, arithmetic calculation, and format conversion.
Before conversion to CSV, the raw data streams are merged into a temporary XML "Super-Document" (v.AggregatedData) for the current company being processed.
Structure:
XML
<data>
<ending_balance>... (From SRC_03) ...</ending_balance>
<activity>... (From SRC_02) ...</activity>
<TRACodes>... (From SRC_01) ...</TRACodes>
<activity_totals>... (Calculated below) ...</activity_totals>
</data>
Lookup Logic: The XSLT uses the Outlet_ID from the Journal Lines to query the TRACodes block and inject the correct external Translation Code into the final output.
A specific XSLT (GenerateActivityTotalsXML.xsl) is applied to the merged XML to generate the <activity_totals> node.
Logic: Aggregates debits and credits from the transaction lines to ensure the summary file matches the detail file.
Two parallel XSLT transformations occur to generate the final flat files:
Stream A: Balance File (GLBalance.xsl)
Input: <ending_balance> nodes.
Output: Comma-Separated Values.
Key Transformation: Denormalizes the hierarchical XML into a single flat row per ledger account/dimension combination.
Stream B: Detail File (GLDetail.xsl)
Input: <activity> nodes.
Output: Comma-Separated Values.
Key Transformation: Flattens complex journal headers and lines into a single row per transaction line. Handles comma escaping in the Description field.
Because the data was extracted per company, it must be re-assembled.
Aggregator Component: DetailGLAggregator and BalanceGLAggregator.
Logic: The aggregators hold all transformed CSV fragments in memory.
Release Condition: When the Splitter signals that the last company has been processed (batch=true), the aggregator releases the combined dataset.
Once the aggregated payload is released:
Header Injection: The static CSV headers are prepended to the top of the data stream.
File Naming:
GL_Balances_YYYYMMDDHHMMSS.csv
GL_Detail_YYYYMMDDHHMMSS.csv
Mechanism: PutIntegrationMessage (Workday Core Connector Standard Action).
Result: Files are attached to the Workday Integration Event. External retrieval is handled by a separate connector or manual download from this event.
Mechanism: cc:send-error hooked to global-error-handler.
Action: If any unhandled exception occurs (e.g., SOAP Fault, Null Pointer), the integration:
Catches the error context.
Sets the integration status to CRITICAL.
Logs the error summary to the Integration Event.
Missing Parameters: If Period or Time Period are missing at launch, the integration fails immediately (Launch Option: required).
Empty Reports: If a Company returns 0 rows, the XSLT produces an empty string for that segment, ensuring the pipeline continues for other companies.
Memory Management: The "Splitter" is critical here. By processing one company at a time and converting to CSV (text) before aggregation, the memory footprint is significantly reduced compared to aggregating the full DOM (XML) of all companies at once.
Retention Policy: Intermediate debug files (WD_Data_*.xml) are set to expire in 30 Days (P30D) to manage storage.