Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
mmcisme1
Active Contributor
My requirement was to create a customer statement - easy enough.  The next requirement was a little harder.  It was to use the invoice OPD to determine e-mail or print.  If it was e-mail then where to send it.

To start out, I'm on HANA On-Premise version 1709.

If you need help with setting up OPD, there are some very nice blogs out there:

Output Management via BRF+

New Output Management for Billing

My problem was really not the setup, it was how to add it to my program.   Once I added it, I needed to understand how it worked.  It took me longer than I thought it would.   (By the way you can use this for BFR+ too)  So it was something nice to learn.

So as usual I'm pressed for time.   Let's get started:

First I found the OPD, in BRF+.   Transaction code BRF+.  Keep in mind this was developed via Webdynpro so switching from client to client you'll have to sign in on the html page.



Aha - my OPD applications



Next I opened up the billing document.  There was a lot of great information here.  But I needed to find something specific.  So I opened up the function.



At this point you can run a simulation to test what will come up.    Very nice.  You can also do this via the OPD transaction.   In the OPD transaction you can see the data that has been added.  So now I'm switching to OPD as it is easier - at least for me - to work with.



I found the function I really wanted was channel.  So next I started programming.  Here are some snippets.
  data: lo_factory    type ref to if_fdt_factory,
c_test_app_id type fdt_uuid,
lo_query type ref to if_fdt_query,
lt_ids type if_fdt_types=>ts_object_id,
ls_ids type if_fdt_types=>id.
types:
lt_ids type sorted table of if_fdt_types=>id
with unique default key .

data: lo_fdt_query type ref to if_fdt_query.

clear lt_ids.
call method cl_fdt_query=>get_instance
receiving
ro_query = lo_fdt_query.
* get application id

call method lo_fdt_query->get_ids
exporting
iv_name = 'OPD_V3_BILLING_DOCUMENT'
importing
ets_object_id = lt_ids.

read table lt_ids into ls_ids index 1.

"get factory for application
lo_factory = cl_fdt_factory=>get_instance( exporting iv_application_id = ls_ids ).
* returning c_test_app_id = lo_factory ).

This just pulled in the id that I needed for the billing document.   I retrieved the id for the function.  Now those of you reading this - I skipped some functions.  That was because they were 1 to 1 relationship.  You'll want to modify for your purpose.  (Try/Catch would be nice to add as well.)
  lo_query = lo_factory->get_query( iv_object_type = if_fdt_constants=>gc_object_type_function ).
lo_query->get_ids(
exporting
iv_name = 'FUNC_CHANNEL'
importing
ets_object_id = lt_ids ).
read table lt_ids into ls_ids index 1.
if sy-subrc = 0.
gv_channel_id = ls_ids.
else.
* Move to error table
endif.

Next was the actual work.  I've read not to use the following as it takes too long.  I've also read this is the best way  to do it.  I wanted to avoid using the actual ids without the names.
        lo_context->set_value( iv_name = 'OUTPUT_TYPE' ia_value = lv_form ).
lo_context->set_value( iv_name = 'ROLE' ia_value = lv_role ).
lo_context->set_value( iv_name = 'BUSINESS_PARTNER_ID' ia_value = lv_kunnr ).

lv_function_id = gv_channel_id.

try.

data lt_abap_parbind type abap_parmbind_tab.
data _v_timestamp2 type if_fdt_types=>timestamp.

field-symbols <fs_any> type any.


clear lr_data.
get reference of lt_out into lr_data.

****************************************************************************************************
* Trigger function processing
****************************************************************************************************
assign lr_data->* to <fs_any>.
call method cl_fdt_function_process=>process
exporting
iv_function_id = lv_function_id
iv_timestamp = _v_timestamp2
io_context = lo_context
importing
ea_result = <fs_any>
changing
ct_name_value = lt_abap_parbind.
lt_out = <fs_any>.

read table lt_out into ls_out
with key exclusive_ind = abap_true.
if sy-subrc = 0 and
ls_out-channel = 'EMAIL'.
gv_print = abap_false.
else.
gv_print = abap_true.
endif.

Now I had if the document should be e-mailed or printed.   I found that our e-mail addresses were stored in transaction BP and not in the OPD.  So I pulled the default e-mail address.

After you've read all this keep in mind.   BRF+ will generate the code for you.  I didn't like all the hard coding.

BRF+ Basics

You can also take all your coding out of it by generating a function module.  Again this is in BRF+, but OPD is really part of BRF+.  You want to be inside your function.  Then click on tools.  There will be an option to generate a function module.  Again the hard coding made me hesitant to use it. I like more control.



More details in the following and you'll notice some duplication from my post and this one.  It really helped me a lot.

My learnings in BRF+

 

Pretty cool.  Now I can think of a lot of uses for BRF+.   Those custom tables that I have that determine something like highest dollar amount, those could easily be switched to BRF+.

That's my quick example.  Now a challenge - if you have a better way of doing this - please add it in the comments.
26 Comments