Change data of Export Controls check
Overview
You can adapt the data used in the Export Controls check. Just implement the BAdI for each business object accordingly:
For sales documents, use BAdI /AEB/CMP_EC_ORDER_06.
For deliveries, use BAdI /AEB/CMP_EC_DLV_03.
For purchase documents, use BAdI /AEB/CMP_EC_PD_03.
For service orders, use BAdI /AEB/CMP_EC_SO_03.
For service transactions (S4), use BAdI /AE1/CMP_EC_ST_02.
Before you start the implementation, have a closer look on the data structures used in the Export Controls check:
The whole transaction is provided in an object-oriented structure. To access the relations and fields, use the given get/set/add -methods.
A transaction is the checked document, i.e. a sales order. Linked to that are the according items i.e. sales order items. For Trade Compliance Management all checks are executed on item level, which also hold the classification values such as the Export Control Number
Simple Example on item quantity
Let's start with a simple implementation to change the quantity on item level:
DATA:
items TYPE /aeb/if_cmp_pb_ec_item_do=>tt_ec_item_do,
curr_item TYPE REF TO /aeb/if_cmp_pb_ec_item_do,
quantity type TYPE REF TO /AEB/CL_01_DEC_15_3_NV.
items = im_value->get_items( ).
loop at items into curr_item.
quantity = im_nullable_value_factory->dec_15_3( '1' ).
curr_item->set_quantity( quantity ).
endloop.
Explanation of this code snippet: First we access the items by calling the method get_items. The result ist a list of instances of type interface /aeb/ifcmp_ec_item_do.
Then we loop over these instances. The quantity and any other plain field is provided as a so called "nullable value". We use the nullable values to differ between "null" and "0.0".
To create such nullable value use the give factory parameter _im_nullable_value_factory. This parameter has a lot of methods to create each type we support.
In our case we use the type dec15_3. After you have assigned the quantity value to the according variable, you can apply it to the item by using the set-method _set_quantity.
Using the context instead of reading the database
Ok now let us extend the example by using a z-field of table VBAP to set the quantity:
DATA:
items TYPE /aeb/if_cmp_pb_ec_item_do=>tt_ec_item_do,
curr_item TYPE REF TO /aeb/if_cmp_pb_ec_item_do,
quantity type TYPE REF TO /AEB/CL_01_DEC_15_3_NV,
item_ref TYPE REF TO /AEB/CL_01_CHAR_255_NV,
posnr type posnr,
vbaps type /AEB/CMP_PB_VBAPS,
curr_vbap type vbap.
items = im_value->get_items( ).
loop at items into curr_item.
item_ref = curr_item->get_reference_id( ).
posnr = item_ref->v.
vbaps = im_Context_bc->get_vbaps( ).
read table vbaps into curr_vbap with key posnr = posnr.
quantity = im_nullable_value_factory->dec_15_3( curr_vbap-z_quantity ).
curr_item->set_quantity( quantity ).
endloop.
As you can see, we don't read the vbap from the database, and rather get it from the context object using the method get_vbaps. To find the right item, we use the reference id from the curr_item.
Changing classifcations
Ok, now let's overwrite the export control number for the EU jurisdiction:
DATA:
items TYPE /aeb/if_cmp_pb_ec_item_do=>tt_ec_item_do,
curr_item TYPE REF TO /aeb/if_cmp_pb_ec_item_do,
item_ref TYPE REF TO /AEB/CL_01_CHAR_255_NV,
classification TYPE REF TO /aeb/if_cmp_pb_ec_prd_cls_do,
classifications TYPE /AEB/IF_CMP_PB_EC_PRD_CLS_DO=>TT_EC_PRODUCT_CLASSIFICATION,
classification_code TYPE REF TO /AEB/CL_01_CHAR_50_NV,
classification_number TYPE REF TO /AEB/CL_01_CHAR_50_NV,
posnr type posnr,
vbaps type /AEB/CMP_PB_VBAPS,
curr_vbap type vbap.
items = im_value->get_items( ).
loop at items into curr_item.
item_ref = curr_item->get_reference_id( ).
posnr = item_ref->v.
vbaps = im_Context_bc->get_vbaps( ).
read table vbaps into curr_vbap with key posnr = posnr.
classifications = curr_item->get_product_classifications( ).
loop at classifications into classification.
classification_code = classification->GET_CLASSIFICATION_IDENTCODE( ).
if classification_code->v = 'ClassificationAusfuhrliste'.
classification_number = im_nullable_value_factory->char_50( curr_vbap-z_ecn ).
classification->set_classification_number( classification_number ).
endif.
endloop.
endloop.
In this example you see that you just have to find the classification and update it. But it is not neccessary to update the item or the transaction.
You could also add another classification. The following example will do that.
DATA:
items TYPE /aeb/if_cmp_pb_ec_item_do=>tt_ec_item_do,
curr_item TYPE REF TO /aeb/if_cmp_pb_ec_item_do,
item_ref TYPE REF TO /aeb/cl_01_char_255_nv,
classification TYPE REF TO /aeb/if_cmp_pb_ec_prd_cls_do,
classifications TYPE /aeb/if_cmp_pb_ec_prd_cls_do=>tt_ec_product_classification,
classification_code TYPE REF TO /aeb/cl_01_char_50_nv,
classification_no TYPE REF TO /aeb/cl_01_char_50_nv,
posnr TYPE posnr,
vbaps TYPE /aeb/cmp_pb_vbaps,
curr_vbap TYPE vbap.
items = im_value->get_items( ).
loop at items into curr_item.
item_ref = curr_item->get_reference_id( ).
posnr = item_ref->v.
vbaps = im_Context_bc->get_vbaps( ).
read table vbaps into curr_vbap with key posnr = posnr.
classification = im_data_object_factory->new_cmp_pb_ec_prd_cls_do( ).
classification_code = im_nullable_value_factory->char_50( 'ADD_CODE_1' ).
classification->set_classification_identcode( classification_code ).
classification_no = im_nullable_value_factory->char_50( curr_vbap-add_code_1_val ).
classification->set_classification_number( classification_no ).
curr_item->add_product_classification( classification ).
endloop.
Just use the "add"-method to add a new classification. To create an instance for a new classification use the method "new_cmp_pb_ec_prd_cls_do" of the parameter "im_data_object_factory".
And now we like to use Product Classification to overwrite the classifications by profile to the items.
DATA:
items TYPE /aeb/if_cmp_pb_ec_item_do=>tt_ec_item_do,
curr_item TYPE REF TO /aeb/if_cmp_pb_ec_item_do,
classifications TYPE /aeb/if_cmp_pb_ec_prd_cls_do=>tt_ec_product_classification.
items = im_value->get_items( ).
loop at items into curr_item.
classifications = im_classification_bc->get_classifications_for(
im_classification_profile = 'CUS_CLS_PROFILE' "this profile has exist in Product Classification
im_ec_item = item ).
curr_item->set_product_classifications( classifications ).
endloop.
Manage item values
If you have the requirement to overwrite the values you must keep in mind that whenever you change the document value you also should update the plugin values (also called jurisdiction values), which simply represent the same value converted to to amounts in different currencies. (These additional amounts per currency are relevant, for example, if licenses are setup in a currency different to the document currency. In general, the document currency combined with the plug-in values results in a list of all currencies that are transferred to Trade Compliance Management. Each currency may only appear once here. This list is transferred in the EC check as valueOfGoods. When a license is created, the document currency is transferred as the original value and the appropriate currency for the jurisdiction of the license is determined and also transferred. All possibly required currencies for the creation of the licenses must therefore be available.)
So let's update the document values and also the additional jurisdiction value for EU-jurisdiction (here we need the value in EUR currency). For our next case the value we like to use as document value is again stored in a z-field of table vbap.
DATA:
items TYPE /aeb/if_cmp_pb_ec_item_do=>tt_ec_item_do,
curr_item TYPE REF TO /aeb/if_cmp_pb_ec_item_do,
item_ref TYPE REF TO /aeb/cl_01_char_255_nv,
posnr TYPE posnr,
vbaps TYPE /aeb/cmp_pb_vbaps,
curr_vbap TYPE vbap,
amount_of_money TYPE REF TO /aeb/if_cmp_pb_ec_aom_do,
value TYPE REF TO /aeb/cl_01_dec_15_2_nv,
amount_of_moneys TYPE /aeb/if_cmp_pb_ec_aom_do=>tt_ec_amount_of_money.
items = im_value->get_items( ).
LOOP AT items INTO curr_item.
item_ref = curr_item->get_reference_id( ).
posnr = item_ref->v.
vbaps = im_context_bc->get_vbaps( ).
READ TABLE vbaps INTO curr_vbap WITH KEY posnr = posnr.
amount_of_money = curr_item->get_document_value( ).
value = im_nullable_value_factory->dec_15_2( curr_vbap-z_doc_value ).
amount_of_money->set_value( value ).
amount_of_moneys = curr_item->get_plugin_values( ).
LOOP AT amount_of_moneys INTO amount_of_money.
IF amount_of_money->get_currency_iso( )->v = 'EUR'.
value = im_nullable_value_factory->dec_15_2( curr_vbap-z_doc_value_in_eur ).
amount_of_money->set_value( value ).
ENDIF.
ENDLOOP.
ENDLOOP.
Make sure that you do not include amounts in the same currency twice in document value and in plugin value: The document currency must not be included in the plug-in currency. Also, if you add a plugin value the added currency must not already exist.
Add or change partner information
Another usecase might be that you like to add an addtional partner, because you have this partner information in Z-Fields of the VBAK table,e.g. the end user. In this example we assume that the standard won't fill the end user.
DATA:
partner TYPE REF TO /aeb/if_cmp_pb_ec_partner_do,
prt_code TYPE REF TO /aeb/cl_01_char_20_nv,
name TYPE REF TO /aeb/cl_01_char_40_nv,
country TYPE REF TO /aeb/cl_01_char_2_nv,
vbak TYPE vbak.
vbak = im_context_bc->get_vbak( ).
partner = im_data_object_factory->new_cmp_pb_ec_partner_do( ).
prt_code = im_nullable_value_factory->char_20( 'ENDUSER_STD' ).
name = im_nullable_value_factory->char_40( vbak-z_euser_name ).
ctry = im_nullable_value_factory->char_2( vbak-z_euser_ctry ).
partner->set_identcode( prt_code ).
partner->set_name1( name ).
partner->set_country_iso( country ).
im_value->add_partner( partner ).
DATA:
curr_partner TYPE REF TO /aeb/if_cmp_pb_ec_partner_do,
curr_role TYPE REF TO /aeb/cl_01_char_50_nv,
new_identcode TYPE REF TO /aeb/cl_01_char_20_nv.
LOOP AT im_value->get_partners( ) INTO curr_partner.
CASE curr_partner->get_role_identcode( )->v.
WHEN 'CONSIGNOR_STD'.
new_identcode = im_nullable_value_factory->char_20( 'Company no.' ).
curr_partner->set_identcode( new_identcode ).
WHEN 'SELLER_STD'.
new_identcode = im_nullable_value_factory->char_20( 'Company no.' ).
curr_partner->set_identcode( new_identcode ).
ENDCASE.
ENDLOOP.
Again we use the imcontext_bc to get data for the business object. Do not use database statemens for transactional data here. For the country you have to provide the country ISO code, not the country key.
With the _add_partner method you can easily add the partner to the transaction. In the same way it would also work for the items.
Overwride completion status
Now let us overwrite the completion status of the EU-ExportControls No and the ECCN from item data.
DATA:
items TYPE /aeb/if_cmp_pb_ec_item_do=>tt_ec_item_do,
curr_item TYPE REF TO /aeb/if_cmp_pb_ec_item_do,
item_ref TYPE REF TO /aeb/cl_01_char_255_nv,
compl_statuss TYPE /aeb/if_cmp_pb_ec_pcst_do=>tt_ec_product_completion_sta,
posnr TYPE posnr,
vbaps TYPE /aeb/cmp_pb_vbaps,
curr_vbap TYPE vbap,
curr_compl_status TYPE REF TO /aeb/if_cmp_pb_ec_pcst_do,
is_complete TYPE REF TO /aeb/cl_01_boolean_nv.
items = im_value->get_items( ).
LOOP AT items INTO curr_item.
item_ref = curr_item->get_reference_id( ).
posnr = item_ref->v.
vbaps = im_context_bc->get_vbaps( ).
READ TABLE vbaps INTO curr_vbap WITH KEY posnr = posnr.
compl_statuss = curr_item->get_product_completion_status( ).
LOOP AT compl_statuss INTO curr_compl_status.
CASE curr_compl_status->get_plugin_identcode( )->v.
WHEN 'DE-EU-Plugin'.
IF curr_vbap-z_eu_sta = 'X'.
is_complete = im_nullable_value_factory->boolean( 'X' ).
ELSE.
is_complete = im_nullable_value_factory->boolean( '-' ).
ENDIF.
curr_compl_status->set_is_product_complete( is_complete ).
WHEN 'US-EAR-Plugin'.
IF curr_vbap-z_us_sta = 'X'.
is_complete = im_nullable_value_factory->boolean( 'X' ).
ELSE.
is_complete = im_nullable_value_factory->boolean( '-' ).
ENDIF.
curr_compl_status->set_is_product_complete( is_complete ).
ENDCASE.
ENDLOOP.
ENDLOOP.
Updated 4 months ago