Business Object Journal Entry (I_JournalEntryTP) is available in S/4 HANA Cloud environment. It provides operations:
You can try to build your own ‘Posting’ Fiori application by creating custom RAB business object. The posting can be achieved by calling the ‘Post’ action in Journal Entry object.
This blog will show a sample demo. Please note: This demo is only a demonstration of the technology and does not provide any guidance for the business.
The Fiori application will look like:
Worklist
Input Transactional Data
Save
Steps:
@EndUserText.label : 'Journal Entry Header'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zgje_header {
key client : abap.clnt not null;
key uuid : sysuuid_x16 not null;
bukrs : bukrs;
gjahr : gjahr;
belnr : belnr_d;
waers : waers;
bldat : bldat;
budat : budat;
bktxt : bktxt;
created_by : abp_creation_user;
created_at : abp_creation_tstmpl;
last_changed_by : abp_lastchange_user;
last_changed_at : abp_lastchange_tstmpl;
local_last_changed_at : abp_locinst_lastchange_tstmpl;
}
@EndUserText.label : 'Journal Entry Item'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zgje_item {
key client : abap.clnt not null;
key uuid : sysuuid_x16 not null;
key buzei : buzei not null;
@Semantics.amount.currencyCode : 'zgje_header.waers'
wrbtr : fins_vwcur12;
sgtxt : sgtxt;
hkont : hkont;
kostl : kostl;
prctr : prctr;
item_created_by : abp_creation_user;
item_created_at : abp_creation_tstmpl;
item_last_changed_by : abp_lastchange_user;
item_last_changed_at : abp_lastchange_tstmpl;
item_local_last_changed_at : abp_locinst_lastchange_tstmpl;
}
@EndUserText.label : 'Journal Entry Header Draft Table'
@AbapCatalog.enhancement.category : #EXTENSIBLE_ANY
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zgje_header_d {
key mandt : mandt not null;
key uuid : sysuuid_x16 not null;
belnr : belnr_d;
bukrs : bukrs;
gjahr : gjahr;
waers : waers;
bldat : bldat;
budat : budat;
bktxt : bktxt;
created_by : abp_creation_user;
created_at : abp_creation_tstmpl;
last_changed_by : abp_lastchange_user;
last_changed_at : abp_lastchange_tstmpl;
local_last_changed_at : abp_locinst_lastchange_tstmpl;
"%admin" : include sych_bdl_draft_admin_inc;
}
@EndUserText.label : 'Journal Entry Item Draft'
@AbapCatalog.enhancement.category : #EXTENSIBLE_ANY
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zgje_item_d {
key mandt : mandt not null;
key uuid : sysuuid_x16 not null;
key buzei : buzei not null;
@Semantics.amount.currencyCode : 'zgje_item_d.waers'
wrbtr : fins_vwcur12;
waers : waers;
sgtxt : sgtxt;
hkont : hkont;
kostl : kostl;
prctr : prctr;
item_created_by : abp_creation_user;
item_created_at : abp_creation_tstmpl;
item_last_changed_by : abp_lastchange_user;
item_last_changed_at : abp_lastchange_tstmpl;
"%admin" : include sych_bdl_draft_admin_inc;
}
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'GL Journal Entry'
define root view entity ZR_GeneralJournalEntry
as select from zgje_header
composition [0..*] of ZR_GeneralJournalEntryItem as _Item
{
key uuid as Uuid,
belnr as belnr,
bukrs as Bukrs,
gjahr as Gjahr,
waers as Waers,
bldat as Bldat,
budat as Budat,
bktxt as Bktxt,
@Semantics.user.createdBy: true
created_by as Created_By,
@Semantics.systemDateTime.createdAt: true
created_at as Created_At,
@Semantics.user.lastChangedBy: true
last_changed_by as Last_Changed_By,
@Semantics.systemDateTime.lastChangedAt: true
last_changed_at as Last_Changed_At,
@Semantics.systemDateTime.localInstanceLastChangedAt: true
local_last_changed_at as Local_Last_Changed_At,
_Item
}
@AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'GL Journal Entry Item'
@Metadata.ignorePropagatedAnnotations: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
define view entity ZR_GeneralJournalEntryItem
as select from zgje_item
association to parent ZR_GeneralJournalEntry as _Header on $projection.Uuid = _Header.Uuid
{
key uuid as Uuid,
key buzei as Buzei,
@Semantics.amount.currencyCode: 'Waers'
wrbtr as Wrbtr,
_Header.Waers as Waers,
sgtxt as sgtxt,
hkont as hkont,
kostl as Kostl,
prctr as Prctr,
@Semantics.user.createdBy: true
item_created_by as Item_Created_By,
@Semantics.systemDateTime.createdAt: true
item_created_at as Item_Created_At,
@Semantics.user.lastChangedBy: true
item_last_changed_by as Item_Last_Changed_By,
@Semantics.systemDateTime.localInstanceLastChangedAt: true
item_last_changed_at as Item_Last_Changed_At,
_Header
}
CLASS zgje_transaction_handler DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
CLASS-DATA: go_instance TYPE REF TO zgje_transaction_handler.
CLASS-METHODS: get_instance RETURNING VALUE(result) TYPE REF TO zgje_transaction_handler.
TYPES: BEGIN OF ty_temp_key,
cid TYPE abp_behv_cid,
pid TYPE abp_behv_pid,
END OF ty_temp_key,
tt_temp_key TYPE STANDARD TABLE OF ty_temp_key WITH DEFAULT KEY,
BEGIN OF ty_final_key,
cid TYPE abp_behv_cid,
bukrs TYPE bukrs,
belnr TYPE belnr_d,
gjahr TYPE gjahr,
END OF ty_final_key,
tt_final_key type STANDARD TABLE OF ty_final_key WITH DEFAULT KEY,
tt_header TYPE STANDARD TABLE OF zgje_header WITH DEFAULT KEY.
DATA: temp_key TYPE tt_temp_key.
METHODS: set_temp_key IMPORTING it_temp_key TYPE tt_temp_key,
convert_temp_to_final RETURNING VALUE(result) TYPE tt_final_key,
additional_save IMPORTING it_create type tt_header
it_delete TYPE tt_header,
clean_up.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zgje_transaction_handler IMPLEMENTATION.
METHOD get_instance.
IF go_instance IS NOT BOUND.
go_instance = NEW #( ).
ENDIF.
result = go_instance.
ENDMETHOD.
METHOD additional_save.
data: lt_create type TABLE of zgje_header.
DATA(lt_je_key) = convert_temp_to_final( ).
loop at it_create into data(ls_create).
read TABLE lt_je_key into data(ls_je_key) with key cid = ls_create-uuid.
if sy-subrc = 0.
ls_create-belnr = ls_je_key-belnr.
append ls_create to lt_create.
endif.
ENDLOOP.
IF lt_create IS NOT INITIAL.
INSERT zgje_header FROM TABLE @lt_create.
ENDIF.
IF it_delete IS NOT INITIAL.
DELETE zgje_header FROM TABLE @it_delete.
ENDIF.
ENDMETHOD.
METHOD clean_up.
CLEAR temp_key.
ENDMETHOD.
METHOD convert_temp_to_final.
DATA: ls_final_key TYPE ty_final_key.
IF temp_key IS NOT INITIAL.
LOOP AT temp_key INTO DATA(ls_temp_key).
CONVERT KEY OF i_journalentrytp
FROM ls_temp_key-pid
TO FINAL(lv_root_key).
ls_final_key-cid = ls_temp_key-cid.
ls_final_key-bukrs = lv_root_key-companycode.
ls_final_key-belnr = lv_root_key-accountingdocument.
ls_final_key-gjahr = lv_root_key-fiscalyear.
APPEND ls_final_key TO result.
ENDLOOP.
ENDIF.
ENDMETHOD.
METHOD set_temp_key.
temp_key = it_temp_key.
ENDMETHOD.
ENDCLASS.
managed with additional save
implementation in class zbp_r_generaljournalentry unique;
strict ( 2 );
with draft;
define behavior for ZR_GeneralJournalEntry //alias <alias_name>
//persistent table zgje_header
with unmanaged save
draft table zgje_header_d
lock master
total etag Last_Changed_At
authorization master ( instance )
etag master Local_Last_Changed_At
{
create;
update ;
delete ;
association _Item { create; with draft; }
draft action Resume;
draft action Edit;
draft action Activate optimized;
draft action Discard;
draft determine action Prepare;
determination Post on save {create;}
mapping for zgje_header corresponding;
field ( readonly, numbering : managed ) Uuid;
field ( readonly ) belnr;
}
define behavior for ZR_GeneralJournalEntryItem //alias <alias_name>
persistent table zgje_item
draft table zgje_item_d
lock dependent by _Header
authorization dependent by _Header
etag master Item_Last_Changed_At
{
update ;
delete ;
field ( readonly ) Uuid;
field ( mandatory: create,readonly : update ) Buzei;
association _Header { with draft; }
mapping for zgje_item corresponding;
}
CLASS lhc_zr_generaljournalentry DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS get_instance_authorizations FOR INSTANCE AUTHORIZATION
IMPORTING keys REQUEST requested_authorizations FOR zr_generaljournalentry RESULT result.
METHODS post FOR DETERMINE ON SAVE
IMPORTING keys FOR zr_generaljournalentry~post.
ENDCLASS.
CLASS lhc_zr_generaljournalentry IMPLEMENTATION.
METHOD get_instance_authorizations.
ENDMETHOD.
METHOD post.
DATA: lt_entry TYPE TABLE FOR ACTION IMPORT i_journalentrytp~post,
ls_entry LIKE LINE OF lt_entry,
ls_glitem LIKE LINE OF ls_entry-%param-_glitems,
ls_amount LIKE LINE OF ls_glitem-_currencyamount,
lt_temp_key TYPE zgje_transaction_handler=>tt_temp_key,
ls_temp_key LIKE LINE OF lt_temp_key.
READ ENTITIES OF zr_generaljournalentry IN LOCAL MODE
ENTITY zr_generaljournalentry ALL FIELDS WITH CORRESPONDING #( keys ) RESULT FINAL(header)
ENTITY zr_generaljournalentry BY \_item ALL FIELDS WITH CORRESPONDING #( keys ) RESULT FINAL(item).
"start to call I_JournalEntryTP~Post
LOOP AT header REFERENCE INTO DATA(ls_header).
CLEAR ls_entry.
ls_entry-%cid = ls_header->uuid. "use UUID as CID
ls_entry-%param-companycode = ls_header->bukrs.
ls_entry-%param-businesstransactiontype = 'RFPO'.
ls_entry-%param-accountingdocumenttype = 'AB'.
ls_entry-%param-accountingdocumentheadertext = ls_header->bktxt.
ls_entry-%param-documentdate = ls_header->bldat.
ls_entry-%param-postingdate = ls_header->budat.
ls_entry-%param-createdbyuser = ls_header->created_by.
LOOP AT item REFERENCE INTO DATA(ls_item) USING KEY entity WHERE uuid = ls_header->uuid.
CLEAR ls_glitem.
ls_glitem-glaccountlineitem = ls_item->%data-buzei.
ls_glitem-glaccount = ls_item->%data-hkont.
ls_glitem-costcenter = ls_item->%data-kostl.
ls_glitem-profitcenter = ls_item->%data-prctr.
ls_glitem-documentitemtext = ls_item->%data-sgtxt.
CLEAR ls_amount.
ls_amount-currencyrole = '00'.
ls_amount-currency = ls_header->waers.
ls_amount-journalentryitemamount = ls_item->%data-wrbtr.
APPEND ls_amount TO ls_glitem-_currencyamount.
APPEND ls_glitem TO ls_entry-%param-_glitems.
ENDLOOP.
APPEND ls_entry TO lt_entry.
ENDLOOP.
IF lt_entry IS NOT INITIAL.
MODIFY ENTITIES OF i_journalentrytp
ENTITY journalentry
EXECUTE post FROM lt_entry
MAPPED FINAL(ls_post_mapped)
FAILED FINAL(ls_post_failed)
REPORTED FINAL(ls_post_reported).
IF ls_post_failed IS NOT INITIAL.
LOOP AT ls_post_reported-journalentry INTO DATA(ls_report).
APPEND VALUE #( uuid = ls_report-%cid
%create = if_abap_behv=>mk-on
%is_draft = if_abap_behv=>mk-on
%msg = ls_report-%msg ) TO reported-zr_generaljournalentry.
ENDLOOP.
ENDIF.
LOOP AT ls_post_mapped-journalentry INTO DATA(ls_je_mapped).
ls_temp_key-cid = ls_je_mapped-%cid.
ls_temp_key-pid = ls_je_mapped-%pid.
APPEND ls_temp_key TO lt_temp_key.
ENDLOOP.
ENDIF.
zgje_transaction_handler=>get_instance( )->set_temp_key( lt_temp_key ).
ENDMETHOD.
ENDCLASS.
CLASS lsc_zr_generaljournalentry DEFINITION INHERITING FROM cl_abap_behavior_saver.
PROTECTED SECTION.
METHODS save_modified REDEFINITION.
METHODS cleanup_finalize REDEFINITION.
ENDCLASS.
CLASS lsc_zr_generaljournalentry IMPLEMENTATION.
METHOD save_modified.
"unmanaged save for table ZGJE_HEADER
DATA: Lt_create type TABLE of ZGJE_HEADER,
lt_delete type TABLE of ZGJE_HEADER.
lt_create = CORRESPONDING #( create-zr_generaljournalentry mapping from entity ).
lt_delete = CORRESPONDING #( delete-zr_generaljournalentry mapping from entity ).
zgje_transaction_handler=>get_instance( )->additional_save( it_create = lt_create
it_delete = lt_delete ).
ENDMETHOD.
METHOD cleanup_finalize.
zgje_transaction_handler=>get_instance( )->clean_up( ).
ENDMETHOD.
ENDCLASS.
@EndUserText.label: 'GL Journal Entry Projection'
@AccessControl.authorizationCheck: #NOT_REQUIRED
@Metadata.allowExtensions: true
define root view entity ZC_GeneralJournalEntry
provider contract transactional_query
as projection on ZR_GeneralJournalEntry
{
key Uuid,
belnr,
Bukrs,
Gjahr,
Waers,
Bldat,
Budat,
Bktxt,
@Semantics.user.createdBy: true
Created_By,
@Semantics.systemDateTime.createdAt: true
Created_At,
@Semantics.user.lastChangedBy: true
Last_Changed_By,
@Semantics.systemDateTime.lastChangedAt: true
Last_Changed_At,
@Semantics.systemDateTime.localInstanceLastChangedAt: true
Local_Last_Changed_At,
_Item : redirected to composition child ZC_GeneralJournalEntryItem
}
@EndUserText.label: 'GL Journal Item Projection'
@AccessControl.authorizationCheck: #NOT_REQUIRED
@Metadata.allowExtensions: true
define view entity ZC_GeneralJournalEntryItem
as projection on ZR_GeneralJournalEntryItem
{
key Uuid,
key Buzei,
@Semantics.amount.currencyCode: 'Waers'
Wrbtr,
Waers,
sgtxt,
hkont,
Kostl,
Prctr,
@Semantics.user.createdBy: true
Item_Created_By,
@Semantics.systemDateTime.createdAt: true
Item_Created_At,
@Semantics.user.lastChangedBy: true
Item_Last_Changed_By,
@Semantics.systemDateTime.localInstanceLastChangedAt: true
Item_Last_Changed_At,
_Header : redirected to parent ZC_GeneralJournalEntry
}
@Metadata.layer: #CUSTOMER
annotate view ZC_GeneralJournalEntry with
{
@UI.facet: [ { id: 'Header',
purpose: #STANDARD,
type: #IDENTIFICATION_REFERENCE,
label: 'Entry',
position: 10 } ,
{ id: 'Items',
purpose: #STANDARD,
type: #LINEITEM_REFERENCE,
label: 'Items',
position: 20,
targetElement: '_Item'}]
// @UI.identification: [{ position: 10 }]
// Uuid;
@Consumption.valueHelpDefinition: [{ entity: { name:'I_CompanyCode', element: 'CompanyCode' } }]
@UI: { lineItem: [{ position: 10}],selectionField: [{ position: 10 }],identification: [{ position: 20 }] }
Bukrs;
@UI: { lineItem: [{ position: 20}],selectionField: [{ position: 20 }],identification: [{ position: 30 }] }
Gjahr;
@UI: { lineItem: [{ position: 30}],selectionField: [{ position: 30 }],identification: [{ position: 40 }] }
@Consumption.semanticObject: 'AccountingDocument'
belnr;
@Consumption.valueHelpDefinition: [{ entity: { name:'I_Currency', element: 'Currency' } }]
@UI: { lineItem: [{ position: 40}],selectionField: [{ position: 40 }],identification: [{ position: 50 }] }
Waers;
@UI: { lineItem: [{ position: 50}],selectionField: [{ position: 50 }],identification: [{ position: 60 }] }
Bldat;
@UI: { lineItem: [{ position: 60}],selectionField: [{ position: 60 }],identification: [{ position: 70 }] }
Budat;
@UI: { lineItem: [{ position: 70}],identification: [{ position: 80 }] }
Bktxt;
}
@Metadata.layer: #CUSTOMER
annotate view ZC_GeneralJournalEntryItem with
{
@UI.facet: [ { id: 'Item',
purpose: #STANDARD,
type: #IDENTIFICATION_REFERENCE,
label: 'Item',
position: 10 } ]
@UI: { lineItem: [{ position: 10}],identification: [{ position: 10 }] }
Buzei;
@UI: { lineItem: [{ position: 20}],identification: [{ position: 20 }] }
sgtxt;
@UI: { lineItem: [{ position: 30}],identification: [{ position: 30 }] }
Wrbtr;
@UI: { lineItem: [{ position: 40}],identification: [{ position: 40 }] }
@Consumption.valueHelpDefinition: [{ entity: { name:'I_GLAccount', element: 'GLAccount' } }]
hkont;
@UI: { lineItem: [{ position: 50}],identification: [{ position: 50 }] }
@Consumption.valueHelpDefinition: [{ entity: { name:'I_CostCenter', element: 'CostCenter' } }]
Kostl;
@UI: { lineItem: [{ position: 60}],identification: [{ position: 60 }] }
@Consumption.valueHelpDefinition: [{ entity: { name:'I_ProfitCenterStdVH', element: 'ProfitCenter' } }]
Prctr;
}
projection;
strict ( 2 );
use draft;
define behavior for ZC_GeneralJournalEntry //alias <alias_name>
{
use create;
use update;
use delete;
use action Resume;
use action Edit;
use action Activate;
use action Discard;
use action Prepare;
use association _Item { create; with draft; }
}
define behavior for ZC_GeneralJournalEntryItem //alias <alias_name>
{
use update;
use delete;
use association _Header { with draft; }
}
@EndUserText.label: 'Manage_GL_Posting'
define service Z_EXT_GL_POSTING {
expose ZC_GeneralJournalEntry;
expose ZC_GeneralJournalEntryItem;
}