Skip to Content

Introdução

Muitas empresas enviam o DANFE da NF-e em formato PDF para os clientes no mesmo e-mail no qual enviam o XML da NF-e. Então, o pessoal do departamento fiscal da sua empresa chega na sua mesa e fala “olha, eu também quero!”.

Para que isso seja possível, acabamos desenvolvendo uma função no ECC que recebe a chave de acesso da NF-e e retorna o PDF do DANFE.

Da mesma forma, o mesmo usuário gostaria de poder visualizar o DANFE no monitor web do SAP NF-e. A SAP disponibilizou esta funcionalidade no SAP NF-e utilizando 2 formulários Adobe, que geram o PDF em runtime, mas estes não são exatamente iguais ao DANFE original gerado pelo ECC.

Este blog mostra como baixar o PDF do DANFE gerado pelo  ECC no monitor do SAP NF-e, reutilizando a função criada originalmente para recuperar o PDF do DANFE para envio do PDF via e-mail.

Solução

Para permitir o download do PDF do DANFE original, gerado pelo ECC, irei desenvolver dois módulos de função no lado do ECC, ajustar o programa de impressão e criar um implicit enhancement point na classe que trata o evento de baixar o DANFE no lado do SAP NF-e.

Desenvolvimento no ECC


No lado do ECC, alguns ajustes serão necessários no programa de impressão do DANFE para a gente consiga exportar o PDF do DANFE após a execução do programa de impressão. Isso foi coberto pelo excelente blog do Fabio Purcino AragaoComo gerar o DANFE em PDF , por isso não vou entrar nos detalhes da alteração do programa de impressão.

Criei uma função Z, que recebe o número do documento e retorna o arquivo do PDF, conforme abaixo:


FUNCTION Z_SD_NFE_GET_DANFE_PDF.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     REFERENCE(I_DOCNUM) TYPE  J_1BDOCNUM
*"  EXPORTING
*"     REFERENCE(ET_FILE) TYPE  TLINE_T
*"     REFERENCE(E_FILESIZE) TYPE  INT4
*"  EXCEPTIONS
*"      DOCUMENT_NOT_FOUND
*"      NFE_NOT_APPROVED
*"      NFE_NOT_PRINTED
*"      CONVERSION_EXCEPTION
*"      PRINT_PROGRAM_ERROR
*"----------------------------------------------------------------------
   TABLES: nast , tnapr.
   TYPES: BEGIN OF ty_doc,
            docnum LIKE j_1bnfdoc-docnum,
            form   LIKE j_1bnfdoc-form,
            code   LIKE j_1bnfe_active-code,
            printd LIKE j_1bnfe_active-printd,
            conting LIKE j_1bnfe_active-conting,
          END OF ty_doc.
   DATA: ls_doc    TYPE ty_doc,
         lv_subrc  TYPE i VALUE 0,
         lv_screen TYPE i VALUE 0,
         lv_buf_id TYPE indx_srtfd.
   SELECT SINGLE a~docnum a~form b~code b~printd b~conting
     FROM j_1bnfdoc AS a
     INNER JOIN j_1bnfe_active AS b
     ON b~docnum = a~docnum
     INTO ls_doc
     WHERE a~docnum EQ i_docnum.
   IF sy-subrc NE 0.
     RAISE document_not_found.
   ENDIF.
   IF ls_doc-conting = abap_false.
     IF ls_doc-code NE '100'.
       RAISE nfe_not_approved.
     ENDIF.
     IF ls_doc-printd NE 'X'.
       RAISE nfe_not_printed.
     ENDIF.
   ENDIF.
   lv_buf_id = 'DANFE_OTF_' && ls_doc-docnum.
   SELECT SINGLE * FROM tnapr INTO tnapr WHERE kschl = ls_doc-form.
   nast-kappl = tnapr-kappl.
   nast-OBJKY = ls_doc-docnum.
   nast-kschl = tnapr-kschl.
   nast-spras = 'P'.
   nast-erdat = sy-datum.
   nast-eruhr = sy-uzeit.
   nast-nacha = 1.
   nast-anzal = 1.
   nast-vsztp = 1.
   nast-ldest = 'LOCL'.
   nast-nauto = 'X'.
   PERFORM entry IN PROGRAM znfe_print_danfe USING lv_subrc lv_screen.
   IF lv_subrc NE 0.
     RAISE print_program_error.
   ENDIF.
   DATA: it_pdf TYPE TABLE OF itcoo.
   DATA: it_otf TYPE tsfotf.
   IMPORT e_parm = it_otf[] FROM SHARED BUFFER INDX(ST) ID lv_buf_id.
   DELETE FROM SHARED BUFFER INDX(ST) ID lv_buf_id.
   it_pdf[] = it_otf[].
   CALL FUNCTION 'CONVERT_OTF'
     EXPORTING
       FORMAT                = 'PDF'
       MAX_LINEWIDTH         = 132
     IMPORTING
       BIN_FILESIZE          = e_filesize
     TABLES
       OTF                   = it_pdf
       LINES                 = et_file
     EXCEPTIONS
       ERR_MAX_LINEWIDTH     = 1
       ERR_FORMAT            = 2
       ERR_CONV_NOT_POSSIBLE = 3
       ERR_BAD_OTF           = 4
       OTHERS                = 5.
   IF sy-subrc NE 0.
     RAISE conversion_exception.
   ENDIF.
ENDFUNCTION.

Note que a função faz uso de um IMPORT FROM SHARED BUFFER. No meu programa de impressão eu faço o EXPORT, conforme abaixo:

znfe_print_danfe.PNG

Criei uma função Z, marcada como RFC Enabled, para recuperar os e-mails do parceiro (Comprador ou Transportador), assim como o PDF do DANFE, caso solicitado, conforme abaixo:


FUNCTION Z_SD_NFE_GET_B2B_DATA.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(IV_ACCESS_KEY) TYPE  J_1B_NFE_ACCESS_KEY_DTEL44
*"     VALUE(IV_SCENARIO) TYPE  CHAR10
*"     VALUE(IV_GET_DANFE) TYPE  FLAG OPTIONAL
*"  EXPORTING
*"     VALUE(ET_COMM) TYPE  ZNFE_COMMPARAM_T
*"     VALUE(EV_DANFE) TYPE  XSTRING
*"----------------------------------------------------------------------
   DATA: lv_parvw TYPE j_1bparvw,
         lv_parid TYPE j_1bparid,
         lv_partyp TYPE j_1bpartyp,
         lv_docnum TYPE j_1bdocnum,
         lv_adrnr TYPE adrnr,
         lt_email TYPE TABLE OF ad_smtpadr,
         lt_file TYPE TLINE_T,
         lv_filesize TYPE int4,
         ls_comm TYPE znfe_commparam,
         ls_key TYPE J_1B_NFE_ACCESS_KEY.
   FIELD-SYMBOLS: <fs_mail> TYPE ad_smtpadr.
   MOVE iv_access_key TO ls_key.
   CASE iv_scenario.
     WHEN 'BUYER'.
       lv_parvw = 'AG'.
     WHEN 'CARRIER'.
       lv_parvw = 'SP'.
     WHEN OTHERS.
       RETURN.
   ENDCASE.
   SELECT SINGLE b~docnum b~parid b~partyp
     INTO (lv_docnum, lv_parid, lv_partyp)
     FROM j_1bnfe_active AS a
     INNER JOIN j_1bnfnad AS b ON a~docnum = b~docnum
    WHERE a~REGIO = ls_key-regio AND
          a~NFYEAR = ls_key-NFYEAR AND
          a~NFMONTH = ls_key-NFMONTH AND
          a~STCD1 = ls_key-STCD1 AND
          a~MODEL = ls_key-MODEL AND
          a~SERIE = ls_key-SERIE AND
          a~NFNUM9 = ls_key-NFNUM9 AND
          a~DOCNUM9 = ls_key-DOCNUM9 AND
          a~CDV = ls_key-cdv AND
          b~parvw = lv_parvw.
   IF sy-subrc NE 0.
     RETURN.
   ENDIF.
   CASE lv_partyp.
     WHEN 'C'.
       SELECT SINGLE adrnr INTO lv_adrnr FROM kna1 WHERE kunnr = lv_parid.
     WHEN 'V'.
       SELECT SINGLE adrnr INTO lv_adrnr FROM lfa1 WHERE lifnr = lv_parid.
     WHEN 'B'.
       SELECT SINGLE adrnr INTO lv_adrnr FROM j_1bbranch
         WHERE bukrs = lv_parid(4) AND branch = lv_parid+4.
   ENDCASE.
   SELECT a~smtp_addr
     INTO TABLE lt_email
     FROM ( adr6 AS a
    INNER JOIN adrt AS t ON
          a~addrnumber EQ t~addrnumber
      AND a~consnumber EQ t~consnumber )
    WHERE a~addrnumber EQ lv_adrnr
      AND t~comm_type  EQ 'INT'
      AND t~remark     EQ 'NFE'.
   IF sy-subrc EQ 0.
     LOOP AT lt_email ASSIGNING <fs_mail>.
       ls_comm-type = 'MAIL'.
       ls_comm-value = <fs_mail>.
       APPEND ls_comm TO et_comm.
     ENDLOOP.
   ENDIF.
   IF iv_get_danfe EQ abap_true.
     CALL FUNCTION 'Z_SD_NFE_GET_DANFE_PDF'
       EXPORTING
         I_DOCNUM             = lv_docnum
       IMPORTING
         ET_FILE              = lt_file
         E_FILESIZE           = lv_filesize
       EXCEPTIONS
         DOCUMENT_NOT_FOUND   = 1
         NFE_NOT_APPROVED     = 2
         NFE_NOT_PRINTED      = 3
         CONVERSION_EXCEPTION = 4
         PRINT_PROGRAM_ERROR  = 5
         OTHERS               = 6.
     DATA: lv_str TYPE string.
     CONCATENATE LINES OF lt_file INTO lv_str.
     CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
       EXPORTING
         TEXT     = lv_str
         ENCODING = '4102'
       IMPORTING
         BUFFER   = ev_danfe
       EXCEPTIONS
         FAILED   = 1
         OTHERS   = 2.
   ENDIF.
ENDFUNCTION.

Desenvolvimento no SAP NF-e

No lado do SAP NF-e, é necessário criar um implicit enhancement point na classe /XNFE/CL_NFE_OUT para desviar a lógica para efetuar o download do PDF para o ECC via RFC e não via formulário standard do SAP NF-e.

Abra a classe /XNFE/CL_NFE_OUT na SE24, vá no menu Edit -> Enhancement Operations -> Show Implicit Enhancement Options.

/wp-content/uploads/2015/04/xnfe_cl_nfe_out_683570.png

Irá aparecer uma linha nova, logo abaixo da linha que declara o método. Clique nesta linha e vá no menu Edit -> Enhancement Operations -> Create Implementation:

/wp-content/uploads/2015/04/xnfe_cl_nfe_out_enh01_683582.png

Selecione Data Declaration como método de Enhancement.


No código, coloque o trecho abaixo:


DATA: lv_danfe_file TYPE string,
         lv_logsys TYPE logsys,
         lv_rfcdest TYPE bdbapidst,
         lv_danfe TYPE xstring.
   "get filename
   concatenate /xnfe/if_wd_constants=>cv_xml_file_front_nfe
         me->mv_id /xnfe/if_wd_constants=>cv_pdf_extension into lv_danfe_file.
   "Read Logical System
   SELECT SINGLE logsys
     INTO lv_logsys
     FROM /xnfe/outnfehd
    WHERE guid = me->mv_guid.
   IF sy-subrc EQ 0.
     "Read RFC Destination
     CALL FUNCTION '/XNFE/READ_RFC_DESTINATION'
       EXPORTING
         iv_logsys     = lv_logsys
       IMPORTING
         ev_rfcdest    = lv_rfcdest
       EXCEPTIONS
         no_dest_found = 1.
     "Get NF-e DANFE`s PDF
     IF sy-subrc EQ 0.
       CALL FUNCTION 'Z_SD_NFE_GET_B2B_DATA'
         DESTINATION lv_rfcdest
       EXPORTING
         iv_access_key = me->mv_id
         iv_scenario = 'BUYER'
         iv_get_danfe = abap_true
       IMPORTING
         ev_danfe = lv_danfe.
       "open download dialog and show PDF
       cl_wd_runtime_services=>attach_file_to_response(
           i_filename      = lv_danfe_file
           i_content       = lv_danfe
           i_mime_type     = /xnfe/if_wd_constants=>cv_pfd_mimetype
           i_in_new_window = abap_true
           i_inplace       = abap_false ).
     ENDIF.
   ENDIF.
RETURN.

Salve e ative o código.

Efetue um teste e veja que agora o PDF baixado via monitor NF-e é o mesmo vindo do ECC e não mais o gerado pelo GRC. Caso necessário, você pode implementar uma lógica no seu programa de impressão para que seja impressa uma marca-d’água indicando que o DANFE é uma cópia.

Nota: Gostou do editor ABAP com fundo preto e cara de terminal *nix? Veja como fazer no seu SAP Logon seguindo o blog Make your ABAP editor go dark | Bruno Lucattelli doBruno Lucattelli .

[]’s

JN

To report this post you need to login first.

Be the first to leave a comment

You must be Logged on to comment or reply to a post.

Leave a Reply