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) 😉