Back to Blog
6 min. read

Streamline Your Supply Chain #3: Converting Purchase Order JSON into EDIFACT EDI D97A Format Using Mule 4

EDIFACT D97A is a standard electronic data interchange (EDI) message used to transmit purchase orders between buyers and suppliers. It contains detailed information about the items being ordered, quantities, prices, delivery dates, and other relevant terms and conditions.

Mulesoft EDIFACT Connector

The Mulesoft EDIFACT Connector is a powerful tool that can be used to integrate EDIFACT messages, including D97A purchase orders, into your Mule applications. It provides a simple and efficient way to process and transform EDIFACT messages, making it easier to automate business processes and improve data exchange between trading partners.

  • EDI Message Parsing and Validation: The connector can parse and validate EDIFACT messages, ensuring that they comply with the relevant standards and contain all the required information.
  • Message Transformation: The connector can be used to transform EDIFACT messages into other formats, such as XML or JSON, or to map them to specific data structures.
  • Integration with Other Systems: The connector can be integrated with other systems, such as ERP, CRM, and WMS systems, to automate business processes and improve data flow.
  • Error Handling and Recovery: The connector provides robust error handling and recovery mechanisms to ensure that EDI messages are processed correctly and any errors are addressed promptly.

Prerequisites:

  • Mule 4 Runtime
  • Anypoint Studio
  • EDIFACT EDI Connector installed in Anypoint Studio
  • Purchase Order JSON Payload (Refer to the last Page

Steps:

1. Create a Mule Flow
○ Open Anypoint Studio and create a new Mule project.
○ Install EDIFACT EDI Module from Exchange

○ In the palette, search for and drag an HTTP Listener component onto the flow canvas. Configure the listener to receive incoming JSON requests.

2. Transform JSON to EDIFACT Purchase Order:
○ Drag a Transform Message component onto the flow. The Datweave script for transform message is saved to resources -> dwl folder.
○ After Transform Message component drag Write operation from EDIFACT Module.

										<ee:transform doc:name="Json to Edifact Java - PO" doc:id="51a2c5c0-8792-4b64-8fd7-50a4d05fabd0" >
		<ee:message >
		<ee:set-payload resource="dwl/edifact-outbound-po.dwl" />
		</ee:message>
</ee:transform>
<edifact:write doc:name="Write" doc:id="38711428-771e-400f-8dc8-67b4312851ac" config-ref="EDIFACT_Write_D97A_ORDERS"/>

									

○ The edifact: write operation requires EDIFACT config reference. Create EDIFACT config in global elements.

										</edifact:config>
<edifact:config name="EDIFACT_Write_D97A_ORDERS" doc:name="EDIFACT EDI Config" doc:id="60574700-aaaa-417b-80c2-ee79633120fc" lineEnding="CRLF" alwaysSendUNA="true" requestAcks="true" interchangeIdSelf="SENDER" interchangeIdQualifierSelf="ZZZ" interchangeIdPartner="RECEIVER" interchangeIdQualifierPartner="ZZZ">
		<edifact:schemas >
		<edifact:schema value="/edifact_schemas/ORDERS.esl" />
		</edifact:schemas>
	</edifact:config>
									

○ In the config we need to provide schema for our Purchase Order, you can find that schema in EDIFACT EDI Jar File

○ Look for ORDERS.esl file in edifact.d97a folder, copy it inside the resources -> edifact_schemas folder. There are many versions of Purchase Order. We are using the edifact.d97a version. Also, copy the basedefs.esl file from the same edifact.d97a version folder and paste it in resources -> edifact_schemas folder.

○ In the DataWeave editor, create a transformation script that maps the extracted JSON data to the corresponding EDIFACT d97a Purchase Orders segments.

										%dw 2.0
output application/java
---
{
	"Errors": [],
	"Delimiters": "+:*'?",
	Messages: {
		D97A: {
			ORDERS: payload map ( payload01 , indexOfPayload01 ) -> {
				Interchange: {
					UNB0101: "UNOA",
					UNB0102: "1",
					UNB0201: payload01.B2BMessage.Header.SenderID,
					UNB0301: payload01.B2BMessage.Header.ReceiverID,
					UNB0401: now() as String {
						format: "yyyyMMdd"
					} as Number, // CurrentDate
					UNB0402: now() as String {
						format: "hhmm"
					} as Number,
					UNB05: payload01.B2BMessage.Header.MessageID,
					UNB07: "ORDERS"
				},
				Heading: {
					"0020_BGM": {
						BGM0101: payload01.B2BMessage.Data.PurchaseOrder.POType,
						BGM0201: payload01.B2BMessage.Data.PurchaseOrder.PONumber,
						BGM03: payload01.B2BMessage.Data.PurchaseOrder.POPurpose
					},
					"0030_DTM": [{
						DTM0101: "2",
						DTM0102: payload01.B2BMessage.Data.PurchaseOrder.PODate
					}],
					"0080_Segment_group_1": payload01.B2BMessage.Data.PurchaseOrder.References map (ref,ind) ->{
						"0090_RFF": {
							RFF0101: ref.Reference.'Type',
							RFF0102: ref.Reference.Value
						}
					},
					"0110_Segment_group_2": [{
						"0120_NAD": {
							NAD0501: payload01.B2BMessage.Data.PurchaseOrder.DeliveryParty.ShipToLocation.Address.AddressLine1,
							NAD08: payload01.B2BMessage.Data.PurchaseOrder.DeliveryParty.ShipToLocation.Address.PostalCode,
							NAD07: payload01.B2BMessage.Data.PurchaseOrder.DeliveryParty.ShipToLocation.Address.State,
							NAD0201: payload01.B2BMessage.Data.PurchaseOrder.DeliveryParty.LocationId,
							NAD01: "DP",
							NAD0502: payload01.B2BMessage.Data.PurchaseOrder.DeliveryParty.ShipToLocation.Address.AddressLine2,
							NAD06: payload01.B2BMessage.Data.PurchaseOrder.DeliveryParty.ShipToLocation.Address.City,
							NAD09: payload01.B2BMessage.Data.PurchaseOrder.DeliveryParty.ShipToLocation.Address.Country
						},
						"0210_Segment_group_5": [{
							"0220_CTA": {
								CTA01: "PD",
								CTA0202: payload01.B2BMessage.Data.PurchaseOrder.BuyerName
							},
							"0230_COM": [{
								COM0101: payload01.B2BMessage.Data.PurchaseOrder.BuyerPhone,
								"COM0102": "TE"
							}
							]
						}]
					}],
					"0280_Segment_group_7": [{
						"0290_CUX": {
							CUX0101: "1",
							CUX0102: payload01.B2BMessage.Data.PurchaseOrder.Currency,
							CUX0103: "9"
						}
					}]
				},
				"Summary": {
				},
				"Id": "ORDERS",
				"MessageHeader": {
					"UNH01": "72",
					"UNH0201": "ORDERS",
					"UNH0202": "D",
					"UNH0203": "97A",
					"UNH0204": "UN"
				},
				Detail: {
					"1010_Segment_group_28": payload01.B2BMessage.Data.PurchaseOrder.POLineItems map ( pOLineItem , indexOfPOLineItem ) -> {
						"1020_LIN": {
							LIN01: pOLineItem.LineNum,
							LIN0301: pOLineItem.SupplierItemNum
						},
						"1040_IMD": [{
							IMD0304: pOLineItem.ItemDescription
						}],
						"1060_QTY": [{
							QTY0102: pOLineItem.Quantity as Number
						}],
						"1280_Segment_group_32": [{
							"1290_PRI": {
								"PRI0101": "INF",
								PRI0102: pOLineItem.UnitPrice as Number
							}
						}]
					}
				}
			}
		}
	},
	"FunctionalAcksGenerated": [{
		"Interchange": {
			"UNB07": "CONTRL",
			"UNB0102": "1",
			"UNB0201": "MYTHICAL",
			"UNB0202": "ZZZ",
			"UNB0301": "WHITEROCK",
			"UNB0302": "ZZZ",
			"UNB0401": 240724,
			"UNB0402": 1921,
			"UNB05": "190",
			"UNB0101": "UNOA"
		},
		"Heading": {
			"0020_UCI": {
				"UCI01": "190",
				"UCI0302": "ZZZ",
				"UCI04": "7",
				"UCI0202": "ZZZ",
				"UCI0301": "MYTHICAL",
				"UCI0201": "WHITEROCK"
			}
		},
		"Id": "CONTRL",
		"Name": "Application error and acknowledgement message"
	}]
}
									

Let’s try to understand mapping between input Json and EDIFACT D97A EDI output.

In the Transform Message component the input Json is transformed into Java Object.

1. In the Output Java Object – we can see Delimiters, Messages, Interchange, FuctionalAcksToSend
2. EDIFACT message uses delimiters to separate the different elements within a message. These delimiters are specific characters that indicate the start and end of each element. We have used +:*’?
3. Purchase Order details from input JSON are mapped inside Messages, If we look at the hierarchy of Messages Node there is version – D97A then inside it ORDERS (Array) -. Inside ORDERS there are different object where you can map Purchase Order details
4. Purchase Order details such as PONumber, PODate BuyerEmailId BuyerName, POPurpose, CustomerId, CustomerName, POType are mapped to different segements inside Heading
5. POLineItems are mapped to objects inside the Details section.

Let’s see different sections under Messages -> D97A -> ORDERS

Note: we will only see the sections used inside the dataweave script , for more details refer EDIFACT specification

1. Interchange

The Interchange section is essential for identifying the sender, receiver, and context of the message. It also provides a framework for the organization of the message content.

Example:

UNB Defines the sender, receiver, message date, time, and reference number.
UNH Defines the message type, message version, message reference number, and message date.

2. Heading

Each Segment inside Heading has different use.

● The BGM (Beginning of Message | 0020_BGM Inside dataweave script) – It is a header segment that provides information about the overall message, such as the document type, document number, and date. It is typically located at the beginning of the message, after the UNB segment.

BGM001 Document type code
BGM002 Document type
BGM003 Document number
BGM004 Document Date

● The DTM (Date Time Segment | 0030_DTM Inside dataweave script) – It is a header segment. It can be used to specify dates related to the message itself, the goods or services being traded, or other relevant events.

DTM001 Date/time qualifier
DTM002 Date/time
DTM003 Date/time format
DTM004 Date/time zone

● Similarly there are other section with specific purpose. Please refer below screenshot:

● 0080_Segment_group_1 (0080_Segment_group_1 – Inside dataweave script) – It is a collection of segments that provide additional information about the document being exchanged.
In our Example we are using 0090_RFF – used to provide additional references or identifiers related to the document being processed

RFF0101 Reference Type
RFF0101 Reference Value

● 0110_Segment_group_2 (0110_Segment_group_2 – Inside dataweave script) – It is used to provide information about the parties involved in the transaction, such as the sender, receiver, and third parties.
In our Example we are using 0120_NAD – to provide detailed information about a party’s name and address.

NAD001 Delivery Party identification code
NAD0501 Delivery party Address Line 1
NAD0502 Delivery party Address Line 2
NAD006 Delivery Party city
NAD007 Delivery Party place
NAD008 Delivery Party postal code
NAD009 Delivery Party Country

3. Detail

0110_Segment_group_2 – segment group within the Detail section of an EDIFACT. message is used to provide information about the packaging details associated with a shipment. It can include details such as:
1020_LIN – to provide information about each individual item or service being ordered or shipped

LIN01 Line-Item Number
LIN0301 Item Number

1040_IMD – to provide additional information about an item or service being ordered or shipped

IMD0304 Line Item Description

1060_QTY – to provide information about the quantity of an item or service being ordered or shipped

QTY0101 Specifies the total quantity of the item
QTY0102 Specifies the quantity per package or other unit

1290_PRI– to provide information about the price of an item or service

PRI0102 Line Item Unit Price

4. Message Header – This section that provides essential information about the entire message. It defines the context of the message, including the sender, receiver, message type, and reference numbers.

The Message Header consists of two primary segments:

UNB: We have already discussed this header in Interchange section
UNH: Please refer below table

UNH0201 Message reference number
UNH0202 Message type code
UNH0203 Message version number
UNH0204 Controlling Agency (UN – United Nations in our example)

5. FunctionalAcksGenerated (Functional Acknowledgement): It is a type of message in EDIFACT that is sent in response to a specific application-level message to indicate the success or failure of the processing of that message. It is a crucial component of EDIFACT for ensuring the reliability and integrity of data exchanges.

There are two main types of Functional Acknowledgments in EDIFACT:

Positive Acknowledgment: This type of FA is sent when the application-level message has been processed successfully. It indicates that the message was received, understood, and accepted.
Negative Acknowledgment: This type of FA is sent when there was an error or problem during the processing of the application-level message. It provides details about the error or problem, allowing the sender to take corrective action.
The structure of a Functional Acknowledgment message is similar to that of other EDIFACT messages, with a header, body, and trailer.

Reference – EDIFACT D97A Purchase Order

Deploy and Test:

● Deploy the Mule application to your Mule runtime environment.
● Send a POST request containing the JSON purchase order to the configured endpoint of the HTTP Listener.
● Verify that the Mule flow successfully transforms the JSON data and generates the EDIFACT D97A EDI message in the specified output location.

Additional Considerations:

● Error Handling: Implement error handling mechanisms to gracefully handle potential issues during data transformation or file writing.
● Security: Ensure proper authentication and authorization mechanisms are in place when receiving and processing external requests.
● Testing: Thoroughly test your Mule flow with various JSON payloads and edge cases to ensure accurate EDIFACT EDI generation.

By following these steps, you can leverage Mule 4’s EDIFACT EDI connector and DataWeave to automate the conversion of JSON purchase orders EDIFACT D97A EDI messages, streamlining your B2B integrations.

Input Purchase Order JSON payload

										[
    {
        "B2BMessage": {
            "Header": {
                "ReceiverID": "MYTHICAL",
                "MessageID": "190",
                "ReceiveDateTime": "2024-07-26T12:56:37.622+05:30",
                "SenderID": "WHITEROCK",
                "MessageType": "enterprise-inbound-po",
                "BusinessKey": "1"
            },
            "Data": {
                "PurchaseOrder": {
                    "POPurpose": "9",
                    "POType": "220",
                    "PONumber": "123350",
                    "CustomerId": "WHITEROCK",
                    "CustomerName": "WHITEROCK",
                    "BuyerName": "Karen Smith",
                    "BuyerPhone": "030-5678913",
                    "Currency": "USD",
                    "BuyerEmailID": "abc_email_id",
                    "PODate": "20011107",
                    "References": [
                        {
                            "Reference": {
                                "Type": "CT",
                                "Value": "97.8400.1734V"
                            }
                        }
                    ],
                    "DeliveryParty": {
                        "LocationId": "T01626003",
                        "ShipToLocation": {
                            "ShipToLocationCode": "T01626003",
                            "Address": {
                                "AddressLine1": "Hardware BV",
                                "AddressLine2": "Coal Lane",
                                "City": "Bradford",
                                "PostalCode": "BD9 1SJ",
                                "State": "Yorkshire",
                                "Country": ""
                            }
                        }
                    },
                    "POLineItems": [
                        {
                            "PurchaseOrderLineId": "1-1",
                            "LineNum": "1",
                            "Quantity": "3",
                            "UnitPrice": "3999",
                            "ItemDescription": "SEAGATE VIPER EXT LVD 200G ULTRIUM",
                            "SupplierItemNum": "STU62001LW-K",
                            "CarrierName": "EXEL GLOBAL LOGIS",
                            "POLineLocation": {
                                "LineLocationId": "T01626003",
                                "ShipToLocation": {
                                    "ShipToLocationCode": "T01626003",
                                    "ShipToLocationName": "T01626003",
                                    "Address": {
                                        "AddressLine1": "Hardware BV",
                                        "AddressLine2": "Coal Lane",
                                        "City": "Bradford",
                                        "PostalCode": "BD9 1SJ",
                                        "State": "Yorkshire",
                                        "Country": ""
                                    }
                                }
                            }
                        },
                        {
                            "PurchaseOrderLineId": "1-2",
                            "LineNum": "2",
                            "Quantity": "2",
                            "UnitPrice": "3799",
                            "ItemDescription": "SEAGATE VIPER INT LVD 200G ULTRIUM+",
                            "SupplierItemNum": "STU42001LW-K",
                            "CarrierName": "EXEL GLOBAL LOGIS",
                            "POLineLocation": {
                                "LineLocationId": "T01626003",
                                "ShipToLocation": {
                                    "ShipToLocationCode": "T01626003",
                                    "ShipToLocationName": "T01626003",
                                    "Address": {
                                        "AddressLine1": "Hardware BV",
                                        "AddressLine2": "Coal Lane",
                                        "City": "Bradford",
                                        "PostalCode": "BD9 1SJ",
                                        "State": "Yorkshire",
                                        "Country": ""
                                    }
                                }
                            }
                        },
                        {
                            "PurchaseOrderLineId": "1-3",
                            "LineNum": "3",
                            "Quantity": "1",
                            "UnitPrice": "7099",
                            "ItemDescription": "SEAGATE VIPER EXT LVD ULTRIUM1 11CA",
                            "SupplierItemNum": "STUL620001LW-K",
                            "CarrierName": "EXEL GLOBAL LOGIS",
                            "POLineLocation": {
                                "LineLocationId": "T01626003",
                                "ShipToLocation": {
                                    "ShipToLocationCode": "T01626003",
                                    "ShipToLocationName": "T01626003",
                                    "Address": {
                                        "AddressLine1": "Hardware BV",
                                        "AddressLine2": "Coal Lane",
                                        "City": "Bradford",
                                        "PostalCode": "BD9 1SJ",
                                        "State": "Yorkshire",
                                        "Country": ""
                                    }
                                }
                            }
                        },
                        {
                            "PurchaseOrderLineId": "1-4",
                            "LineNum": "4",
                            "Quantity": "1",
                            "UnitPrice": "379",
                            "ItemDescription": "SEA AUTOLOADER RACKMOUNT KIT 5U",
                            "SupplierItemNum": "STUQ",
                            "CarrierName": "EXEL GLOBAL LOGIS",
                            "POLineLocation": {
                                "LineLocationId": "T01626003",
                                "ShipToLocation": {
                                    "ShipToLocationCode": "T01626003",
                                    "ShipToLocationName": "T01626003",
                                    "Address": {
                                        "AddressLine1": "Hardware BV",
                                        "AddressLine2": "Coal Lane",
                                        "City": "Bradford",
                                        "PostalCode": "BD9 1SJ",
                                        "State": "Yorkshire",
                                        "Country": ""
                                    }
                                }
                            }
                        }
                    ]
                }
            }
        }
    }
]