FUNCTION Z_BAPI_FLIGHT_GETLIST.
*"----------------------------------------------------------------------
*"*"Lokale Schnittstelle:
*"  IMPORTING
*"     VALUE(AIRLINE) LIKE  BAPISFLKEY-AIRLINEID OPTIONAL
*"     VALUE(DESTINATION_FROM) LIKE  BAPISFLDST STRUCTURE  BAPISFLDST
*"       OPTIONAL
*"     VALUE(DESTINATION_TO) LIKE  BAPISFLDST STRUCTURE  BAPISFLDST
*"       OPTIONAL
*"     VALUE(MAX_ROWS) LIKE  BAPISFLAUX-BAPIMAXROW OPTIONAL
*"  TABLES
*"      DATE_RANGE STRUCTURE  BAPISFLDRA OPTIONAL
*"      EXTENSION_IN STRUCTURE  BAPIPAREX OPTIONAL
*"      FLIGHT_LIST STRUCTURE  BAPISFLDAT OPTIONAL
*"      EXTENSION_OUT STRUCTURE  BAPIPAREX OPTIONAL
*"      RETURN STRUCTURE  BAPIRET2 OPTIONAL
*"      FLUG_LIST STRUCTURE  ZBAPISFLDAT OPTIONAL
*"----------------------------------------------------------------------

  data:
   lt_airline_rg type table of airline_range_item,
   lv_airline_item type airline_range_item,
   lt_airportfr_rg type table of airport_range_item,
   lt_airportto_rg type table of airport_range_item,
   lt_cityfr_rg type table of city_range_item,
   lt_cityto_rg type table of city_range_item,
   lt_countryfr_rg type table of country_range_item,
   lt_countryto_rg type table of country_range_item.

  data: lt_sflights2 like sflights2 occurs 0 with header line.

  DATA: additional_info LIKE bapisfladd. "neu!
  REFRESH: flug_list. "neu!

  clear: msg1_hlp, msg2_hlp.
  refresh: return, flight_list, extension_out.



*********** Authority check *******************************************
  authority-check object 'S_FLBOOK'
           id 'ACTVT'  field '03'.
  if sy-subrc <> 0.
    call function 'BALW_BAPIRETURN_GET2'
         EXPORTING
              TYPE   = 'E'
              CL     = 'BC_IBF'
              NUMBER = '004'
         IMPORTING
              RETURN = RETURN.
    append return.
    perform final_return_message                "BAPI was not successful
      USING     'E'
      CHANGING  return[].
    return.
  endif.
*********** End of Authority check ************************************


*********** BAdI 1 for Customer specific coding ***********************
* At this point there should be a BAdI that the customer can use to   *
* check the data in the parameter ExtensionIn.                        *
* Unfortunately there was no time to define and implement the BAdI in *
* this release. This will be done at a later time.                    *
* We are aware that this is inconsistent with the existence of the    *
* ExtensionIn. However, this BAPI is for learning purposes only and   *
* not productive. Therefore we think it better to show how to define  *
* the ExtensionIn (even though it can not be used here) instead of    *
* leaving it out. ("Showing some is better than nothing")             *
*********** End of BAdI 1 *********************************************


*********** Check and interprete selection data ***********************
*                                                                     *
* For each relevant parameter the following tasks are done:           *
* - check data entry if they conform to check tables or domain values *
* - for non-initial parameter move data to internal range table       *
*   (otherwise initial parameters would yield to empty selection!)    *
***********************************************************************

****** Check and interprete AIRLINE *************
  if airline is not initial.
    translate airline to upper case.               "#EC SYNTCHAR
    clear lv_airline_item.
    select single mandt from scarr into lv_mandt
           where carrid = airline.
    if sy-subrc <> 0.
      write airline to msg1_hlp.
      call function 'BALW_BAPIRETURN_GET2'          "airline not found
          EXPORTING
              TYPE      = 'E'
              CL        = 'BC_IBF'
              NUMBER    = 50
              PAR1      = MSG1_HLP
              PARAMETER = 'AIRLINE'
          IMPORTING
              RETURN    = RETURN.
      append return.
    else.
      lv_airline_item-sign   = 'I'.
      lv_airline_item-option = 'EQ'.
      lv_airline_item-low    = airline.
      append lv_airline_item to lt_airline_rg.
    endif.
  endif.
****** End of AIRLINE ***************************

****** Check and interprete DESTINATION_FROM ****
  perform destination_check
    USING
       destination_from
    CHANGING
       lt_airportfr_rg[]
       lt_cityfr_rg[]
       lt_countryfr_rg[]
       return[].
****** End of DESTINATION_FROM ******************

****** Check and interprete DESTINATION_TO ******
  perform destination_check
    USING
       destination_to
    CHANGING
       lt_airportto_rg[]
       lt_cityto_rg[]
       lt_countryto_rg[]
       return[].
****** End of DESTINATION_TO ********************

****** Check and interprete DATE_RANGE **********
  perform date_range_check
    USING
       date_range[]
       'DATE_RANGE'
    CHANGING
       return[].
****** End of DATE_RANGE ************************

****** Return in case of errors in input data******
  read table return with key type = 'E'.
  if sy-subrc = 0.
    perform final_return_message                "BAPI was not successful
      USING     'E'
      CHANGING  return[].
    return.
  endif.
*********** End of Checking selection data ****************************



*********** Read relevant flights and return data *********************
  select * from sflights2 into table lt_sflights2 up to max_rows rows
        where carrid    in lt_airline_rg
          and fldate    in date_range
          and countryfr in lt_countryfr_rg
          and cityfrom  in lt_cityfr_rg
          and airpfrom  in lt_airportfr_rg
          and countryto in lt_countryto_rg
          and cityto    in lt_cityto_rg
          and airpto    in lt_airportto_rg.

* create warning message if selection is empty
  if sy-subrc <> 0.
    call function 'BALW_BAPIRETURN_GET2'        "empty flight list
       EXPORTING
           TYPE   = 'W'
           CL     = 'BC_IBF'
           NUMBER = 56
       IMPORTING
           RETURN = RETURN.
    append return.

* convertion of results to external data represenatation (BAPI format)
  else.
    loop at lt_sflights2.
* Fllen der Felder von BAPISFLDAT
      call function 'MAP2E_SFLIGHTS2_TO_BAPISFLDAT'
          EXPORTING
              SFLIGHTS2 = lt_sflights2
          CHANGING
              BAPISFLDAT = flight_list
          EXCEPTIONS
              ERROR_CONVERTING_CURR_AMOUNT.
      if sy-subrc <> 0.
        call function 'BALW_BAPIRETURN_GET2' "Currency conversion error
             EXPORTING
                  TYPE      = 'W'
                  CL        = 'BC_IBF'
                  NUMBER    = 15
                  PARAMETER = 'FLIGHT_LIST'
                  ROW       = sy-tabix
             IMPORTING
                  RETURN = return.
        append return.
      endif.
      flight_list-arrdate = flight_list-flightdate
                           + lt_sflights2-period.  "Compute Arrival date
*** Beginn Einschub
      MOVE-CORRESPONDING flight_list TO flug_list.
* Fllen der Felder von ZBAPISFLDAT
      CALL FUNCTION 'MAP2E_SFLIGHTS2_TO_BAPISFLADD'
        EXPORTING
          sflights2  = lt_sflights2
        CHANGING
          bapisfladd = additional_info.
      MOVE-CORRESPONDING additional_info TO flug_list.
* Determine availibility
      flug_list-economax  = lt_sflights2-seatsmax.
      flug_list-seatsfree = lt_sflights2-seatsmax -
                              lt_sflights2-seatsocc.
      APPEND flug_list.
      CLEAR flug_list.
*** Ende Einschub
      append flight_list.
      clear flight_list.
    endloop.
  endif.

*********** BAdI 2 for Customer specific coding ***********************
* At this point there should be a BAdI that the customer can use to   *
* proceed his data and fill the parameter ExtensionOut.               *
* Unfortunately there was no time to define and implement the BAdI in *
* this release. This will be done at a later time.                    *
* We are aware that this is inconsistent with the existence of the    *
* ExtensionOut. However, this BAPI is for learning purposes only and  *
* not productive. Therefore we think it better to show how to define  *
* the ExtensionOut (even though it can not be used here) instead of   *
* leaving it out. ("Showing some is better than nothing")             *
*********** End of BAdI 2 *********************************************

* Create a success return message
  perform final_return_message                  "BAPI was successful
    USING     'S'
    CHANGING  return[].


endfunction.
*********** End of function *******************************************

********* Form for checking range entries in DATE_RANGE ***************
*                                                                     *
* Check if sign and option in range are filled with permitted values  *
*  sign:   I or E;                                                    *
*  option: EQ, NE, GT, GE, LE, LT, BT, NB, CP or NP.                  *
* Remark: Both parameters are checked independently to find all       *
*         errors. Below function only yields the first error and      *
*         therefore can not return both errors if appropriate         *
***********************************************************************
form date_range_check
    USING
       VALUE(date_range) type date_range_type
       VALUE(par_name)   type syst-msgv1
    CHANGING
       return type return_type.

data: date_range_item type bapisfldra,
      return_item type bapiret2,
      ret1 type bapiret1,
      cnt1 like sy-tabix.

loop at date_range into date_range_item.
  translate date_range_item-sign to upper case.         "#EC SYNTCHAR
  translate date_range_item-option to upper case.       "#EC SYNTCHAR
  cnt1 = sy-tabix.
  call function 'BALW_RANGES_CHECK'         "checking the sign
      EXPORTING
          SIGN   = date_range_item-sign
          OPTION = 'EQ'
      IMPORTING
          RETURN = ret1.
  if ret1 is not initial.
    move-corresponding ret1 to return_item.
    return_item-parameter = par_name.
    return_item-row       = cnt1.
    append return_item to return.
  endif.
  clear ret1.
  call function 'BALW_RANGES_CHECK'         "checking the option
      EXPORTING
          SIGN   = 'I'
          OPTION = date_range_item-option
      IMPORTING
          RETURN = ret1.
  if ret1 is not initial.
    move-corresponding ret1 to return_item.
    return_item-parameter = par_name.
    return_item-row       = cnt1.
    append return_item to return.
  endif.
endloop.
endform.
********* End of form for DATE_RANGE **********************************

********* Form for checking entries in DESTINATION ********************
*                                                                     *
* In destination parameters we look for non-initial values in the     *
* following fields (in this order):                                   *
* - Airport-ID                                                        *
* - City and Country                                                  *
* - City only                                                         *
* - Country only                                                      *
* If we find non-initial values we do:                                *
* - check if values are permitted                                     *
* - if yes, include them into respective internal range table         *
* - if no, write return error message                                 *
* - in both cases do not(!) continue with other fields                *
***********************************************************************

form destination_check
    USING
       VALUE(destination) type bapisfldst
    CHANGING
       lt_airport_rg type airport_range
       lt_city_rg type city_range
       lt_country_rg type country_range
       return type return_type.

data: lv_airport_item type line of airport_range,
      lv_city_item type line of city_range,
      lv_country_item type line of country_range,
      return_item type bapiret2,

      cnt like sy-dbcnt,
      lv_dest type sfl_dest.

  translate destination-airportid to upper case.      "#EC SYNTCHAR
  translate destination-city to upper case.           "#EC SYNTCHAR
  translate destination-countr to upper case.         "#EC SYNTCHAR
  translate destination-countr_iso to upper case.     "#EC SYNTCHAR

* Convertion to internal data representation
  call function 'MAP2I_BAPISFLDST_TO_SFL_DEST'
      EXPORTING
           BAPISFLDST = destination
      CHANGING
           SFL_DEST   = lv_dest
      EXCEPTIONS
           ERROR_CONVERTING_ISO_CODE.
  if sy-subrc <> 0.
    write destination-countr_iso to msg1_hlp.
    call function 'BALW_BAPIRETURN_GET2'      "Country conversion error
         EXPORTING
              TYPE      = 'E'
              CL        = 'BC_IBF'
              NUMBER    = 17
              PAR1      = MSG1_HLP
         IMPORTING
              RETURN = return_item.
      append return_item to return.
  endif.

* Checking Airport-ID
  if lv_dest-airportid is not initial.
    select single mandt from sairport into lv_mandt
           where id = lv_dest-airportid.
* Remark: we only need sy-subrc as result of select,
*         therefore we only read one field (mandt)
    if sy-subrc <> 0.
      write lv_dest-airportid to msg1_hlp.
      call function 'BALW_BAPIRETURN_GET2'      "airportid not found
          EXPORTING
              TYPE   = 'E'
              CL     = 'BC_IBF'
              NUMBER = 51
              PAR1   = MSG1_HLP
          IMPORTING
              RETURN = return_item.
      append return_item to return.
    else.
      lv_airport_item-sign   = 'I'.
      lv_airport_item-option = 'EQ'.
      lv_airport_item-low    = lv_dest-airportid.
      append lv_airport_item to lt_airport_rg.
    endif.
* Checking City and Country
* (City and Country are only considered if no airport was provided)
  else.
    if lv_dest-city is not initial.
      if lv_dest-country is not initial.
        select mandt from sgeocity into table lt_mandt
                    where city    = lv_dest-city
                    and   country = lv_dest-country.
      else.
        select mandt from sgeocity into table lt_mandt
                    where city    = lv_dest-city.
      endif.
      cnt = sy-dbcnt.
* cnt = SY-DBCNT shows now if city exists and if it is unique
      if cnt = 0.
        write lv_dest-city to msg1_hlp.
        write lv_dest-country to msg2_hlp.
        call function 'BALW_BAPIRETURN_GET2'     "city not found
            EXPORTING
                TYPE   = 'E'
                CL     = 'BC_IBF'
                NUMBER = 52
                PAR1   = MSG1_HLP
                PAR2   = MSG2_HLP
            IMPORTING
                RETURN = return_item.
        append return_item to return.
      else.
        if cnt > 1.
          write lv_dest-city to msg1_hlp.
          write lv_dest-country to msg2_hlp.
          call function 'BALW_BAPIRETURN_GET2'   "city not unique
              EXPORTING
                  TYPE   = 'W'
                  CL     = 'BC_IBF'
                  NUMBER = 53
                  PAR1   = MSG1_HLP
                  PAR2   = MSG2_HLP
              IMPORTING
                  RETURN = return_item.
          append return_item to return.
        endif.
        lv_city_item-sign   = 'I'.
        lv_city_item-option = 'EQ'.
        lv_city_item-low    = lv_dest-city.
        append lv_city_item to lt_city_rg.
      endif.
      if lv_dest-country is not initial.
        lv_country_item-sign   = 'I'.
        lv_country_item-option = 'EQ'.
        lv_country_item-low    = lv_dest-country.
        append lv_country_item to lt_country_rg.
      endif.
* Check country (only if city is initial)
    else.
      if lv_dest-country is not initial.
        select single mandt from t005 into lv_mandt
               where land1 = lv_dest-country.
        if sy-subrc <> 0.
          write lv_dest-country to msg1_hlp.
          call function 'BALW_BAPIRETURN_GET2'     "country not found
              EXPORTING
                  TYPE   = 'E'
                  CL     = 'BC_IBF'
                  NUMBER = 12
                  PAR1   = MSG1_HLP
              IMPORTING
                  RETURN = return_item.
          append return_item to return.
        else.
          lv_country_item-sign   = 'I'.
          lv_country_item-option = 'EQ'.
          lv_country_item-low    = lv_dest-country.
          append lv_country_item to lt_country_rg.
        endif.
      endif.
    endif.
  endif.
endform.
****** End of DESTINATION check ***************************************