All Blogs in this Series –
AI Powered Invoice Management with SAP RAP and ABAP on Cloud
AI Powered Invoice Management with SAP RAP and ABAP on Cloud – Part 1
AI Powered Invoice Management with SAP RAP and ABAP on Cloud – Part 2
AI Powered Invoice Management with SAP RAP and ABAP on Cloud – Part 3
If you want to know the reference of this blog, please go through the Part 1 & Part 2 sections of this AI Powered Invoice Management Series.
This is going to be the last part of the AI Powered Invoice Management Series. What we are focusing here is –
- Creating a Unmanaged scenario
- Creation of a ABAP Workflow
- Creation of a NodeJS based Wrapper on top of the ABAP Unmanaged API
Process Flow
On-premise developments ( Create RAP Unmanaged API )
Create a custom table –
Create CDS Entity
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Interface of WF Trigger'
define root view entity Z_I_INV_PO_WF
as select from
// zinv_po_status
ekko left outer join
zinv_po_status on ekko.ebeln = zinv_po_status.ebeln
{
// key ekko.ebeln,
key zinv_po_status.ebeln,
zinv_po_status.amount,
zinv_po_status.status
}
Create a Projection view –
@EndUserText.label: 'Peojection view for INV PO WF'
@AccessControl.authorizationCheck: #NOT_REQUIRED
define root view entity Z_P_INV_PO_WF
provider contract transactional_query
as projection on Z_I_INV_PO_WF {
key ebeln,
amount,
status
}
Create Behavior Definition –
unmanaged
implementation in class zbp_i_inv_po_wf unique;
define behavior for Z_I_INV_PO_WF
{
create;
}
projection;
//strict;
define behavior for Z_P_INV_PO_WF //alias <alias_name>
{
use create;
// use update;
// use delete;
}
Implement the Behavior class
CLASS lhc_z_i_inv_po_wf DEFINITION INHERITING FROM
cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS create FOR MODIFY
IMPORTING entities FOR CREATE z_i_inv_po_wf.
METHODS read FOR READ
IMPORTING keys FOR READ z_i_inv_po_wf RESULT result.
ENDCLASS.
CLASS lhc_z_i_inv_po_wf IMPLEMENTATION.
METHOD create.
DATA: ls_line TYPE zinv_po_status,
lt_lines TYPE TABLE OF zinv_po_status.
LOOP AT entities ASSIGNING FIELD-SYMBOL(<ls_entity>).
ls_line = CORRESPONDING #( <ls_entity> ).
APPEND ls_line TO lt_lines.
DATA : lv_objectkey TYPE swr_struct-object_key.
DATA: lt_input_container TYPE TABLE OF swr_cont,
lv_subrc TYPE sy-subrc,
lv_value TYPE swe_evtid,
lt_msglns TYPE TABLE OF swr_messag,
lt_msgstr TYPE TABLE OF swr_mstruc.
lv_objectkey = ls_line-ebeln.
lt_input_container = VALUE #( ( element = 'PurchasingDocument'
value = ls_line-ebeln ) ( element = 'TargetValue' value = ls_lineamount ) ).
CALL FUNCTION 'SAP_WAPI_CREATE_EVENT' STARTING NEW TASK
lv_objectkey
EXPORTING
object_type = 'ZINV_PUORD'
object_key = lv_objectkey
event = 'PROCESS_PAY_FOR_INV'
TABLES
input_container = lt_input_container
message_lines = lt_msglns
message_struct = lt_msgstr.
ENDLOOP.
zcl_inv_payment=>update_table( it_table = lt_lines ).
ENDMETHOD.
METHOD read.
ENDMETHOD.
ENDCLASS.
CLASS lsc_z_i_inv_po_wf DEFINITION INHERITING FROM
cl_abap_behavior_saver.
PROTECTED SECTION.
METHODS finalize REDEFINITION.
METHODS check_before_save REDEFINITION.
METHODS save REDEFINITION.
METHODS cleanup REDEFINITION.
METHODS cleanup_finalize REDEFINITION.
ENDCLASS.
CLASS lsc_z_i_inv_po_wf IMPLEMENTATION.
METHOD finalize.
ENDMETHOD.
METHOD check_before_save.
ENDMETHOD.
METHOD save.
ENDMETHOD.
METHOD cleanup.
ENDMETHOD.
METHOD cleanup_finalize.
ENDMETHOD.
ENDCLASS.
On-premise developments ( Workflow Developments )
Create a basic workflow –
Now implement global variables –
Add decisions Approve and Reject in the Workflow
Configure the bindings
Create Events in SWo1 and set the parameters –
Here are the parameter lists of the workflow –
SAP CF NodeJS Express server to trigger the Workflow
Create a NPM package and create index.js
var express = require('express');
var app = express();
var PORT = 8080;
var lib = require('./lib');
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.post('/trigger_wf', async function (req, res) {
await lib.trigger_wf(req, res);
});
app.get('/', async function (req, res) {
await lib.base(req, res);
});
app.listen(PORT, function (err) {
if (err) console.log(err);
console.log("Server listening on PORT", PORT);
});
Now create the lib.js file
const SapCfAxios = require('sap-cf-axios').default;
const xsenv = require('@sap/xsenv');
module.exports = {
base: async function base(req, res) {
res.send(JSON.stringify({ 'uri': '/trigger_wf' }));
},
trigger_wf: async function trigger_wf(req, res) {
var custurl = process.env['MURL'];
console.log('I am here');
// var data = req.body;
console.log('--------------------')
console.log(req.body);
var data = req.body;
var post_body = {
"ebeln": data.ebeln,
"amount": data.amount,
"status": data.status
}
console.log(post_body);
try {
console.log('--------------------')
const axios_DUMMY_GET = SapCfAxios('DUMMY_GET');
const response = await axios_DUMMY_GET({
method: 'post',
url: custurl,
headers:{
"X-Requested-With" : "X"
},
data: post_body
});
console.log('--------------------')
console.log(JSON.stringify(response.data.d))
res.json({ "STATUS": "Post Successful" });
} catch (error) {
console.log(JSON.stringify(error));
res.json({ "STATUS": "Error in Post", "MES":
JSON.stringify(error) });
}
}
}
and use manifest.yml file to deploy your nodejs to cloud foundry environment
Note – Here sap-cf-axios is used to create a secure communication tunnel to call the on-premise destination through the SAP BTP destination and Cloud Connectors.
Thanks for having patience reading out the blog till the end. Hope to hear from you….