
After the previous Blog on DDD code
Request was for Geocode calculation code.
SAP Transportation Management provides standard way of Geocode Calculation of Locations based on Region or Pin code.
First we have to define Geocoding Levels.
These are standard Strategy provided by SAP TM.
But we get requirements from customer to calculate Geocode based on Exact Address.
At Transaction /SCMTMS/LOC3, you will find following section at location
SAP HANA Spatial Service is recommended approach and you do not have to do any code for same, Details are mentioned in the below link.
When customer does not want to use HANA Spatial Service and have HERE or any other api's for Geo Code calculation.
These are the configuration steps you can use and also added the code which you copy and use it.
This Customizing activity contains general information about setting up the process controller for use with geocoding.
The process controller is a framework that allows you to define your own services, strategies, and methods for a specific application process. For example, if you want to use a strategy to determine geocoordinates different from the standard we deliver, you can define your own strategy using the process controller and assign it to a specific service.
Activities
You can make settings for the process controller in the following Customizing activities:
Assign the Strategy to GC level and GIS Zone
Go to Sm59 and create a connection to GIS provider
Create a Class ZCL_GEOCODE_CONNECTOR
class ZCL_GEOCODE_CONNECTOR definition
public
final
create public .
public section.
types TY_REQUEST_REF type ref to /SCMB/S_GEOCODING_REQUEST_INT .
types:
ty_t_requests TYPE STANDARD TABLE OF ty_request_ref
WITH KEY table_line .
types:
BEGIN OF ty_s_request_mapping,
request_id TYPE guid_16,
adrc_new TYPE adrc_struc,
adrc_old TYPE adrc_struc,
latitude TYPE geolat,
longitude TYPE geolon,
altitude TYPE geoalt,
geoprec TYPE geoprecis,
geosrcid TYPE geosrcid,
tzone TYPE timezone,
adrc_corr TYPE adrc_struc,
messages TYPE bapiret2_t,
requests TYPE ty_t_requests,
END OF ty_s_request_mapping .
types:
ty_t_request_mapping TYPE SORTED TABLE OF ty_s_request_mapping
WITH UNIQUE KEY adrc_new
WITH UNIQUE HASHED KEY request_id COMPONENTS request_id .
constants C_GEOPREC_INITIAL_OKAY type GEOPRECIS value '9999' ##NO_TEXT.
methods GET_STANDARD_COORDINATES
importing
!IO_METHPAR type ref to /SCTM/CL_METH_PARAMETER
!IT_REQUEST type /SCTM/TT_REQUEST .
class-methods CAST_REQUEST
importing
!IO_REQUEST type ref to /SCTM/CL_REQUEST
returning
value(RO_REQUEST) type ref to /SCMB/CL_GEOCODING_REQUEST .
methods EXECUTE_REQUESTS
importing
!IV_DIALOG type BOOLE_D
changing
!CT_REQUESTS type TY_T_REQUEST_MAPPING .
METHOD get_standard_coordinates.
*It can be assumed that only a single request is passed to this method containing all
*relevant requests: No comprehensive request handling required
TYPES:
BEGIN OF ty_s_request,
adrc TYPE adrc_struc,
request TYPE REF TO /scmb/s_geocoding_request_int,
END OF ty_s_request,
ty_t_requests TYPE STANDARD TABLE OF ty_s_request.
DATA: lt_requests TYPE ty_t_requests,
ls_request TYPE ty_s_request.
DATA: lo_request TYPE REF TO /sctm/cl_request,
lo_geocoding_request TYPE REF TO /scmb/cl_geocoding_request.
DATA: lt_request_mapping TYPE ty_t_request_mapping,
ls_request_mapping TYPE ty_s_request_mapping.
DATA: ls_adrc_previous TYPE adrc_struc.
DATA: lv_num_igs TYPE int4,
lv_num_ori TYPE int4.
FIELD-SYMBOLS: <fs_request> TYPE ty_s_request.
*Map given request structure to optimized Geocoding Structure
*- combine all requests with the same address -> avoid duplicate determinations
LOOP AT it_request INTO lo_request.
lo_geocoding_request = cast_request( lo_request ).
CHECK lo_geocoding_request IS NOT INITIAL.
CLEAR lt_request_mapping.
*Sort requests according to address specification to avoid read by address
LOOP AT lo_geocoding_request->mt_requests REFERENCE INTO ls_request-request.
CHECK ls_request-request->return_code <> /scmb/if_dist_dur_det=>gc_lddd_return_success.
IF ls_request-adrc IS INITIAL.
MOVE-CORRESPONDING ls_request-request->addr_new TO ls_request-adrc. "#EC ENHOK
ENDIF.
CHECK ls_request-adrc IS NOT INITIAL.
APPEND ls_request TO lt_requests.
ENDLOOP.
SORT lt_requests BY adrc.
LOOP AT lt_requests ASSIGNING <fs_request>.
*Be pessimistic -> only a successful geo-coding resets this status
<fs_request>-request->return_code = /scmb/if_dist_dur_det=>gc_lddd_return_failed.
<fs_request>-request->geo_precision = c_geoprec_initial_okay.
lv_num_ori = lv_num_ori + 1.
IF <fs_request>-adrc <> ls_adrc_previous.
*New unique address
IF ls_request_mapping-requests IS NOT INITIAL.
ls_request_mapping-request_id = /sctm/cl_guid_convert=>get_guid_x16( ).
INSERT ls_request_mapping INTO TABLE lt_request_mapping.
CLEAR ls_request_mapping-requests.
ENDIF.
ls_request_mapping-adrc_new = <fs_request>-adrc.
MOVE-CORRESPONDING <fs_request>-request->addr_old TO ls_request_mapping-adrc_old. "#EC ENHOK
ls_adrc_previous = ls_request_mapping-adrc_new.
ENDIF.
INSERT <fs_request>-request INTO TABLE ls_request_mapping-requests.
ENDLOOP.
* Take over last request
IF ls_request_mapping IS NOT INITIAL.
ls_request_mapping-request_id = /sctm/cl_guid_convert=>get_guid_x16( ).
INSERT ls_request_mapping INTO TABLE lt_request_mapping.
ENDIF.
execute_requests( EXPORTING iv_dialog = lo_geocoding_request->mv_dialog
CHANGING ct_requests = lt_request_mapping ).
CHECK lo_geocoding_request->mo_message_handler->mv_detail_messages = abap_true.
lv_num_igs = lines( lt_request_mapping ).
MESSAGE s083(/scmb/lddd) WITH lv_num_igs lv_num_ori
INTO lo_geocoding_request->mo_message_handler->mv_message.
lo_geocoding_request->mo_message_handler->add_msg_from_sys( ).
ENDLOOP.
ENDMETHOD.
METHOD cast_request.
TRY.
ro_request ?= io_request.
CATCH cx_sy_move_cast_error.
CLEAR ro_request.
ENDTRY.
ENDMETHOD
METHOD execute_requests.
DATA: lv_api TYPE string,
lv_bahne TYPE string,
lv_bahns TYPE string,
lv_latitude TYPE geolat,
lv_longitude TYPE geolon,
et_data TYPE REF TO data,
lv_destination TYPE c VALUE 'HERE_GEOCODE' LENGTH 15,
lr_data TYPE REF TO data,
lr_request TYPE ty_request_ref.
FIELD-SYMBOLS: <data> TYPE data,
<items> TYPE any,
<position> TYPE any,
<structure> TYPE any,
<table> TYPE ANY TABLE,
<field> TYPE any,
<field_value> TYPE data
.
"qq=street=Main%20Street;city=Jeddah;postalCode=22334;state=15;country=SA
TRY.
*Map Train Station and Express Station as Geo code to location.
LOOP AT ct_requests ASSIGNING FIELD-SYMBOL(<s_request_current>).
CHECK <s_request_current>-adrc_new IS NOT INITIAL.
LOOP AT <s_request_current>-requests INTO lr_request.
SELECT SINGLE bezei FROM t005u WHERE spras = @SY-langu
AND land1 = @<s_request_current>-adrc_new-country
AND bland = @<s_request_current>-adrc_new-region
INTO @DATA(lv_region).
IF <s_request_current>-adrc_new-street IS NOT INITIAL.
CONCATENATE 'street=' <s_request_current>-adrc_new-street INTO lv_api.
ENDIF.
IF lv_api IS INITIAL.
IF <s_request_current>-adrc_new-city1 IS NOT INITIAL.
CONCATENATE 'city=' <s_request_current>-adrc_new-city1 INTO lv_api.
ENDIF.
ELSEIF <s_request_current>-adrc_new-city1 IS NOT INITIAL.
CONCATENATE lv_api ';city=' <s_request_current>-adrc_new-city1 INTO lv_api.
ENDIF.
IF lv_api IS INITIAL.
IF <s_request_current>-adrc_new-post_code1 IS NOT INITIAL.
CONCATENATE 'postalCode=' <s_request_current>-adrc_new-post_code1 INTO lv_api.
ENDIF.
ELSEIF <s_request_current>-adrc_new-post_code1 IS NOT INITIAL.
CONCATENATE lv_api ';postalCode=' <s_request_current>-adrc_new-post_code1 INTO lv_api.
ENDIF.
IF lv_api IS INITIAL.
IF lv_region IS NOT INITIAL.
CONCATENATE 'state=' lv_region INTO lv_api.
ENDIF.
ELSEIF lv_region IS NOT INITIAL.
CONCATENATE lv_api ';state=' lv_region INTO lv_api.
ENDIF.
IF lv_api IS INITIAL.
IF <s_request_current>-adrc_new-country IS NOT INITIAL.
CONCATENATE 'country=' <s_request_current>-adrc_new-country INTO lv_api.
ENDIF.
ELSEIF <s_request_current>-adrc_new-country IS NOT INITIAL.
CONCATENATE lv_api ';country=' <s_request_current>-adrc_new-country INTO lv_api.
ENDIF.
CONCATENATE '?qq=' lv_api
INTO lv_api.
CALL FUNCTION 'Z_FM_HERE_MAP_REST_API'
EXPORTING
im_destination = lv_destination
im_api = lv_api
IMPORTING
et_data = et_data.
CHECK et_data IS BOUND.
*Fetch Items
ASSIGN et_data->* TO <data>.
ASSIGN COMPONENT 'ITEMS' OF STRUCTURE <data> TO <items>.
ASSIGN <items>->* TO <table>.
LOOP AT <table> ASSIGNING <structure>.
*Fetch Sections
ASSIGN <structure>->* TO <data>.
ASSIGN COMPONENT 'POSITION' OF STRUCTURE <data> TO <position>.
ASSIGN <position>->* TO FIELD-SYMBOL(<ls_position>).
* if <ls_position> is ASSIGNED.
ASSIGN COMPONENT 'LAT' OF STRUCTURE <ls_position> TO <field>.
IF <field> IS ASSIGNED.
lr_data = <field>.
ASSIGN lr_data->* TO <field_value>.
<s_request_current>-latitude = <field_value>.
ENDIF.
UNASSIGN: <field>, <field_value>.
ASSIGN COMPONENT 'LNG' OF STRUCTURE <ls_position> TO <field>.
IF <field> IS ASSIGNED.
lr_data = <field>.
ASSIGN lr_data->* TO <field_value>.
<s_request_current>-longitude = <field_value>.
ENDIF.
UNASSIGN: <field>, <field_value>.
<s_request_current>-geoprec = '0900'. " Street
*Transfer result to original request(s) in case coordinates could be determined
LOOP AT <s_request_current>-requests INTO lr_request.
CHECK <s_request_current>-longitude IS NOT INITIAL
OR <s_request_current>-latitude IS NOT INITIAL.
lr_request->return_code = /scmb/if_dist_dur_det=>gc_lddd_return_success.
lr_request->xpos = <s_request_current>-longitude.
lr_request->ypos = <s_request_current>-latitude.
lr_request->geo_precision = <s_request_current>-geoprec.
ENDLOOP.
ENDLOOP.
CLEAR lr_request.
ENDLOOP.
ENDLOOP.
CATCH cx_sy_arithmetic_error cx_sy_conversion_error INTO exc.
ENDTRY.
ENDMETHOD.
Create a Function Module
FUNCTION z_fm_here_map_rest_api.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" REFERENCE(IM_DESTINATION) TYPE CHAR15
*" VALUE(IM_API) TYPE STRING
*" EXPORTING
*" REFERENCE(ET_DATA) TYPE REF TO DATA
*"----------------------------------------------------------------------
*HTTP Client Abstraction
DATA: lo_client TYPE REF TO if_http_client,
lo_rest_client TYPE REF TO cl_rest_http_client,
lo_response TYPE REF TO if_rest_entity,
* lv_apikey TYPE string VALUE 'M-AGoC0QrkXBQqmFSnfpbsf14BFVrpmr9UNEKTVFAUQ'." Rohit on 28-08-2022
CHECK im_api IS NOT INITIAL.
*Concatenate api key and app id for authentication
* CONCATENATE im_api '&app_id=' lv_app_id '&apiKey=' lv_apikey INTO im_api.
CONCATENATE im_api '&apiKey=' lv_apikey INTO im_api.
*consume service from RFC Destination
cl_http_client=>create_by_destination(
EXPORTING
destination = im_destination " Logical destination (specified in function call)
IMPORTING
client = lo_client " HTTP Client Abstraction
EXCEPTIONS
argument_not_found = 1
destination_not_found = 2
destination_no_authority = 3
plugin_not_active = 4
internal_error = 5
OTHERS = 6 ).
CHECK lo_client IS BOUND.
CREATE OBJECT lo_rest_client
EXPORTING
io_http_client = lo_client.
*Get data in JSON
CALL METHOD lo_client->request->set_header_field
EXPORTING
name = 'Accept'
value = 'application/json'.
*Pass API
cl_http_utility=>set_request_uri(
EXPORTING
request = lo_client->request " HTTP Framework (iHTTP) HTTP Request
uri = im_api " URI String (in the Form of /path?query-string)
).
*Pass method as GET
lo_rest_client->if_rest_client~get( ).
CHECK lo_rest_client IS BOUND.
* HTTP response
lo_response = lo_rest_client->if_rest_client~get_response_entity( ).
CHECK lo_response IS BOUND.
* HTTP return status
DATA(http_status) = lo_response->get_header_field( '~status_code' ).
*Status code should be success
CHECK http_status = '200' OR http_status = '201'.
* HTTP JSON return string
DATA(json_response) = lo_response->get_string_data( ).
CHECK json_response IS NOT INITIAL.
*Convert JSON into Internal table
CALL METHOD /ui2/cl_json=>deserialize
EXPORTING
json = json_response
pretty_name = /ui2/cl_json=>pretty_mode-user
assoc_arrays = abap_true
CHANGING
data = et_data.
ENDFUNCTION.
Discover further insights into SAP Premium Engagement and explore how an international team of specialists can assist you in maximizing the value of your SAP solutions.
If you already are a Premium Engagement customer, contact your Technical Quality Manager (TQM) to discuss how Premium Engagement Service can help you with a custom-tailored and efficient service portfolio to make your project a success!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
7 | |
5 | |
4 | |
2 | |
2 | |
2 | |
2 | |
2 | |
1 | |
1 |