Redetermine conditions in sales orders massively using BOL
Component | Suuport Pachage |
---|---|
BBPCRM | SAPKU70204 |
SAP_ABA | SAPKA73105 |
SAP_BASIS | SAPKB73105 |
WEBCUIF | SAPK-73105INWEBCUIF |
The scnenario
We want to redetermine all the conditions of sales orders without modifying any data which forces the pricing redetermination (PRICE_DATE, STATUS, etc.)
Should we use BOL to perform mass changes?
Well, IMHO you shouldn’t use the BOL to manage large amount of data, why? Well, that’s a good question, in theory less amount of software layers, better performance, but one reason why I would choose an API instead of BOL is using aRFC to improve the performance via parallelization, as you already know you must initialize the BOL core and load the specific sets for each aRFC, so I don’t believe this is the right path, but if don’t agree with my view I will be more than happy to discuss even change this lines 🙂
Then, Why we should use BOL?
BOL has numerous advantages, modern/uniform layer to access data, tools for modelling, etc. my intention is not enter in detail why we should or not using BOL, but I think a very brief overview will situate you for what comes next.
We should use BOL, some times, because there’s no other option, and my example is one of those cases, there’s no complete API to redetermine conditions. If you want to develop this functionality you should trace all the FM involved in during the process and put all the pieces together (for more detail, I would suggest to trace the stack until the FM PRC_PD_ITEM_UPDATE_MULTI or PRC_PD_ITEM_UPDATE is triggered), the problem is you are decoupling the logic in the GENIL layer or in the controller of the CRMD_ORDER into a custom spot, like a report, the logic decoupled is how the standard works right here, right now, but guess what, SP and ehp will come, and new FM can be included/excluded bugs fixed, etc. and your code will remind the same, so you must take an eye every time you apply a note, sp or ehp, from my point of view this is a huge waste of time.
The small reward
Here is the sample of the code as reward to bear all my “philosophical” stuff, keep in mind this is just a sample use it with care.
DATA: lt_param TYPE crmt_name_value_pair_tab.
DATA: lv_error_w TYPE string,
lv_object_id_w TYPE string.
DATA: lo_bol_core TYPE REF TO cl_crm_bol_core,
lo_query TYPE REF TO cl_crm_bol_query_service,
lo_result TYPE REF TO if_bol_entity_col,
lo_entity TYPE REF TO cl_crm_bol_entity,
lo_col TYPE REF TO if_bol_entity_col,
lo_bol_trans TYPE REF TO if_bol_transaction_context.
DATA: lv_bpath_query TYPE string.
FIELD-SYMBOLS: <ls_param> LIKE LINE OF lt_param.
lo_bol_core = cl_crm_bol_core=>get_instance( ).
lo_bol_core->start_up( iv_appl_name = 'ONEORDER' ).
lo_query = cl_crm_bol_query_service=>get_instance( 'BTQuery1O' ).
lo_query->set_property( EXPORTING iv_attr_name = 'OBJECT_ID'
iv_value = lv_object_id_w ).
lo_result = lo_query->get_query_result( ).
TRY.
IF lo_result->size( ) EQ 0.
* Error handling
ENDIF.
lo_entity = lo_result->get_first( ).
IF lo_entity->lock( ) EQ abap_false.
* Error handling
ENDIF.
CATCH cx_sy_move_cast_error.
* Error handling
ENDTRY.
lv_bpath_query = `./BTOrderHeader/BTHeaderPridoc/CondHSetRel/*$`.
lo_col = lo_entity->get_related_entities_by_bpath( iv_bpath_statement = lv_bpath_query ).
IF lo_col->size( ) EQ 0.
* Error handling
ENDIF.
lo_entity ?= lo_col->get_first( ).
CLEAR lt_param.
APPEND INITIAL LINE TO lt_param ASSIGNING <ls_param>.
<ls_param>-name = 'RETAIN_MANUAL_CONDITIONS'.
<ls_param>-value = abap_true.
TRY.
lo_entity->execute( iv_method_name = 'Update' it_param = lt_param ).
lo_bol_core->modify( ).
lo_bol_trans = lo_bol_core->get_transaction( ).
lo_bol_trans->save( ).
lo_bol_trans->commit( ).
lo_bol_core->reset( EXPORTING iv_include_bal_reset = abap_true ).
CATCH: cx_crm_genil_model_error cx_crm_bol_meth_exec_failed.
* Error handling
ENDTRY.
If you want to redetermine the conditions at item level you can use the following BPath: ./BTOrderHeader/BTHeaderPridoc/CondItemSetRel/*$ and loop at the collection executing the method for each entity (CondISet), one nice thing to considerer is the entity CondISet has the attribute ITEM_NO, well don’t let the name confuse you, that’s the item GUID (CRMD_ORDERADM_I-GUID) 😉
Cheers!
Luis
Luiz ,
Essentially this code does the same as the "Retain Manual Conditions" . Can we pass other parameters which there in ECC using the BOL relations ? Didn't check but it would be interesting to see if we can or not.
~Kavindra
Basically you have the options to retain or not. I'm afraid is not so complex as the one you have in ECC 🙁
Hello Luis,
I copied and pasted your code.
I tried to run it in a abap report.
Each time I got the exception cx_crm_genil_model_error cx_crm_bol_meth_exec_failed generated. when the following line executes :
lo_entity->execute( iv_method_name = 'Update' it_param = lt_param ).
Have you came across the same issue ?
Best Regards
Abdou
Nope, did you check if your CRM release matches with mine? I did a copy paste of the code in a local report and worked fine for me 😕
Hello Luis,
many thanks for your fast answer.
I just check and it seems to nearly match :
It should be ok ?
That's weird, the code is exactly the same? did you try it in a local report with just the code?
Hello Luis,
That's what I tried. I created a report Y_ABO_TEST_BOL_004.
It is always the same line with the execute.
I looked in the slg1. There was no log. I tried to refresh the price on webui, so I assume it is not authorisation issue.
REPORT Y_ABO_TEST_BOL_004.
DATA: lt_param TYPE crmt_name_value_pair_tab.
DATA: lv_error_w TYPE string,
lv_object_id_w TYPE string.
DATA: lo_bol_core TYPE REF TO cl_crm_bol_core,
lo_query TYPE REF TO cl_crm_bol_query_service,
lo_result TYPE REF TO if_bol_entity_col,
lo_entity TYPE REF TO cl_crm_bol_entity,
lo_col TYPE REF TO if_bol_entity_col,
lo_bol_trans TYPE REF TO if_bol_transaction_context.
DATA: lv_bpath_query TYPE string.
FIELD-SYMBOLS: <ls_param> LIKE LINE OF lt_param.
lv_object_id_w = '0005018681'.
lo_bol_core = cl_crm_bol_core=>get_instance( ).
lo_bol_core->start_up( iv_appl_name = 'ONEORDER' ).
lo_query = cl_crm_bol_query_service=>get_instance( 'BTQuery1O' ).
lo_query->set_property( EXPORTING iv_attr_name = 'OBJECT_ID'
iv_value = lv_object_id_w ).
lo_result = lo_query->get_query_result( ).
TRY.
IF lo_result->size( ) EQ 0.
* Error handling
ENDIF.
lo_entity = lo_result->get_first( ).
IF lo_entity->lock( ) EQ abap_false.
* Error handling
ENDIF.
CATCH cx_sy_move_cast_error.
* Error handling
ENDTRY.
lv_bpath_query = './BTOrderHeader/BTHeaderPridoc/CondHSetRel/*$'.
lo_col = lo_entity->get_related_entities_by_bpath( iv_bpath_statement = lv_bpath_query ).
IF lo_col->size( ) EQ 0.
* Error handling
ENDIF.
lo_entity ?= lo_col->get_first( ).
CLEAR lt_param.
APPEND INITIAL LINE TO lt_param ASSIGNING <ls_param>.
<ls_param>-name = 'RETAIN_MANUAL_CONDITIONS'.
<ls_param>-value = abap_true.
TRY.
lo_entity->execute( iv_method_name = 'Update' it_param = lt_param ).
lo_bol_core->modify( ).
lo_bol_trans = lo_bol_core->get_transaction( ).
lo_bol_trans->save( ).
lo_bol_trans->commit( ).
lo_bol_core->reset( EXPORTING iv_include_bal_reset = abap_true ).
CATCH: cx_crm_genil_model_error cx_crm_bol_meth_exec_failed.
* Error handling
ENDTRY.
Really really weird, I checked your code, it works 🙁 can you put a break point on the class/mehod CL_CRM_CNDSET_GENIL_API_IF->IF_GENIL_APPL_INTLAY~EXECUTE_OBJECT_METHOD and debugg from there, also I would check SU53 just to be sure there's no authority check issue (it would surprise me, but who knows...)
I also would try redetermine the condition by the standard application, log on on the WebUI go to one sales order detail and from there on the conditions assignment block push the redetermine conditions retaining manual ones, it's very important you perform those steps on the WebUI, if you do it on SAP GUI the standard code executed won't be the "same" as mine.
Hello Luis,
I don't know this reason why but today the same code is working 😆
Thank you so much !!!!
Best Regards
Abdou
Hello Luis,
It's indeed very interesting way of using BOL for this and I wish I could have come across this blog before. I had similar requirement for mass price re determination and I used CRM_ORDER_MAINTAIN to achieve this.
Thanks for you feedback, maybe you can write a blog about how to archieve the same using the CRM_ORDER_MAINAIN, I believe another approach is allways welcome 🙂
Sure Luiz!! I would love to do that. 🙂
Hi,
I am trying to change the pricing condition of an item, from a custom button on header overview page.
With the help your blog I could get the item CONDSET, could you help me with the bol query for CONDLINE.