lunes, octubre 26, 2009

Calcular impuesto de un precio determinado

Para conocer cuál es el impuesto que le corresponde a un importe determinado podremos utilizar la siguiente FM estándar:



Donde "l_taxcom" es una estructura de entrada en la que rellenaremos los campos necesarios y "l_fwste" es el importe resultante del impuesto que le corresponde al precio indicado.

Para que la función devuelva dicho importe, deberemos informar como mínimo los siguientes campos de la estructura "TAXCOM":
  • TAXCOM-BUKRS = Sociedad correspondiente
  • TAXCOM-MWSKZ = Indicador de impuestos correspondiente
  • TAXCOM-KPOSN <> '00000'
  • TAXCOM-XMWST = 'X'
    En la mayoría de los casos querremos calcular el impuesto que le corresponde a un determinado material, para ello será necesario acceder al registro info correspondiente (tablas EINA/EINE).

    miércoles, septiembre 23, 2009

    Server certificate rejected by ChainVerifier

    En ocasiones, los servidores FTPS firman sus propios certificados. Esto implica que SAP no será capaz de dar por bueno el certificado, mostrando el siguiente mensaje de error:



    Para hacer que SAP acepte el certificado deberemos seguir los siguientes pasos:

    1º Añadir el certificado del cliente al directorio de certificados de confianza (TrustedCAs) mediante el SAP J2EE Visual Administrator, tal como dice la nota SAP 821267.

    2º Una vez importado el certificado, el siguiente paso consiste en asociar la dirección IP del servidor FTP al nombre canónico que se especifica en el certificado. Esta es una manera de validar que el certificado viene de quien se espera que venga. En mi caso, para realizar las pruebas de conexión utilicé el cliente FTP "curl" y para acceder al servidor ponía su dirección IP (12.34.567.89). Esto hacía que no coincidiera con la dirección que especificaba el certificado ("ServidorFTP"), tal como reflejan los mensajes informativos que aparecían al establecer la comunicación:



    Al añadir la entrada correspondiente en el fichero HOST, podremos acceder con éxito utilizando el nombre  común ("ServidorFTP"):



    Lo que para "curl" es un simple aviso, para SAP es determinante y si no coinciden no dejará acceder. Así que la dirección "ServidorFTP" es la que tendremos que especificar en el adaptador FTP para que SAP acepte el certificado con éxito.

    server_ftps

    Enlaces de referencia:

        martes, julio 28, 2009

        Añadir timestamp al nombre de un fichero mediante Java mapping

        En el siguiente código se muestra cómo añadir el timestamp al nombre de un fichero a través de una UDF (User-Defined Function) mediante acceso a las variables del sistema.



        Como variables de entrada tenemos el nombre del fichero y un indicador (addTimestamp) para decidir si hay que incluir el timestamp o no.

        Enlaces de referencia:

          viernes, junio 19, 2009

          Error during STOR/APPE epilogue

          Uno de los posibles motivos por los que no haya llegado un fichero a un servidor FTP es que el servidor esté lleno. Este caso aparecerá reflejado en la herramienta de visualización de mensajes de XI (XI Message Display Tool), informando un log similar al siguiente:


          Error during communication with SLD: User credentials are invalid or user is denied access

          Este error aparece cuando se intenta acceder al "Runtime Workbench" del repositorio de XI, en este caso, tras introducir las credenciales de usuario, aparece el error "Following error occurred while executing the application: Error during communication with System Landscape Directory: User credentials are invalid or user is denied access". El problema puede estar en que el usuario de XI "XIRWBUSER" o "PIRWBUSER" (dependiendo de la versión de XI) está bloqueado.

          En la entrada Usuario PIRWBUSER bloqueado frecuentemente se indica cómo solucionar este problema.

          Más información:

          http://sap.ittoolbox.com/groups/technical-functional/sap-basis/error-during-communication-with-system-landscape-directory-user-credentials-are-invalid-or-user-is-denied-access-1718332

          martes, junio 16, 2009

          Cliente FTP multiprotocolo y multiplataforma

          En ocasiones, existen servidores FTP que hacen uso del protocolo TLS. Esto requiere configurar de la manera adecuada el firewall tras el que se encuentra el servidor XI para que se pueda conectar de manera correcta con dicho servidor FTP.

          Para comprobar si el firewall estaba bien configurado, busqué un cliente FTP multiprotocolo disponible para varios sistemas operativos (UNIX, AIX, Linux, Windows,...) de manera que me permitiera realizar una prueba de conexión desde un equipo, en mi caso con Windows, exterior a la red y, una vez logrado conectar con el servidor FTP, reproducir los mismos comandos, pero esta vez desde el cliente FTP instalado en el servidor XI.

          El cliente utilizado fue el Curl y el enlace de descarga es http://curl.haxx.se/download.html (recomiendo usar el wizard de descarga para obtener la últiva versión: http://curl.haxx.se/dlwiz/).

          El cliente funciona por comandos. En Windows no necesita instalación, basta descomprimir el archivo en una carpeta local y seguidamente ejecutar los comandos. La versión que utilicé fue la curl-7.19.5-ssl-sspi-zlib-static-bin-w32.zip.

          El servidor FTP requería:
          • Protocolo: TLS
          • Puerto: 990
          • Conexión: pasiva

            Para las pruebas de conexión basta con que funcione algunos de los siguientes comandos:

            Comandos que muestran el contenido de la carpeta raíz del servidor de pruebas:

            C:\curl>curl -k -u <user>:<pass> --ftp-ssl -1 ftp://ftp.server.com:990

            C:\curl>curl -k -u <user>:<pass> --ftp-ssl-reqd -1 ftp://ftp.server.com:990

            C:\curl>curl -k -u <user>:<pass> --ftp-pasv --ftp-ssl -1 ftp://ftp.server.com:990


            Resultado:

            drwxrwxr-x   5 (?)      (?)          4096 Mar 31 13:14 dir

            Comandos que muestran un listado del directorio /DIR/:

            C:\curl>curl -k -u <user>:<pass> --ftp-pasv --ftp-ssl -1 ftp://ftp.server.com:990/dir/

            Resultado:

            drwxrwxr-x   2 (?)      (?)          4096 Jun  8 16:27 input
            drwxrwxr-x   2 (?)      (?)          4096 Jun  8 16:28 output



            A continuación indico el significado de las opciones utilizadas:

            -k/--insecure
            (SSL) This option explicitly allows curl to perform "insecure" SSL connections
            and transfers. All SSL connections are attempted to be made secure by using the
            CA certificate bundle installed by default. This makes all connections considered
            "insecure" fail unless -k/--insecure is used.

            -u/--user <user:password>
            Specify the user name and password to use for server authentication. Overrides
            -n/--netrc and --netrc-optional.
            If you just give the user name (without entering a colon) curl will prompt for
            a password.
            If you use an SSPI-enabled curl binary and do NTLM authentication, you can
            force curl to pick up the user name and password from your environment by simply
            specifying a single colon with this option: "-u :".
            If this option is used several times, the last one will be used.

            --ftp-ssl
            (FTP) Try to use SSL/TLS for the FTP connection. Reverts to a non-secure
            connection if the server doesn’t support SSL/TLS. See also --ftp-ssl-control and
            --ftp-ssl-reqd for different levels of encryption required. (Added in 7.11.0)

            --ftp-ssl-reqd
            (FTP) Require SSL/TLS for the FTP connection. Terminates the connection if the
            server doesn’t support SSL/TLS. (Added in 7.15.5)

            -1/--tlsv1
            (SSL) Forces curl to use TLS version 1 when negotiating with a remote TLS server.


            Lo único que falta es probar que estos mismos comandos funcionan desde el servidor de XI con la configuración actual del firewall.

            jueves, mayo 14, 2009

            Objetos de autorización (AUTHORITY-CHECK OBJECT)

            Los objetos de autorización disponibles se encuentran en las transacciones SU20 y SU21. Mediante la primera podremos buscar por campo/elemento de datos los objetos disponibles. Por ejemplo, podemos buscar qué objetos de autorización existen asociados al campo división (GSBER). Al hacer doble clic sobre el resultado de la búsqueda accederemos a la pantalla de "Ámbito de autorización" donde se detalla, en la sección inferior, los objetos de utilización que utilizan el criterio seleccionado. Para el caso del campo División, nos puede ser útil los objetos de autorización que se encuentran en la clase de objeto FI.

            La transacción SU21 ofrece más detalle sobre los objetos de autorización. Si quisiéramos conocer la composición del objeto F_BKPF_GSB, el cual se encuentra en la clase FI, deberemos buscar por el nombre del objeto mediante el icono de los prismáticos y hacer doble clic sobre el mismo. El objeto F_BKPF_GSB está compuesto de la siguiente manera:

            F_BKPF_GSB

            Tras conocer la composición del objeto, podremos hacer uso del mismo del siguiente modo:



            Donde p_gsber es el campo que contiene la división sobre la que se quiere comprobar si el usuario tiene permiso. También se puede hacer uso del identificador ACTVT para determinar el tipo de actividad que se quiere comprobar. Las atividades permitidas del objeto se pueden visualizar en la parte inferior de la ventana de descripción del objeto en la transacción SU21.

            jueves, abril 30, 2009

            Reemplazar caracteres por espacios en blanco

            El siguiente código reemplaza los caracteres que concuerden con las expresiones lógicas por un espacio en blanco. Nótese como la definición del espacio en blanco se realiza mediante comillas simples inversas (`), esto es así porque se trata de una expresión de "sustitución".



            Significado de las expresiones:
            • GC_ISO_EXP: sustituye los caracteres típicos de ficheros XML y de texto por espacios en blanco (< >' " & ; : ¨ ^).
            • GC_LN: sustituye los caracteres que NO sean minúsculas (\l) ni mayúsculas (\u) ni numéricos (\d).
            • GC_LC: sustituye los caracteres que NO sean minúsculas (\l) ni mayúsculas (\u) ni numéricos (\d) ni el guión (-) ni la barra (/).
            • GC_LNG: sustituye los caracteres que NO sean minúsculas (\l) ni mayúsculas (\u) ni numéricos (\d) ni el guión (-) .

              La constante GC_ISO contiene los caracteres imprimibles propios del conjunto ISO 8859-1, para las pruebas.

              martes, abril 28, 2009

              Función de mapeo de usuario para decodificar un campo en Base64

              La siguiente función definida por usuario o User-Defined Function (UDF) decodifica el contenido de un campo en base64.

              decodebase64

              En este caso he utilizado la librería "sun.misc.BASE64Decoder" de la que es propietaria SUN. Podría valer cualquier otra, pero es la que utilizaban en el código de referencia que utilicé para este ejemplo: https://www.sdn.sap.com/irj/scn/weblogs?blog=/pub/wlg/9793

              De manera análoga se puede codificar un campo en Base64 utilizando la librería correspondiente.

              martes, marzo 24, 2009

              Comprobar conexión servidor hacia fuera

              A la hora de consumir un web service externo es necesario saber si la conexión hacia el exterior está configurara correctamente (puertos del firewall, etc.). Una manera sencilla de realizar dicha comprobación es a través de la creación de una conexión HTTP con servidor externo (tipo G) en la transacción SM59 y en la que incluiremos la dirección del servidor al que se desea acceder. Para comprobar si hay conexión bastará pulsar el botón "Test de conexión".

              test_external_server

              Una mala configuración puede provocar que se reciban timeouts a la hora de invocar el web service o que se produzcan fallos a la hora de crear el socket de comunicación...

              jueves, marzo 05, 2009

              Timeouts en escenarios síncronos

              Existen ocaciones en las que los programas que utilizamos pueden tardar mucho en función de la cantidad de datos que le vayamos a pedir. Esto puede dar lugar a que si nos encontramos en un escenario síncrono podamos obtener un timeout como respuesta.


              500 Connection timed out


              Error: -5
              Version: 7000
              Component: ICM
              Date/Time: Thu Mar 5 09:57:12 2009
              Module: icxxthr_mt.c
              Line: 2698
              Server: PI_Server
              Error Tag: {-}
              Detail: Connection to partner timed out after 60s
              © 2001-2005, SAP AG

              En mi caso, el escenario en el que se producía el error era de tipo síncrono (SOAP -> RFC). Y el timeout aparecía cuando la función tenía que recopilar demasiados datos.

              En la transacción SM21 aparece una versión más detallada del error:

              http_rfc-session-has-been-deleted-following-timeout

              Una de las maneras de ampliar el tiempo de timeout es a través de la transacción SMICM. En el menú Pasar a -> Servicios (Shift+F1) veremos que el tiempo definido para el servicio HTTP es de 60 segundos, por lo que bastará marcar dicho servicio y editarlo (menú Servicio -> Modificar) para asignarle el tiempo que deseemos.

              servicios3

              NOTA: Hay que tener en cuenta que estos cambios se perderán si se reinicia el servicio ICM, tal como notifica el siguiente mensaje:

              warning

              Una de las opciones posibles para definir de manera definitiva esta parametrización es por medio de la creación del parámetro de perfil icm/server_port_<xx> a través de la transacción RZ10. Ejemplo:

              icm/server_port_0 = PROT=HTTP,PORT=8000,TIMEOUT=30,PROCTIMEOUT=600

              Los posibles valores vienen descritos en el link Timeout Options for ICM and Web Dispatcher.

              Este parámetro se debe incluir en un fichero del sistema, por lo que deberá ser un administrador el que realice la configuración.

              Links de referencia:

                lunes, marzo 02, 2009

                Cómo Eliminar un Componente del Integration Builder

                Si por casualidad has importado desde el System Landscape Directory una versión de software de un componente por error y la deseas eliminar, deberás hacer doble clic sobre la misma y en la ventana del componente seleccionar la opción Software Component Version -> Delete (Ctrl+D).

                delete_soft_comp1

                martes, febrero 17, 2009

                Convertir Workarea a Caracteres

                En ocasiones es necesario pasar el contenido de un área de trabajo a una ristra de caracteres (sobre todo cuando se desea crear un fichero de texto a partir de una tabla interna con campos de distintos tipos). Para esos casos podremos utilizar la función estándar C147_WORKAREA_TO_CHARFIELD que nos simplificará mucho la vida.


                viernes, enero 23, 2009

                Campos de extensión de las BAPIs

                Directamente copiado del texto de ayuda de los campos ExtensionIn/Out  de las BAPIs:

                Txt.brv.
                ExtensionIn

                Description
                With the parameters ExtensionIn and ExtensionOut, it is possible to enhance the interface of a BAPI without modification to achieve the automatic processing of customer-specific data.

                The data is passed on in a table. The format of the individual data records of this table is determined via the structure BAPIPAREX. This structure contains several data record fields (VALUEPART1, VALUEPART2 etc.) and a field for the name of an auxiliary structure (STRUCTURE). Because per data record the data is written piecewise consecutively to the data record fields available for the purpose, an auxiliary structure is needed for the interpretation of the data.

                In the event that an SAP database table is to be enhanced by additional fields, BAPI table extensions are especially suitable as auxiliary structures. A BAPI table extension can either be already predefined by SAP or created by the customer. Examples of auxiliary structures and BAPI table extensions can be found at the following points:

                Description of the various customer enhancement options
                Enhancement of BAPI based on existing SAP database tables
                Enhancement of BAPI through incorporation of additional customers' own database tables
                Enhancement of BAPI by import data that does not show up the database level
                Note that only fields of the data type CHAR and similar data types may be used in the BAPI parameter ExtensionIn/ExtensionOut.

                If the customer Include contains deviating parameters, the configurable message ME 887 is invoked. However, the data is not adopted in the target structure from the container.

                Default
                The auxiliary structures have been defined as follows:

                Header data:
                BAPI_TE_MEOUTHEADER
                BAPI_TE_MEOUTHEADERX
                Item data:
                BAPI_TE_MEOUTITEM
                BAPI_TE_MEOUTITEMX
                Account assignment data:
                BAPI_TE_MEOUTACCOUNT
                BAPI_TE_MEOUTACCOUNTX

                Ejemplo:
                CLEAR le_extensionin.
                le_mepoheader-campo_extendido = <valor_del_campo>.
                le_extensionin-structure  = 'BAPI_TE_MEPOHEADER'.
                le_extensionin-valuepart1 = le_mepoheader.
                APPEND le_extensionin TO lt_extensionsin.

                CLEAR le_extensionin.
                le_mepoheaderx-campo_extendido = 'X'.
                le_extensionin-structure  = 'BAPI_TE_MEPOHEADERX'.
                le_extensionin-valuepart1 = le_mepoheaderx.
                APPEND le_extensionin TO lt_extensionsin.
                  CALL FUNCTION 'BAPI_PO_CREATE1'
                    EXPORTING
                      poheader         = le_header
                      poheaderx        = le_headerx
                    IMPORTING
                      exppurchaseorder = l_numdoc
                    TABLES
                      return           = lt_return
                      poitem           = lt_items
                      poitemx          = lt_itemsx
                      poaccount        = lt_accounts
                      poaccountx       = lt_accountsx
                      extensionin      = lt_extensionsin.