Alma Invoices to Duke Accounts Payable (AP) Integration
This page defines the requirements to export Alma invoice data for submission to the Duke Accounts Payable system in the format designated by Duke AP.
Integration Diagram

Current Aleph Process Description
- References:
- Current Flat File Layout from Duke Accounts Payable
- Documentation about the current Aleph Invoice Processing Procedure and Accounting Invoice Workflow
- Current scripts: https://gitlab.oit.duke.edu/aleph/home/-/tree/23_prod/home-slash-aleph/r3?ref_type=heads
Each of the Duke University libraries sends a separate file to Duke AP. The process is initiated by a service from Aleph (custom-12 service) run on demand which generates an extract, the contents of which can be filtered based on:
- Ordering Unit
- Invoice type (regular, prepaid, proforma, deposit, internal (for credit card payments), void)
- Payment Status (paid, not ready to be paid, ready to be paid, payment authorization given, paid and sent to R/3, user invoice)
A custom script reads the data extracted from Aleph to generate a flat file in the format described below in this document.
Frequency
DUL runs their extract of invoices for payment 2-3 times per week - not sure about each of the independent libraries.
SAP Upgrade
Duke Accounts Payable will convert from SAP R/3 to R/4 (not sure of the exact timeline), but has asked that we continue to send our data in the same format.
SAP Interface Overview
The following overview of the interface was provided by Duke Accounts Payable to all university departments that need to submit invoices electronically.
The interface provides a means of creating R/3 invoices from non-R/3 applications.
- The external application writes information to a file (fixed format, 290 characters wide).
- The data file is transferred to the R/3 environment.
- A program creates R/3 invoices from the data file.
Underlying Requirements / Assumptions
- No zero dollar amounts can be sent.
- Documents must be balanced (sum of credits equals sum of debits).
Technical Overview File Structure
In this section, we’ll describe what the interface file should look like. It is an ordered file of headers and line items. An R/3 invoice document consists of a header with 2 or more line items. A document consists of 1 header with 2-950 non-zero dollar amount line items whose sum of debits and credits is $ 0.00.
A file to be sent to R/3 can contain multiple documents. As such, it is a header, followed by 2-950 line items, followed by a header with 2-950 line items…..In other words, a File is composed of Documents – Documents are composed of a Header Record followed by 2-950 Line Item Records. There are two types of line layouts – headers and line items.
Structures, Fields and Positions
- All fields are represented as character.
- Dates are given in the format mmddyyyy.
- Positions are given as start/stop within the structure, and as start/stop within the combined record.
- All records are fixed format and 290 characters in length.
Alma Invoice Export
After an invoice is exported, it is marked as Waiting for Payment, depending on the configuration of the institution’s handle_invoice_payment parameter. See the Configuration section below for more information about configuration settings required for this integration.
For details, see Invoicing Workflow and Working with Invoices Waiting for Payment.
Note that vendors do not usually use the same invoice number twice. The combination of invoice number and vendor code, therefore, usually uniquely identifies the invoice. However, some institutions work with vendors that use the same invoice number multiple times (for serials, for example). These institutions must set the invoice_not_unique parameter to true (see Alma OLH). They then use the unique invoice identifier assigned by Alma as the unique identifier of the invoice. All three fields—invoice number, vendor code, and unique identifier—are exported by Alma. The unique identifier is stored in the financial system and supplied as part of the import, for invoice identification.
Running the Export Job
This job is meant to be scheduled; however, for testing purposes, it is possible to manually run a finance job. To do this, the user must have the General Administrator role to run the job.- On the Integration Profile List page, locate the profile and select Edit in the row actions list. The General Information tab appears.
- Select the Actions tab. The details you defined appear.
- To run an export job immediately, select Run in the relevant section. The job is run and the file is sent to / taken from the configured FTP location. If email notifications are enabled in Alma, you receive notification via email.
ETL Requirements
- Once the invoice export job runs, the exported files need to be transformed into the format defined by Duke AP in this specification document.
- Paid Payment Status Update: Alma doesn't change the payment status of the invoice from "Waiting for Payment" to "Closed" automatically upon extract. This would cause a time-consuming addition to our staff's workflow for invoice processing, so the Alma Payment Confirmation job will run after the transformation is complete. This job will pick up an XML file from the S/FTP server containing all invoices that were just extract to update the payment information. If the invoice was sent to AP, the payment status is set to 'Paid.' If the invoice meets any of the error criteria, such as a blank barcode value for DUL or Law, the payment status is set to 'REJECTED.'
If invoice export is configured, Alma assigns invoices that are ready for payment a Ready to Be Paid status. When the export job runs, all the invoices with this status are exported, except for the following:
- Invoices marked as Internal copy
- invoices marked as Prepaid
Note that all invoices that meet the criteria for export are included across all libraries. The owner library of the invoice is one of the fields in the file and is also included in the export file name, but we can't run the job separately for each independent library. We can split the output into separate files for each library if that is preferred; however we won't be able to use the "split by owner" feature since it's based on the invoice owner, not the PO line owner. Our invoices were all migrated to Alma with the institution "Duke University " as the invoice owner and in the future any imported invoices will be assigned an invoice owner of Duke University. Instead, we'll need to split the files ourselves based on the PO Line Owner value.
- From the documentation: For an Export Invoices For Payment job, select Split by Owner to split the files into separate files, one for each invoice owner (library). When split by owner, the exported file names are named <LibraryName>_<OwnershipType>…xml where <OwnershipType> is LBR for library or INT for institution. For example, BC01_LBR.
Error Handling
1. Invoices that are setup with a payment method other than "Accounting Department" (credit card, bank transfer, or special payment) but aren't marked as "Prepaid" or as an "internal copy" will be sent to an error report.
This is a screen shot of the section of user interface invoice summary screen where a user can indicate that the invoice is Prepaid or Internal copy. It is at the bottom of the screen and it isn't a required field.
2. Barcode is required for invoices sent from DUL or Law, but not for Ford or Med. This is setup in the APay Center of SAP according to John Burkett and the contact for more info is Wayne Staton.
3. New library is added to Alma and used on purchase orders, but hasn't been added to this integration. If invoice_line_list.invoice.line.po_line_info.po_line_owner value doesn’t exist in the defined crosswalk list in AI-169.
4. Out of balance: Reject the invoice if the invoice header amount from the extract XML file doesn't equal the sum of the line amounts. During testing, we discovered that this could happen if a user leaves the header prorata box checked and creates special payment invoice lines (shipping, service charges, discounts, etc). In that scenario, only regular payment invoice lines are included in the extract and could cause an imbalance between the lines and the header.
Currently, each library runs this process independently in Aleph using different frequencies. Since Alma extracts all invoices together, discussions are scheduled beginning on 3/20/24 to determine the frequency of this process in Alma.
Configure Settings related to Invoices
Go to Configuration Menu > Acquisitions > General > Other Settings
- The handle_invoice_payment parameter defines what happens to an invoice after it is approved:
- true - The invoice is sent to the Waiting for Payment Invoices list to await automatic or manual handling.
- false - The invoice is marked as paid and closed. (This occurs regardless of whether invoices are exported to an ERP system or not - i.e., regardless of the setting of the invoice_skip_erp parameter described below).
For details on how this setting affects the invoicing workflow, see Invoicing Workflow. We need to set this parameter to true so that we can track which invoices have been exported to AP and sent successfully. As of 2/19/24, this parameter is already set to true in our local Duke environment of Alma.
2. The invoice_skip_erp parameter defines whether the invoice workflow skips the step where the invoice is sent to an external ERP system for payment (true), or the step is performed and invoices are sent to an external ERP system for payment (false). Note: On 2/29/24 Julie set this value to "false" in our local Duke Alma environment so that we can generate sample files for testing.
Configure the invoice export job
- To run the Invoices export job, we must first activate the InvoicePaymentLetter letter, with the channel SUBMISSION; see Enabling/Disabling Letters. As of 2/19/24, this has already been activated in the local Duke Alma environment.
- An integration profile has been created in Alma to enable the job schedule and S/FTP destination for exported files. Go to Configuration Menu > General > External Systems > Integration Profiles > Invoice Export. In the "Actions" tab, see Export Invoices for Payment to change the job schedule.
Configure the payment confirmation job
An integration profile has been created in Alma to enable the job schedule and S/FTP directory where the payment confirmation input files will be stored. Go to Configuration Menu > General > External Systems > Integration Profiles > Invoice Payment Confirmation. In the "Actions" tab, see Import Payment Confirmation to change the job schedule.
Data Element Mapping
Please refer to the yellow column in the tables below for information about how Duke Libraries populates the fields in the header and line item records:
zinvoice_header
This is the format for the header section that begins each document.
ZINVOICE_HEADER | Length | Screen Field | Record Start | Record Stop | Mandatory | Justification | Description | How does Duke Libraries populate this field based on current Aleph invoice data? | New source field in Alma Invoice Export file based on https://developers.exlibrisgroup.com/wp-content/uploads/alma/xsd/invoice_payment.xsd | ||||||||||
INDICATOR | 1 |
| 1 | 1 | Y |
| Set to H for Header | “H” | "H" | ||||||||||
XBLNR | 16 | H7 | 2 | 17 | Y | L | Reference - Vendor invoice number | Invoice number | invoice_number | ||||||||||
LIFNR | 10 | H10 | 18 | 27 | Y | R | R/3 Vendor Number | R3 Vendor Code | vendor_additional_code | ||||||||||
ZBLDAT | 10 | H1 | 28 | 37 | Y |
| Document Date mmddyyyy | Invoice date - format mm/dd/yyyy | invoice_date Update 4/18/24 - The current output file from Aleph includes backslashes, so I've updated the format here to mm/dd/yyyy (J. Brannon) | ||||||||||
ZCRDE | 2 | H9 | 38 | 39 | Y |
| Credit/Debit Indicator CR/DE | C convert to CR D convert to DE | Alma just sends an amount value: If the invoice_amount_sum value is negative set to 'CR', if positive, set to 'DE' Update 5/26/24: Also, if the invoice_line_list.invoice_line.line_type = 'DISCOUNT,' set to 'DE.' | ||||||||||
ZWRBTR | 16 | H11 | 40 | 55 | Y | R | Total Invoice Amount - 99999999.99 | If currency of invoice is USD use total amount; otherwise convert to USD using Aleph currency rate table | Update 5/17/24: For foreign currency invoices, we can't use the rate value from the XML to do the calculation defined below because it is the rate at the time the extract was run rather than the rate at the date of the invoice. The XML exports the line item amounts in both USD and the foreign currency amount. The USD local amount uses the exchange rate that was in effect on the invoice date, so we should instead calculate this total invoice amount on the header by adding up the amounts in the invoice line ZWRBTR data element for each invoice line.
| ||||||||||
ZBUDAT | 10 | H4 | 56 | 65 |
|
| Posting Date mmddyyyy | blank | blank | ||||||||||
BKTXT | 25 | H8 | 66 | 90 |
| L | Document Header Text | “PERKLIB” “MEDLIB” ”LAWLIB” or “FORDLIB” Passed in as a parameter based on Ordering Unit selected when the custom-12 services is run in Aleph | Updated 3/31/24 to change the source data element to 'invoice_line_list.invoice.line.po_line_info.po_line_owner' and to list all of the library id values to crosswalk to 'PERKLIB' Invoices migrated from Aleph to Alma as "owned" at the institution level (Duke University). Future imported invoices will also be assigned an invoice owner of "Duke University" Therefore, we need to look at the PO Line Owner to determine which library owns the invoice. The po_line_owner data element contains the library name rather than the code and the list of names is in the table below.
| ||||||||||
BUKRS | 4 | H3 | 91 | 94 | Y | L | Company Code | “0010” for all libraries except “0091” for Kunshan (China campus) | “0010” for all invoices except for invoices paid for DKU. DKU invoices need this field to be set to “0091” Logic to identify DKU invoices: If Pos. 8-9 of fund_info_list.fund_info.external_id contains '91', set this BUKRS Company code to "0091"; else "0010" Ex: Fund PXXDXXXDKUXX631 has an external id value of 646100W914520015 which is currently the only DKU fund. | ||||||||||
WAERS | 5 | H5 | 95 | 99 |
| L | Currency Key - USD | blank | blank | ||||||||||
BLART | 2 | H2 | 100 | 101 |
| L | Document Type | blank | blank | ||||||||||
ZDZFBDT | 10 | H16 | 102 | 111 |
|
| Baseline Date mmddyyy | blank | blank | ||||||||||
DZLSCH | 1 | H19 | 112 | 112 |
|
| Payment Method | blank | blank | ||||||||||
DZTERM | 4 | H15 | 113 | 116 |
| L | Terms of Payment | Populated based on contents of Aleph invoice note field. If contains “PI” for pay immediately, set this to “N00”; otherwise blank | If notelist.note.content contains "PI" set this value to N00; otherwise blank. | ||||||||||
ZWMWST | 16 | H12 | 117 | 132 |
| R | Tax Amount in document currency | blank | blank | ||||||||||
CALC_TAX | 1 | H13 | 133 | 133 |
|
| Calculate Tax flag | blank | blank | ||||||||||
MWSKZ | 2 | H14 | 134 | 135 |
| L | Tax Code | blank | blank | ||||||||||
WSKTO | 13 | H18 | 136 | 148 |
| R | Cash Discount | blank | blank | ||||||||||
NAME1 | 30 |
| 149 | 178 |
| L | Name of Vendor (1 time) | blank | blank | ||||||||||
NAME2 | 30 |
| 179 | 208 |
| L | Name of Vendor (1 time) | blank | blank | ||||||||||
STRAS | 30 |
| 209 | 238 |
| L | Vendor address (1 time) | blank | blank | ||||||||||
PFACH | 10 |
| 239 | 248 |
| L | Vendor PO Box (1 Time) | blank | blank | ||||||||||
ORT01 | 25 |
| 249 | 273 |
| L | Vendor City (1 Time) | blank | blank | ||||||||||
LAND1 | 3 |
| 274 | 276 |
| L | Vendor Country (1 Time ) | blank | blank | ||||||||||
PSTLZ | 10 |
| 277 | 286 |
| L | Vendor Zip Code (1 Time) | blank | blank | ||||||||||
REGIO | 3 |
| 287 | 289 |
| L | Vendor State (1 Time ) | blank | blank | ||||||||||
KIDNO | 30 |
| 290 | 319 |
| L | Payment Reference | blank | blank | ||||||||||
UZAWE | 2 |
| 320 | 321 |
| L | Payment Supplement | Populated based on contents of Aleph invoice note field. If contains “PC” (hold check for pickup), set this to “9”; otherwise blank | If notelist.note.content contains "PC" (hold check for pickup), set this value to "9"; otherwise blank. | ||||||||||
STCD1 | 16 |
| 322 | 337 |
| L | Social Security Number | blank | blank | ||||||||||
STCD2 | 11 |
| 338 | 348 |
| L | Social Security Number | blank | blank | ||||||||||
BARCODE | 10 |
| 349 | 358 |
| L | Barcode | Populated based on contents of Aleph note field where a barcode is stored. Each hardcopy invoice has a barcode sticker attached and the barcode # is stored in Aleph and sent to AP via this field. | No barcode field in Alma. The barcode will be stored at the beginning of the notelist.note.content element. Additional processing instructions may follow the barcode. For example, if invoice is coded to be paid immediately the string contains a “;”(semicolon) directly behind the barcode number followed by the code "PI" (##PI##). |
zinvoice_line
This is the format for the line item detail section. The line items follow the header and there should be one record for each line item (up to 950).
ZINVOICE_LINE | Length | Screen Field | Record Start | Record Stop | Mandatory | Justification | Description | How does Duke Libraries populate this field based on Aleph invoice data? | New source field in Alma Invoice Export file |
Indicator | 1 |
| 1 | 1 | Y |
| Set to L for Line | “L” | "L" |
XBLNR | 16 |
| 2 | 17 | Y | L | Reference - Vendor invoice number | Invoice number | invoice_number |
LIFNR | 10 |
| 18 | 27 | Y | R | R/3 Vendor Number | R3 Vendor code | vendor_additional_code |
ZBLDAT | 10 |
| 28 | 37 | Y |
| Document Date mmddyyyy | Invoice date | invoice_date format mm/dd/yyyy |
ZCRDE | 2 | L2 | 38 | 39 | Y |
| Credit/Debit Indicator CR/DE | C convert to CR D convert to DE | Correction 4/18/24: Include this indicator on the header and line item (J. Brannon) If the invoice_line.total_price value is negative set to 'CR', if positive, set to 'DE' Update 5/26/24: Also, if the invoice_line_list.invoice_line.line_type = 'DISCOUNT,' set to 'DE.' |
ZWRBTR | 16 | L4 | 40 | 55 | Y | R | Line Item Amount - 99999999.99 | Budget_local_sum |
Correction 4/19: The invoice line total price is in foreign currency, so need to use the local amount value instead which contains USD. invoice_line_list.invoice_line.fund_info_list.local_amount.sum |
ACCOUNT_TYPE | 1 |
| 56 | 56 | Y |
| Account Type (C, W, P, F, I ) | Pos. 7 of r3_budget | Pos. 7 of fund_info_list.fund_info.external_id |
ACCOUNT_CODE | 24 | L3 | 57 | 80 | Y | L | Primary Cost Object |
|
Update 5/26/24: Write to Pos. 8-14 |
HKONT | 10 | L5 | 81 | 90 | Y | L | General Ledger Account |
|
Update 5/26/24: Write to Pos. 1-6 |
SGTXT | 50 | L1 | 91 | 140 |
| L | Item text | blank | blank |
ACCOUNT_TYPE2 | 1 |
| 141 | 141 |
|
| Account Type (C, W, P, F, I ) | blank | blank |
ACCOUNT_CODE2 | 24 |
| 142 | 165 |
| L | Second Cost Object | blank | blank |
ACCOUNT_TYPE3 | 1 |
| 166 | 166 |
|
| Account Type (C, W, P, F, I ) | blank | blank |
ACCOUNT_CODE3 | 24 |
| 167 | 190 |
| L | Third Cost Object | blank | blank |
ACCOUNT_TYPE4 | 1 |
| 191 | 191 |
|
| Account Type (C, W, P, F, I ) | blank | blank |
ACCOUNT_CODE4 | 24 |
| 192 | 215 |
| L | Fourth Cost Object | blank | blank |
Alma Invoices Export
See https://developers.exlibrisgroup.com/alma/apis/docs/xsd/invoice_payment.xsd/#Overview
Rules for data transformations and value crosswalks are defined in the mapping tables above. The following are additional requirements related to handling of the Alma invoice output file:
- This integration will split the Alma output file into a separate file for each independent library using the PO owner as defined in the 'BKTXT' data element in the data mapping table of the invoice line header.
- Any zero-dollar line items included in the Alma output file will be stripped out of the output file (where invoice_line.total_price = 0)
- A report will be generated containing the contents of the Alma XML output file converted to .csv format for use by library staff. The zero-dollar line items will be excluded from that report. A separate report will be generated for each library and contain the following data elements:
Column Header Name | Description | Alma xml source data object |
---|---|---|
InvoiceNumber | Invoice number | invoice_list.invoice.invoice_number |
VendorCode | Library system vendor code | invoice_list.invoice.vendor_code |
VendorName | Vendor name | invoice_list.invoice.vendor_name |
VendorAdditionalCode | SAP system vendor code | invoice_list.invoice.vendor_additional_code |
InvoiceDate | Invoice date | invoice_list.invoice.invoice_date |
InvoiceAmountSum | Total invoice amount | invoice_list.invoice.invoice_amount.sum |
CreditDebit | Credit or debit transaction code. If the invoice_amount_sum value is negative this is set to ‘CR', if positive, it’s set to 'DE' | If invoice_list.invoice.invoice_amount_sum value is negative (contains “-”) set to 'CR', if positive, set to 'DE' |
DiscountAmount | invoice_list.invoice.additional_charges.discount_amount | |
InsuranceAmount | invoice_list.invoice.additional_charges.insurance_amount | |
OverheadAmount | invoice_list.invoice.additional_charges.overhead_amount | |
ShipmentAmount | invoice_list.invoice.additional_charges.shipment_amount | |
TotalAdditionalCharges | invoice_list.invoice.additional_charges.total_charges_amount | |
Barcode | Barcode value from the notes | The barcode is stored at the beginning of ‘invoice_list.invoice.notelist.note.content’ |
InvoiceNote | Full note field | invoice_list.invoice.notelist.note.content |
Invoice Owner | The library that owns the invoice | invoice_list.invoice.invoice_owner |
InvoiceLineNumber | Invoice line # | invoice_list.invoice.invoice_line_list.invoice_line.line_number |
InvoiceLineType | Invoice line type | invoice_list.invoice.invoice_line_list.invoice_line.line_type |
InvoiceLineQty | Invoice line qty | invoice_list.invoice.invoice_line_list.invoice_line.quantity |
POLineOwner | The library that owns the purchase order line associated with this invoice line | invoice_list.invoice.invoice_line_list.invoice_line.po_line_info.po_line_owner |
PONumber | Purchase order number of the PO line associated with this invoice | invoice_list.invoice.invoice_line_list.invoice_line.po_line_info.po_number |
POLineNumber | Purchase order line number of the PO line associated with this invoice | invoice_list.invoice.invoice_line_list.invoice_line.po_line_info.po_line_number |
POLinePrice | PO line price | invoice_list.invoice.invoice_line_list.invoice_line.po_line_info.po_line_price |
FundCode | Alma fund code | fund_info_list.fund_info.code |
Amount | Amount of the line in the currency used on the order | invoice_list.invoice.invoice_line_list.invoice_line.fund_info_list.fund_info.amount.sum |
Currency | Currency of this line item amount used on the order | invoice_list.invoice.invoice_line_list.invoice_line.fund_info_list.fund_info.amount.currency |
LocalAmount | Amount of the line in local currency (converted from the foreign currency to USD) | invoice_list.invoice.invoice_line_list.invoice_line.fund_info_list.fund_info.amount.local_amount.sum |
LocalCurrency | Local currency - USD | invoice_list.invoice.invoice_line_list.invoice_line.fund_info_list.fund_info.amount.local_amount.currency |
- Validate that the file was exported to the expected S/FTP server using the schedule defined in the Alma integration profile.
- Validate that the expected set of invoices are included in the batch file.
- Each batch should follow the data extract criteria defined above - include all invoices that have moved to "Ready to be Paid" status since the last batch run.
- Validate that each transformation and mapping detailed in the Data Mapping tables are executed as expected.
- Duke University AP will continue to require the same format for sending invoice information by summer 2024 (batch file load rather than API).
- What if we have an issue with one of the extracts and Financial Services staff ask to run it again?
For documents that have been approved and are in a finalized state (and locked for edits), include this change log to keep track of future changes.
Date | Description of Changes | Updated By |
---|---|---|
2/16/2024 | Integration plan created. | Julie Brannon |
3/29/24 | Added updates to Data Element Mapping > zinvoice_header about currency and company code | Julie Brannon |
3/31/24 | Updated the mapping for zinvoice_header 'BKTXT' change the Alma source data element to 'invoice_line_list.invoice.line.po_line_info.po_line_owner' and to list all of the library id values to crosswalk to 'PERKLIB' | Julie Brannon |
4/10/24 | Updated how to identify DKU funds to set the company code value in the ZINVOICE_HEADER | Julie Brannon |
4/16/24 | Added link to a data validation spreadsheet https://duke.box.com/s/n4kcwd1n2iz0iauw1pcbe42miak5ofup | Julie Brannon |
4/18/24 | Updated the Data Transformation Rules section to include splitting the output into files by library and excluding zero-dollar invoice lines. Data Mapping Correction to line item ZCRDE - previously sent to blank, but we do need to include this indicator on the line item. If the invoice_line.total_price value is negative set to 'CR', if positive, set to 'DE' | Julie Brannon |
4/19/24 |
| Julie Brannon |
4/29/24 | New library was created in Alma - added it to the zinvoice header crosswalk of PO line-owner values for data element BKTXT. | Julie Brannon |
4/30/24 | Added information about error handling to the Data Extract Criteria section | Julie Brannon |
5/26/24 |
| Julie Brannon |
5/29/24 | Mapping table for invoice lines: Updated source of Account Code and HKONT - these are swapped. The comments in the current Aleph script are incorrect, so need to change this specification to match what the current code is doing rather than the comments in the code about the derivation from the fund external id. | Julie Brannon |
11/8/2024 | Added updated diagram | Julie Brannon |