Página 1 de 1

Para os que dormem sobre um get/read aberto

Enviado: 16 Jun 2008 20:29
por Romeuk
Pessoal

Procurei em todo o forum solução para um problema que eu tinha e que também outros tem ou já tiveram: Como tratar de dar um "chega pra lá" naqueles amáveis usuários que "dormem" sobre um registro bloqueado e não saem nunca do modo de edição.
A solução mais prática que vi foi o uso da função KeySec().
Mas bolei uma solução tupiniquim, que resolveu bem o meu problema, embora seja aplicável apenas aos casos get/read. Acho que com um TBrowse já não dá pra usar. Mas vamos lá:

O macete é não bloquear o registro para edição. Apenas permita que o gajo leia o registro em questão e atribua a variáveis os valores dos diferentes campos.
O registro só é bloqueado no instante que o cara cair fora do read.
Tipo assim:

1) Atribua a variáveis os valores dos campos:
global xCampo[fcount()]
for i = 1 to fcount()
xCampo := fieldget(i)
next


2) Depois crie o conjunto get/read:
@ 2, 4 SAY Fieldname(1) color cColor1 GET xCampo[1] color cColor2 //ANOMES
@ 2, 24 SAY Fieldname(2) color cColor1 GET xCampo[2] color cColor2 //LOTE
@ 2, 34 SAY Fieldname(3) color cColor1 GET xCampo[3] color cColor2 //DIG
@ 2, 44 SAY Fieldname(4) color cColor1 GET xCampo[4] color cColor2 //DOM
@ 2, 54 SAY Fieldname(5) color cColor1 GET xCampo[5] color cColor2 //FAM
@ 2, 64 SAY Fieldname(6) color cColor1 GET xCampo[6] color cColor2
.
.
.
read

3) Quando o read for liberado, grave
if updated()
try
rlock()
for i = 1 to fcount()
fieldput(i, xCampo)
next
dbcommit()
dbunlock()
catch
//Aqui eu coloquei uma rotina para gravar em outro banco de dados os casos em que //deu rolo. Até este momento não houve nenhum registro de ocorrencia de problemas.

end
endif

Pode ser que já tenha sido postado sobre isto, mas achei que valia a pena registrar.


Até

Re: Para os que dormem sobre um get/read aberto

Enviado: 19 Jun 2008 14:05
por Othelo
Ola Romeuk
bem eu faco um pouco diferente...
desenvolvi uma estrutura que me permite trabalhar com ambiente multiusuario e uma mesma rotina fazendo a inclusao, alteracao, exclusao e detalhe, nao sei se é mais correta, mas pra mim que preciso estar sempre alterando rotinas, incluindo funcoes e mexendo no codigo, seria uma verdadeira loucura alterar a rotina de incluir, de alterar, de excluir.... principalmente porque a tela e os dados sao os mesmos, o que muda na verdade é a gravacao no DB e o tratamento das operacoes..
Veja um exemplo:

Código: Selecionar todos

*-----------------------------------------------------------------------------
*
*  Departamento de Informatica - CPD MK
*
*  Sistema....:
*  Programa...: Cd_ICM01.prg
*  Autor......: Erwin Bogner - Analista Programador
*  Objetivo...: Cadastro de Percentuais de ICMS por Estado
*  Parametros.: NIL
*  Saidas.....: NIL
*  Dt.Criacao.: 19 de Dezembro de 1996
*
*  Dt.Atualiz.: 20.11.2001.
*
*-----------------------------------------------------------------------------

LOCAL GetList := {}
LOCAL Tel_001 := SaveScreen( 00,00,24,79 )
LOCAL CorAnt  := SetColor()

LOCAL aaCampo[04], aaMasca[04], aaPictu[04]

aaCampo[01] := "ICMS->CD_ESTAD"
aaCampo[02] := "ICMS->NO_ESTAD"
aaCampo[03] := "ICMS->PER_ICMS"
aaCampo[04] := "ICMS->PER_ICM2"
*
aaMasca[01] := "UF"
aaMasca[02] := "Nome Estado"
aaMasca[03] := "% ICM"
aaMasca[04] := "% ICM2"
*
aaPictu[01] := "!!"
aaPictu[02] := "@!@X20" 
aaPictu[03] := "@ZE 999,99"
aaPictu[04] := "@ZE 999,99" 
*
SELE ICMS
SET ORDER TO 1
GO TOP

Modulo( 'Cadastro ICMS' )
Moldura( 04,00,23,79,3,1,1,"ICMS p/Estado",'B+/BG+','BG+/B+' )
Opcoes( 22, { '<F2> Inclui','<F3> Altera','<F4> Exclui','<F6> Pesquisa','<ESC> Retorna' } )
DBEDIT( 05,01,21,78,aaCampo,'J_ManICMS',aaPictu,aaMasca )
//
SELE ICMS
SET ORDER TO 1
GO TOP
//
RestScreen( 04,00,23,79,Tel_001 )
SetColor( CorAnt )
RETURN   

*-----------------------------------------------------------------------------
FUNCTION J_ManICMS( Modo )
*-----------------------------------------------------------------------------
* Funcao.....:
* Parametros.:
* Retorna....:
*

LOCAL GetList := {}
LOCAL Tel_001 := SaveScreen( 00,00,24,79 )
LOCAL Cursor  := SetCursor(1)
LOCAL CorAnt  := SetColor()
LOCAL xDate   := date()
LOCAL nTecla  := LastKey()

LOCAL xOpcao  := SPACE(1)
LOCAL XESTADO := 0

DO CASE
   CASE nTecla == -1
      IF M->DIREITO == 'M' .OR. ValAcesso( M->sUsuario,09,94 )
         DO Man_ICMS01 WITH 'I'
      ENDIF
      //
      RestScreen( 00,00,24,79,Tel_001 )
      RETURN( 1 )
   CASE nTecla == -2
      IF M->DIREITO == 'M' .OR. ValAcesso( M->sUsuario,09,95 )
         DO Man_ICMS01 WITH 'A'
      ENDIF
      //
      RestScreen( 00,00,24,79,Tel_001 )
      RETURN( 12 )
   CASE nTecla == -3
      IF M->DIREITO == 'M' .OR. ValAcesso( M->sUsuario,09,96 )
         DO Man_ICMS01 WITH 'E'
         GO TOP
      ENDIF
      //
      RestScreen( 00,00,24,79,Tel_001 )
      RETURN( 1 )
   CASE nTecla == -4
      DO Man_ICMS01 WITH 'D'
      //
      RestScreen( 00,00,24,79,Tel_001 )
      RETURN( 1 )
   CASE nTecla == -5
      @ 24,00
      @ 24,01 SAY 'Digite o Estado ==> ' GET XESTADO       PICT '99999999'
      READ
      IF LastKey() # 27
         SET SOFTSEEK ON
         SEEK AllTRIM( XESTADO )
         SET SOFTSEEK OFF
      ENDIF
      //
      RestScreen( 00,00,24,79,Tel_001 )
      KeyBoard ' '
      RETURN( 1 )
   CASE nTecla == 27                             // Retorna (Esc (27) )
      RestScreen( 00,00,24,79,Tel_001 )
      KeyBoard ' '
      RETURN(0)
ENDCASE
IF Modo >= 1 .AND. Modo <= 4
   MDBEdit( Modo )
ENDIF
RETURN( 1 )

*-----------------------------------------------------------------------------
PROCEDURE Man_ICMS01( PFUNC )
*-----------------------------------------------------------------------------
* Funcao.....: Rotina de manutencao da base de dados de cadastro de ICMS's
* Parametros.: PFUNC -> variavel indicando forma de atuacao da procedure
* Retorna....: NIL
*

LOCAL GetList := {}
LOCAL Tel_001 := SaveScreen( 00,00,24,79 )
LOCAL Tel_002 := SaveScreen( 00,00,24,79 )
LOCAL Cursor  := SetCursor(1)
LOCAL CorAnt  := SetColor()
LOCAL xDate   := date()

LOCAL xEstado := SPACE(2)
LOCAL xNome__ := SPACE(20)
LOCAL xP_ICMS := 0
LOCAL xP_ICM2 := 0

IF PFUNC$('AED')                                 // Consulta/Alteracao/Exclusao
   xEstado := ICMS->CD_ESTAD
   xNome__ := ICMS->NO_ESTAD
   xP_ICMS := ICMS->PER_ICMS
   xP_ICM2 := ICMS->PER_ICM2
ENDIF

Modelo( PFUNC )
Moldura( 10,20,17,59,3,1,1,'ICMS','B+/BG+','BG+/B+' )
SetColor( 'W+/B+' )
@ 12,25 SAY 'Estado ===> '
@ 13,25 SAY 'Nome =====> '
@ 14,25 SAY '% ICMS ===> '
@ 15,25 SAY '% ICMS 2==> '
SetColor( CorAnt )

Tel_002 := SaveScreen( 00,00,24,79 )

DO WHILE .T.
   //
   RestScreen( 00,00,24,79,Tel_002 )
   //
   Centra( 24,'Digite a Sigla do Estado ou <ESC> para Voltar.','W+/BG+',1)
   @ 12,37 GET xEstado                                     PICT '!!'
   IF PFUNC$( 'IA' )
      READ
      IF LastKey() == 27
         EXIT
      ENDIF
   ELSE
      CLEAR GETS
   ENDIF
   //
   Centra( 24,'Digite o Nome do Estado ou <ESC> para Voltar.','W+/BG+',1)
   @ 13,37 GET xNome__                                     PICT '@!@X20'
   IF PFUNC$( 'IA' )
      READ
      IF LastKey() == 27
         LOOP
      ENDIF
   ELSE
      CLEAR GETS
   ENDIF
   //
   Centra( 24,'Digite o Percentual de ICMS (1_2) do Estado ou <ESC> para Voltar.','W+/BG+',1)
   @ 14,37 GET xP_ICMS                                     PICT '@ZE 999.99'
   @ 15,37 GET xP_ICM2                                     PICT '@ZE 999.99'
   IF PFUNC$( 'IA' )
      READ
      IF LastKey() == 27
         LOOP
      ENDIF
   ELSE
      CLEAR GETS
   ENDIF
   //
   SELE ICMS
   IF PFUNC == 'D'
      Mensagem( 24,'Pressione qquer tecla para continuar consulta...','W+/R+',20 )
      EXIT
   ENDIF
   //
   IF Confirma( 20,'Confirma a Execucao da Operacao Solicitada ?' )
      //
      SELE ICMS
      IF PFUNC == 'I'
         IF AdiReg( 20 )
            REPLACE ICMS->DT_INCLU    WITH xDate       ,;
                    ICMS->SITUACAO    WITH PFUNC
            COMMIT
            UNLOCK
         ENDIF
      ENDIF
      IF RegLock( 20 )
         IF PFUNC$('AI')
            REPLACE ICMS->SITUACAO    WITH PFUNC
            REPLACE ICMS->CD_ESTAD    WITH  xEstado    ,;
                    ICMS->NO_ESTAD    WITH  xNome__    ,;
                    ICMS->PER_ICMS    WITH  xP_ICMS    ,;
                    ICMS->PER_ICM2    WITH  xP_ICM2
         ELSE
            REPLACE ICMS->SITUACAO    WITH PFUNC
            DELE
         ENDIF
         REPLACE ICMS->USU         WITH M->sUsuario        ,;
                 ICMS->OPE         WITH PFUNC              ,;
                 ICMS->EST         WITH Cript( M->ESTACAO) ,;
                 ICMS->MAQ         WITH Cript( M->MAQUINA) ,;
                 ICMS->DTA         WITH F_DT()
         //
         // Controle Transferencia
         //
         DO CASE
            CASE PARAM->TRANSFER == '1'
               REPLACE ICMS->FLAGTR1 WITH 'T'
            CASE PARAM->TRANSFER == '2'
               REPLACE ICMS->FLAGTR2 WITH 'T'
            CASE PARAM->TRANSFER == '3'
               REPLACE ICMS->FLAGTR3 WITH 'T'
         ENDCASE
         //
         COMMIT
         UNLOCK
      ENDIF
   ENDIF
   EXIT
ENDDO
//
RestScreen( 00,00,24,79,Tel_001 )
SetCursor( Cursor )
SetColor( CorAnt )
KeyBoard ' '
RETURN
*-------------------------------------------------------------------------------
Por favor... deem suas opnioes!
Abracos

Re: Para os que dormem sobre um get/read aberto

Enviado: 21 Jun 2008 19:39
por alaminojunior
O macete é não bloquear o registro para edição. Apenas permita que o gajo leia o registro em questão e atribua a variáveis os valores dos diferentes campos.
O registro só é bloqueado no instante que o cara cair fora do read.
Mas este sempre foi o procedimento correto mesmo, e sempre será: sempre editar variáveis, e nunca os campos.
E mesmo assim, no momento de travar o registro para gravar, precisa prever que outro usuário o tenha feito, por isso, uma rotina que verifique se o bloqueio foi feito ou não, e caso não, tente outras n vezes, é essencial.

Re: Para os que dormem sobre um get/read aberto

Enviado: 25 Jun 2008 09:21
por Othelo
Com certeza o procedimento é nunca travar um registro durante um get, sempre carregar os campos do DB em variaveis, edita-las e no final, somente no final fazer a atualizacao do registro, e sempre atualizar o registro sem que o usuario tenha a necessidade de intervir, caso contrario, teremos uma brecha para dar problemas :? .
o que eu fazia para encher o saco de usuarios moles que travam em cima dos get/readers era ativar uma protecao de tela, ai o usuario perdia a imagem do que estava fazendo e era obrigado a voltar ao sistema.
Ps: claro que no mesmo ponto onde ele estava :D