lunes, 30 de septiembre de 2013

Añadir nuevos campos a las transacciones QM01/QM02/QM03/QM10

El modulo de QM del sistema Sap, contiene las funcionalidades para grabar y tratar los diferentes problemas de calidad que puedan surgir en la ejecución de servicios o procesos de fabricación. Los avisos de calidad pueden servir de ayudad para tratar problemas tanto internos como externos:
  • Reclamaciones presentadas por clientes
  • Reclamaciones a proveedores
  • Problemas internos
  • Otros problemas propios del usuario
En esta entrada vamos a  explicar como añadir nuevos campos a las transacciones QM01/QM02/QM03/QM10 para la gestión de avisos de calidad.

Creamos un nuevo append a la tabla QMEL con los nuevos campos para los avisos de calidad.

append a la tabla QMEL
El siguiente paso es, añadir una nueva subscreen , que contiene los nuevos campos, a la clase de aviso de calidad correspondiente.

Transacción SPRO -> IMG referencia SAP -> Gestión de calidad -> Aviso de calidad -> Resumen de la clase de aviso


Seleccionamos la clase de aviso que queremos modificar y doble clic en "Formato de imagen p.vista ampliada"


Clases de aviso de calidad
En "Formato de imagen p.vista ampliada" se configuran  todas las pestañas que aparecen a la hora de introducir o visionar datos en las transacciones de QM. Cada pestaña puede contener hasta 5 subscreens.

Doble clic en la pestaña donde queremos incluir la nueva subscreen.

Pestañas asignadas a un aviso de calidad
subcreens asignadas a la pestaña "Ejecución" de la clase de aviso de calidad F2

Antes de  añadir nuestra subscreen, hay que decidir entre el ámbito de imagen 090 y el 091
  • El ámbito de imagen 90:  La subscreen se utilizara en todas las clases de aviso
  • El ámbito de imagen 91:  La subscreen solo se utilizara en la clase de aviso seleccionado
Si utilizamos el ámbito de imagen 90, no tenemos que indicar el número de subscreen. Por defecto, para el ámbito de imagen 90, la subscreen es la número 0090 del grupo de funciones XQQM. Para el ámbito de imagen 91, si que es obligatorio indicar una subcreen,  que debe pertenecer también al grupo de funciones XQQM.

Así que el siguiente paso es crear  una nueva dynpro en el grupo de funciones ZQQM.

 Transacción SE80 -> Grupo de funciones -> XQQM -> Crear -> Dynpro -> nº 0100

Si ya existe una dynpro 0100, pues crearla como 0101 , 102, 103.... a menos que, como hemos dicho, utilicemos el ámbito de imagen 90, que entonces tenemos que crear o modificar la dynpro 0090 del grupo de funciones XQQM.

En la pestaña de atributos, marcar la opción  subscreen para la dynpro y aseguraros de que el número de columnas de la dynpro no excede  de 83.

Grupo de funciones XQQM
Atributos de la dynpro
Añadir los campos de la vista VIQMEL, que contiene los campos de la tabla QMEL  y es la que utilizan las exits como veremos mas adelante,  a la subscreen. Grabar y activar.

editor de dynpros

En este punto, ya es posible ver los campos en las transacciones QM01/QM02/QM03. pero ni guardan , ni muestran ningun dato. necesitamos implementar el código que permita guardar y leer los datos.
    Los nuevos campos ya aparecen en las transacciones pero no funcionan
    Implementar la ampliación QQMA0001 en la transacción CMOD para poder grabar y recuperar los datos.
    Necesitamos implementar las siguientes exits de la ampliación QQMA0001:

    • EXIT_SAPMIWO0_008: Seria el PBO de la subcreen, para transportar los datos desde la base de datos a pantalla.
    • EXIT_SAPMIWO0_009: Seria el PAI de la subcreen, para transportar los datos de la pantalla a la base de datos.
    Si has utilizado los campos de la VIQMEL en la subscreen, no es necesario que implementes la EXIT_SAPMIWO0_008, se traspasan automáticamente. Pero si tendrás que implementar la exit para poder guardar los datos introducidos en las transacciones de QM.

    Doble clic sobre EXIT_SAPMIWO0_009 y aceptamos crear el include ZXQQMU08. Dentro del include, escribimos nuestro código para mover los datos de la base de datos a los campos de la subcreen:

    MOVE: viqmel-ZZCAMPO1 to e_viqmel-ZZCAMPO1,
          viqmel-ZZPERNR  to e_viqmel-ZZPERNR,
          viqmel-ZZCAMPO2 to e_viqmel-ZZCAMPO2.

    Con un breakpoint, se puede ver como mueve los datos antes de guardarlos.
    Y en la transacción SE11 comprobamos que se han guardado los datos en la tabla QMEL

    debugger de la EXIT_SAPMIWO0_009

    Tabla QMEL con los nuevos campos
    Para que veáis como se utilizan las dos exit. vamos a incluir un elemento radio button para ZZCAMPO2 de forma que solo pueda tener 3 valores:  ALTA, MEDIA y BAJA. Modificamos la subscreen y añadimos los radiobuttons con las tres opciones

    Editor de dynpros: radiobuttons
    Las variables globales para el radiobutton las creamos en el include ZXQQMTOP, que se crea haciendo doble clic sobre la instrucción "include ZXQQMTOP" en el include LXQQMTOP del grupo de funciones XQQM.

    include ZXQQMTOP 
    Transacción CMOD, accedemos al proyecto con la ampliación  , si no existe lo creamos y le asignamos la ampliación  saltamos a componentes de la ampliación.


    componentes de la ampliación QQMA0001

    Doble clic sobre EXIT_SAPMIWO0_008 y aceptamos crear el include ZXQQMU07. Dentro del include, escribimos nuestro codigo para mover los datos de la base de datgos a los campos de la subcreen:

    * Radio Button ZZCAMPO2 ( PRIORIDAD)
    CASE viqmel-ZZCAMPO2.
      WHEN 'ALTA'.
        CLEAR: WG_MEDIA, WG_BAJA.
        WG_ALTA = 'X'.
      WHEN 'MEDIA'.
        CLEAR: WG_ALTA, WG_BAJA.
        WG_MEDIA = 'X'.
      WHEN OTHERS.
        CLEAR: WG_MEDIA, WG_ALTA.
        WG_BAJA = 'X'.
    ENDCASE.

    Doble clic sobre EXIT_SAPMIWO0_009 y aceptamos crear el include ZXQQMU07. Dentro del include, escribimos nuestro código para guardar la opción del radiobutton del campo ZZCAMPO2.

    move: viqmel-ZZCAMPO1 to e_viqmel-ZZCAMPO1,
          viqmel-ZZPERNR  to e_viqmel-ZZPERNR.
    
    IF ( WG_ALTA IS NOT INITIAL ).
      MOVE 'ALTA' TO e_viqmel-ZZCAMPO2.
    ELSEIF ( WG_MEDIA IS NOT INITIAL ).
      MOVE 'MEDIA' TO e_viqmel-ZZCAMPO2.
    ELSEIF ( WG_BAJA IS NOT INITIAL ).
      MOVE 'BAJA' TO e_viqmel-ZZCAMPO2.
    ENDIF..

    Y así queda el aviso de calidad:

    aviso de calidad con radiobuttons
    Por ultimo, so queda modificar el listado de avisos de calidad ( transacción QM10 ) para incluir los nuevos campos. Modificamos la estructura RQMQMEL1 y añadimos los nuevos campos.

    append a la estructura RQMQMEL1
    nuevos campos en la QM10

    Referencias:

    domingo, 8 de septiembre de 2013

    Bapis para cambiar la unidad de medida

    La unidad de medida base, es la base para la gestión de stock y evaluación. Las cantidades de material disponible o en almacén (cuantos) se cuentan utilizando la unidad de medida base. toda cantidad que este medida en otra unidad, se convierte a la unidad de medida base para el calculo.

    Todo material en Sap, tiene asignada una unidad de medida base. Se puede ver la unidad de medida base asignada a un material en el maestro de materiales, transacción MM03, en la pestaña de Datos básicos 1.

    Unidad de medida base para el material en le maestro de materiales
    En la base de datos, esta información se encuentra en el campo  MARA-MEINS.

    Se pueden definir otras unidades de medida alternativa para el material y su factor de conversión en el Maestro de Materiales -> Datos adicionales -> Unidades de medida.

    Unidades de medida alternativa y su relación
    La información sobre las unidades de medida alternativa esta almacenada en la tabla MARM: Unidades de medida para el material.

    En Abap, cuando necesitemos realizar alguna conversion entre unidades de medida podemos utilizar:

    MATERIAL_UNIT_CONVERSION

    Esta bapi, convierte una cantidad de un material en unidades de medida base a una unidad de medida alternativa y viceversa. Es obligatorio que una de las dos unidades de medida implicadas en la conversión sea la unidad de medida base del material (MARA-MEINS).


    *&---------------------------------------------------------------------*
    *&      Form  convert_unit_con_material
    *&---------------------------------------------------------------------*
    *  pi_um_inicial / pi_um_final: 1 de ellas, debe ser la UMB del material
    *&---------------------------------------------------------------------*
    FORM convert_unit_con_material USING pi_matnr       TYPE mara-matnr
                                         pi_cantida_ini TYPE gsmng
                                         pi_um_inicial  TYPE t006-msehi
                                         pi_um_final    TYPE t006-msehi
                                   CHANGING po_cantida_fin TYPE gsmng.
    
       call function 'MATERIAL_UNIT_CONVERSION'
             exporting
                  input                = pi_cantida_ini
    *              kzmeinh              = 'X'
                  matnr                = pi_matnr
                  meinh                = pi_um_inicial
                  meins                = pi_um_final
    *              type_umr             = '3'
             importing
                  output               = po_cantida_fin
             exceptions
                  conversion_not_found = 1
                  input_invalid        = 2
                  material_not_found   = 3
                  meinh_not_found      = 4
                  meins_missing        = 5
                  no_meinh             = 6
                  output_invalid       = 7
                  overflow             = 8
                  others               = 9.
    
      IF sy-subrc <> 0.
    *   Mensaje de error
      ENDIF.
    
    ENDFORM.
    

    UNIT_CONVERSION_SIMPLE

    Con esta bapi no es necesario especificar el material ni la unidad de medida base. Convierte la cantidad  que indiquemos de una unidad de medida a otra. También permite redondear el resultado.

    Los factores de conversión de las unidades de medida se configuran en:
       SPRO -> Sap Netweaver -> Parametrizaciones generales -> Verificar unidades de medida

    *&---------------------------------------------------------------------*
    *&      Form  convert_unit_sin_material
    *&---------------------------------------------------------------------*
    FORM convert_unit_sin_material USING pi_cantida_ini TYPE gsmng
                                         pi_um_inicial  TYPE t006-msehi
                                         pi_um_final    TYPE t006-msehi
                                   CHANGING po_cantida_fin TYPE gsmng.
    
    
      CALL FUNCTION 'UNIT_CONVERSION_SIMPLE'
        EXPORTING
          input                = pi_cantida_ini
    *     NO_TYPE_CHECK        = 'X'
    *     ROUND_SIGN           = ' '
          unit_in              = pi_um_inicial
          unit_out             = pi_um_final
        IMPORTING
    *     ADD_CONST            =
    *     DECIMALS             =
    *     DENOMINATOR          =
    *     NUMERATOR            =
          output               = po_cantida_fin
        EXCEPTIONS
          conversion_not_found = 1
          division_by_zero     = 2
          input_invalid        = 3
          output_invalid       = 4
          overflow             = 5
          type_invalid         = 6
          units_missing        = 7
          unit_in_not_found    = 8
          unit_out_not_found   = 9
          OTHERS               = 10.
    
      IF sy-subrc <> 0.
    *   Mensaje de error
      ENDIF.
    
    ENDFORM.                    "convert_unit_sin_material
    

    RS_CONV_EX_2_IN_NO_DD

    No es una bapi para conversión entre unidades. Convierte un string a tipo cantidad, muy útil cuando la fuente de los datos es un fichero de texto plano y necesitas convertir los datos para poder trabajar con ellos.

    *&---------------------------------------------------------------------*
    *&      Form  convert_to_quan
    *&---------------------------------------------------------------------*
    FORM convert_to_quan  USING    p_mengec TYPE c
                          CHANGING p_mengei LIKE marc-eisbe.
    
    
      CONDENSE p_mengec NO-GAPS.
      CALL FUNCTION 'RS_CONV_EX_2_IN_NO_DD'
        EXPORTING
          input_external                    = p_mengec
    *   CONVERT                           =
    *   CURRENCY                          = ' '
       IMPORTING
         output_internal                   = p_mengei
       EXCEPTIONS
         input_not_numerical               = 1
         too_many_decimals                 = 2
         more_than_one_sign                = 3
         ill_thousand_separator_dist       = 4
         too_many_digits                   = 5
         sign_for_unsigned                 = 6
         too_large                         = 7
         too_small                         = 8
         invalid_date_format               = 9
         invalid_date                      = 10
         invalid_time_format               = 11
         invalid_time                      = 12
         invalid_hex_digit                 = 13
         unexpected_error                  = 14
         input_too_long                    = 15
         no_decimals                       = 16
         invalid_float                     = 17
         illegal_type                      = 18
         conversion_exit_error             = 19
         OTHERS                            = 20.
    
    
    ENDFORM.                    " convert_to_quan
    
    

    miércoles, 4 de septiembre de 2013

    GUIXT: El modulo InputAssistant

    Un InputScript es un archivo de texto que contiene instrucciones para procesar datos y navegar a través de diferentes dynpros del sistema Sap. Un InputScript pueden inicializar variables, leer y guardar la información de los campos de una dynpro, procesarlos ( puede llamar a bapis del sistema Sap a través de RFC ) y utilizar esa información para procesar una transacción o dynpro en el sistema Sap.

    Su funcionamiento es muy parecido a los batch input en Sap, pero un inputscript puede guardarse en archivos de texto para luego, ejecutarlo desde un  GuiXT script. 

    InputAssistant es el modulo de GuiXT encargado de ejecutar los InputScripts. Aunque viene incluido en el software de GuiXT, requiere de una licencia valida para su uso. Si intentamos ejecutar un script que requiera el modulo de  InputAssistant, aparecerá un error de licencia no valida o inexistente en la ventana de GuiXT.

    InputAssistant: licencia no valida o inexistente
    El modulo InputAssistant se activa desde el perfil de GuiXT. Rellenando el siguiente formulario ( menú de la izquierda -> INSTALLATION -> TESTKEY ). Synactive nos enviara una licencia de uso valida por 1 mes.

    Perfil de GuiXT: Activar los módulos de GuiXT
    Es posible activar el modulo InputAssistant temporalmente, únicamente durante la sesión activa del sistema Sap. 

    1. Entrar al sistema Sap con nuestro usuario y contraseña.
    2. Sin salir del sistema, saltamos a la ventana de GuiXT y después al perfil de GuiXT.
    3. Marcar la casilla de InputAssistant.
    4. Introducimos una User Key cualquiera ( ej: 1234567890 ).
    5. Comprobar que el el ID del sistema SAP esta en la casilla "Enabled Systems", sino introducirlo.
    6. OK y volvemos al sistema Sap.

    Volvemos a entrar en la transacción  y los mensajes de error de licencia habrán desaparecido. Si salimos del sistema Sap, al volver a entrar,  tendremos que repetir todo el proceso.

    Perfil de GuiXT: activar temporalmente InputAssistant
    Grabación de un InputScript con GuiXT

    Activamos/Desactivamos la grabación de inputscripts desde el menú Options -> Input Recording.
    Otra opción es desde la barra de herramientas de la ventana de GuiXT pulsando el botón "Record".


    Cada vez que realizamos una grabación, se genera un archivo "InputScript.txt" automáticamente, donde quedan registrados todos los datos introducidos y las acciones realizadas.Este archivo, se reescribe con cada nueva grabación, se recomienda que,al finalizar la grabación de un inputscript, re-nombrarlo con otro nombre para poder editarlo posteriormente y evitar así su perdida.

    Los archivos se guardan, por defecto,en la dirección especificada en el perfil de GuiXT.


    Lo mejor es explicar el proceso con un ejemplo. 
    Vamos a grabar un inputscript de la transacción ME2L:

       1.- Activamos la grabación desde la ventana de GuiXT. El botón "Record" cambiara a "ON".


       2.- Desde el sistema Sap, accedemos a la transacción ME2L.


       3.- Rellenamos la pantalla de selección ( Ej. centro 5000 )  y ejecutamos la transacción. 


       4.- Terminada la ejecución , detenemos la grabación en la ventana de GuiXT. El botón "ON" cambiara a "Record".


       5.- Click en el botón "RecScript" de la barra de herramientas de la ventan de GuiXT


       6.- File -> Save As..  Renombrar y grabar el script.

    Ejecutar Un InputScripts

    Se puede ejecutar un inputscript de diferentes formas, lo normal es ejecutarlo a través de una acción del usuario sobre un elemento de la pantalla ( pulsadores, Códigos de función, Menús, etc… ), desde un GuiXT script o desde otro inputscript.

    Continuando con el ejemplo anterior, vamos a crear un botón en la transacción ME2L que cuando el usuario lo pulse, ejecute el inputscript que hemos creado anteriormente.

    Primero creamos el script para modificar la dynpro y añadir el botón a la transacción ME2L

    Pushbutton (toolbar) "@3B\QConsultar centro 5000@Centro 5000" process="centro5000.txt"


    la opción process indica el archivo que contiene el inputscript que debe ejecutarse si el usuario pulsa el botón. El inputscript, al igual que el guixt script,  debe localizarse en uno de los 4 posibles directorios que se pueden especificar en el perfil de GuiXT.


    Testear un InputScripts

    Seamos sinceros, pocas veces en la programación un código funciona a la primera.  A base de prueba y error depuramos el código hasta que funciona como se había diseñado sobre el papel. GuiXT tiene dos opciones para comprobar el funcionamiento del script:
    • Una herramienta para Trazar la ejecución del script.
    • Ejecutar el script en modo visible y poder ver, en tiempo real, como se procesa cada dynpro.
    Para ejecutar el inputscript en modo visible, antes de realizar el evento o acción que lanzara el inputscript, pulsar el botón "visible" de la barra de herramientas de la ventana de GuiXT. Se activara el modo visible y todos los inputscript que se ejecuten a partir de este momento,  mostrara todas las pantallas por la que pasen  deteniéndose en cada comando. Con la tecla “Enter” ejecutaremos el comando y saltara al siguiente comando.

    Al activar el modo visible, el boton "Visible" cambiara a "ON"

    Activar modo visible
    GuiXT InputScript Debug

    El debugger de GuiXT se lanza desde la barra de herramientas de la ventana de GuiXT.


    En  el momento en que se ejecute un inputscript, se lanzara el modo debugger y aparecera en pantalla la ventana del debugger. Si cerramos esta ventana, interrumpiremos el proceso del debugger y continuara  la ejecución normal del inputscript.

    Inputscript debugger

    En la ventana del debugger podemos ver:
    • El contenido de cada variable.
    • Evaluar expresiones que contenga variables, parámetros o campos de entrada.
    • Procesar el inputscript paso a paso.
    • Colocar breakpoint.
    Un script se ejecuta secuencialmente, linea a linea. En la ventana del debugger, la línea que va a ser procesada, aparece resaltada en amarillo. Para colocar un breakpoint bastara hacer doble click sobre la línea deseada, pasando esta a un color azul, un doble click sobre una línea en azul elimina el breakpoint. 

    Cuando se alcanza un breakpoint, la línea aparece en verde. 
    Cualquier error de sintaxis al ejecutar una línea se mostrara en un popup 

    El Debugger solo se activa con Inputscript, no funcionara con GuiXT Scripts.

    El contenido de las variables se muestra es la ventana de la izquierda

    Inputscript Debug: contenido de las variables del script

    Para detectar y solucionar errores de programación, también necesitamos poder trazar la ejecución de nuestro código, poder analizar como y cuando se ha ejecutado cada instrucción. En la barra de herramientas podemos activar el modo "TRACE". 

    Activar TRACE
    Cuando lo activemos, después de ejecutar cualquier inputscript, aparecerá un log con la traza de ejecución del inputscript.

    Trace del inputscript startva01.txt


    Un ejemplo de GuiXT script + InputScript


    En este caso se va a desarrollar un menú de acceso rápido para la creación de pedidos de venta ( transacción VA01 ), el objetivo es que el usuario pueda crear los pedidos para las diferentes organizaciones de venta de una manera rápida y sencilla.

    Desde la transacción VA01, saltamos a la ventana de guiXT. Pulsamos “SCRIPT” en barra de herramientas de la ventana de  GuiXT. Se despliega el editor de scripts que tengamos configurado en el perfil de GuiXT.


    Escribir el siguiente código y guardar el script.

    //Caja e imagen
    box (2,70) (10,110) "Acceso rápido"
    Image (2.7,70.3) (9.2,84.6) "tickets.jpg" "-plain"

    // Orden por defecto
    if not V[VA01_Ordertype]
        Set V[VA01_Ordertype] "CS"
    endif

    // RadioButton de seleción
    RadioButton (3,86) "Ventas canal 1000" Name="VA01_Ordertype" value="CS"
    RadioButton (4,86) "Ventas canal 2000" Name="VA01_Ordertype" value="RO"
    RadioButton (5,86) "Ventas canal 3000" Name="VA01_Ordertype" value="IO"
    RadioButton (6,86) "Menu principal " Name="VA01_Ordertype" value="RE"

    Pushbutton (8,86) "Crear pedido de ventas" "/NVA01" Process="startva01.txt" "size=2"

    Cuando el usuario pulse el botón "Crear pedido de ventas" se ejecutara el inputscript guardado en el archivo startva01.txt.
    Para crear el inputscript, desde la ventana de GuiXT, pulsar "InputScript" en la barra de herramientas de la ventana GuiXT.  Se despliega el editor de scripts que tengamos configurado en el perfil de GuiXT.


    Escribimos el siguiente código y guardamos como startva01.txt en el directorio correspondiente.

    // InputScript "startva01.txt"
    Screen SAPLSMTR_NAVIGATION.0100
    Enter "/nva01"

    // Crear pedido de cliente: Acceso
    Screen SAPMV45A.0101

    IF V[VA01_Ordertype=CS]
       Set F[Clase de pedido] "ZPED"
       Set F[Organización ventas] "1000"
       Set F[Canal distribución] "10"
       Set F[Sector] "10"

       Enter

    ENDIF


    IF V[VA01_Ordertype=RO]
       Set F[Clase de pedido] "ZPED"
       Set F[Organización ventas] "2000"
       Set F[Canal distribución] "10"
       Set F[Sector] "10"

       Enter

    ENDIF


    IF V[VA01_Ordertype=IO]
       Set F[Clase de pedido] "ZPED"
       Set F[Organización ventas] "9000"
       Set F[Canal distribución] "10"
       Set F[Sector] "10"

       Enter

    ENDIF


    IF V[VA01_Ordertype=RE]
       Set F[Clase de pedido] ""
       Set F[Organización ventas] ""
       Set F[Canal distribución] ""
       Set F[Sector] ""
    ENDIF

    Volvemos a entrar en la transacción VA01 para ver el resultado.

    VA01: acceso rápido