lunes, 20 de mayo de 2013

Modulo. Lista de seleccion (F4)

Continuando con la serie de entradas relacionadas con el tema de la estrategia de desarrollo en ILE presento una plantilla de programa de selección de un registro.

Objetivo


Realizar un programa que presenta una ventana de selección (típica consulta de F4 en formato window) donde se podrá un registro para devolver al programa que le ha llamado.
En este ejemplo, se realizará una ventana de selección de países.

Referencias: ILE estrategiaBD Pruebas


Configuración 

Este programa utilizará un componente de acceso a base de datos de lista de países similar al que se definió en la entrada de acceso a BD a través del uso del programa de servicio que lo contiene .
  • El nombre del módulo donde esta el ventana de lista de selección BAN40P1
    • La definición de la pantalla estará definida como BAN40S1
  • Utiliza el programa de servicio BAN01SRV que contiene los componentes de acceso a BD.
    • El miembro (/Copy) con la definición del prototipo con los componentes y con la definición de estructuras será BAN01M1CP
Este ejemplo sirve de plantilla para otro proceso similar.


Fuente de la pantalla. BAN40S1

Se define la pantalla para presentar la lista de registro y para seleccionar un registro.



A                                      DSPSIZ(24 80 *DS3)
A                                      PRINT
A          R BAN40S01                  SFL
A                                      SFLNXTCHG
A            S_OPCION       1A  B  8  4VALUES(' ' '1')
A            S_DSPAIS      35A  O  8 12
A            S_IDPAIS       3A  O  8  8
A          R BAN40C01                  SFLCTL(BAN40S01)
A                                      CF03(03 'Salir')
A                                      RTNCSRLOC(*RECNAME &REGCUR &CAMCUR)
A                                      OVERLAY
A                                      SFLCSRRRN(&CURS01)
A  40N41                               SFLDSP
A N41                                  SFLDSPCTL
A  41                                  SFLCLR
A  40N41                               SFLEND(*MORE)
A                                      SFLSIZ(0010)
A                                      SFLPAG(0009)
A  61                                  SFLMSG('Solo se puede seleccionar u-
A                                      n registro' 61)
A                                      WINDOW(BAN40P01)
A            CURS01         5S 0H
A            NRR            4S 0H      SFLRCDNBR(CURSOR)
A            CAMCUR        10A  H
A            REGCUR        10A  H
A            WKSTNS        10A  O  1 30DSPATR(HI)
A                                  2  3DATE
A                                      EDTCDE(Y)
A                                      DSPATR(HI)
A                                  2 40USER
A                                      DSPATR(HI)
A            D_DSPAIS      25A  B  4 10DSPATR(HI)
A                                  4  4'Pais'
A                                  7  3'Opc'
A                                      DSPATR(HI)
A                                      DSPATR(UL)
A                                  7  8'Pais'
A                                      DSPATR(HI)
A                                      DSPATR(UL)
A                                  5  4'1-Seleccionar'
A                                  1 18'Lista de paises'
A                                      DSPATR(HI)
A                                  1  3'BAN40P1'
A                                      DSPATR(HI)
A          R BAN40P01
A                                      WINDOW(2 15 20 50)
A                                      WDWBORDER((*DSPATR RI) (*CHAR '    -
A                                          '))
A                                 18  5'F3-Salir'
A          R BAN40R00
A                                      KEEP
A                                      ASSUME
A                                  5  3' ' 


Se define:



  • El subfichero (BAN4001) con un campo que recogerá la opción (S_OPCION) y donde se presentan los campos de identificación y descripción de país (S_IDPAIS  y S_DSPAIS)
  • El registro de control (BAN40C01). Tendrá un campo para buscar y para restringir los datos que aparecen en la lista y buscará por descripción de país (D_DSPAIS)
Para las variables de cabecera de pantalla siempre utilizo el prefijo D_ y para las de subfichero S_ y el sufijo será el nombre del campo en el fichero.


Fuente del proceso. BAN40P1

Se presenta el fuente del modulo que controla la lista de selección (F4). Utilizará el componente de acceso de base de datos similar al que se presento en entradas previas en este blog.
Nota: pondré en color azul lo que debería cambiar en esta plantilla del fuente RPG para hacer un nuevo programa de selección de otra entidad.


Definición ficheros y variables

Se define la pantalla de lista para selección y las estructuras de datos que se utilizarán en el programa. Como en todos los fuentes anteriores, se utilizan estructuras de datos para no cambiar las llamadas entre funciones cuando hagamos otro proceso similar; sólo bastaría con cambiar las variables contenidas en las estructura.


*==============================================================
*   Plantilla Pantalla de lista seleccion F4  - V1.0    *==============================================================
H DEBUG DECEDIT('0,') DATEDIT(*DMY.)

FBan40S1   CF   E             WORKSTN USROPN
F                                     INFDS(CURSOR)
F                                     SFILE(Ban40S01:NRR)

D NRR             S              4  0
D G_UltReg        S              4  0

 // Ds de DEFINICION de los campos de busqueda de cabecera
DDs_DatosBus      DS                  QUALIFIED
D TipoOrden                      2
DsPais                        25


 // Ds de DEFINICION de los campos de seleccion del subfichero
DDs_ClaveSel      DS                  QUALIFIED
IdPais                         3
DsPais                        50

 // Ds con la clave seleccionada
D W_ClaveSel      Ds                  LikeDs(Ds_ClaveSel)

 // Ds con los datos de busqueda
D W_DatosBus      Ds                  LikeDs(Ds_DatosBus)



Definición de las estructuras de datos

  • (Ds_DatosBus). Campos de cabecera de la ventana que sirven para buscar y restringir los datos que aparecen en la lista. Hay un campo  fijo siempre que es el tipo de orden (TipoOrden) que servirá para definir la ordenación de la sentencia SQL de lectura y que utilizará para llamar al componente de acceso a base de datos.
    En este ejemplo será el nombre de país (DsPais). 
    • Tiene asociada la variable de trabajo (W_DatosBus) que se utilizará en el programa
  • (Ds_ClaveSel). Contiene los campos asociados al registro de la lista que ha seleccionado el usuario y que en este caso, se devolverán al programa que le llamó. En este ejemplo el id de país y su nombre (IdPais y DsPais)
    • Tiene asociada la variable de trabajo (W_ClaveSel) que se utilizará en el programa

Recursos y definición de prototipos internos.

En esta parte se define recursos comunes y los componentes internos del programa.

/COPY *LIBL/QRPGLESRC,BAN00VAR


DDsp_CargaDsp     PR
D P_DatosBus                          LikeDs(Ds_DatosBus) Const

DDsp_DatosDspLst  PR
D P_Accion                            Like(WAccActual)
D P_AccionCons                  10

DDsp_ObtCab       PR
D P_DatosBus                          LikeDs(Ds_DatosBus)

DDsp_ValidarLst   PR
D P_Error                         n
 * Seleccionado
D P_HaySeleccion                  n
D P_OpcionSel                    1
D P_ClaveSel                          LikeDs(Ds_ClaveSel)


 /COPY *LIBL/QRPGLESRC,BAN01M1CP



 // Ds de DEFINCICION de los parametros de entrada
DDs_Parametros    DS                  Qualified
D IdPais                         3
D DsPais                        50

DBan40P1          PR
D P_Parametros                        LikeDs(Ds_Parametros)
D P_Resultado                    3

DBan40P1          PI
D P_Parametros                        LikeDs(Ds_Parametros)
D P_Resultado                    3


La rutina /Copy (BAN00VAR) contiene definición de variables comunes a todos los programas de pantalla. Se detallará en un apartado.
La rutina /Copy (BAN01M1CP) contiene la definición de los componentes de acceso a base de datos. (Ver entrada de componente de acceso a base de datos)

Procedimientos internos

  • (Dsp_CargaDsp) Se utilizará para cargar los campos y datos de la ventana
  • (Dsp_DatosDspLst) Se utilizará para procesar la lista y obtener la acción realizada por el usuario
  • (Dsp_ObtCab) Se utilizará para obtener los campos de cabecera de pantalla (busqueda) rellenados por el usuario
  • (Dsp_ValidarLst) Se utilizará para validar las opciones de la lista y recuperar el registro seleccionado por el usuario

Parámetros de entrada.
Se define los parámetros de entrada a este programa. Tendrá siempre un estructura de datos (P_Parametros) y un campo de resultado de la operación (P_Resultado).
La estructura de datos (Ds_Parametros) contiene las variables de entrada/salida al programa. En este caso son dos valores de salida que contiene el id de país y su nombre (IdPais y DsPais) del registro de la lista seleccionado por el usuario


Flujo principal

Se presenta el flujo principal del programa. Es necesario mencionar que es no está escrito linealmente sino que está incluido en un bucle y utiliza una variable (WSitActual) para ir cambiando de estado y para cada estado realiza un grupo de acciones determinado; A la finalización de las acciones de un grupo, la variable cambiará de estado y en el siguiente ciclo realizará otras acciones. Cuando alcance un estado de finalización (CSitFinalizar) terminará el proceso.
Si se quiere modificar el flujo de proceso, basta con cambiar el contenido de esta variable al finalizar su grupo de acciones. 

Si se desea incluir nuevas acciones, se crearía una nueva situación incluyendo las instrucciones que fuera y al finalizar estas acciones debería cambiar el contenido de la variables de situación para pasar a otro estado. Lógicamente, habría también que cambiar que alguien llamará a este nuevo grupo cambiado la variable de situación. 


/FREE
   Open Ban40S1;;

   WSitActual= CSitCargarDsp;
   Clear W_DatosBus;
   W_DatosBus.TipoOrden ='2A';

   Dow WSitActual<>CSitFinalizar;
     Select;
       /////////////////////////////////////////////////////
       // VISTA: Cargar la pantalla  ///////////////////////
       /////////////////////////////////////////////////////
       When WSitActual = CSitCargarDsp;
          Dsp_CargaDsp(W_DatosBus);
          WSitActual= CSitShowDatos;

       ////////////////////////////////////////////////////
       // VISTA: Presenta datos de pantalla ///////////////
       ////////////////////////////////////////////////////
       When WSitActual = CSitShowDatos;
          Dsp_DatosDspLst (W_Accion : W_AccionCons);
          Select;
            When W_Accion=CAccSalir;
              P_Resultado = CRtnSalir;
              WSitActual= CSitFinalizar;
            When W_Accion=CAccEnter;
              WSitActual = CSitValidar;
          EndSl;

       ////////////////////////////////////////////////////
       // VISTA: Valida los datos de pantalla  ////////////
       /////////////////////////////////////////////////////
       When WSitActual = CSitValidar;
         Dsp_ValidarLst (W_Error : W_HaySeleccion : W_OpcionSel :
                         W_ClaveSel);
         If Not W_Error;
           If W_HaySeleccion;
             Select;
               When W_OpcionSel='1';
                   P_Parametros.IdPais = W_ClaveSel.IdPais;
                   P_Parametros.DsPais = W_ClaveSel.DsPais;
                   P_Resultado = CRtnConfirmado;
                   WSitActual = CSitFinalizar;
               Other;
                   WSitActual= CSitShowDatos;
             EndSl;
           Else;
             // Recarga la lista segun la selección
             Dsp_ObtCab(W_DatosBus);
             WSitActual = CSitCargarDsp;
           EndIf;
         Else;
           WSitActual = CSitShowDatos;
         EndIf;
      EndSl;
    EndDo;

    Close Ban40S1;
    Eval *InLr=*On;
 /END-FREE


Las situaciones por las que esta pasando el programa son constantes definidas en el /Copy común y son las siguientes:

  • (CSitCargarDsp). Es la inicial. Realizará la carga de los campos de cabecera de pantalla (búsqueda) y la lista del registros del subfichero.
  • (CSitShowDatos). Presenta la pantalla y esperará a que el usuario realice una acción y recogerá el mandato pulsado por el usuario.
    Si ha pulsado el mandato de salida (W_Accion=CAccSalir) devolverá al programa que le llamó que no ha hecho nada () y finalizará (P_Resultado = CRtnSalir). En caso contrario, validará la pantalla.
  • (CSitValidar). Valida el subfichero y si es correcto y el usuario ha seleccionado algo, recoge la selección de registro elegido por el usuario y finaliza devolviéndosela (P_Parametros.IdPais y P_Parametros.DsPais  al programa que le llamó e indicándole que ha confirmado (P_Resultado = CRtnConfirmado).
  • (CSitFinalizar). Finaliza el proceso.


Componente interno de Carga de pantalla

Realiza la carga de la cabecera de la pantalla y del subfichero,


 *=======================================================
 *    Cargar los datos de la lista       
 *=======================================================
PDsp_CargaDsp     B                   
DDsp_CargaDsp     PI
D P_DatosBus                          LikeDs(Ds_DatosBus) Const

D W_MaxReg        S             10I 0
D W_DatosLst      Ds                  Dim(999) LikeDs(Ds_BasPais)
D W_Sel           DS                  LikeDs(Ds_SelPais)
D W_NumReg        S              2  0
D W_TotReg        S             10  0

 // Paginacion
D W_Pag           S             10I 0
D W_NumRegCar     S             10I 0
 /FREE
    // Carga los campos de cabecera de la pantalla
    D_DsPais =  P_DatosBus.DsPais;

    // Inicializa el subfichero
    G_UltReg=*Zeros;
    Nrr=*Zeros;
    *In40=*Off;
    *in41=*On;
    Write Ban40c01;
    *in41=*Off;

     W_MaxReg=99;
     W_Pag       = *Zeros;
     W_NumRegCar = *Zeros;
     W_Sel.S_DsPais = P_DatosBus.DsPais;
     Obt_LstPais(w_DatosLst : W_NumReg : W_TotReg :
                 W_Pag : W_NumRegCar : P_DatosBus.TipoOrden :
                 W_Sel);

     // Carga la lista del subfichero
     DoW  G_UltReg<W_NumReg and G_UltReg<=W_Maxreg;
        G_UltReg=G_UltReg+1;
        S_Opcion = *Blanks;
        S_IdPais = W_DatosLst(G_UltReg).IdPais;
        S_DsPais = W_DatosLst(G_UltReg).DsPais;

        Nrr = G_UltReg;
        Write Ban40S01;
     EndDo;

     // Verificar si ha cargado algun registro para presentarlo
     If G_UltReg>=1;
        *In40=*On;
        Nrr=1;
     EndIf;
 /END-FREE
P                 E


Primero carga las variables de cabecera (D_DsPais=P_DatosBus.DsPais) de la pantalla que son los campos de búsqueda. Lo carga con el contenido que tenga en la estructura; inicialmente serán blancos/ceros pero posteriormente tendrá lo escrito por el usuario.
Después inicializa el subfichero. 
Y por último cargará el subfichero. Para ello leerá el componente de acceso a base de datos (Obt_LstPais) (que se encuentra en el programa de servicio con todos los componentes de acceso a BD) con los parámetros para que devuelva el máximo de registros y utilice la selección del campo de búsqueda indicado por el usuario (W_Sel.S_DsPais=P_DatosBus.DsPais). Leerá la tabla de registros devuelta y por cada uno de ellos, generará un registro en la lista.



Componente interno de Obtener campos de cabecera


PDsp_ObtCab       B                   
DDsp_ObtCab       PI
D P_DatosBus                          LikeDs(Ds_DatosBus)

 /FREE
    P_DatosBus.DsPais = D_DsPais;
 /END-FREE
P                 E



Recupera los datos de cabecera seleccionados por el usuario (D_DsPais) y los carga sobre la estructura de datos para búsqueda (P_DatosBus)


Componente interno de Presentar pantalla


Presenta la pantalla al usuario y recoge el mandato pulsado por el usuario


PDsp_DatosDspLst  B                  
DDsp_DatosDspLst  PI
D P_Accion                            Like(WAccActual)
D P_AccionCons                  10

 /FREE
   // Pie de la ventana
   Write Ban40P01;
   Exfmt Ban40C01;

   Select;
     When *In03=*On;
        P_Accion=CAccSalir;
     Other;
        P_Accion=CAccEnter;
   EndSl;
 /END-FREE
P                 E



Componente interno de Validar pantalla


Se valida el subfichero y se recoge la selección realizada por el usuario.

PDsp_ValidarLst   B                  
DDsp_ValidarLst   PI
D P_Error                         n
 * Seleccionado
D P_HaySeleccion                  n
D P_OpcionSel                    1
D P_ClaveSel                          LikeDs(Ds_ClaveSel)

D WNrr            S              4  0
D WNrrSel         S              4  0
 /FREE
    P_HaySeleccion=*Off;
    P_Error=*off;
    P_ClaveSel=*Zeros;

    *In61=*Off;
    If Nrr>*Zeros;

       // Verifica que no hay errores en la seleccion
       WNrr=1;
       Chain WNrr Ban40S01;
       Dow %Found and Not P_Error;
         If S_Opcion<>*Blanks;
           If Not P_HaySeleccion;
              P_HaySeleccion=*On;
           Else;
              P_Error=*on;
              *In61=*On;
              Nrr=WNrr;
              Iter;
           EndIf;
         EndIf;
         Update Ban40S01;
         WNrr=WNrr+1;
         Chain WNrr Ban40S01;
       EndDo;

       // Comprueba la opcion seleccionada (si la hay)
       If Not P_Error and P_HaySeleccion;
          WNrr=1;
          Chain WNrr Ban40S01;
          Dow %Found and Not P_Error;
            If S_Opcion<>*blanks;
               P_ClaveSel.IdPais   = S_IdPais;
               P_ClaveSel.DsPais   = S_DsPais;
               P_OpcionSel         = S_Opcion;
               S_Opcion            = *Blanks;
               WNrrSel=WNrr;
               Update Ban40S01;
            EndIf;
            WNrr = WNrr+1;
            Chain WNrr Ban40S01;
          EndDo;
          Nrr = WNrrSel;
          EndIf;
        EndIf;
 /END-FREE
P                 E


En el proceso se valida que solo se haya seleccionado un registro. Si no hay error, recupera los datos del registro seleccionado (S_IdPais y S_DsPais) y serán los valores que se devolverán al programa que le ha llamado.



Anexo. /Copy BAN00VAR declaraciones generales y comunes

Presenta la pantalla al usuario y recoge el mandato pulsado por el usuario


 // Estructuras y campos de control de pantalla
D Sistema        SDS
D Usuario               254    263
D WKSTNS                244    253

D CURSOR          DS
D  PXCUR                370    371B 0
D  PXNRC                378    379B 0


 // Constantes de acciones dentro del programa
DWAccActual       S             15
D CAccSalir       C                   'Salir          '
D CAccAlta        C                   'Alta           '
D CAccEnter       C                   'Enter          '
D CAccCons        C                   'ConsultaF4     '
D CAccAnterior    C                   'Anterior       '
D CAccConfirmar   C                   'Confirmar      '
D CPagSig         C                   'PaginaSig      '


 // Constantes de posibles situaciones del programa
D W_Accion        S                   Like(WAccActual)
D W_AccionCons    S             10
D WSitActual      S             15
D CSitCargarDsp   C                   'Cargar_Dsp     '
D CSitFinalizar   C                   'Finalizar      '
D CSitShowDatos   C                   'ShowDatos      '
D CSitValidar     C                   'Validar        '
D CSitAlta        C                   'Alta           '
D CSitRecuperar   C                   'Recuperar      '
D CSitCargarDat   C                   'Cargar_Datos   '
D CSitActualizar  C                   'Actualizar     '
D CSitEnter       C                   'Enter          '

 // Constantes de tipos de ejecucion programa
D CEjeAlt         C                   'Add'
D CEjeMod         C                   'Upd'
D CEjeBor         C                   'Dlt'
D CEjeCon         C                   'Dsp'

*  Validacion
D W_Error         S               n

*  Datos seleccionados de la lista
D W_HaySeleccion  S               n
D W_OpcionSel     S              1


** Variables de trabajo
D w_Resultado     S              3
D CRtnConfirmado  C                   'OK'
D CRtnSalir       C                   'Sal'



Se define para reutilizar en todos los programas de pantalla las siguientes variables que estarán en las diferentes plantillas:
  • Estructuras y variables para pantalla
  • Constantes de acciones realizadas por el usuario (CAccAltaCAccSalir etc.) 
  • Variables y constantes por las que pasa el programa (WSitActualCSitValidar etc.)
  • Constantes de tipo de ejecución para programa mantenimiento (CEjeAlt , CEjeBor etc)
  • Constantes de retorno al programa que le llamó (CRtnConfirmadoCRtnSalir etc)


5 comentarios: