When integrating with external systems to Sage X3, there are several options available. Transactions and common data can be imported by using Sage X3 Objects published as web services or by using import templates. Additionally, custom subprograms can be written and published as a web service to import data to Sage X3. All three methods have their advantages and disadvantages.
Most of the objects in Sage X3 can be published as a web service, and then consumed from an external process. The catch is, not all objects are guaranteed to work when consumed as web services. Only a couple of objects are fully tested and guaranteed by Sage to work. These include the sales order object (SOH), the item master object (ITM) and the customer object (BPC).
This is because there are sometimes interactions required, which may appear as pop-up windows when calling the object directly. In order to make the objects outside of the 3 above work, customizations to the objects may be necessary to bypass these pop-ups when being consumed by web services. A global variable called GIMPORT has been added to most of the Sage X3 objects to bypass informational and warning windows while calling the object from an import template. A similar variable called GWEBSERV is also available to indicate the transaction is being called from a web service, but the logic to bypass the pop-ups has not been added to all of the Sage X3 objects, which is what causes the pop-up windows, and therefore failures of the web service execution.
The main advantage of using an object published as a web service is it adheres to the rules of the object that are present when entering the transaction from the screen. It also provides a means to call the object by using a standard SOAP web service call, providing only the mandatory data, along with any additional data desired to be included.
Standard import templates are available for most of the objects in Sage X3. Additionally, custom import templates can be created from the base templates available to include only the required fields for the specific integration. These import templates can then be called to created one or more transactions in Sage X3. The import templates also use the Sage X3 object, and therefore adhere to the rules inherent in that object. To call an import template, a .txt file must be generated to match the data format defined in the import template, and then the import template must be executed to import the data.
Custom subprograms can be created to add transactions and data directly to Sage X3. The risk with this method is, the object is not included, and there is the risk of missing data and object based rules not being followed. This method is generally acceptable when updating custom tables, but not the best solution for complex objects in Sage X3.
As many may have found when using a standard object as a web service, a background pop-up window may prevent the creation of the record in Sage X3. When using with the object web service, the way around this is to modify the object code to add the GWEBSERV check where pop-up windows occur, which may not be desirable. Since the import templates already have the logic to bypass pop-up windows, a combination of a custom subprogram and an import template can be used to create transactions in X3. Below is an overview of how this can be done.
The first step is to create the import template. This can either be done by using the base import template, or creating a copy of the import template, and including only the fields required.
Below is an example of an import template copied from the base MKMS import template, for material tracking against a work order.
The next step is to create a subprogram which accepts the data values required to call the import template. This subprogram will write a .txt file to a directory on the Sage X3 server, then call the import template to create the transaction.
##############################################################################################################
# MTKMAT - Create Material Consumption via Import Template
##############################################################################################################
Subprog MTKMAT(MFGNUM, MFGTRKDAT, MFGFCY, MATITMREF, QTYSTU, STU, LOC, LOT, SLO, RESULTS)
Value Char MFGNUM
Value Date MFGTRKDAT
Value Char MFGFCY
Value Char MATITMREF() ()
Value Decimal QTYSTU ()
Value Char STU() ()
Value Char LOC() ()
Value Char LOT() ()
Value Char SLO() ()
Variable Char RESULTS() ()
Local Char FNAME (250)
Local Char DIRNM (250)
Local Integer I
Local Integer LISTMAX : LISTMAX = 100
# If No lines sent then return
If MATITMREF(0) = "" : End: Endif
Local File MFGHEAD [MFG]
Local File MFGMAT [MFM]
Local File MFGITM [MFI]
# Step 1 - Write the file
FNAME = filpath("","","")+"\SOLO\Imports\MTK_"+MFGNUM+"_"+MATITMREF(I)+".txt"
Openo FNAME, 0 Using [WF]
adxifs = ";"
adxirs = chr$(13)+chr$(10)
Local Integer MFGLIN
Local Integer BOMSEQ
Local Integer BOMALT
Local Char BOMNUM
For I=0 To maxtab(MATITMREF) - 1
If MATITMREF(I) <> ""
[L]MFGLIN = 0
[L]BOMSEQ = 0
For [F:MFM] Where MFGNUM = [L]MFGNUM and ITMREF = MATITMREF(I)
[L]MFGLIN = [F:MFM]MFGLIN
[L]BOMSEQ = [F:MFM]BOMSEQ
Break
Next
[L]BOMALT = 0
[L]BOMNUM = ""
Read [F:MFI]MFI0=[L]MFGNUM;[L]MFGLIN
If !fstat
[L]BOMALT = [F:MFI]BOMALT
[L]BOMNUM = [F:MFI]ITMREF
Endif
# Header MFGMATTRK
# M;MFGNUM;MFGFCY;MFGLIN;BOMSEQ;ITMREF;BOMNUM;BOMALT;USEQTY;IPTDAT
Wrseq "M", MFGNUM, MFGFCY, [L]MFGLIN, [L]BOMSEQ, MATITMREF(I), [L]BOMNUM, [L]BOMALT, QTYSTU(I), MFGTRKDAT Using [WF]
# Line STOJOU
# L;LOT;SLO;LOC;PCU;QTYPTU
Wrseq "L", LOT(I), SLO(I), LOC(I), STU(I), QTYSTU(I) Using [WF]
Endif
Next
Openo Using [WF]
Close Local File [MFG], [MFM], [MFI]
# Step 2 - Call the Import Template for Material Tracking
Call EXECIML("YMKMS",FNAME,RESULTS)
End
As part of the import template call, a trace file will be opened at the start, then read line by line to either return a list of error(s), or return the generated transaction number to the calling application. Below is an example of an import template execution from code, including opening and reading the generated trace file. The line where it reads the generated transaction number will have to be modified based on the transaction created, and the specific message written to the log file.
###############################################################
# SubProgram Name: EXECIML
# Description: Subprogram to execute an X3 import
# template and return error(s)
# Accepts two parameters:
# IMPTEMP # The import template name
# FNAME # The File Name to be imported
# Returns:
# MESSAGE # List of errors
################################################################
Subprog EXECIML(IMPTEMP, FNAME, MESSAGE)
Value Char IMPTEMP
Value Char FNAME
Variable Char MESSAGE () ()
# Start the trace
Call OUVRE_TRACE ("EXECIML "-IMPTEMP) From LECFIC
Call IMPORTSIL(IMPTEMP, FNAME) From GIMPOBJ
# end/write the trace
Call FERME_TRACE From LECFIC
# open the trace file to get the details
Openi filpath("TRA",GTRACE,"tra",0) Using [ZZZ]
Local Integer I : I = 0
Local Integer LISTMAX : LISTMAX = 100
Local Char XLINE(100)
# read the file
Repeat
Rdseq XLINE Using [ZZZ]
If left$(XLINE,5)="<0001"
MESSAGE(I) = right$(XLINE,6)
I += 1
Elsif left$(XLINE,23)="Creation of WO tracking"
MESSAGE(I) = right$(XLINE,25)
I += 1
Endif
If I >= LISTMAX : Break : Endif
Until fstat <> 0
# close the file
Openi Using [ZZZ]
End
The final step is to take the subprogram created above, and generate a web service to be called from the external application.
Step 1 – Create the subprogram associated with the source code created above.
The subprogram is created by from Development > Script dictionary > Scripts > Subprograms
Make sure the Web services box is checked.
Make sure the dimensions are changed to match the number of dimensions in the subprogram source code.
Step 2 – Publish the web service
From the subprogram, click the Publication to publish the web service. The web service is ready to be called from an external application, such as .net.
As you will see from attempting to integrate external systems with Sage X3, several obstacles may be encountered when calling objects published as web services. Creating a custom web service to generate a transaction using an import template can be used to get around the issue of calling object-based web services.