Bitácora de Sistema

Bitácora de Sistema

Postby jose_murugosa » Thu Aug 27, 2015 3:44 pm

Hola a todos :)

Quería pedir a Uds. sugerencias sobre como hacer para almacenar en una tabla de bitácora todos los tipos de movimientos, terminal y usuario que los realizó, tengo que hacer una modificación para implementar esto en mis aplicaciones y he estado viendo el modo, pero me pareció bueno comentarlo, y quizá recibir algun feedback de quienes ya lo han hecho, y de lo que a vuestro criterio podría ser la solución más adecuada.

Gracias desde ya :)
Saludos/Regards,
José Murugosa
FWH + Harbour + Bcc7. Una seda!
User avatar
jose_murugosa
 
Posts: 1144
Joined: Mon Feb 06, 2006 4:28 pm
Location: Uruguay

Re: Bitácora de Sistema

Postby cuatecatl82 » Thu Aug 27, 2015 4:05 pm

Jose:

Lo que hago es que cada usuario tiene un nombre y contrañesa para poder saber quien entra al sistema y hacer movimientos, cada usuario tiene ciertos niveles y privilegios a funciones dentro del sistema y permisos ya sea para crear nuevos registros, borrarlos, modificarlos o consultar en pantalla o imprimirlos:

Image

En una base de datos guardo cada acción que hacen para luego consultar, sle llamo Auditoria a Usuarios:

Ejemplo y una imagen de como lo tengo en uno de mis sistemas..
Code: Select all  Expand view

Function Auditor(cUser, cAcción,cTime,dDate)
 

Image

Es lo más facil, lo liado es poner la función en cada accion o procedimiento dentro de tu aplicación..

Espero te de una ayuda..
Soluciones y Diseño de Software
Damos Soluciones...

I.S.C. Victor Daniel Cuatecatl Leon
Director y Diseñador de Proyectos

http://www.soldisoft.unlugar.com
http://www.sisa.unlugar.com
danyleon82@hotmail.com
www.facebook.com/victordaniel.cuatecatlleon
User avatar
cuatecatl82
 
Posts: 625
Joined: Wed Mar 14, 2007 6:49 pm
Location: San Cristobal de las Casas, Chiapas México

Re: Bitácora de Sistema

Postby Compuin » Thu Aug 27, 2015 10:21 pm

Saludos

Podrian poner un ejemplo de auditar un usuario que realize una insercion de datos a una tabla?
FWH 20.12
Hbmk2 32/64 Bits (Build 19.29.30133)
Microsoft Visual C 32 Bits
MySql 8.0.24 32/64 Bits
VS Code
Compuin
 
Posts: 1213
Joined: Tue Dec 28, 2010 1:29 pm
Location: Quebec, Canada

Re: Bitácora de Sistema

Postby jose_murugosa » Fri Aug 28, 2015 10:24 am

Muy bello trabajo,

Gracias por tu ayuda, ya me ha dado algunas ideas que combinaré con otras que ya tengo, MUUUUUCHAS GRACIAS :)

Si alguien más quisiera poner su granito de harena lo agradeceré :)

Un fuerte abrazo!!
Saludos/Regards,
José Murugosa
FWH + Harbour + Bcc7. Una seda!
User avatar
jose_murugosa
 
Posts: 1144
Joined: Mon Feb 06, 2006 4:28 pm
Location: Uruguay

Re: Bitácora de Sistema

Postby joseluisysturiz » Sat Aug 29, 2015 12:15 am

Si estas usando algo diferente a MySQL, puedes hacer como lo que dice el colega, llamas una funcion al momento de agregar, modificar, elimina o hasta de imprimir datos, que en mi caso tambien la llamo bitacora de usuario y alli dependiendo de lo que haga, creo un registro que contiene..COD.USER, COD.DEL MODULO, COD.SI A.M.E.R.(Agrego,Modifico,Elimino,Reporte), FECHA y HORA. Si usas MySql, MAriaBD o algo parecido, puedes usar disparadores(trigger) en tus tablas que haga lo antes mencionado, espero te de algunas ideas, gracias, saludos... :shock:
Dios no está muerto...

Gracias a mi Dios ante todo!
User avatar
joseluisysturiz
 
Posts: 2064
Joined: Fri Jan 06, 2006 9:28 pm
Location: Guatire - Caracas - Venezuela

Re: Bitácora de Sistema

Postby FranciscoA » Sat Aug 29, 2015 5:43 pm

José, mira si estos trozos de codigo ayudan en algo. Servirían para controlar accesos desde el menú principal.
Code: Select all  Expand view

static aAMB := {}   //control niveles de acceso
static oWnd

Function Main()

DEFINE WINDOW oWnd MDI TITLE "WINC"
   oWnd:SetMenu( oMenu:=BuildMenu(oBar) ) //MENUINFO 2
ACTIVATE WINDOW oWnd MAXIMIZED
return nil


Function BuildMenu(oBar)
...
         MENUITEM "Comprobantes"
            MENU
            MENUITEM "&Grabar   "    ACTION Comprobante()  WHEN aAMB[1]
            MENUITEM "&Modificar"    ACTION Comprobante()  WHEN aAMB[2]
            MENUITEM "&Consultar"    ACTION ConsulDoc()
            MENUITEM "&Anular/Borrar   "    ACTION BorrAnulDoc()   WHEN aAMB[3]
            ENDMENU
Return nil

/----------------------------------
Function lAutorizado()
local oDlg,oBt1,oBt2, oIco, oCbx, oPw, cItems:={},cVar, cPw, lOK:=.f., lAutoriza:=.f.
LOCAL cPath:=GetPvProfString("config","DrivDirUsers",".\",cIniFile)

SET DELETED ON

dbUseArea(.t.,,cPath+"
\Usuarios","Usuarios",.t.)
usuarios->(dbgotop())

if Usuarios->(bof())  // Si no hay permisos, acceso es total por defecto.
   cUsuario:="
"
   cNombUser:="
No users"
   cPermiso:="
T"
   aAMB:={.T.,.T.,.T.}
   usuarios->(dbCloseArea())
   return .t.
endif

While Usuarios->(!eof())
  aadd(cItems,Usuarios->nombre)
  usuarios->(dbskip())
Enddo

cPw:=space(len(usuarios->codigo))
cVar:=cItems[1]
DEFINE DIALOG oDLG RESOURCE "
USUARIOS" TRANSPARENT
REDEFINE ICON oIco ID 400 OF oDlg RESOURCE "
USUARIOS"
REDEFINE SAY ID 101 OF oDlg
REDEFINE SAY ID 102 OF oDlg
REDEFINE ComboBox oCbx VAR cVar ID 103 OF oDLG ITEMS cItems ON CHANGE (oCbx:GotFocus(),oCbx:Refresh())
REDEFINE GET oPw VAR cPw ID 202 OF oDLG
REDEFINE BUTTONBMP oBt1 ID 312 OF oDLG BITMAP "
ACEPTAR"  TEXTRIGHT  ACTION (lOK:=.t.,oDlg:End())
REDEFINE BUTTONBMP oBt2 ID 313 OF oDLG BITMAP "
CANCELAR" TEXTRIGHT  ACTION (lOK:=.f.,oDlg:End())
ACTIVATE DIALOG oDlg CENTERED
if lOK
   usuarios->(dbgotop())
   locate for ALLTRIM(usuarios->codigo)+ALLTRIM(usuarios->nombre) = ALLTRIM(Encrypt(cPw,"
oleaje"))+ alltrim(cVar)
   IF found()
     if upper(Usuarios->Administ)="
T"  //acceso total
       lAutoriza:=.t.
       cUsuario:=usuarios->codigo
       cNombUser:=cVar
       cPermiso:=usuarios->administ
     elseif upper(Usuarios->Administ)<>"
T" .and. Usuarios->CONTAB=.t.
       lAutoriza:=.t.
       cUsuario:=usuarios->codigo
       cNombUser:=cVar
       cPermiso:=usuarios->administ
     elseif upper(Usuarios->Administ)<>"
T" .and. Usuarios->CONTAB !=.t.
       lAutoriza:=.f.
       MsgStop("
No tiene autorizacion para este modulo.","Alto")
     endif

     //[A]gregar,[M]odificar,[B]orrarAnular
     aAMB := {}  //static para controlar nivel de acceso
     aadd(aAMB,usuarios->Grabar)
     aadd(aAMB,usuarios->Modifi)
     aadd(aAMB,usuarios->AnuBor)

   ELSE
     MsgStop("
Acceso Denegado.","Alto")
   ENDIF
endif
usuarios->(dbCloseArea())
return lAutoriza

Saludos.
Francisco J. Alegría P.
Chinandega, Nicaragua.

Fwxh-MySql-TMySql
User avatar
FranciscoA
 
Posts: 2110
Joined: Fri Jul 18, 2008 1:24 am
Location: Chinandega, Nicaragua, C.A.

Re: Bitácora de Sistema

Postby joseluisysturiz » Sat Aug 29, 2015 7:35 pm

FranciscoA wrote:José, mira si estos trozos de codigo ayudan en algo. Servirían para controlar accesos desde el menú principal.
Code: Select all  Expand view

static aAMB := {}   //control niveles de acceso
static oWnd

Function Main()

DEFINE WINDOW oWnd MDI TITLE "WINC"
   oWnd:SetMenu( oMenu:=BuildMenu(oBar) ) //MENUINFO 2
ACTIVATE WINDOW oWnd MAXIMIZED
return nil


Function BuildMenu(oBar)
...
         MENUITEM "Comprobantes"
            MENU
            MENUITEM "&Grabar   "    ACTION Comprobante()  WHEN aAMB[1]
            MENUITEM "&Modificar"    ACTION Comprobante()  WHEN aAMB[2]
            MENUITEM "&Consultar"    ACTION ConsulDoc()
            MENUITEM "&Anular/Borrar   "    ACTION BorrAnulDoc()   WHEN aAMB[3]
            ENDMENU
Return nil

/----------------------------------
Function lAutorizado()
local oDlg,oBt1,oBt2, oIco, oCbx, oPw, cItems:={},cVar, cPw, lOK:=.f., lAutoriza:=.f.
LOCAL cPath:=GetPvProfString("config","DrivDirUsers",".\",cIniFile)

SET DELETED ON

dbUseArea(.t.,,cPath+"
\Usuarios","Usuarios",.t.)
usuarios->(dbgotop())

if Usuarios->(bof())  // Si no hay permisos, acceso es total por defecto.
   cUsuario:="
"
   cNombUser:="
No users"
   cPermiso:="
T"
   aAMB:={.T.,.T.,.T.}
   usuarios->(dbCloseArea())
   return .t.
endif

While Usuarios->(!eof())
  aadd(cItems,Usuarios->nombre)
  usuarios->(dbskip())
Enddo

cPw:=space(len(usuarios->codigo))
cVar:=cItems[1]
DEFINE DIALOG oDLG RESOURCE "
USUARIOS" TRANSPARENT
REDEFINE ICON oIco ID 400 OF oDlg RESOURCE "
USUARIOS"
REDEFINE SAY ID 101 OF oDlg
REDEFINE SAY ID 102 OF oDlg
REDEFINE ComboBox oCbx VAR cVar ID 103 OF oDLG ITEMS cItems ON CHANGE (oCbx:GotFocus(),oCbx:Refresh())
REDEFINE GET oPw VAR cPw ID 202 OF oDLG
REDEFINE BUTTONBMP oBt1 ID 312 OF oDLG BITMAP "
ACEPTAR"  TEXTRIGHT  ACTION (lOK:=.t.,oDlg:End())
REDEFINE BUTTONBMP oBt2 ID 313 OF oDLG BITMAP "
CANCELAR" TEXTRIGHT  ACTION (lOK:=.f.,oDlg:End())
ACTIVATE DIALOG oDlg CENTERED
if lOK
   usuarios->(dbgotop())
   locate for ALLTRIM(usuarios->codigo)+ALLTRIM(usuarios->nombre) = ALLTRIM(Encrypt(cPw,"
oleaje"))+ alltrim(cVar)
   IF found()
     if upper(Usuarios->Administ)="
T"  //acceso total
       lAutoriza:=.t.
       cUsuario:=usuarios->codigo
       cNombUser:=cVar
       cPermiso:=usuarios->administ
     elseif upper(Usuarios->Administ)<>"
T" .and. Usuarios->CONTAB=.t.
       lAutoriza:=.t.
       cUsuario:=usuarios->codigo
       cNombUser:=cVar
       cPermiso:=usuarios->administ
     elseif upper(Usuarios->Administ)<>"
T" .and. Usuarios->CONTAB !=.t.
       lAutoriza:=.f.
       MsgStop("
No tiene autorizacion para este modulo.","Alto")
     endif

     //[A]gregar,[M]odificar,[B]orrarAnular
     aAMB := {}  //static para controlar nivel de acceso
     aadd(aAMB,usuarios->Grabar)
     aadd(aAMB,usuarios->Modifi)
     aadd(aAMB,usuarios->AnuBor)

   ELSE
     MsgStop("
Acceso Denegado.","Alto")
   ENDIF
endif
usuarios->(dbCloseArea())
return lAutoriza

Saludos.


Francisco, aprovechando lo que publicas, por casualidad tendras la creacion del MENU pero dinamicamente, es decir, dependiendo del nivel del usuario, entonces se agreguen unas opciones y otras no, estas ya creadas en una TABLA o DBF..? gracias, saludos..

En relacion a lo que necesita el colega, es guardar las acciones del usuario durante su estadia en el sistema, algo como un diario, lo que le llamamos..BITACORA DE USUARIO...
Dios no está muerto...

Gracias a mi Dios ante todo!
User avatar
joseluisysturiz
 
Posts: 2064
Joined: Fri Jan 06, 2006 9:28 pm
Location: Guatire - Caracas - Venezuela

Re: Bitácora de Sistema

Postby FranciscoA » Sat Aug 29, 2015 11:23 pm

joseluisysturiz wrote:Francisco, aprovechando lo que publicas, por casualidad tendras la creacion del MENU pero dinamicamente, es decir, dependiendo del nivel del usuario, entonces se agreguen unas opciones y otras no, estas ya creadas en una TABLA o DBF..? gracias, saludos..


JoseLuis, mira si esto es a lo que te refieres:
En tabla usuarios estan los campos logicos: facturas,invent,etc
Despues de autorizar entrada al sistema, chequear a que modulos tiene acceso
Luego en los ItemMenus establecer la condicion

Code: Select all  Expand view
if lAutoriza
  aModulosAcc:={}    //static
    if Usuarios->facturas=.t.
      aadd(aModulosAcc,"FACTURACION")
    endif
    if Usuarios->Invent=.t.
      aadd(aModulosAcc,"INVENTARIO")
    endif
endif
Return lAutoriza

//--------------------------//Controla si tiene acceso o no a determinado modulo
Function ModuloAcces(cModulo)
local lRet:=.f., n:=0

if empty(aModulosAcc)
   Return .t.
endif
 
for n:=1 to len(aModulosAcc)
  if aModulosAcc[n] = upper(cModulo)
     lRet:=.t.
     exit
   endif
next
Return lRet
 


En la creacion del menu se puede hacer: (con esto apareceran, o no, los items del menu
Por supuesto faltaría profundizar mas por cada opcion de cada sub-item (lo he dejado por el momento)
Code: Select all  Expand view
if ModuloAcces("Facturas")
      MENUITEM "&Facturacion"
         MENU
         MENUITEM "Grabar &Facturas"
         MENUITEM "etc"
         ENDMENU
endif

if ModuloAcces("inventario")
      MENUITEM "&Inventario"
         MENU
         MENUITEM "Grabar &Entradas (Compras y otros)"
         MENUITEM "Grabar &Salidas (Salidas diversas)"
         ENDMENU
endif
 


Saludos.
Francisco J. Alegría P.
Chinandega, Nicaragua.

Fwxh-MySql-TMySql
User avatar
FranciscoA
 
Posts: 2110
Joined: Fri Jul 18, 2008 1:24 am
Location: Chinandega, Nicaragua, C.A.

Re: Bitácora de Sistema

Postby FranciscoA » Sat Aug 29, 2015 11:36 pm

JoseLuis
=En relacion a lo que necesita el colega, es guardar las acciones del usuario durante su estadia en el sistema, algo como un diario, lo que le llamamos..BITACORA DE USUARIO...


Upssssss.. "Se te fué la onda" (como decimos aqui)

José:
Efectivamente, uso una function llamada proceso() donde envío lo que hizo el usuario. Solo la uso para modificaciones o borrados.

Ejemplo, despues de comparar los datos pertinentes, si estos son diferentes hago lo siguiente:
if cDescrip <> cDescripAnter
Proceso(cNomUser+ " Hizo cambios en xxx") //cNomUser es static
endif

Code: Select all  Expand view
//------------------------
Function Proceso(cData)
local cOldSele:=Select(), cFile
local nAnoProceso:=Val(GetPvProfString("config","AnoProceso","0",cIniFile))
local cBitacora:=GetPvProfString("config","bitacora","S",cIniFile)
local cEquipo:=GetEnv("COMPUTERNAME")
local cUserWind:=GetEnv("USERNAME")
local cLogAnual

cData:=cData+"  "+Alltrim(cEquipo)+"_"+cUserWind

 if upper(cBitacora)="S"
    CrlProceso(cData,nAnoProceso)
 endif

//*******
 //limpiar Logfile cada año
 if Year(date()) <> nAnoProceso
   cLogAnual:=cExeName+Substr(STR(nAnoProceso,4),3,2)
   FRename( (cPathDef)+"\"+cExeName,(cPathDef)+"\"+cLogAnual )
   CopyFiles( {(cPathDef)+"
\"+cLogAnual},{ GetWinDir()+"\"+cLogAnual} )  //DOBLE CONTROL
   WritePProString("
config","AnoProceso",Str(Year(date())),cIniFile)
 endif

 LogFile( cExeName, {cData} )
//*******

RETURN NIL


Saludos.
Francisco J. Alegría P.
Chinandega, Nicaragua.

Fwxh-MySql-TMySql
User avatar
FranciscoA
 
Posts: 2110
Joined: Fri Jul 18, 2008 1:24 am
Location: Chinandega, Nicaragua, C.A.

Re: Bitácora de Sistema

Postby FranciscoA » Sat Aug 29, 2015 11:40 pm

José, se me quedaba la funcion:
Code: Select all  Expand view
//---------------------------Escribir en un fichero txt
Function CrlProceso(cCadena,nAnoProceso)
local cFile := (cPathDef)+"\Bitaco.txt", nHand, cBitacAno
local cCad:=Dtoc(date())+" "+time()+": "+cCadena
local FO_READWRITE:=2, FO_SHARED:=64 , FS_END:=2     //Fileio.ch

 //limpiar Bitacora cada año
if Year(date()) <> nAnoProceso
   cBitacAno:="BITC"+substr(STR(nAnoProceso,4),3,2)
   CopyFiles( {cFile},{(cPathDef)+"\"+cBitacAno+".txt"} )
   Ferase(cFile)
   WritePProString("
config","AnoProceso",Str(Year(date())),cIniFile)
endif

if !file(cFile)
  nHand := FCreate( cFile )       // creamos el archivo
  FWrite(nHand, cCad + CRLF+"
")   // escribimos en el archivo
  FClose(nHand)                   // cerramos el fichero
else
  nHand := FOpen( cFile, FO_READWRITE + FO_SHARED ) // abrimos  el fichero lect-escrit-compartido
  FSeek(nHand, 0, FS_END)  // nos colocamos al final del fichero
  FWrite(nHand, cCad + CRLF+"
")      // escribimos en el fichero
  FClose(nHand)            // cerramos el fichero
endif

  //WinExec("
NotePad.exe "+cFile)  
  SysRefresh()
Return nil

Saludos.
Last edited by FranciscoA on Sun Aug 30, 2015 2:34 pm, edited 1 time in total.
Francisco J. Alegría P.
Chinandega, Nicaragua.

Fwxh-MySql-TMySql
User avatar
FranciscoA
 
Posts: 2110
Joined: Fri Jul 18, 2008 1:24 am
Location: Chinandega, Nicaragua, C.A.

Re: Bitácora de Sistema

Postby joseluisysturiz » Sun Aug 30, 2015 1:02 am

Francisco, revisare lo del los menu, lo mas importante es como dices, que active o no los sub-menu, estoy pensando en hacer algo como un TREE que las principales sean los titulos del menu y las ramas..cada sub-menu y al final le hacerle un check de activar o no al igual q las cabezeras, si la cabezera tien false..entonces no activo los sub-menu, crei seria algo sencillo y practico...lo que me tiene un poco perdido es crear las cabezeras y sub-menus dinamicamente desde un array que lo cargaria desde la tabla o dbf, si termino algo lo camparto haber si lo vamos mejorando para todos...o si alguien tiene algo que quiera compartir...sera bien recibido..gracias..saludos... :shock:
Dios no está muerto...

Gracias a mi Dios ante todo!
User avatar
joseluisysturiz
 
Posts: 2064
Joined: Fri Jan 06, 2006 9:28 pm
Location: Guatire - Caracas - Venezuela

Re: Bitácora de Sistema

Postby russimicro » Sun Aug 30, 2015 4:02 pm

Code: Select all  Expand view


Creación menu en forma dinámica desde una tabla

estructura de la tabla menu.dbf

- ccodigousu = código del usuario para filtrar su menu
- ccodigomen (character 20)= código del menu en estructura tipo árbol :  
     primer nivel 01,02,03,etc
        segundo nivel 0101, 0102,0103... etc
            tercer nivel  010101, 010102,010103...etc
- cnombremen = nombre de la opción del menu
- lActOpcMen (lógico)= activa o desactiva opción del menu para el usuario filtrado
 - cFunEjeMen = function a ejecturar según opcion

// el llamado desde la window principal
DEFINE WINDOW oWnd FROM 0, 0 TO 46, 128                           ;
      TITLE HB_OEMTOANSI("ZERUS. Sistema de Gesti¢n Empresarial")    ;
      BRUSH oBrush                                                   ;
      ICON oIco                                                      ;
      MENU  MenuPrincipal(oWnd)                                      ;
      MENUINFO 3                                                     ;
      MDI


FUNCTION MenuPrincipal(oWnd,cCodUsu)

   LOCAL cAliAct := ALIAS()

   //INDEX ON CCODIGOMEN TAG ORDER1 TO &(cPatSis+"\menu.cdx")
lUsaTab(cPatSis+"\", 'MENU.Dbf','MEN','MENU.CDX',.F.,NIL,'DBFCDX')

   SET FILTER TO MEN->cCodigoUsu == cCodUsu

   SELECT MEN
   DBSETORDER(1)
   GO TOP

   MENU oMenu 2007

       DO WHILE MEN->( !EOF() )

          HB_IDLESTATE()

          IF MEN->lActOpcMen
             MENUITEM HB_OEMTOANSI( ALLTRIM(MEN->cNombreMen) )
          ELSE
             MENUITEM HB_OEMTOANSI( ALLTRIM(MEN->cNombreMen) ) DISABLED
          ENDIF

          MENU
              MENUX(1)
          ENDMENU

       ENDDO

   ENDMENU

RETURN


//**************************************************************************************

FUNCTION MENUX( nNroNiv )

   LOCAL bBloEje, nNivAct

   nNivAct := SUBS( MEN->cCodigoMen, 1, nNroNiv * 2 )
   DO WHILE MEN->( !EOF() ) .AND. SUBS( MEN->cCodigoMen,1,nNroNiv * 2 ) == nNivAct

      IF LEN(ALLTRIM(MEN->cCodigoMen)) > nNroNiv * 2
         cFunEje := MEN->cFunEjeMen
         cNomOpc := HB_OEMTOANSI(MEN->cNombreMen)
         cRegAct := ALLTRIM(MEN->cCodigoMen)

         MEN->( DBSKIP() )
         cRegSig := SUBS( MEN->cCodigoMen,1,( nNroNiv + 1 ) * 2 )

         IF cRegAct == cRegSig

            IF MEN->lActOpcMen  // cRegAct
               MENUITEM ( ALLTRIM(cNomOpc) )
            ELSE
               MENUITEM ( ALLTRIM(cNomOpc) ) DISABLED
            ENDIF

            SELECT MEN
            SKIP -1
            MENU
              MenuX( nNroNiv + 1 )
            ENDMENU

         ELSE

            bBloEje := &( "
{||" + IF( EMPTY( cFunEje ), ".T.", ALLTRIM( cFunEje ) ) + "}" )

            IF MEN->lActOpcMen
               MENUITEM ( ALLTRIM(cNomOpc) ) ACTION ( bBloEje )  BLOCK bBloEje
            ELSE
               MENUITEM ( ALLTRIM(cNomOpc) ) DISABLED ACTION ( bBloEje )  BLOCK bBloEje
            ENDIF

         ENDIF
      ELSE
         MEN->( DBSKIP() )
      ENDIF

   ENDDO

RETURN  NIL


johnson russi

russimicro
 
Posts: 225
Joined: Sun Jan 31, 2010 3:30 pm
Location: Bucaramanga - Colombia

Re: Bitácora de Sistema

Postby jose_murugosa » Mon Aug 31, 2015 11:21 pm

muchas muchas gracias por sus ideas y aportes.. los comenzaré a analizar y luego les cuento como va quedando .. :) muy amables todos!!!!
Realmente me estan ayudando mucho!!

Saludos,
Saludos/Regards,
José Murugosa
FWH + Harbour + Bcc7. Una seda!
User avatar
jose_murugosa
 
Posts: 1144
Joined: Mon Feb 06, 2006 4:28 pm
Location: Uruguay


Return to FiveWin para Harbour/xHarbour

Who is online

Users browsing this forum: No registered users and 96 guests