Wednesday, December 15, 2010

Approve PO in Page of Approving PR, do Error in My Bapi

Posted by Aries Wandari

I create bapi to track the date PO reach full release, since PO release date is only tracked on header change and its takes long time to pull it from SAP directly. To minimize data extracted from CDHDR, only history data of 'ME21N', 'ME22N', 'ME23N', 'ME29N', 'ME28' are pulled. User reporting some release dates of PO is invalid. Debugging shows that some user is approving PO via PR approval page ME54N and ME55.

SELECT objectid changenr udate tcode objectid
into (i_cdhdr-ebeln, i_cdhdr-changenr, i_cdhdr-frgdt, i_cdhdr-tcode, i_cdhdr-objectid)
FROM CDHDR
WHERE udate in p_erdat AND OBJECTCLAS = 'EINKBELEG'
AND TCODE in ('ME21N','ME22N','ME23N','ME29N','ME28','ME54N','ME55').
  append i_cdhdr.
endselect.

 

image

---------------------

FUNCTION ZBAPI_PO .
*"----------------------------------------------------------------------
*"*"Local interface:
*"  IMPORTING
*"     VALUE(DATELO) TYPE  ZBAPIPOSTR-BEDAT OPTIONAL
*"     VALUE(DATEHI) TYPE  ZBAPIPOSTR-BEDAT OPTIONAL
*"     VALUE(DOCLO) TYPE  ZBAPIPOSTR-EBELN OPTIONAL
*"     VALUE(DOCHI) TYPE  ZBAPIPOSTR-EBELN OPTIONAL
*"     VALUE(DATETY) TYPE  ZBAPIPRSTR-LOEKZ OPTIONAL
*"  EXPORTING
*"     VALUE(RETURN) TYPE  BAPIRET2
*"  TABLES
*"      TBLPO STRUCTURE  ZBAPIPOSTR OPTIONAL
*"----------------------------------------------------------------------
*
*  CHANGES :
*  20-04-2010  Creation Imam F
*  15-07-2010  Farid
*  ADD FRGDT  > RELEASE DATE
*      NETWR2 > TOTAL VALUE IN LOCAL PRICE
*      EINDT  > TARGET DELIV DATE
*      BLDAT  > GR DOCUMENT DATE
*      BLDAT2 > IR DOCUMENT DATE
*      BUDAT  > GR POSTING DATE
*      BUDAT2 > IR POSTING DATE
*  Parameter based on docno or amend date (from table history)

*DATA DEFINITION
data: begin of p_badat occurs 0,
        sign   type char1,
        option type char2,
        low    like ekko-bedat,
        high   like ekko-bedat,
end of p_badat.
data: begin of p_erdat occurs 0,
        sign   type char1,
        option type char2,
        low    like ekko-aedat,
        high   like ekko-aedat,
end of p_erdat.
data: begin of p_ebeln occurs 0,
        sign   type char1,
        option type char2,
        low    like ekko-ebeln,
        high   like ekko-ebeln,
end of p_ebeln.

data: begin of i_po occurs 0.
        include structure ZBAPIPOSTR.
data: OBJECTID9 like cdhdr-objectid.
data: frggr like ekko-frggr.
data: frgsx like ekko-frgsx.
data: end of i_po.

data : begin of i_t001k occurs 0,
  bwkey like t001k-bwkey,
  bukrs like t001k-bukrs,
end of i_t001k.

data : begin of i_t024 occurs 0,
  ekgrp like t024-ekgrp,
  eknam like t024-eknam,
end of i_t024.

DATA : BEGIN OF IT16FS OCCURS 0,
          FRGGR LIKE T16FS-FRGGR,      "Release group
          FRGSX LIKE T16FS-FRGSX,      "Release code
          FRGC1 LIKE T16FS-FRGC1,      "Release code
          FRGC2 LIKE T16FS-FRGC2,      "Release code
          FRGC3 LIKE T16FS-FRGC3,      "Release code
          FRGC4 LIKE T16FS-FRGC4,      "Release code
          FRGC5 LIKE T16FS-FRGC5,      "Release code
       END OF IT16FS.
DATA: frg like T16FS-FRGC2.

DATA :  tp_name like THEAD-TDNAME,
        lines type TLINE occurs 0 with header line.

DATA : BEGIN OF i_ekkn OCCURS 0,
  EBELN like ekkn-ebeln,
  EBELP like ekkn-EBELP,
  KOSTL like ekkn-kostl,
  AUFNR like ekkn-aufnr,
  SAKTO like ekkn-sakto,
  GSBER like ekkn-gsber,
end of i_ekkn.

DATA : BEGIN OF i_ekbe OCCURS 0,
  EBELN like ekbe-ebeln,
  EBELP like ekbe-EBELP,
  BEWTP like ekbe-bewtp,
  BELNR like ekbe-belnr,
  ELIKZ like ekbe-elikz,
  BUDAT like ekbe-budat,
  BLDAT like ekbe-bldat,
end of i_ekbe.

DATA : BEGIN OF i_eket OCCURS 0,
  EBELN like eket-ebeln,
  EBELP like eket-EBELP,
  EINDT like eket-eindt,
end of i_eket.

DATA : objnr type COBRB-OBJNR.
DATA : xbewtp like i_ekbe-bewtp.

DATA : BEGIN OF i_cdhdr occurs 0,
  ebeln like ekko-ebeln,
  changenr like cdhdr-changenr,
  FRGDT like cdhdr-udate,
  tcode like cdhdr-tcode,
  objectid like cdhdr-objectid,
  tabname like cdpos-tabname,
  fname like cdpos-fname,
  value_new like cdpos-value_new,
end of i_cdhdr.

FIELD-SYMBOLS: <fs> like i_cdhdr.

DATA: i_hdrrel like table of i_cdhdr with header line.

*DATA: i_cdhdr type sorted table of t_cdhdr with non-unique key changenr objectid with header line.

data : begin of i_t16fw occurs 0,
  frggr like t16fw-frggr,
  frgco like t16fw-frgco,
  werks like t16fw-werks,
  bname like usr21-bname,
  smtp_addr like adr6-smtp_addr,
end of i_t16fw.

data : begin of i_lfa1 occurs 0,
  lifnr like lfa1-lifnr,
  name1 like lfa1-name1,
  name2 like lfa1-name2,
  anred like lfa1-anred,
end of i_lfa1.

DATA : loc_amount TYPE EKPO-NETWR, opt(3) type c.

*only DATE or DOC, not both
if not DATELO is initial.
  if DATEHI is initial.
    DATEHI = DATELO.
  endif.

  p_erdat-sign = 'I'.
  p_erdat-option = 'BT'.
  p_erdat-low = datelo.
  p_erdat-high = datehi.
  append p_erdat.

  opt = 'DAT'.

elseif ( not DOCLO is initial ).
  if DOCHI is initial.
    DOCHI = DOCLO.
  endif.

  p_ebeln-sign = 'I'.
  p_ebeln-option = 'BT'.
  p_ebeln-low = doclo.
  p_ebeln-high = dochi.
  append p_ebeln.

  opt = 'DOC'.
endif.

* PO selection based on PO history
  if ( opt = 'DAT' ).

    SELECT objectid changenr udate tcode objectid
    into (i_cdhdr-ebeln, i_cdhdr-changenr, i_cdhdr-frgdt, i_cdhdr-tcode, i_cdhdr-objectid)
    FROM CDHDR
    WHERE udate in p_erdat AND OBJECTCLAS = 'EINKBELEG'
    AND TCODE in ('ME21N','ME22N','ME23N','ME29N','ME28','ME54N','ME55').
      append i_cdhdr.
    endselect.

    i_hdrrel[] = i_cdhdr[].

    sort i_cdhdr by ebeln.
    delete adjacent duplicates from i_cdhdr comparing ebeln.

    if not i_cdhdr is initial.
      SELECT a~ebeln b~ebelp b~loekz b~aedat txz01 matnr werks lgort matkl
        infnr menge meins netpr peinh netwr wepos weunb repos webre mtart
        a~bstyp bsart a~statu lponr zterm zbd1t ekorg ekgrp waers wkurs bedat
        knumv unsez procstat bednr frgke frgzu lifnr a~ebeln as objectid9
        frggr frgsx banfn bnfpo a~mandt a~ernam elikz
      INTO CORRESPONDING FIELDS OF TABLE i_po
      FROM EKKO as a inner join EKPO as b on a~EBELN = b~EBELN
      for all entries in i_cdhdr
      WHERE
      a~ebeln = i_cdhdr-ebeln.
    endif.

* PO selection based on input PO doc
  elseif ( opt = 'DOC' ) and ( not p_ebeln is initial ).
     SELECT a~ebeln b~ebelp b~loekz b~aedat txz01 matnr werks lgort matkl
        infnr menge meins netpr peinh netwr wepos weunb repos webre mtart
        a~bstyp bsart a~statu lponr zterm zbd1t ekorg ekgrp waers wkurs bedat
        knumv unsez procstat bednr frgke frgzu lifnr a~ebeln as objectid9
        frggr frgsx banfn bnfpo a~mandt ernam elikz
     INTO CORRESPONDING FIELDS OF TABLE i_po
     FROM EKKO as a inner join EKPO as b on a~EBELN = b~EBELN
     WHERE
     a~ebeln in p_ebeln.

     if not i_po[] is initial.
       SELECT objectid changenr udate tcode objectid
       into (i_hdrrel-ebeln, i_hdrrel-changenr, i_hdrrel-frgdt, i_hdrrel-tcode, i_hdrrel-objectid)
       FROM CDHDR
       for all entries in i_po
       WHERE objectid = i_po-objectid9 AND OBJECTCLAS = 'EINKBELEG'
       AND TCODE in ('ME21N','ME22N','ME23N','ME29N','ME28','ME54N','ME55').
         append i_hdrrel.
       endselect.
     endif.

  endif.

*if not i_po is initial. this fail
IF not i_po[] is initial.

* populate detail change (cdpos) only from ME29N and ME28 (approval)
  delete i_hdrrel where tcode = 'ME21N' or tcode = 'ME22N' or tcode = 'ME23N'.
  loop at i_hdrrel assigning <fs>.
    select fname value_new into (<fs>-fname, <fs>-value_new)
    from cdpos
    where changenr = <fs>-changenr and fname = 'PROCSTAT' and value_new = '5'.
    endselect.
  endloop.

*get last full release approval history
  sort i_hdrrel by ebeln changenr descending.
  delete adjacent duplicates from i_hdrrel comparing ebeln.

* DATA SELECTON
  select bwkey bukrs into table i_t001k
  from T001K order by BWKEY BUKRS.

  select ekgrp eknam into table i_t024
  from T024 order by ekgrp eknam.

  select FRGGR FRGSX FRGC1 FRGC2 FRGC3 FRGC4 FRGC5
  into table IT16FS
  from T16FS.
  sort IT16FS by FRGGR FRGSX.

  if sy-subrc = 0.
        SELECT EBELN EBELP KOSTL AUFNR SAKTO into table i_ekkn
        from EKKN for all entries in i_po
        where EBELN = i_po-EBELN
                and  EBELP = i_po-EBELP.
        sort i_ekkn by ebeln ebelp.

*farid: get target delivery status and actual deliv date
        SELECT EBELN EBELP BEWTP BELNR ELIKZ BUDAT BLDAT into table i_ekbe
        from EKBE for all entries in i_po
        where EBELN = i_po-EBELN
                and  EBELP = i_po-EBELP.
*E > GR, Q > MIRO, sort belnr asc so catch first gr
        sort i_ekbe by ebeln ebelp bewtp belnr.

*farid: get target delivery date
        SELECT EBELN EBELP EINDT into table i_eket
        from EKET for all entries in i_po
        where EBELN = i_po-EBELN
                and  EBELP = i_po-EBELP.
        sort i_eket by ebeln ebelp.

        SELECT frggr frgco werks bname smtp_addr into table i_t16fw
        from T16FW as a inner join USR21 as b on a~objid = b~bname
        left outer join ADR6 as c on c~addrnumber = b~addrnumber
        and c~persnumber = b~persnumber
        order by werks frggr frgco.

        SELECT lifnr name1 name2 anred into table i_lfa1
        from LFA1 for all entries in i_po
        where lifnr = i_po-lifnr.
        sort i_lfa1 by lifnr.
  endif.
endif.

*DATA PROCESSING
loop at i_po.
  read table i_t001k with key BWKEY = i_po-werks
  binary search.
  if sy-subrc = 0.
    i_po-BUKRS = i_t001k-bukrs.
  endif.

  read table i_t024 with key EKGRP = i_po-ekgrp
  binary search.
  if sy-subrc = 0.
    i_po-eknam = i_t024-eknam.
  endif.

*->  Change PO status
  clear xbewtp.

*search GR, bewtp = E, get the first because sort by belnr asc
  read table i_ekbe with key EBELN = i_po-ebeln
      EBELP = i_po-ebelp BEWTP = 'E' binary search.
  if sy-subrc = 0.
    i_po-bldat = i_ekbe-bldat.
    i_po-budat = i_ekbe-budat.
    xbewtp = i_ekbe-bewtp.
    CASE i_ekbe-bewtp.
      WHEN 'E'.
        if i_ekbe-elikz = 'X'.
          i_po-STATUS = 'GR Total'.
        else.
          i_po-STATUS = 'GR Partial'.
        endif.
      WHEN 'Q'.
        i_po-STATUS = 'Invoiced'.
      WHEN OTHERS.
        i_po-STATUS = i_ekbe-bewtp.
    ENDCASE.
  endif.

*search IR, bewtp = Q, get the first because sort by belnr asc
  read table i_ekbe with key EBELN = i_po-ebeln
      EBELP = i_po-ebelp BEWTP = 'Q' binary search.
  if sy-subrc = 0.
    i_po-bldat2 = i_ekbe-bldat.
    i_po-budat2 = i_ekbe-budat.
  endif.

  IF i_po-LOEKZ = 'X' or i_po-LOEKZ = 'L'.
    i_po-STATUS = 'Deleted'.
  ENDIF.

*get target deliv date
  read table i_eket with key EBELN = i_po-ebeln
      EBELP = i_po-ebelp  binary search.
  if sy-subrc = 0.
    i_po-eindt = i_eket-eindt.
  endif.

* Release Status
  IF i_po-FRGKE = '2'.
    i_po-rlssts = 'Released'.
  ELSE.
    read table IT16FS with key
      FRGGR = i_po-FRGGR
      FRGSX = i_po-FRGSX
      binary search.
    if sy-subrc = 0.
      if i_po-FRGZU = 'X'.
        frg = IT16FS-FRGC2.
      elseif i_po-FRGZU = 'XX'.
        frg = IT16FS-FRGC3.
      elseif i_po-FRGZU = 'XXX'.
        frg = IT16FS-FRGC4.
      elseif i_po-FRGZU = 'XXXX'.
        frg = IT16FS-FRGC5.
      else.
        frg = IT16FS-FRGC1.
      endif.
      if frg = 'H1'.
        i_po-rlssts = 'WAppr HOD'.
      elseif frg = 'M1'.
        i_po-rlssts = 'WAppr GM'.
      elseif frg = 'D1'.
        i_po-rlssts = 'WAppr Director'.
      elseif frg = 'P1'.
        i_po-rlssts = 'WAppr President'.
      else.
        if xbewtp = 'E' or xbewtp = 'Q'.
          i_po-rlssts = 'Released'.
        else.
          i_po-rlssts = 'WAppr'.
        endif.
      endif.

*     reading next approval id & email
      read table i_t16fw with key frggr = i_po-frggr
        frgco = frg binary search.
      if sy-subrc = 0.
        i_po-bname = i_t16fw-bname.
        i_po-smtp_addr = i_t16fw-smtp_addr.
      endif.

    else.
      i_po-rlssts = 'WAppr'.
    endif.
  ENDIF.

*-> get PR item text
    refresh lines.
    concatenate i_po-banfn i_po-bnfpo into tp_name.

    call function 'READ_TEXT'
      EXPORTING
        id                      = 'B01'
        language                = sy-langu
        name                    = tp_name
        object                  = 'EBAN'
      TABLES
        lines                   = lines
      EXCEPTIONS
        id                      = 1
        language                = 2
        name                    = 3
        not_found               = 4
        object                  = 5
        reference_check         = 6
        wrong_access_to_archive = 7.

    read table lines index 1.
    move lines-tdline to i_po-itemtxt.
    clear lines.

*get cost center & IO
  read table i_ekkn with key ebeln = i_po-ebeln
  ebelp = i_po-ebelp
  binary search.
  if sy-subrc = 0.
    i_po-sakto = i_ekkn-sakto.
    i_po-aufnr = i_ekkn-aufnr.
    i_po-kostl = i_ekkn-kostl.
    i_po-gsber = i_ekkn-gsber.
  endif.
    if not i_po-AUFNR is initial.
      if i_po-BSART = 'ZWOR'.
        concatenate  'OR' i_po-AUFNR into objnr.
        select single KOSTL into i_po-KOSTL from COBRB
        where OBJNR = objnr.
      else.
        select single KOSTV into i_po-KOSTL from COAS
        where AUFNR = i_po-AUFNR.
      endif.
    endif.

* calculate amount
*   if i_pr-peinh = 0 or i_pr is initial.
*     i_pr-peinh = 1.
*   endif.
*   i_pr-AMOUNT = i_pr-menge * i_pr-preis / i_pr-peinh.

*-> get PO release date from changes table
*farid: if full release, get date from i_hdrrel
  clear i_po-frgdt.
  read table i_hdrrel with key ebeln = i_po-ebeln.
  if ( sy-subrc = 0 ) and ( i_po-frgke = '2' ).
    i_po-frgdt = i_hdrrel-frgdt.
  endif.

*-> get PO Status
  read table i_lfa1 with key lifnr = i_po-lifnr
  binary search.
  if sy-subrc = 0.
    i_po-name1 = i_lfa1-name1.
    i_po-name2 = i_lfa1-name2.
    i_po-anred = i_lfa1-anred.
  endif.

*farid: Get PO Value at Local Currency
              CALL FUNCTION 'CONVERT_TO_LOCAL_CURRENCY'
                 EXPORTING
                   CLIENT = i_po-MANDT
                   DATE = i_po-BEDAT
                   FOREIGN_AMOUNT = i_po-NETWR
                   FOREIGN_CURRENCY = i_po-WAERS
                   LOCAL_CURRENCY  = 'USD'
                   RATE = 0
                   TYPE_OF_RATE = 'M'
                   READ_TCURR = 'X'
                IMPORTING
                   LOCAL_AMOUNT = loc_amount
                   EXCEPTIONS
                   NO_RATE_FOUND = 1
                   OVERFLOW = 2
                   NO_FACTORS_FOUND = 3
                   NO_SPREAD_FOUND = 4
                   DERIVED_2_TIMES = 5.

              IF SY-SUBRC = 0.
                i_po-NETWR2 = loc_amount.
              ENDIF.

*  MODIFY i_po.
  if i_po-ebeln ne space.
    MOVE-CORRESPONDING i_po to TBLPO.
    APPEND TBLPO.
  endif.

  CLEAR i_po.
  CLEAR TBLPO.

endloop.   "i_po

ENDFUNCTION.

Wednesday, December 8, 2010

abap error Unable to interpret "/" as a number

Posted by Aries Wandari

I have batch bdc program to close PR, but always error on assigning PR item on ME52 screen “Unable to interpret / as a number”.

Below is screen where error happen, when PR item number inserted.

image 

My old itab already shows that bnfpo is like eban-bnfpo. Change it to character type did solve the problem.

data: begin of itab occurs 0,
             banfn like eban-banfn,
             'bnfpo like eban-bnfpo, 'error here
             bnfpo(5) type C,
        end of itab.

LOOP AT ITAB into wa_itab.

perform open_group.

perform bdc_dynpro      using 'SAPMM06B' '0105'.
perform bdc_field       using 'BDC_CURSOR'
                              'EBAN-BANFN'.
perform bdc_field       using 'BDC_OKCODE'
                              '/00'.
perform bdc_field       using 'EBAN-BANFN'
                              wa_itab-BANFN.
perform bdc_dynpro      using 'SAPMM06B' '0106'.
perform bdc_field       using 'BDC_CURSOR'
                              'RM06B-BNFPO'.
perform bdc_field       using 'BDC_OKCODE'
                              '/00'.
perform bdc_field       using 'RM06B-BNFPO'
                              wa_itab-BNFPO.
perform bdc_dynpro      using 'SAPMM06B' '0106'.
perform bdc_field       using 'BDC_CURSOR'
                              'EBAN-BNFPO(01)'.
perform bdc_field       using 'BDC_OKCODE'
                              '=DETA'.
perform bdc_field       using 'RM06B-BNFPO'
                              wa_itab-BNFPO.

perform bdc_field       using 'RM06B-TCSELFLAG(01)'
                              'X'.
perform bdc_dynpro      using 'SAPMM06B' '0102'.
perform bdc_field       using 'BDC_CURSOR'
                              'EBAN-EBAKZ'.
perform bdc_field       using 'BDC_OKCODE'
                              '=BU'.
perform bdc_transaction using 'ME52'.

endloop.