Skip to main content

jde-api

The JD Edwards EnterpriseOne Application Interface Services (AIS) Server REST APIs provide services that AIS clients can use to interact with EnterpriseOne applications. JD Edwards calls it REST APIs, but they are not following the REST standard. It is actually a http-based API which mimics the user interactions in the JD Edwards website.

The documentation cam be found on REST API for JD Edwards EnterpriseOne AIS Server

AIS client

Appshare uses an AIS client with a fluent interface to make interaction with the AIS services easier.

import

import {jdedwards} from "@appshare/jde-api";

The AIS client features are:

  • All services of AIS are present in this API.
  • The service selects the versioned endpoints based on the AIS server version
  • The client handles network errors
  • The client refreshes the token before expiry
  • Numbers and Dates are converted in the way AIS requires it.
  • The client has request based cache support.
  • UDC support

All interaction with AIS starts by importing and calling the jdedwards() function. The code completion will help when you add the dots after each call.

A basic example to call a service

const { data, error, message } = await jdedwards()
.cache(`W01012B-${category}`)
.form("W01012B")
.returns("1[19,20,40,44]")
.allResults()
.actions()
.value("54", category)
.checkboxOn("63")
.add((builder) => {
if (condition === "true") {
builder.value("add", "add");
}
})
.doFind("15")
.executeToList({
alphaName: "20",
address: "19",
});

if (error) {
return message;
}

return data;

JD Edwards uses IDs for all form elements and controls. These are accessible though the "Help" -> "Item Help" in JD Edwards. To find these IDs more quickly we developed a Chrome extension Steltix JDE Reveal.

Data Service

Execute queries over EnterpriseOne tables and business views.

See https://docs.oracle.com/en/applications/jd-edwards/cross-product/9.2/rest-api/op-v2-dataservice-post.html

Simple query data request

This data request will return a list with records matching the condition.

const { data, error, message } = await jdedwards()
.data("F0006")
.query()
.equal("MCU", "businessUnit")
.executeToList();
if (error) {
throw message;
}

return data;

Simple query data request on a view.

This data request will return a list with records matching the condition.

info

When querying a business view, you must use the table alias in the condition.

const { data, error, message } = await jdedwards()
.data("V0101XPI")
.query()
.equal("F0101.AN8", "addressNumber")
.executeToList({
addressLine: "F0116.ADD1",
});
if (error) {
throw message;
}

return data;

Paged query data request

This example shows how to fetch data in easily manageable chunks over several successive service calls. For data service calls you must indicate on the first call that you expect to receive next page links, this indication on the request keeps the data set open waiting to receive the next requests. Set the 'enableNextPageProcessing' to true. It is important to note that the size of each data set is determined up front, with the first request to that form/grid. The 'maxPageSize' indicates the chunk size for each call.

let result;
if (nextPageLink == "") {
result = await jdedwards()
.data("V0101XPI")
.maxPageSize("20")
.enableNextPageProcessing(true)
.query()
.equal("AT1", category)
.execute();
} else {
resp = await jdedwards().dataNextPage(nextPageLink, "V0101XPI");
}

const resultList = result.toList();
return {
data: resultList.data,
moreRecords: resultList.summary.moreRecords,
nextPageLink: resp.getLinkNext(),
};

Aggregate data request

The following shows an example of an aggregation data request.

  const request = await jdedwards()
.data("F4311")
.allResults()
.query()
.stringNotBlank("MCU")
.less("NXTR", "999")
.less("LTTR", "980")
.aggregation()
.countDistinct("MCU")
.orderByAggregation("MCU", "COUNT_DISTINCT", "DESC")
.orderByColumn("MCU", "ASC")
.groupBy("MCU");

const rawResult = await request.execute();

if (rawResult.isAggregationSuccess()) {
const dataResult = rawResult.getAggregation();
...
}

Form Service

Request to execute an EnterpriseOne form. Optionally, perform actions on the form and receive data from the form in the response.

See https://docs.oracle.com/en/applications/jd-edwards/cross-product/9.2/rest-api/op-v2-formservice-post.html

  const {data,error,message} = await jdedwards()
.form("W01012B")
.input("id", "value")
.bypassFormServiceEREvent(false)
.maxPageSize(250)
.version("version")
.formServiceDemo("true")
.showActionControls(true)
.stopOnWarning(true)
.actions()
.qbe("qbe", "qbe")
.qbeBoolean("boolean", true)
.qbeBoolean("booleanString", "true")
.qbeNumber("number", 123.45)
.qbeDate("date", new Date("01 Jan 2020 00:00:00 GMT"))
.doFind();
.executeToList({
fieldName1: "fieldID1",
fieldName2: "fieldID2",
});

// server will return fieldID1 and fieldID2 in response.

if (error) {
throw message;
}

return data;

tip

executeToList will return a list of records from the grid. you can use singleResult() before the actions() to get a single record back. you can use maxPageSize(size) to limit the number of records returned. by default it will return all records.

Get Control values outside the grid use the executeToObject method.

  const { data, error, message } = await jdedwards()
.form("W01012B")
.singleResult() // to get a single record
.actions()
.qbe("1[19]", addressNumber) // qbe on grid id 1 field id 19
.doFind("15"); // do find action with action id 15
.executeToObject({
fieldName1: "123", // map field id 123 to fieldName1
fieldName2: "3", // map field id 3 to fieldName2
});

if (error) {
throw message;
}
return data; `{ fieldName1: "value", fieldName2: "value" }`

Get Grid and Control values use the execute method

const result = await jdedwards()
.form("W01012B")
.returns("123|1[19,123]") // * The returnControlIDs string is bar delimited, without a starting or ending bar. Form fields are just a single value. Grid fields are indicated with a grid id, followed by a bracketed list of grid columns. Subform fields are indicated with subform id underscore field id. @example 33|34|17[24,26,28]|50_45|50_53|50_9[35,39,41]
.actions()
.qbe("1[19]", addressNumber) // qbe on grid id 1 field id 19
.doFind("15") // do find action with action id 15
.executeV2();

if (error) {
throw message;
}

const { data, error, message } = result.toList({
fieldName1: "123",
fieldName2: "456",
});
if (error) {
throw message;
}

// data is now [{ fieldName1: "value", fieldName2: "value" }, ...] from the grid.

const headerValue = result.toObject({
fieldName1: "123",
fieldName2: "456",
}).data;

// headerValue is now { fieldName1: "value", fieldName2: "value" } from the header.

Form with conditional actions

  const { data, error, message } = await jdedwards()
.form("W01012B")
.actions()
.add((builder) => {
if (condition === "true") {
builder.value("add", "add");
}
})
.doFind();
.executeToList();


if (error) {
throw message;
}
return data;


Form with update

  const { data, error, message } = await jdedwards()
.form("W01012B")
.returns(["123", "456"])
.singleResult()
.actions()
.value("field1_123", "value")
.boolean("field1_123", true)
.number("field1_123", 123.45)
.date("field1_123", new Date("01 Jan 2020 00:00:00 GMT"))
.checkboxOn("field1_123")
.combo("field1_123", "combo")
.radio("field1_123")
.doOk();
.executeToList();

if (error) {
throw message;
}
return data;

Form with grid update

const { data, error, message } = await jdedwards()
.form("W01012B")
.returns("1[19,20,40,44]")
.allResults()
.actions()
.grid("1") // grid id
.insertRow()
.cell("18", "promotion")
.cell("19", "requestDate")
.cell("23", "quantity")
.updateRow(1) // Update the first row
.cell("18", "promotion")
.cell("19", "requestDate")
.cell("23", "quantity")
.end()
.end()
.doOk()
.executeToList();

Form with Delete

const { error, message } = await jdedwards()
.form("W01012B")
.singleResult()
.actions()
.qbe("1[19]", addressNumber)
.value("54", "*")
.doFind("15")
.selectFirstRow()
.doDelete("61")
.executeToList();

if (error) {
throw message;
}

Application Stack Service (appstack)

Execute stateful calls to applications including flows from one form to another.

See https://docs.oracle.com/en/applications/jd-edwards/cross-product/9.2/rest-api/op-v2-appstack-post.html

Multiple forms in one call

const appstack = jdedwards().appstack();
appstack
.start("W01012B")
.returns("1[19,20,40,44]")
.allResults()
.actions()
.add((builder) => {
if (condition === "true") {
builder.value("add", "add");
}
})
.value("54", "category");
appstack
.next("W01012B")
.returns("1[19,20,40,44]")
.actions()
.value("54", "category");
appstack
.next("W01012B")
.returns("1[19,20,40,44]")
.actions()
.value("54", "category");
const result = await appstack.executeToList();

Multiple forms with client side decision

appstack
.start("W01012B")
.showActionControls(true)
.aliasNaming(false)
.useWarnings(true)
.returns("1[19,20,40,44]")
.allResults()
.actions()
.value("54", "category");
appstack
.next("W01012B")
.showActionControls(true)
.aliasNaming(false)
.useWarnings(true)
.returns("1[19,20,40,44]")
.actions()
.value("54", "category");
const result = await appstack.execute();

// Do some logic on the result and continue the appstack

appstack
.continue("W01012B", result)
.returns("1[19,20,40,44]")
.actions()
.value("54", "category");
appstack
.next("W01012B")
.returns("1[19,20,40,44]")
.actions()
.value("54", "category");
const resultContinued = await appstack.execute();

Business Function Service

Execute an EnterpriseOne Business Function.

See https://docs.oracle.com/en/applications/jd-edwards/cross-product/9.2/rest-api/op-v2-bsfnservice-post.html

const result = await jdedwards()
.businessFunction("FormatLocation")
.input(1, branch)
.input(2, location)
.input(15, "2")
.outputIds([3])
.execute();

return result.getStringValue(3);

message Service

Sends an EnterpriseOne message (PPAT) to external email systems or the EnterpriseOne Work Center email system.

See https://docs.oracle.com/en/applications/jd-edwards/cross-product/9.2/rest-api/op-v2-message-post.html

const result = await jdedwards()
.message("subject", "messageText")
.toEmail("to-1@example.com")
.execute();

orchestrator Service

Execute an EnterpriseOne Orchestration

See https://docs.oracle.com/en/applications/jd-edwards/cross-product/9.2/rest-api/op-orchestrator-orchestration-post.html

const result = await jdedwards()
.orchestrator("orchestration")
.inputs([{ name: "10", value: "inputArray" }])
.input("1", "inoutValue")
.body({ "custom:": "value" })
.execute();

discover Orchestrations

const response = await jdedwards().discover().execute();
return response?.orchestrations;

Processing Option Service

Enables the caller to get the processing option values for an application and version.

See https://docs.oracle.com/en/applications/jd-edwards/cross-product/9.2/rest-api/op-v2-poservice-post.html

const result = await jdedwards()
.processingOption("application", "version")
.execute();

udomanager Service

Request details of Watchlist or query user defined objects (UDOs).

See https://docs.oracle.com/en/applications/jd-edwards/cross-product/9.2/rest-api/op-v2-udomanager-operation-post.html

Simple request

return await jdedwards().udomanager().execute();

All Queries request

return await jdedwards().udomanager().allQueries().execute();

All Watchlists request

return await jdedwards().udomanager().allWatchlists().execute();

Watchlist request

return await jdedwards().udomanager().watchlist("ube").execute();

query request

return await jdedwards().udomanager().query("q").execute();

watchlist Service

Execute the specified Watchlist. The response includes record count as well as Watchlist definition metadata.

See https://docs.oracle.com/en/applications/jd-edwards/cross-product/9.2/rest-api/op-v2-watchlist-post.html

return await jdedwards().watchlist("watchlist").execute();

report Service

Execute the specified report.

See https://docs.oracle.com/en/applications/jd-edwards/cross-product/9.2/rest-api/op-v2-report-execute-post.html

const report = jdedwards()
.report("R55HMRLBN")
.version(getParameterValue("R55HMRLBL_H1"))
.dataSelection()
.criterion()
.subject("V46L10A", "LPNU", "F46L10")
.operator("AND")
.compare("VALUE_IN_LIST", "LIST")
.in(printLPNUList);

return await report.execute();

reportStatus Service

Use the batch job number to get the completion status of the report.

See https://docs.oracle.com/en/applications/jd-edwards/cross-product/9.2/rest-api/op-v2-report-status-post.html

return await jdedwards().reportStatus("jobNumber").execute();

Attachments

Get the text attachments

export async function getTextAttachments({
structure = "",
keys = [],
form = "",
preserveHtml = false,
}) {
try {
return await jdedwards()
.attachment(structure, keys, form)
.text()
.list(preserveHtml);
} catch (error) {
return [];
}
}

Update text attachments

export async function updateTextAttachment({
structure = "",
keys = [],
form = "",
itemName = "",
text = "",
sequence = -1,
}) {
try {
await jdedwards()
.attachment(structure, keys, form)
.text()
.sequence(sequence)
.itemName(itemName)
.update(text);
return true;
} catch (error) {
return false;
}
}

insert text attachment

export async function insertTextAttachment({
structure = "",
keys = [],
form = "",
itemName = "",
text = "",
}) {
const returnObject = {
error: true,
message: translate("Error inserting text attachment"),
sequence: -1,
};
try {
const response = await jdedwards()
.attachment(structure, keys, form)
.text()
.itemName(itemName)
.insert(text);
if (response.hasOwnProperty("sequence")) {
returnObject.error = false;
returnObject.message = "";
returnObject.sequence = response.sequence;
}
return returnObject;
} catch (error) {
return returnObject;
}
}

delete attachment

export async function deleteAttachment({
structure = "",
keys = [],
form = "",
sequence = -1,
}) {
try {
await jdedwards().attachment(structure, keys, form).delete(sequence);
return true;
} catch (error) {
return false;
}
}

Get the file attachments

export async function getFileAttachments({
structure = "",
keys = [],
form = "",
includeData = false,
thumbnailSize = undefined,
cache = false,
}) {
try {
const jde = cache
? jdedwards().cache(`${structure}-${keys.join("-")}-${form}`)
: jdedwards();
return await jde.attachment(structure, keys, form).file().list({
includeUrls: true,
includeData,
thumbnailSize,
});
} catch (error) {
return [];
}
}

Update file attachment

export async function uploadFileAttachment({
structure = "",
keys = [],
form = "",
image = null,
itemName = "",
}) {
const returnObject = {
error: true,
message: translate("Error uploading file attachment"),
sequence: -1,
uniquefilename: "",
itemName: "",
};
try {
const response = await jdedwards()
.attachment(structure, keys, form)
.file()
.itemName(itemName)
.upload(image);
if (response.hasOwnProperty("sequence")) {
returnObject.error = false;
returnObject.message = "";
returnObject.sequence = response.sequence;
returnObject.uniquefilename = response.uniquefilename;
returnObject.itemName = response.itemName;
}
return returnObject;
} catch (error) {
return returnObject;
}
}

download file attachment

export async function downloadFileAttachment({
structure = "",
keys = [],
form = "",
sequence = -1,
returnBlob = false,
}) {
try {
return await jdedwards()
.attachment(structure, keys, form)
.file()
.sequence(sequence)
.download(returnBlob);
} catch (error) {
return null;
}
}