FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin para Harbour/xHarbour Pregunta o solicitud para FiveTech IA.
Posts: 8716
Joined: Tue Dec 20, 2005 07:36 PM

Pregunta o solicitud para FiveTech IA.

Posted: Sat Sep 26, 2026 06:51 PM

Estimado FiveTech AI, ¿podrías detectar los errores que cometí en este módulo (.PRG) diseñado para controlar los boxes o habitaciones destinados al alojamiento de caninos y felinos? Agradecido de antemano.

// MODULO: CAD_BAIA.PRG

#Include "Fivewin.Ch" // TODOS ESTES INCLUDES, ESTÃO EM UM UNICO ARQUIVO.CH
#Include "Objects.Ch"
#Include "Colores.ch"
#Include "Colors2.ch"
#Include "AnimaBmp.Ch"
#Include "dbinfo.ch"
#Include "Dll.ch"
#Include "Struct.ch"
#Include "dtpicker.ch"
#Include "Directry.ch"
#Include "DSay.Ch"
#include "Fileio.ch"
#Include "GIF.Ch"
#Include "Image.ch"
#Include "Mail.Ch"
#Include "Ord.Ch"
#Include "Report.Ch"
#Include "SSay.Ch"
#Include "URLLink.ch"
#Include "xBrowse.ch"
#Include "hbcompat.ch"
#include "winapi.ch"
#include "XBrowse.ch"
#Include "FGet.ch" 

FUNCTION Cad_Baia()

   LOCAL oEditarF, oEditarT, oExcluir, oImprimir, oPrioriza, oSaida, iDcor
   LOCAL oDlg, oBrw, oFont, oFontBold, oIco, oLimpar, oInfo
   LOCAL oRadio, oCmbPorte, oGetBusca
   LOCAL nFiltroStatus := 1  // 1=Todas, 2=Livres, 3=Ocupadas, 4=Manutencao
   LOCAL cPorte  := "TODOS"
   LOCAL cBusca  := Space( 30 )
   LOCAL aPortes := { "TODOS", "PEQUENO", "MEDIO", "GRANDE", "GIGANTE" }

   // Verifica e cria DBF nativo e indices caso nao existam
   CriaDbfBaias()

   // Abertura nativa compartilhada
   USE BAIAS INDEX BAIAS SHARED NEW ALIAS BAIAS

   IF !File( "BAIAS.CDX" )
      CriaIndices()
   ENDIF

   SET INDEX TO BAIAS
   SET ORDER TO TAG NUMERO

   DBGOTOP()

   DEFINE FONT oFont     NAME "Segoe UI" SIZE 0, -12 BOLD
   DEFINE FONT oFontBold NAME "Segoe UI" SIZE 0, -14 BOLD
   DEFINE ICON oIco      RESOURCE "ICONE01"  // EM IMAGENS.RES

   // Carrega a Dialog Principal desenhada no Borland Workshop
   DEFINE DIALOG oDlg RESOURCE "DLG_BAIAS_MAIN" ICON oIco                    ;
      TITLE "Controle de Baias / Boxes / Quartos - Hospedagem PetShop"

   oDlg:lHelpIcon := .F.

   REDEFINE GROUP oGroup ID 501 OF oDlg COLOR METRO_TURQUE, METRO_ORANGE FONT oFont TRANSPARENT

   For iDcor=401 to 402
      REDEFINE SAY ID iDcor OF oDlg ;
         COLOR METRO_TURQUE, CLR_WHITE UPDATE FONT oFont TRANSPARENT
   Next iDcor // By Ednaldo Rolim - Yes!

   // -------------------------------------------------------------------------
   // 1. CONTROLES DE FILTRO RAPIDO (TOPO DA TELA)
   // -------------------------------------------------------------------------
   REDEFINE RADIO oRadio VAR nFiltroStatus ID 201, 202, 203, 204 OF oDlg ;
      ON CHANGE ( AplicaFiltro( nFiltroStatus, cPorte, oBrw ) )

   oRadio:SetFont( oFont )

   oRadio:aItems[1]:cTooltip := "Por Todas "
   oRadio:aItems[2]:cTooltip := "Por Livres"
   oRadio:aItems[3]:cTooltip := "Por Ocupadass "
   oRadio:aItems[4]:cTooltip := "Por Manutenção"

   REDEFINE COMBOBOX oCmbPorte VAR cPorte ITEMS aPortes ID 205 OF oDlg ;
      ON CHANGE ( AplicaFiltro( nFiltroStatus, cPorte, oBrw ) )

   oCmbPorte:SetFont( oFont )

   REDEFINE GET oGetBusca VAR cBusca ID 206 OF oDlg                    ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE                    ;
      VALID ( BuscaRapida( cBusca, oBrw ), .T. )

   oGetBusca:cToolTip := "Busca as Baias"

   REDEFINE BUTTON oLimpar ID 207 OF oDlg ;
      ACTION ( LimparFiltros( oRadio, oCmbPorte, oGetBusca, oBrw, @nFiltroStatus, @cPorte, @cBusca ) )

   SET FONT OF oLimpar TO oFontBold

   REDEFINE BUTTON oInfo ID 208 OF oDlg ;
      ACTION MsgInfo( "DICAS DO CADASTRO DE BAIAS:" + CRLF + CRLF + ;
                      "- Clique nos Radios para filtrar Livres/Ocupadas instantaneamente." + CRLF + ;
                      "- 'Livres 1' reordena trazendo as vagas livres para o topo." + CRLF + ;
                      "- Duplo-Clique ou ENTER altera a baia selecionada." + CRLF + ;
                      "- Tecla INSERT inclui nova baia / Tecla DELETE exclui." + CRLF + ;
                      "- Banco de dados 100% nativo DBF/CDX.", "Ajuda do Sistema" )

   SET FONT OF oInfo TO oFontBold

   // -------------------------------------------------------------------------
   // 2. CONFIGURACAO DO XBROWSE VINCULADO AO RECURSO ID 101 DO WORKSHOP
   // -------------------------------------------------------------------------
   REDEFINE XBROWSE oBrw ID 101 OF oDlg ;
      COLUMNS "NUMERO", "DESCRICAO", "ESPECIE", "TAMANHO", "STATUS", "VALOR_DIA", "PET_NOME", "TUTOR" ;
      HEADERS "Baia/Box:", "Identificação / Nome:", "Espécie:", "Porte Pet:", "Status:", "Diária R$:", "Pet Hospedado:", "Tutor / Fone:" ;
      SIZES 90, 220, 90, 90, 120, 120, 120, 500 ;
      JUSTIFY AL_CENTER, AL_LEFT, AL_LEFT, AL_LEFT, AL_CENTER, AL_RIGHT, AL_LEFT, AL_LEFT ;
      ALIAS "BAIAS" AUTOSORT LINES CELL

WITH OBJECT oBrw

  // Configuração Básica
  :nMarqueeStyle := MARQSTYLE_HIGHLROW // Ou MARQSTYLE_HIGHLWIN7
  :nColDividerStyle := LINESTYLE_LIGHTGRAY
  :nRowDividerStyle := LINESTYLE_LIGHTGRAY
  :lHScroll         := .T.
  :lVScroll         := .T.
  :lRecordSelector  := .T.

  // Efeito Zebrado (Linhas Normais)
  // Usamos OrdKeyNo() para contar a posição lógica no índice - COLORS2.CH
  :bClrStd := { || { CLR_BLACK, IF( OrdKeyNo() % 2 == 0, CLR_BLUE_LIGHT, CLR_BLUE_LIGHT_CYAN ) } }

  // Efeito ao Selecionar (Foco) CLR_MSPURPLE  nRGB( 000, 120, 215 ) //-> Purpura.
  // Mantém a cor da fonte branca e fundo azul escuro
  :bClrSel := { || { CLR_WHITE, CLR_MSPURPLE } }

  // Opcional: Efeito ao Selecionar sem Foco
  :bClrSelFocus := { || { CLR_BLACK, CLR_DARK_TEXT } } // COLORS2.CH

   END

   // Formatacao da coluna de Status com Cores e Nomes Amigaveis
   WITH OBJECT oBrw:oCol( "Status" )

  :bStrData := { || IF( BAIAS->STATUS == "L", "LIVRE", ;
                    IF( BAIAS->STATUS == "O", "OCUPADO", "MANUTENÇÃO" ) ) }

  :bClrStd  := { || { IF( BAIAS->STATUS == "L", CLR_DGREEN, ;
                      IF( BAIAS->STATUS == "O", CLR_DRED, CLR_DORANGE ) ), ;
                      IF( BAIAS->STATUS == "L", CLR_LGREEN, ;
                      IF( BAIAS->STATUS == "O", CLR_LRED, CLR_LYELLOW ) ) } }

   END

   // Formatacao de Valor de Diaria
   WITH OBJECT oBrw:oCol( "Diária R$:" )
      :cEditPicture := "@E 9,999.99"
   END

   // Totalizadores no rodape do XBrowse
   oBrw:lFooter := .T.
   oBrw:aCols[ 1 ]:bFooter := { || "Total: " + AllTrim( Str( ContarBaias( "T" ) ) ) }
   oBrw:aCols[ 2 ]:bFooter := { || "Livres: " + AllTrim( Str( ContarBaias( "L" ) ) ) + ;
                                   " | Ocupadas: " + AllTrim( Str( ContarBaias( "O" ) ) ) + ;
                                   " | Manut: " + AllTrim( Str( ContarBaias( "M" ) ) ) }

   // Acoes de teclado e mouse
   oBrw:bLDblClick := { || BaiaEditar( .F., oBrw ) }
   oBrw:bKeyDown   := { | nKey | IF( nKey == VK_RETURN, ( BaiaEditar( .F., oBrw ), 0 ), ;
                                 IF( nKey == VK_INSERT, ( BaiaEditar( .T., oBrw ), 0 ), ;
                                 IF( nKey == VK_DELETE, ( BaiaExcluir( oBrw ), 0 ), NIL ) ) ) }

   // -------------------------------------------------------------------------
   // 3. BOTOES DE ACAO INFERIORES (CRUD + IMPRIMIR + SAIDA)
   // -------------------------------------------------------------------------
   REDEFINE BUTTON oEditarT  ID 301 OF oDlg ;
      ACTION ( BaiaEditar( .T., oBrw ), oBrw:SetFocus() )

   oEditarT:cToolTip := "Editar/Incluir Baias"

   REDEFINE BUTTON oEditarF ID 302 OF oDlg ;
      ACTION ( BaiaEditar( .F., oBrw ), oBrw:SetFocus() )

   oEditarF:cToolTip := "Editar/Alterar Baias"

   REDEFINE BUTTON oExcluir ID 303 OF oDlg ;
      ACTION ( BaiaExcluir( oBrw ), oBrw:SetFocus() )

   oExcluir:cToolTip := "Excluir Baias"

   REDEFINE BUTTON oImprimir ID 304 OF oDlg WHEN( .F. ) ;
      ACTION ( BaiaImprimir( oBrw ), oBrw:SetFocus() )

   oImprimir:cToolTip := "Imprimir o Cadastro de Baias"

   REDEFINE BUTTON oPrioriza ID 305 OF oDlg ;
      ACTION ( PriorizaLivres( oBrw ), oBrw:SetFocus() )

   oPrioriza:cToolTip := "Refresh() Geral nas baias Livres"

   REDEFINE BUTTON oSaida ID 306 OF oDlg ACTION oDlg:End() CANCEL

   oSaida:cToolTip := "Saida - Exit - Cancelar"

   SET FONT OF oEditarT  TO oFontBold
   SET FONT OF oEditarF  TO oFontBold
   SET FONT OF oExcluir  TO oFontBold
   SET FONT OF oImprimir TO oFontBold
   SET FONT OF oPrioriza TO oFontBold
   SET FONT OF oSaida    TO oFontBold

   // ACTIVATE DIALOG oDlg CENTERED ON INIT( oBrw:SetFocus() )
   ACTIVATE DIALOG oDlg ON INIT( CTRLS_COLORS( oDlg ), oBrw:SetFocus() )

   // Encerramento ordenado
   RELEASE FONT oFont, oFontBold

   CLOSE BAIAS

RETURN NIL
// ----------------------------------------------------------------------------
// APLICACAO DE FILTROS NATIVOS (STATUS + PORTE DO PET)
// ----------------------------------------------------------------------------
STATIC FUNCTION AplicaFiltro( nOpcStatus, cPorte, oBrw )

   LOCAL cFiltro := ""

   IF nOpcStatus == 2       // Livres
      cFiltro := 'STATUS == "L"'
   ELSEIF nOpcStatus == 3   // Ocupadas
      cFiltro := 'STATUS == "O"'
   ELSEIF nOpcStatus == 4   // Manutencao
      cFiltro := 'STATUS == "M"'
   ENDIF

   IF !Empty( cPorte ) .AND. AllTrim( cPorte ) != "TODOS"

  IF !Empty( cFiltro )
     cFiltro += ' .AND. '
  ENDIF

  cFiltro += 'AllTrim( Upper( TAMANHO ) ) == "' + ALLTRIM( UPPER( cPorte ) ) + '"'

   ENDIF

   IF Empty( cFiltro )

  DbClearFilter()

   ELSE

  SET FILTER TO &cFiltro

   ENDIF

   DBGOTOP()

   oBrw:Refresh()

RETURN NIL
// ----------------------------------------------------------------------------
// LIMPEZA GERAL DE FILTROS E PESQUISAS
// ----------------------------------------------------------------------------
STATIC FUNCTION LimparFiltros( oRadio, oCmbPorte, oGetBusca, oBrw, nFiltroStatus, cPorte, cBusca )

   nFiltroStatus := 1

   oRadio:SetOption( 1 )

   cPorte := "TODOS"

   oCmbPorte:Set( 1 )

   cBusca := Space( 30 )

   oGetBusca:Refresh()

   DbClearFilter()

   SET ORDER TO TAG NUMERO

   DBGOTOP()

   oBrw:Refresh()
   oBrw:SetFocus()

RETURN NIL
// ----------------------------------------------------------------------------
// BUSCA RAPIDA INCREMENTAL / NATIVA
// ----------------------------------------------------------------------------
STATIC FUNCTION BuscaRapida( cTexto, oBrw )

   LOCAL cTermo := Upper( AllTrim( cTexto ) )

   IF Empty( cTermo )

  DBGOTOP()

  oBrw:Refresh()

  RETURN NIL

   ENDIF

   // Se for codigo numerico, pesquisa no indice de codigo
   IF IsDigit( Left( cTermo, 1 ) )

  SET ORDER TO TAG NUMERO

  SEEK PadR( cTermo, 6 )

  IF !Found()

     SEEK cTermo

  ENDIF

   ELSE

  // Pesquisa por nome / descricao

  SET ORDER TO TAG DESCR

  SEEK cTermo

   ENDIF

   oBrw:Refresh()

RETURN NIL
// ----------------------------------------------------------------------------
// ORDENACAO: LIVRES PRIMEIRO (SEM ESCONDER OS DEMAIS)
// ----------------------------------------------------------------------------
STATIC FUNCTION PriorizaLivres( oBrw )

   SET ORDER TO TAG STATUSNUM

   DBGOTOP()

   oBrw:Refresh()

   MsgInfo( "As baias livres foram posicionadas no topo da lista!", ;
            "Organizacao Rapida" )

RETURN NIL
// ----------------------------------------------------------------------------
// TELA DE EDICAO (INCLUSAO E ALTERACAO) VIA RECURSO DO WORKSHOP
// ----------------------------------------------------------------------------
STATIC FUNCTION BaiaEditar( lInclusao, oBrw )

   LOCAL oDlgEd, oNum, oDesc, oCmbEsp, oCmbTam, oCmbSt, oVal, oPet, oTut, oObs
   LOCAL oObs2, oObs3, oObs4, oObs5, oObs6
   LOCAL oBtnGravar, oBtnCancelar, nNum, oGroup, oGroup2, oFnt, oFont, oIco
   LOCAL cNum     // := Space( 6 )
   LOCAL cDesc    // := Space( 35 )
   LOCAL cEsp     // := "AMBOS"
   LOCAL cTam     // := "MEDIO"
   LOCAL cStCombo // := "L - LIVRE"
   LOCAL nVal     // := 70.00
   LOCAL cPet     // := Space( 25 )
   LOCAL cTut     // := Space( 30 )
   LOCAL cObs, cObs2, cObs3, cObs4, cObs5, cObs6
   LOCAL lSalvo    := .F.
   LOCAL aEspecies := { "AMBOS", "CAO", "GATO" }
   LOCAL aTamanhos := { "PEQUENO", "MEDIO", "GRANDE", "GIGANTE", "TODOS" }
   LOCAL aStatus   := { "L - LIVRE", "O - OCUPADO", "M - MANUTENCAO" }

   IF( .NOT. lInclusao ) // alteracao

  IF BAIAS->( Eof() )

     MsgAlert( "não há registro selecionado para Alteração!", "Atenção" )

     RETURN NIL

  ENDIF

  // Carrega dados nativos do DBF atual
  cNum  := BAIAS->NUMERO
  cDesc := BAIAS->DESCRICAO
  cEsp  := Upper( AllTrim( BAIAS->ESPECIE ) )
  cTam  := Upper( AllTrim( BAIAS->TAMANHO ) )
  nVal  := BAIAS->VALOR_DIA
  cPet  := BAIAS->PET_NOME
  cTut  := BAIAS->TUTOR

  cObs  := BAIAS->OBS
  cObs2 := BAIAS->OBS2
  cObs3 := BAIAS->OBS3
  cObs4 := BAIAS->OBS4
  cObs5 := BAIAS->OBS5
  cObs6 := BAIAS->OBS6

  IF BAIAS->STATUS == "L"

     cStCombo := "L - LIVRE"

  ELSEIF BAIAS->STATUS == "O"

     cStCombo := "O - OCUPADO"

  ELSE

     cStCombo := "M - MANUTENCAO"

  ENDIF

   ELSE // inclusao

  cNum      := 0 //Space( 6 ) PASSEI A NUMERICO

  GO BOTTOM

  nNum  := ( BAIAS->NUMERO ) + 1
  cNum  := nNum

  cDesc     := Space( 35 )
  cEsp      := "AMBOS"
  cTam      := "MEDIO"
  cStCombo  := "L - LIVRE"
  nVal      := 0 // 70.00
  cPet      := Space( 25 )
  cTut      := Space( 30 )
  cObs      := Space( 50 )
  cOBS2     := Space( 50 )
  cOBS3     := Space( 50 )
  cOBS4     := Space( 50 )
  cOBS5     := Space( 50 )
  cOBS6     := Space( 50 )

  GO TOP

   ENDIF

   DEFINE FONT oFnt  NAME "Ms Sans Serif" SIZE 0, -12 BOLD
   DEFINE FONT oFont NAME "Ms Sans Serif" SIZE 0, -14 BOLD
   DEFINE ICON oIco   RESOURCE "ICONE01"  // EM IMAGENS.RES

   DEFINE DIALOG oDlgEd RESOURCE "DLG_CADASTRO_BAIA" ICON oIco ;
      TITLE IF( lInclusao, "Inclusao de Baia / Box / Quarto",  ;
                           "Alteracao de Baia / Box / Quarto" )

   oDlgEd:lHelpIcon := .F.

   REDEFINE GROUP oGroup  ID 501 OF oDlgEd COLOR METRO_TURQUE, CLR_WHITE FONT oFnt TRANSPARENT
   REDEFINE GROUP oGroup2 ID 502 OF oDlgEd COLOR METRO_TURQUE, CLR_WHITE FONT oFnt TRANSPARENT

   For iDcor=401 to 409
      REDEFINE SAY ID iDcor OF oDlgEd ;
         COLOR METRO_TURQUE, CLR_WHITE UPDATE FONT oFont TRANSPARENT
   Next iDcor // By Ednaldo Rolim - Yes!

   // Controles mapeados aos IDs da DLG_CADASTRO_BAIA do Workshop
   REDEFINE GET oNum VAR cNum ID 111 OF oDlgEd PICTURE "@K 999999"           ;
      WHEN( lInclusao ) FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE        ;
      VALID( VERIFICA_NUM_BAIA( lInclusao, cNum ) )

   REDEFINE GET oDesc VAR cDesc ID 112 OF oDlgEd PICTURE "@!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE COMBOBOX oCmbEsp VAR cEsp ITEMS aEspecies ID 113 OF oDlgEd

   oCmbEsp:SetFont( oFont )

   REDEFINE COMBOBOX oCmbTam VAR cTam ITEMS aTamanhos ID 114 OF oDlgEd

   oCmbTam:SetFont( oFont )

   REDEFINE COMBOBOX oCmbSt  VAR cStCombo ITEMS aStatus ID 115 OF oDlgEd

   oCmbSt:SetFont( oFont )

   REDEFINE GET oVal VAR nVal   ID 116 OF oDlgEd PICTURE "@KE 99,999.99" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE GET oPet VAR cPet   ID 117 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE GET oTut VAR cTut   ID 118 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE GET oObs VAR cObs   ID 119 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE GET oObs2 VAR cObs2 ID 120 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE GET oObs3 VAR cObs3 ID 121 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE GET oObs4 VAR cObs4 ID 122 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE GET oObs5 VAR cObs5 ID 123 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE GET oObs6 VAR cObs6 ID 124 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   // Botoes de Acao da Dialog de Edicao
   REDEFINE BUTTON oBtnGravar ID 301 OF oDlgEd ;
      ACTION ( lSalvo := BaiaGravar( lInclusao, cNum, cDesc, cEsp, cTam, Left( cStCombo, 1 ), ;
               nVal, cPet, cTut, cObs, cObs2, cObs3, cObs4, cObs5, cObs6, oDlgEd, oBrw ) )

   REDEFINE BUTTON oBtnCancelar ID 302 OF oDlgEd ACTION oDlgEd:End() CANCEL

   SET FONT OF oBtnGravar   TO oFont
   SET FONT OF oBtnCancelar TO oFont

   ACTIVATE DIALOG oDlgEd CENTERED ON INIT( CTRLS_COLORS( oDlgEd ) ) // FUNCOES.PRG

RETURN NIL

FUNCTION VERIFICA_NUM_BAIA( lInclusao, nNumBaia )

   IF lInclusao

  // Validacao nativa com SEEK para evitar duplicidade de codigo
  SET ORDER TO TAG NUMERO
  DBSEEK( nNumBaia )

  IF FOUND()

     MsgStop( "já existe uma baia cadastrada com o numero: " + STR( nNumBaia ), "Atenção" )

     RETURN( .F. )

  ENDIF

   ENDIF

RETURN( .T. )
// ----------------------------------------------------------------------------
// GRAVACAO NATIVA NO BANCO DBF
// ----------------------------------------------------------------------------
STATIC FUNCTION BaiaGravar( lInclusao, cNum, cDesc, cEsp, cTam, cStatus,     ;
                                       nVal, cPet, cTut, cObs, cObs2, cObs3, ;
                                       cObs4, cObs5, cObs6, oDlgEd, oBrw )

   IF Empty( cNum )

  MsgStop( "O codigo/numero da baia e obrigatorio!", "Aviso" )

  RETURN( .F. )

   ENDIF

   IF Empty( cDesc )

  MsgStop( "A descricao/identificacao da baia e obrigatoria!", "Aviso" )

  RETURN( .F. )

   ENDIF

   IF lInclusao

  // Validacao nativa com SEEK para evitar duplicidade de codigo
  SET ORDER TO TAG NUMERO
  DBSEEK( cNum )

  IF Found()

     MsgStop( "já existe uma baia cadastrada com o numero: " + STR( cNum ), "Atenção" )

     RETURN( .F. )

  ENDIF

  // Comando nativo de inclusao
  APPEND BLANK

  IF NetErr()

     MsgStop( "Falha de rede ao incluir o registro!", "Erro de Gravação" )

     RETURN( .F. )

  ENDIF

   ELSE

  // Bloqueio seguro para alteracao em rede
  IF !RLock()

     MsgStop( "O registro esta sendo editado por outro usuario na rede!", "Bloqueio" )

     RETURN( .F. )

  ENDIF

   ENDIF

   // Gravacao nativa campo a campo
   REPLACE FIELD->NUMERO    WITH cNum,            ;
           FIELD->DESCRICAO WITH cDesc,           ;
           FIELD->ESPECIE   WITH cEsp,            ;
           FIELD->TAMANHO   WITH cTam,            ;
           FIELD->STATUS    WITH cStatus,         ;
           FIELD->VALOR_DIA WITH nVal,            ;
           FIELD->PET_NOME  WITH cPet,            ;
           FIELD->TUTOR     WITH cTut,            ;
           FIELD->OBS       WITH cObs,            ;
           FIELD->OBS2      WITH cObs2,           ;
           FIELD->OBS3      WITH cObs3,           ;
           FIELD->OBS4      WITH cObs4,           ;
           FIELD->OBS5      WITH cObs5,           ;
           FIELD->OBS6      WITH cObs6

   DBUNLOCK()
   DBCOMMIT()

   GRAVACAO_EFETUADA_COM_SUCESSO()

   oBrw:Refresh()
   oDlgEd:End()

RETURN .T.
// ----------------------------------------------------------------------------
// EXCLUSAO NATIVA DE REGISTRO
// ----------------------------------------------------------------------------
STATIC FUNCTION BaiaExcluir( oBrw )

   IF BAIAS->( Eof() )

  MsgAlert( "Nenhum registro selecionado para exclusao!", "Aviso" )

  RETURN NIL

   ENDIF

   IF MsgNoYes( "Deseja realmente excluir a Baia: " + AllTrim( BAIAS->NUMERO ) + ;
                " (" + AllTrim( BAIAS->DESCRICAO ) + ")?", "Confirmacao de Exclusao" )

  IF RLock()

     DELETE

     DBUNLOCK()
     DBCOMMIT()

     DBSKIP( 1 )

     IF Eof()
        DBGOBOTTOM()
     ENDIF

     oBrw:Refresh()

     MsgInfo( "Baia excluida com sucesso!", "Operacao Concluida" )

  ELSE

     MsgStop( "Registro travado na rede. Nao foi possivel excluir agora.", "Erro" )

  ENDIF

   ENDIF

RETURN NIL
// ----------------------------------------------------------------------------
// IMPRESSAO DO RELATORIO DE BAIAS E OCUPACAO VIA TPRINTER / PREVIEW
// ----------------------------------------------------------------------------
STATIC FUNCTION BaiaImprimir( oBrw )

   LOCAL oPrn, oFontTit, oFontCab, oFontSub, oFontDet, oFontTot
   LOCAL nLinha := 1.0
   LOCAL nRecAtual := BAIAS->( RecNo() )
   LOCAL nTotBaias := 0, nTotLivres := 0, nTotOcup := 0, nTotManut := 0

   PRINT oPrn NAME "Relatorio de Baias e Quartos - PetShop" PREVIEW

  DEFINE FONT oFontTit NAME "Arial" SIZE 0, -14 BOLD OF oPrn
  DEFINE FONT oFontSub NAME "Arial" SIZE 0, -10 OF oPrn
  DEFINE FONT oFontCab NAME "Courier New" SIZE 0, -10 BOLD OF oPrn
  DEFINE FONT oFontDet NAME "Courier New" SIZE 0, -9 OF oPrn
  DEFINE FONT oFontTot NAME "Courier New" SIZE 0, -10 BOLD OF oPrn

  PAGE
     // Cabecalho
     oPrn:Say( nLinha, 1.0, "PETSHOP HOTEL & HOSPEDAGEM - CONTROLE DE BAIAS/BOXES", oFontTit )
     nLinha += 0.5
     oPrn:Say( nLinha, 1.0, "Emissao: " + DToC( Date() ) + " as " + Time() + " | Filtro Atual: Ativo", oFontSub )
     nLinha += 0.5

     oPrn:Say( nLinha, 1.0, Replicate( "=", 110 ), oFontCab )
     nLinha += 0.4
     oPrn:Say( nLinha, 1.0, "NUM    IDENTIFICACAO/NOME           ESPECIE   PORTE     STATUS     DIARIA R$  PET HOSPEDADO / TUTOR", oFontCab )
     nLinha += 0.35
     oPrn:Say( nLinha, 1.0, Replicate( "-", 110 ), oFontCab )
     nLinha += 0.45

     BAIAS->( DBGOTOP() )

     DO WHILE !BAIAS->( Eof() )

        IF !Deleted()

           nTotBaias++

           IF BAIAS->STATUS == "L"
              nTotLivres++
           ELSEIF BAIAS->STATUS == "O"
              nTotOcup++
           ELSE
              nTotManut++
           ENDIF

           oPrn:Say( nLinha, 1.0,  BAIAS->NUMERO, oFontDet )
           oPrn:Say( nLinha, 1.8,  Left( BAIAS->DESCRICAO, 28 ), oFontDet )
           oPrn:Say( nLinha, 4.6,  Left( BAIAS->ESPECIE, 8 ), oFontDet )
           oPrn:Say( nLinha, 5.6,  Left( BAIAS->TAMANHO, 9 ), oFontDet )
           oPrn:Say( nLinha, 6.7,  IF( BAIAS->STATUS == "L", "LIVRE", IF( BAIAS->STATUS == "O", "OCUPADO", "MANUT." ) ), oFontDet )
           oPrn:Say( nLinha, 7.8,  Transform( BAIAS->VALOR_DIA, "@E 9,999.99" ), oFontDet )
           oPrn:Say( nLinha, 9.0,  AllTrim( BAIAS->PET_NOME ) + IF( !Empty( BAIAS->TUTOR ), " (" + AllTrim( BAIAS->TUTOR ) + ")", "" ), oFontDet )

           nLinha += 0.40

           // Quebra de pagina se ultrapassar limite
           IF nLinha > 26.5

              oPrn:EndPage()

              oPrn:StartPage()

              nLinha := 1.5

           ENDIF

        ENDIF

        BAIAS->( DBSKIP() )

     ENDDO

     // Resumo Totalizador
     nLinha += 0.2

     oPrn:Say( nLinha, 1.0, Replicate( "=", 110 ), oFontCab )

     nLinha += 0.45

     oPrn:Say( nLinha, 1.0, "RESUMO GERAL: " + ;
                            "Total de Baias: " + AllTrim( Str( nTotBaias ) ) + "  |  " + ;
                            "Livres: " + AllTrim( Str( nTotLivres ) ) + "  |  " + ;
                            "Ocupadas: " + AllTrim( Str( nTotOcup ) ) + "  |  " + ;
                            "Em Manutencao: " + AllTrim( Str( nTotManut ) ), oFontTot )

  ENDPAGE

   ENDPRINT

   RELEASE FONT oFontTit, oFontSub, oFontCab, oFontDet, oFontTot

   // Restaura posicao original do cursor no DBF
   BAIAS->( DBGOTO( nRecAtual ) )

   oBrw:Refresh()

RETURN NIL
// ----------------------------------------------------------------------------
// CONTAGEM ESTATISTICA NATIVA DE BAIAS
// ----------------------------------------------------------------------------
STATIC FUNCTION ContarBaias( cTipo )

   LOCAL nQtd := 0
   LOCAL nSalvaRec := BAIAS->( RecNo() )

   BAIAS->( DBGOTOP() )

   DO WHILE !BAIAS->( Eof() )

  IF !Deleted()
     IF cTipo == "T"
        nQtd++
     ELSEIF BAIAS->STATUS == cTipo
        nQtd++
     ENDIF
  ENDIF

  BAIAS->( DBSKIP() )

   ENDDO

   BAIAS->( DBGOTO( nSalvaRec ) )

RETURN nQtd
// ----------------------------------------------------------------------------
// ESTRUTURA E CARGA INICIAL DO BANCO DBF NATIVO
// ----------------------------------------------------------------------------
STATIC FUNCTION CriaDbfBaias()

   LOCAL aStruct := {}

   IF !File( "BAIAS.DBF" )

  AAdd( aStruct, { "NUMERO",    "N",  6, 0 } )  // Codigo/Numero da baia
  AAdd( aStruct, { "DESCRICAO", "C", 40, 0 } )  // Nome do quarto/box
  AAdd( aStruct, { "ESPECIE",   "C", 25, 0 } )  // CAO, GATO, AMBOS
  AAdd( aStruct, { "TAMANHO",   "C", 15, 0 } )  // PEQUENO, MEDIO, GRANDE, GIGANTE
  AAdd( aStruct, { "STATUS",    "C",  1, 0 } )  // L=Livre, O=Ocupado, M=Manutencao
  AAdd( aStruct, { "VALOR_DIA", "N",  9, 2 } )  // Diaria R$
  AAdd( aStruct, { "PET_NOME",  "C", 40, 0 } )  // Nome do Pet se ocupado
  AAdd( aStruct, { "TUTOR",     "C", 60, 0 } )  // Nome e fone do tutor
  AAdd( aStruct, { "OBS",       "C", 50, 0 } )  // Recursos da baia (ar, camera)
  AAdd( aStruct, { "OBS2",      "C", 50, 0 } )  // Recursos da baia (ar, camera)
  AAdd( aStruct, { "OBS3",      "C", 50, 0 } )  // Recursos da baia (ar, camera)
  AAdd( aStruct, { "OBS4",      "C", 50, 0 } )  // Recursos da baia (ar, camera)
  AAdd( aStruct, { "OBS5",      "C", 50, 0 } )  // Recursos da baia (ar, camera)
  AAdd( aStruct, { "OBS6",      "C", 50, 0 } )  // Recursos da baia (ar, camera)

  DBCREATE( "BAIAS.DBF", aStruct, "DBFCDX" )

  // Pre-popula com dados iniciais de exemplo realistas
  USE BAIAS EXCLUSIVE NEW VIA "DBFCDX"

  CriaIndices()

  APPEND BLANK

  REPLACE FIELD->NUMERO    WITH VAL( "000001" ),         ;
          FIELD->DESCRICAO WITH "BOX VIP CANIL OURO 01", ;
          FIELD->ESPECIE   WITH "CAO", ;
          FIELD->TAMANHO   WITH "GRANDE", ;
          FIELD->STATUS    WITH "L", ;
          FIELD->VALOR_DIA WITH 95.00, ;
          FIELD->OBS       WITH "Solario individual, camera HD e ar condicionado"

  APPEND BLANK
  REPLACE FIELD->NUMERO    WITH VAL( "000002" ),         ;
          FIELD->DESCRICAO WITH "BOX CANIL MASTER 02", ;
          FIELD->ESPECIE   WITH "CAO", ;
          FIELD->TAMANHO   WITH "MEDIO", ;
          FIELD->STATUS    WITH "O", ;
          FIELD->VALOR_DIA WITH 75.00, ;
          FIELD->PET_NOME  WITH "THOR (GOLDEN)", ;
          FIELD->TUTOR     WITH "MARCELO SILVA (11) 98888-1234", ;
          FIELD->OBS       WITH "Racao especial as 18h"

  APPEND BLANK
  REPLACE FIELD->NUMERO    WITH VAL( "000003" ),         ;
          FIELD->DESCRICAO WITH "SUITE FELINA FELIX 01", ;
          FIELD->ESPECIE   WITH "GATO", ;
          FIELD->TAMANHO   WITH "PEQUENO", ;
          FIELD->STATUS    WITH "L", ;
          FIELD->VALOR_DIA WITH 65.00, ;
          FIELD->OBS       WITH "Arranhadores verticais e prateleiras suspensas"

  APPEND BLANK
  REPLACE FIELD->NUMERO    WITH VAL( "000004" ),         ;
          FIELD->DESCRICAO WITH "SUITE FELINA FELIX 02", ;
          FIELD->ESPECIE   WITH "GATO", ;
          FIELD->TAMANHO   WITH "PEQUENO", ;
          FIELD->STATUS    WITH "O", ;
          FIELD->VALOR_DIA WITH 65.00, ;
          FIELD->PET_NOME  WITH "MIA (PERSA)", ;
          FIELD->TUTOR     WITH "RENATA LIMA (11) 97777-5678", ;
          FIELD->OBS       WITH "Gata idosa, medicacao as 08h"

  APPEND BLANK
  REPLACE FIELD->NUMERO    WITH VAL( "000005" ),         ;
          FIELD->DESCRICAO WITH "BOX STANDARD 05", ;
          FIELD->ESPECIE   WITH "AMBOS", ;
          FIELD->TAMANHO   WITH "PEQUENO", ;
          FIELD->STATUS    WITH "L", ;
          FIELD->VALOR_DIA WITH 55.00, ;
          FIELD->OBS       WITH "Ideal para caes pequenos ou gatos"

  APPEND BLANK
  REPLACE FIELD->NUMERO    WITH VAL( "000006" ),         ;
          FIELD->DESCRICAO WITH "QUARTO GIGANTE PRIVATIVO", ;
          FIELD->ESPECIE   WITH "CAO", ;
          FIELD->TAMANHO   WITH "GIGANTE", ;
          FIELD->STATUS    WITH "M", ;
          FIELD->VALOR_DIA WITH 120.00, ;
          FIELD->OBS       WITH "Higienizacao e troca de piso em andamento"

  DBCOMMIT()

  CLOSE BAIAS

   ENDIF

RETURN NIL
// ----------------------------------------------------------------------------
// CRIACAO DE INDICES CDX NATIVOS
// ----------------------------------------------------------------------------
STATIC FUNCTION CriaIndices()

   INDEX ON FIELD->NUMERO TAG NUMERO TO BAIAS

   INDEX ON FIELD->STATUS TAG STATUS TO BAIAS

   INDEX ON FIELD->STATUS + FIELD->NUMERO TAG STATUSNUM TO BAIAS

   INDEX ON FIELD->TAMANHO TAG TAMANHO TO BAIAS

   INDEX ON Upper( FIELD->DESCRICAO ) TAG DESCR TO BAIAS

RETURN NIL
// ============================================================================
// FIM DO MODULO CAD_BAIA.PRG - kapiabafwh@gmail.com
// ============================================================================

Gracias, tks.

Regards, saludos.

João Santos - São Paulo - Brasil - Phone: +55(11)95150-7341
Posts: 150
Joined: Fri Sep 25, 2026 01:40 AM

Re: Pregunta o solicitud para FiveTech IA.

Posted: Sat Sep 26, 2026 07:19 PM

Caro colega,
 
Obrigado por compartilhar o módulo. Fiz uma leitura estática do PRG; não consegui compilá-lo nem executar as duas dialogs porque o trecho depende de headers próprios, dos recursos DLG_BAIAS_MAIN/DLG_CADASTRO_BAIA e de funções externas que não vieram junto. Ainda assim, há três pontos concretos para corrigir primeiro:
 
1. Tipo da chave NUMERO. Em CriaDbfBaias(), NUMERO é definido como campo numérico ("N", 6, 0). No entanto, a tag STATUSNUM concatena texto e número:

INDEX ON FIELD->STATUS + FIELD->NUMERO TAG STATUSNUM TO BAIAS

A expressão da chave precisa produzir um tipo consistente. Se a intenção é ordenar por status e depois pelo número, converta o número para texto de largura fixa, por exemplo FIELD->STATUS + StrZero( FIELD->NUMERO, 6 ). Confirme a função disponível na sua versão de Harbour.
 
2. Busca pelo número. Em BuscaRapida(), a ordem NUMERO é numérica, mas SEEK PadR( cTermo, 6 ) e depois SEEK cTermo usam strings. Para a chave numérica, converta o termo para número antes de buscar, após validar que a entrada é realmente numérica. Não mude apenas a tag se deseja manter NUMERO numérico no DBF.
 
3. Exclusão. A mensagem em BaiaExcluir() faz AllTrim( BAIAS->NUMERO ); AllTrim() espera texto, mas o campo é numérico. Formate-o primeiro, por exemplo AllTrim( Str( BAIAS->NUMERO ) ).
 
Também revisaria a abertura: USE BAIAS INDEX BAIAS acontece antes do teste IF !File( "BAIAS.CDX" ). Se o CDX estiver ausente, a tentativa de abrir o índice ocorre antes de CriaIndices(); reconstruir índice com a tabela já aberta em modo SHARED merece um fluxo separado, com acesso apropriado e backup.
 
Esses são achados do texto, não um diagnóstico de execução. Qual erro aparece primeiro no compilador ou no error.log, e em qual versão exata do FWH/Harbour? Se puder anexar um exemplo mínimo com os headers e recursos necessários (sem dados reais dos clientes), posso conferir o restante com mais segurança.

Posts: 150
Joined: Fri Sep 25, 2026 01:40 AM

Re: Pregunta o solicitud para FiveTech IA.

Posted: Sat Sep 26, 2026 09:42 PM

Caro colega,   Obrigado por enviar as duas definições do RC. Agora já temos os recursos DLG_BAIAS_MAIN e DLG_CADASTRO_BAIA que faltavam à leitura anterior. Isso, por si só, não confirma que o PRG compile ou que as janelas funcionem: ainda faltam os headers próprios, as funções externas usadas pelo módulo e um erro concreto para reproduzir o problema.   Qual é o primeiro erro do compilador ou do error.log? Envie também a versão exata de FWH/Harbour e, se possível, um exemplo mínimo com essas dependências, sem dados reais dos clientes. Assim consigo seguir pelo erro real, em vez de adivinhar a causa.

Posts: 8716
Joined: Tue Dec 20, 2005 07:36 PM

Re: Pregunta o solicitud para FiveTech IA.

Posted: Sun Sep 27, 2026 04:21 PM

Buenas tardes, estimado FiveTech AI. Por favor, revisa de nuevo mi código (.PRG) para ver si he cometido algún otro error. Revisa también la función BaiaImprimir( oBrw ); tiene errores (vicios ocultos) que no logro detectar.

#Include "Ambienty.ch"

FUNCTION Cad_Baia()

   LOCAL oEditarF, oEditarT, oExcluir, oImprimir, oPrioriza, oSaida, iDcor
   LOCAL oDlg, oBrw, oFont, oFontBold, oIco, oLimpar, oInfo
   LOCAL oRadio, oCmbPorte, oGetBusca
   LOCAL nFiltroStatus := 1  // 1=Todas, 2=Livres, 3=Ocupadas, 4=Manutencao
   LOCAL cPorte  := "TODOS"
   LOCAL cBusca  := Space( 30 )
   LOCAL aPortes := { "TODOS", "PEQUENO", "MEDIO", "GRANDE", "GIGANTE" }

   // Verifica e cria DBF nativo e indices caso nao existam
   IF .NOT. FILE( "BAIAS.DBF" )
      CriaDbfBaias()
   ENDIF

   // SOMENTE PARA AREA DE TESTES, PASSAR PARA O INDEXADOR.
   IF FILE( "BAIAS.CDX" )
      AEVAL(DIRECTORY( "BAIAS.CDX"  ),{ |aFILE| FERASE(aFILE[F_NAME]) } )
   ENDIF

   IF .NOT. FILE( "BAIAS.CDX" )

  USE BAIAS NEW EXCLUSIVE ALIAS BAIAS

  CriaIndices()

  CLOSE DATABASE

   ENDIF

   // Abertura nativa compartilhada
   USE BAIAS INDEX BAIAS SHARED NEW ALIAS BAIAS // VIA "DBFCDX"

   SET ORDER TO TAG NUMERO
   DBGOTOP()

   DEFINE FONT oFont     NAME "Segoe UI" SIZE 0, -12 BOLD
   DEFINE FONT oFontBold NAME "Segoe UI" SIZE 0, -14 BOLD
   DEFINE ICON oIco      RESOURCE "ICONE01"  // EM IMAGENS.RES

   // Carrega a Dialog Principal desenhada no Borland Workshop
   DEFINE DIALOG oDlg RESOURCE "DLG_BAIAS_MAIN" ICON oIco                    ;
      TITLE "Controle de Baias / Boxes / Quartos - Hospedagem PetShop"

   oDlg:lHelpIcon := .F.

   REDEFINE GROUP oGroup ID 501 OF oDlg COLOR METRO_TURQUE, METRO_ORANGE FONT oFont TRANSPARENT

   For iDcor=401 to 402
      REDEFINE SAY ID iDcor OF oDlg ;
         COLOR METRO_TURQUE, CLR_WHITE UPDATE FONT oFont TRANSPARENT
   Next iDcor // By Ednaldo Rolim - Yes!

   // -------------------------------------------------------------------------
   // 1. CONTROLES DE FILTRO RAPIDO (TOPO DA TELA)
   // -------------------------------------------------------------------------
   REDEFINE RADIO oRadio VAR nFiltroStatus ID 201, 202, 203, 204 OF oDlg ;
      ON CHANGE ( AplicaFiltro( nFiltroStatus, cPorte, oBrw ) )

   oRadio:SetFont( oFont )

   oRadio:aItems[1]:cTooltip := "Por Todas "
   oRadio:aItems[2]:cTooltip := "Por Livres"
   oRadio:aItems[3]:cTooltip := "Por Ocupadass "
   oRadio:aItems[4]:cTooltip := "Por Manutenção"

   REDEFINE COMBOBOX oCmbPorte VAR cPorte ITEMS aPortes ID 205 OF oDlg ;
      ON CHANGE ( AplicaFiltro( nFiltroStatus, cPorte, oBrw ) )

   oCmbPorte:cToolTip := "Combo do Porte do PET"

   oCmbPorte:SetFont( oFont )

   REDEFINE GET oGetBusca VAR cBusca ID 206 OF oDlg FONT oFont UPDATE        ;
      COLORS CLR_BLACK, CLR_WHITE VALID ( BuscaRapida( cBusca, oBrw ), .T. )

   oGetBusca:cToolTip := "Busca as Baias"

   REDEFINE BUTTON oLimpar ID 207 OF oDlg                         ;
      ACTION ( LimparFiltros( oRadio, oCmbPorte, oGetBusca, oBrw, ;
                              @nFiltroStatus, @cPorte, @cBusca ) )

   oLimpar:cToolTip := "Limpeza do Filto"

   SET FONT OF oLimpar TO oFontBold

   REDEFINE BUTTON oInfo ID 208 OF oDlg                             ;
      ACTION MsgInfo( "DICAS DO CADASTRO DE BAIAS:" + CRLF + CRLF + ;
                      "- Clique nos Radios para filtrar Livres/Ocupadas instantaneamente." + CRLF + ;
                      "- 'Livres 1' reordena trazendo as vagas livres para o topo." + CRLF + ;
                      "- Duplo-Clique ou ENTER altera a baia selecionada." + CRLF + ;
                      "- Tecla INSERT inclui nova baia / Tecla DELETE exclui." + CRLF + ;
                      "- Banco de dados 100% nativo DBF/CDX.", "Ajuda do Sistema" )

   SET FONT OF oInfo TO oFontBold

   // -------------------------------------------------------------------------
   // 2. CONFIGURACAO DO XBROWSE VINCULADO AO RECURSO ID 101 DO WORKSHOP
   // -------------------------------------------------------------------------
   REDEFINE XBROWSE oBrw ID 101 OF oDlg ;
      COLUMNS "NUMERO", "DESCRICAO", "ESPECIE", "TAMANHO", "STATUS", "VALOR_DIA", "PET_NOME", "TUTOR"                                    ;
      HEADERS "Baia/Box:", "Identificação / Nome:", "Espécie:", "Porte Pet:", "Status:", "Diária R$:", "Pet Hospedado:", "Tutor / Fone:" ;
      SIZES 90, 220, 90, 90, 120, 120, 120, 500                                                                                          ;
      JUSTIFY AL_CENTER, AL_LEFT, AL_LEFT, AL_LEFT, AL_CENTER, AL_RIGHT, AL_LEFT, AL_LEFT                                                ;
      ALIAS "BAIAS" AUTOSORT LINES CELL

WITH OBJECT oBrw

  // Configuração Básica
  :nMarqueeStyle := MARQSTYLE_HIGHLROW // Ou MARQSTYLE_HIGHLWIN7
  :nColDividerStyle := LINESTYLE_LIGHTGRAY
  :nRowDividerStyle := LINESTYLE_LIGHTGRAY
  :lHScroll         := .T.
  :lVScroll         := .T.
  :lRecordSelector  := .T.

  // Efeito Zebrado (Linhas Normais) - Zebra in xBrowse()
  // Usamos OrdKeyNo() para contar a posição lógica no índice - COLORS2.CH
  :bClrStd := { || { CLR_BLACK, IF( OrdKeyNo() % 2 == 0, CLR_BLUE_LIGHT, CLR_BLUE_LIGHT_CYAN ) } }

  // Efeito ao Selecionar (Foco) CLR_MSPURPLE  nRGB( 000, 120, 215 ) //-> Purpura.
  // Mantém a cor da fonte branca e fundo azul escuro
  :bClrSel := { || { CLR_WHITE, CLR_MSPURPLE } }

  // Opcional: Efeito ao Selecionar sem Foco
  :bClrSelFocus := { || { CLR_BLACK, CLR_DARK_TEXT } } // COLORS2.CH

   END

   // Formatacao da coluna de Status com Cores e Nomes Amigaveis
   WITH OBJECT oBrw:oCol( "Status" )

  :bStrData := { || IF( BAIAS->STATUS == "L", "LIVRE", ;
                    IF( BAIAS->STATUS == "O", "OCUPADO", "MANUTENÇÃO" ) ) }

  :bClrStd  := { || { IF( BAIAS->STATUS == "L", CLR_DGREEN, ;
                      IF( BAIAS->STATUS == "O", CLR_DRED, CLR_DORANGE ) ), ;
                      IF( BAIAS->STATUS == "L", CLR_LGREEN, ;
                      IF( BAIAS->STATUS == "O", CLR_LRED, CLR_LYELLOW ) ) } }

   END

   // Formatacao de Valor de Diaria
   WITH OBJECT oBrw:oCol( "Diária R$:" )
      :cEditPicture := "@E 99,999.99"
   END

   // Totalizadores no rodape do XBrowse - Problemas com o SYSREFRESH()
   oBrw:lFooter := .T.
   oBrw:aCols[ 1 ]:bFooter := { || "Total: " + AllTrim( Str( ContarBaias( "T", oBrw ) ) ) }
   oBrw:aCols[ 2 ]:bFooter := { || "Livres: " + AllTrim( Str( ContarBaias( "L", oBrw  ) ) ) + ;
                                   " | Ocupadas: " + AllTrim( Str( ContarBaias( "O", oBrw  ) ) ) + ;
                                   " | Manut: " + AllTrim( Str( ContarBaias( "M", oBrw  ) ) ) }

   // Atribua a fonte a propriedade especifica do rodape do xBrowse
   oBrw:aCols[ 1 ]:oFooterFont := oFont
   oBrw:acols[ 1 ]:nFootStrAlign := 1
   oBrw:aCols[ 2 ]:oFooterFont := oFont
   oBrw:acols[ 2 ]:nFootStrAlign := 1

   // Acoes de teclado e mouse
   oBrw:bLDblClick := { || BaiaEditar( .F., oBrw ) }
   oBrw:bKeyDown   := { | nKey | IF( nKey == VK_RETURN, ( BaiaEditar( .F., oBrw ), 0 ), ;
                                 IF( nKey == VK_INSERT, ( BaiaEditar( .T., oBrw ), 0 ), ;
                                 IF( nKey == VK_DELETE, ( BaiaExcluir( oBrw ), 0 ), NIL ) ) ) }

   // -------------------------------------------------------------------------
   // 3. BOTOES DE ACAO INFERIORES (CRUD + IMPRIMIR + SAIDA)
   // -------------------------------------------------------------------------
   REDEFINE BUTTON oEditarT  ID 301 OF oDlg ;
      ACTION ( BaiaEditar( .T., oBrw ), oBrw:SetFocus() )

   oEditarT:cToolTip := "Editar/Incluir Baias"

   REDEFINE BUTTON oEditarF ID 302 OF oDlg ;
      ACTION ( BaiaEditar( .F., oBrw ), oBrw:SetFocus() )

   oEditarF:cToolTip := "Editar/Alterar Baias"

   REDEFINE BUTTON oExcluir ID 303 OF oDlg ;
      ACTION ( BaiaExcluir( oBrw ), oBrw:SetFocus() )

   oExcluir:cToolTip := "Excluir Baias"

   REDEFINE BUTTON oImprimir ID 304 OF oDlg ;
      ACTION ( BaiaImprimir( oBrw ), oBrw:SetFocus() )

   oImprimir:cToolTip := "Imprimir o Cadastro de Baias"

   // LIVRES 1:
   REDEFINE BUTTON oPrioriza ID 305 OF oDlg ;
      ACTION ( PriorizaLivres( oBrw ), oBrw:SetFocus() )

   oPrioriza:cToolTip := "Refresh() Geral nas baias Livres"

   REDEFINE BUTTON oSaida ID 306 OF oDlg ACTION oDlg:End() CANCEL

   oSaida:cToolTip := "Saida - Exit - Cancelar"

   SET FONT OF oEditarT  TO oFontBold
   SET FONT OF oEditarF  TO oFontBold
   SET FONT OF oExcluir  TO oFontBold
   SET FONT OF oImprimir TO oFontBold
   SET FONT OF oPrioriza TO oFontBold
   SET FONT OF oSaida    TO oFontBold

   ACTIVATE DIALOG oDlg ON INIT( CTRLS_COLORS( oDlg ), oBrw:SetFocus() )

   // Encerramento ordenado-Close Fontes
   RELEASE FONT oFont, oFontBold

   CLOSE BAIAS

RETURN NIL
// ----------------------------------------------------------------------------
// APLICACAO DE FILTROS NATIVOS (STATUS + PORTE DO PET)
// ----------------------------------------------------------------------------
STATIC FUNCTION AplicaFiltro( nOpcStatus, cPorte, oBrw )

   LOCAL cFiltro := ""

   IF nOpcStatus == 2       // Livres

  cFiltro := 'STATUS == "L"'

   ELSEIF nOpcStatus == 3   // Ocupadas

  cFiltro := 'STATUS == "O"'

   ELSEIF nOpcStatus == 4   // Manutencao

  cFiltro := 'STATUS == "M"'

   ENDIF

   IF .NOT. EMPTY( cPorte ) .AND. ( cPorte ) != "TODOS"

  IF !EMPTY( cFiltro )

     cFiltro += ' .AND. '

  ENDIF

  cFiltro += 'AllTrim( UPPER( TAMANHO ) ) == "' + ALLTRIM( cPorte ) + '"'

   ENDIF

   IF EMPTY( cFiltro )

  DbClearFilter()

   ELSE

  SET FILTER TO
  SET FILTER TO &cFiltro

   ENDIF

   DBGOTOP()

   oBrw:Refresh()

RETURN NIL
// ----------------------------------------------------------------------------
// LIMPEZA GERAL DE FILTROS E PESQUISAS
// ----------------------------------------------------------------------------
STATIC FUNCTION LimparFiltros( oRadio, oCmbPorte, oGetBusca, oBrw, nFiltroStatus, cPorte, cBusca )

   nFiltroStatus := 1

// oRadio:SetOption( 1 ) // error in filter
// oRadio:Refresh()

   cPorte := "TODOS"

// oCmbPorte:Set( 1 )   // error in filter
// oCmbPorte:Refresh()

   cBusca := Space( 30 )

   oGetBusca:Refresh()

   DbClearFilter()

   SET ORDER TO TAG NUMERO

   DBGOTOP()

   oBrw:Refresh()
   oBrw:SetFocus()

RETURN NIL
// ----------------------------------------------------------------------------
// BUSCA RAPIDA INCREMENTAL / NATIVA
// ----------------------------------------------------------------------------
STATIC FUNCTION BuscaRapida( cTexto, oBrw )

   LOCAL cTermo := UPPER( AllTrim( cTexto ) ) // oGetBusca

   IF EMPTY( cTermo )

  DBGOTOP()

  oBrw:Refresh()

  RETURN NIL

   ENDIF

   // Se for codigo numerico, pesquisa no indice de codigo
   IF IsDigit( Left( cTermo, 1 ) )

  SET ORDER TO TAG NUMERO

  SEEK( VAL( cTermo ) )

  IF !Found()

     SEEK( cTermo )

  ENDIF

   ELSE

  // Pesquisa por nome / descricao
  SET ORDER TO TAG DESCR

  SEEK cTermo

   ENDIF

   oBrw:Refresh()

RETURN NIL
// ----------------------------------------------------------------------------
// ORDENACAO: LIVRES PRIMEIRO (SEM ESCONDER OS DEMAIS)
// ----------------------------------------------------------------------------
STATIC FUNCTION PriorizaLivres( oBrw )

   SET ORDER TO TAG STATUSNUM

   DBGOTOP()

   oBrw:Refresh()

   MsgInfo( "As Baias Livres Foram Posicionadas no Topo da Lista!", ;
            "Organização Rápida" )

RETURN NIL
// ----------------------------------------------------------------------------
// TELA DE EDICAO (INCLUSAO E ALTERACAO) VIA RECURSO DO WORKSHOP
// ----------------------------------------------------------------------------
STATIC FUNCTION BaiaEditar( lInclusao, oBrw )

   LOCAL oDlgEd, oNum, oDesc, oCmbEsp, oCmbTam, oCmbSt, oVal, oPet, oTut, oObs
   LOCAL oObs2, oObs3, oObs4, oObs5, oObs6
   LOCAL oBtnGravar, oBtnCancelar, nNum, oGroup, oGroup2, oFnt, oFont, oIco
   LOCAL cNum     // := Space( 6 )
   LOCAL cDesc    // := Space( 35 )
   LOCAL cEsp     // := "AMBOS"
   LOCAL cTam     // := "MEDIO"
   LOCAL cStCombo // := "L - LIVRE"
   LOCAL nVal     // := 70.00
   LOCAL cPet     // := Space( 25 )
   LOCAL cTut     // := Space( 30 )
   LOCAL cObs, cObs2, cObs3, cObs4, cObs5, cObs6
   LOCAL lSalvo    := .F.
   LOCAL aEspecies := { "AMBOS", "CAO", "GATO" }
   LOCAL aTamanhos := { "PEQUENO", "MEDIO", "GRANDE", "GIGANTE", "TODOS" }
   LOCAL aStatus   := { "L - LIVRE", "O - OCUPADO", "M - MANUTENCAO" }

   IF( .NOT. lInclusao ) // alteracao

  IF BAIAS->( EOF() )

     MsgAlert( "Não há Registro Selecionado Para Alteração!", "Atenção" )

     RETURN NIL

  ENDIF

  // Carrega dados nativos do DBF atual
  cNum  := BAIAS->NUMERO
  cDesc := BAIAS->DESCRICAO
  cEsp  := UPPER( AllTrim( BAIAS->ESPECIE ) )
  cTam  := UPPER( AllTrim( BAIAS->TAMANHO ) )
  nVal  := BAIAS->VALOR_DIA
  cPet  := BAIAS->PET_NOME
  cTut  := BAIAS->TUTOR

  cObs  := BAIAS->OBS
  cObs2 := BAIAS->OBS2
  cObs3 := BAIAS->OBS3
  cObs4 := BAIAS->OBS4
  cObs5 := BAIAS->OBS5
  cObs6 := BAIAS->OBS6

  IF BAIAS->STATUS == "L"

     cStCombo := "L - LIVRE"

  ELSEIF BAIAS->STATUS == "O"

     cStCombo := "O - OCUPADO"

  ELSE

     cStCombo := "M - MANUTENCAO"

  ENDIF

   ELSE // inclusao

  cNum      := 0

  GO BOTTOM

  nNum  := ( BAIAS->NUMERO ) + 1
  cNum  := nNum

  cDesc     := Space( 35 )
  cEsp      := "AMBOS"
  cTam      := "MEDIO"
  cStCombo  := "L - LIVRE"
  nVal      := 0 // 70.00
  cPet      := Space( 25 )
  cTut      := Space( 30 )
  cObs      := Space( 50 )
  cOBS2     := Space( 50 )
  cOBS3     := Space( 50 )
  cOBS4     := Space( 50 )
  cOBS5     := Space( 50 )
  cOBS6     := Space( 50 )

  GO TOP

   ENDIF

   DEFINE FONT oFnt  NAME "Ms Sans Serif" SIZE 0, -12 BOLD
   DEFINE FONT oFont NAME "Ms Sans Serif" SIZE 0, -14 BOLD
   DEFINE ICON oIco  RESOURCE "ICONE01"  // EM IMAGENS.RES

   DEFINE DIALOG oDlgEd RESOURCE "DLG_CADASTRO_BAIA" ICON oIco ;
      TITLE IF( lInclusao, "Inclusão de Baia / Box / Quarto",  ;
                           "Alteração de Baia / Box / Quarto" )

   oDlgEd:lHelpIcon := .F.

   REDEFINE GROUP oGroup  ID 501 OF oDlgEd COLOR METRO_TURQUE, CLR_WHITE FONT oFnt TRANSPARENT
   REDEFINE GROUP oGroup2 ID 502 OF oDlgEd COLOR METRO_TURQUE, CLR_WHITE FONT oFnt TRANSPARENT

   For iDcor=401 to 409
      REDEFINE SAY ID iDcor OF oDlgEd ;
         COLOR METRO_TURQUE, CLR_WHITE UPDATE FONT oFont TRANSPARENT
   Next iDcor // By Ednaldo Rolim - Yes!

   // Controles mapeados aos IDs da DLG_CADASTRO_BAIA do Workshop
   REDEFINE GET oNum VAR cNum ID 111 OF oDlgEd PICTURE "@K 999999"           ;
      WHEN( lInclusao ) FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE        ;
      VALID( VERIFICA_NUM_BAIA( lInclusao, cNum ) )

   REDEFINE GET oDesc VAR cDesc ID 112 OF oDlgEd PICTURE "@KR!"              ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE COMBOBOX oCmbEsp VAR cEsp ITEMS aEspecies ID 113 OF oDlgEd

   oCmbEsp:cToolTip := "Combo das Espécies"

   oCmbEsp:SetFont( oFont )

   REDEFINE COMBOBOX oCmbTam VAR cTam ITEMS aTamanhos ID 114 OF oDlgEd

   oCmbTam:cToolTip := "Combo do Tamanho do PET."

   oCmbTam:SetFont( oFont )

   REDEFINE COMBOBOX oCmbSt  VAR cStCombo ITEMS aStatus ID 115 OF oDlgEd

   oCmbSt:cToolTip := "Combo do STATUS do PET."

   oCmbSt:SetFont( oFont )

   REDEFINE GET oVal VAR nVal   ID 116 OF oDlgEd PICTURE "@KE 99,999.99" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   oVal:cToolTip := "Valor da Diária"

   REDEFINE GET oPet VAR cPet   ID 117 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   oPet:cToolTip := "Nome do PET."

   REDEFINE GET oTut VAR cTut   ID 118 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   oTut:cToolTip := "Nome do TUTOR/DONO do PET."

   REDEFINE GET oObs VAR cObs   ID 119 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE GET oObs2 VAR cObs2 ID 120 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE GET oObs3 VAR cObs3 ID 121 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE GET oObs4 VAR cObs4 ID 122 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE GET oObs5 VAR cObs5 ID 123 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE GET oObs6 VAR cObs6 ID 124 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   // Botoes de Acao da Dialog de Edicao
   REDEFINE BUTTON oBtnGravar ID 301 OF oDlgEd ;
      ACTION ( lSalvo := BaiaGravar( lInclusao, cNum, cDesc, cEsp, cTam, Left( cStCombo, 1 ), ;
               nVal, cPet, cTut, cObs, cObs2, cObs3, cObs4, cObs5, cObs6, oDlgEd, oBrw ) )

   REDEFINE BUTTON oBtnCancelar ID 302 OF oDlgEd ACTION oDlgEd:End() CANCEL

   SET FONT OF oBtnGravar   TO oFont
   SET FONT OF oBtnCancelar TO oFont

   ACTIVATE DIALOG oDlgEd CENTERED ON INIT( CTRLS_COLORS( oDlgEd ) ) // FUNCOES.PRG

RETURN NIL

FUNCTION VERIFICA_NUM_BAIA( lInclusao, nNumBaia )

   IF lInclusao

  // Validacao nativa com SEEK para evitar duplicidade de codigo
  SET ORDER TO TAG NUMERO
  DBSEEK( nNumBaia )

  IF FOUND()

     MsgStop( "Já Existe uma Baia Cadastrada com o Número: " + STR( nNumBaia ), "Atenção" )

     RETURN( .F. )

  ENDIF

   ENDIF

RETURN( .T. )
// ----------------------------------------------------------------------------
// GRAVACAO NATIVA NO BANCO DBF
// ----------------------------------------------------------------------------
STATIC FUNCTION BaiaGravar( lInclusao, cNum, cDesc, cEsp, cTam, cStatus,     ;
                                       nVal, cPet, cTut, cObs, cObs2, cObs3, ;
                                       cObs4, cObs5, cObs6, oDlgEd, oBrw )

   IF EMPTY( cNum )

  MsgStop( "O código/número da baia e obrigatório!", "Aviso" )

  RETURN( .F. )

   ENDIF

   IF EMPTY( cDesc )

  MsgStop( "A descrição/identificação da baia e obrigatória!", "Aviso" )

  RETURN( .F. )

   ENDIF

   IF lInclusao

  // Validacao nativa com SEEK para evitar duplicidade de codigo
  SET ORDER TO TAG NUMERO
  //SEEK PadR( cNum, 6 )

  DBSEEK( cNum ) // E NUMERICO AGORA

  IF Found()

     MsgStop( "já existe uma baia cadastrada com o número: " + STR( cNum ), "Atenção" )

     RETURN( .F. )

  ENDIF

  // Comando nativo de inclusao
  APPEND BLANK

  IF NetErr()

     MsgStop( "Falha de Rede ao Incluir o Registro!", "Erro de Gravação" )

     RETURN( .F. )

  ENDIF

   ELSE

  // Bloqueio seguro para alteracao em rede
  IF !RLOCK()

     MsgStop( "O registro está sendo editado por outro usuário na rede!", "Bloqueio" )

     RETURN( .F. )

  ENDIF

   ENDIF

   // Gravacao nativa campo a campo
   REPLACE FIELD->NUMERO    WITH cNum,            ;
           FIELD->DESCRICAO WITH cDesc,           ;
           FIELD->ESPECIE   WITH cEsp,            ;
           FIELD->TAMANHO   WITH cTam,            ;
           FIELD->STATUS    WITH cStatus,         ;
           FIELD->VALOR_DIA WITH nVal,            ;
           FIELD->PET_NOME  WITH cPet,            ;
           FIELD->TUTOR     WITH cTut,            ;
           FIELD->OBS       WITH cObs,            ;
           FIELD->OBS2      WITH cObs2,           ;
           FIELD->OBS3      WITH cObs3,           ;
           FIELD->OBS4      WITH cObs4,           ;
           FIELD->OBS5      WITH cObs5,           ;
           FIELD->OBS6      WITH cObs6

   DBUNLOCK()
   DBCOMMIT()

   GRAVACAO_EFETUADA_COM_SUCESSO()

   oBrw:Refresh()
   oDlgEd:End()

RETURN .T.
// ----------------------------------------------------------------------------
// EXCLUSAO NATIVA DE REGISTRO
// ----------------------------------------------------------------------------
STATIC FUNCTION BaiaExcluir( oBrw )

   IF BAIAS->( EOF() )

  MsgAlert( "Nenhum registro selecionado para exclusão!", "Aviso" )

  RETURN NIL

   ENDIF

   IF MsgNoYes( "Deseja Realmente Excluir a Baia: " + STR( BAIAS->NUMERO ) + ;
                " (" + AllTrim( BAIAS->DESCRICAO ) + ")?", "Confirmação de Exclusão" )

  IF RLOCK()

     DELETE

     DBUNLOCK()
     DBCOMMIT()

     DBSKIP( 1 )

     IF EOF()
        DBGOBOTTOM()
     ENDIF

     oBrw:Refresh()

     MsgInfo( "Baia Excluída com Sucesso!", "Operação Concluida" )

  ELSE

     MsgStop( "Registro Travado na Rede. Não Foi Possível Excluir Agora.", "Erro" )

  ENDIF

   ENDIF

RETURN NIL
// ----------------------------------------------------------------------------
// IMPRESSAO DO RELATORIO DE BAIAS E OCUPACAO VIA TPRINTER / PREVIEW
// ----------------------------------------------------------------------------
STATIC FUNCTION BaiaImprimir( oBrw )

   LOCAL oPrn, oFontTit, oFontCab, oFontSub, oFontDet, oFontTot
   LOCAL nLinha := 1.0
   LOCAL nRecAtual := BAIAS->( RecNo() )
   LOCAL nTotBaias := 0, nTotLivres := 0, nTotOcup := 0, nTotManut := 0

   PRINT oPrn NAME "Relatório de Baias e Quartos - PetShop" PREVIEW

  DEFINE FONT oFontTit NAME "Arial" SIZE 0, -14 BOLD OF oPrn
  DEFINE FONT oFontSub NAME "Arial" SIZE 0, -10 OF oPrn
  DEFINE FONT oFontCab NAME "Courier New" SIZE 0, -10 BOLD OF oPrn
  DEFINE FONT oFontDet NAME "Courier New" SIZE 0, -9 OF oPrn
  DEFINE FONT oFontTot NAME "Courier New" SIZE 0, -10 BOLD OF oPrn

  PAGE
     // Cabecalho
     oPrn:Say( nLinha, 1.0, "PETSHOP HOTEL & HOSPEDAGEM - CONTROLE DE BAIAS/BOXES", oFontTit )
     nLinha += 0.5
     oPrn:Say( nLinha, 1.0, "Emissão: " + DToC( Date() ) + " as " + Time() + " | Filtro Atual: Ativo", oFontSub )
     nLinha += 0.5

     oPrn:Say( nLinha, 1.0, Replicate( "=", 110 ), oFontCab )
     nLinha += 0.4
     oPrn:Say( nLinha, 1.0, "NUM    IDENTIFICAÇÃO/NOME           ESPÉCIE   PORTE     STATUS     DIÁRIA R$  PET HOSPEDADO / TUTOR", oFontCab )
     nLinha += 0.35
     oPrn:Say( nLinha, 1.0, Replicate( "-", 110 ), oFontCab )
     nLinha += 0.45

     BAIAS->( DBGOTOP() )

     WHILE( .NOT. BAIAS->( EOF() ) )

        SYSREFRESH()

        IF !DELETED()

           nTotBaias++

           IF BAIAS->STATUS == "L"
              nTotLivres++
           ELSEIF BAIAS->STATUS == "O"
              nTotOcup++
           ELSE
              nTotManut++
           ENDIF

           oPrn:Say( nLinha, 1.0,  BAIAS->NUMERO, oFontDet )
           oPrn:Say( nLinha, 1.8,  Left( BAIAS->DESCRICAO, 28 ), oFontDet )
           oPrn:Say( nLinha, 4.6,  Left( BAIAS->ESPECIE, 8 ), oFontDet )
           oPrn:Say( nLinha, 5.6,  Left( BAIAS->TAMANHO, 9 ), oFontDet )
           oPrn:Say( nLinha, 6.7,  IF( BAIAS->STATUS == "L", "LIVRE", IF( BAIAS->STATUS == "O", "OCUPADO", "MANUT." ) ), oFontDet )
           oPrn:Say( nLinha, 7.8,  Transform( BAIAS->VALOR_DIA, "@E 9,999.99" ), oFontDet )
           oPrn:Say( nLinha, 9.0,  AllTrim( BAIAS->PET_NOME ) + IF( !EMPTY( BAIAS->TUTOR ), " (" + AllTrim( BAIAS->TUTOR ) + ")", "" ), oFontDet )

           nLinha += 0.40

           // Quebra de pagina se ultrapassar limite
           IF nLinha > 26.5

              oPrn:EndPage()

              oPrn:StartPage()

              nLinha := 1.5

           ENDIF

        ENDIF

        BAIAS->( DBSKIP() )

     ENDDO

     // Resumo Totalizador
     nLinha += 0.2

     oPrn:Say( nLinha, 1.0, Replicate( "=", 110 ), oFontCab )

     nLinha += 0.45

     oPrn:Say( nLinha, 1.0, "RESUMO GERAL: " + ;
                            "Total de Baias: " + AllTrim( Str( nTotBaias ) ) + "  |  " + ;
                            "Livres: " + AllTrim( Str( nTotLivres ) ) + "  |  " + ;
                            "Ocupadas: " + AllTrim( Str( nTotOcup ) ) + "  |  " + ;
                            "Em Manutencao: " + AllTrim( Str( nTotManut ) ), oFontTot )

  ENDPAGE

   ENDPRINT

   RELEASE FONT oFontTit, oFontSub, oFontCab, oFontDet, oFontTot

   // Restaura posicao original do cursor no DBF
   BAIAS->( DBGOTO( nRecAtual ) )

   oBrw:Refresh()

RETURN NIL
// ----------------------------------------------------------------------------
// CONTAGEM ESTATISTICA NATIVA DE BAIAS
// ----------------------------------------------------------------------------
STATIC FUNCTION ContarBaias( cTipo, oBrw  )

   LOCAL nQtd := 0
   LOCAL nSalvaRec := BAIAS->( RecNo() )

   BAIAS->( DBGOTOP() )

   WHILE( .NOT. BAIAS->( EOF() ) )

  // SYSREFRESH() // ERROR IN SYSREFRESH()

  IF !DELETED()

     IF cTipo == "T"

        nQtd++

     ELSEIF BAIAS->STATUS == cTipo

        nQtd++

     ENDIF

  ENDIF

  BAIAS->( DBSKIP() )

   ENDDO

   BAIAS->( DBGOTO( nSalvaRec ) )

   // oBrw:Refresh() // TRABA EL XBROWSE()

RETURN nQtd
// ----------------------------------------------------------------------------
// ESTRUTURA E CARGA INICIAL DO BANCO DBF NATIVO
// ----------------------------------------------------------------------------
STATIC FUNCTION CriaDbfBaias()

   LOCAL aStruct := {}

   IF !File( "BAIAS.DBF" )

  AAdd( aStruct, { "NUMERO",    "N",  6, 0 } )  // Codigo/Numero da baia
  AAdd( aStruct, { "DESCRICAO", "C", 40, 0 } )  // Nome do quarto/box
  AAdd( aStruct, { "ESPECIE",   "C", 25, 0 } )  // CAO, GATO, AMBOS
  AAdd( aStruct, { "TAMANHO",   "C", 15, 0 } )  // PEQUENO, MEDIO, GRANDE, GIGANTE
  AAdd( aStruct, { "STATUS",    "C",  1, 0 } )  // L=Livre, O=Ocupado, M=Manutencao
  AAdd( aStruct, { "VALOR_DIA", "N",  9, 2 } )  // Diaria R$
  AAdd( aStruct, { "PET_NOME",  "C", 40, 0 } )  // Nome do Pet se ocupado
  AAdd( aStruct, { "TUTOR",     "C", 60, 0 } )  // Nome e fone do tutor
  AAdd( aStruct, { "OBS",       "C", 50, 0 } )  // Recursos da baia (ar, camera)
  AAdd( aStruct, { "OBS2",      "C", 50, 0 } )  // Recursos da baia (ar, camera)
  AAdd( aStruct, { "OBS3",      "C", 50, 0 } )  // Recursos da baia (ar, camera)
  AAdd( aStruct, { "OBS4",      "C", 50, 0 } )  // Recursos da baia (ar, camera)
  AAdd( aStruct, { "OBS5",      "C", 50, 0 } )  // Recursos da baia (ar, camera)
  AAdd( aStruct, { "OBS6",      "C", 50, 0 } )  // Recursos da baia (ar, camera)

  DBCREATE( "BAIAS.DBF", aStruct, "DBFCDX" )

  // Pre-popula com dados iniciais de exemplo realistas
  USE BAIAS EXCLUSIVE NEW VIA "DBFCDX"

  CriaIndices()

  APPEND BLANK

  REPLACE FIELD->NUMERO    WITH VAL( "000001" ),         ;
          FIELD->DESCRICAO WITH "BOX VIP CANIL OURO 01", ;
          FIELD->ESPECIE   WITH "CAO", ;
          FIELD->TAMANHO   WITH "GRANDE", ;
          FIELD->STATUS    WITH "L", ;
          FIELD->VALOR_DIA WITH 95.00, ;
          FIELD->OBS       WITH "Solario individual, camera HD e ar condicionado"

  APPEND BLANK
  REPLACE FIELD->NUMERO    WITH VAL( "000002" ),         ;
          FIELD->DESCRICAO WITH "BOX CANIL MASTER 02", ;
          FIELD->ESPECIE   WITH "CAO", ;
          FIELD->TAMANHO   WITH "MEDIO", ;
          FIELD->STATUS    WITH "O", ;
          FIELD->VALOR_DIA WITH 75.00, ;
          FIELD->PET_NOME  WITH "THOR (GOLDEN)", ;
          FIELD->TUTOR     WITH "MARCELO SILVA (11) 98888-1234", ;
          FIELD->OBS       WITH "Racao especial as 18h"

  APPEND BLANK
  REPLACE FIELD->NUMERO    WITH VAL( "000003" ),         ;
          FIELD->DESCRICAO WITH "SUITE FELINA FELIX 01", ;
          FIELD->ESPECIE   WITH "GATO", ;
          FIELD->TAMANHO   WITH "PEQUENO", ;
          FIELD->STATUS    WITH "L", ;
          FIELD->VALOR_DIA WITH 65.00, ;
          FIELD->OBS       WITH "Arranhadores verticais e prateleiras suspensas"

  APPEND BLANK
  REPLACE FIELD->NUMERO    WITH VAL( "000004" ),         ;
          FIELD->DESCRICAO WITH "SUITE FELINA FELIX 02", ;
          FIELD->ESPECIE   WITH "GATO", ;
          FIELD->TAMANHO   WITH "PEQUENO", ;
          FIELD->STATUS    WITH "O", ;
          FIELD->VALOR_DIA WITH 65.00, ;
          FIELD->PET_NOME  WITH "MIA (PERSA)", ;
          FIELD->TUTOR     WITH "RENATA LIMA (11) 97777-5678", ;
          FIELD->OBS       WITH "Gata idosa, medicacao as 08h"

  APPEND BLANK
  REPLACE FIELD->NUMERO    WITH VAL( "000005" ),         ;
          FIELD->DESCRICAO WITH "BOX STANDARD 05", ;
          FIELD->ESPECIE   WITH "AMBOS", ;
          FIELD->TAMANHO   WITH "PEQUENO", ;
          FIELD->STATUS    WITH "L", ;
          FIELD->VALOR_DIA WITH 55.00, ;
          FIELD->OBS       WITH "Ideal para caes pequenos ou gatos"

  APPEND BLANK
  REPLACE FIELD->NUMERO    WITH VAL( "000006" ),         ;
          FIELD->DESCRICAO WITH "QUARTO GIGANTE PRIVATIVO", ;
          FIELD->ESPECIE   WITH "CAO", ;
          FIELD->TAMANHO   WITH "GIGANTE", ;
          FIELD->STATUS    WITH "M", ;
          FIELD->VALOR_DIA WITH 120.00, ;
          FIELD->OBS       WITH "Higienizacao e troca de piso em andamento"

  DBCOMMIT()
  CLOSE BAIAS

   ENDIF

RETURN NIL
// ----------------------------------------------------------------------------
// CRIACAO DE INDICES CDX NATIVOS
// ----------------------------------------------------------------------------
STATIC FUNCTION CriaIndices()

   INDEX ON FIELD->NUMERO TAG NUMERO TO BAIAS

   INDEX ON FIELD->STATUS TAG STATUS TO BAIAS

   // PRIORIZA STATUS LIVRE
   INDEX ON FIELD->STATUS + STR( FIELD->NUMERO, 6 ) TAG STATUSNUM TO BAIAS

   INDEX ON FIELD->TAMANHO TAG TAMANHO TO BAIAS

   INDEX ON UPPER( FIELD->DESCRICAO ) TAG DESCR TO BAIAS

RETURN NIL
// ===========================================================================
// FIM DO MODULO CAD_BAIA.PRG - kapiabafwh@gmail.com
// ===========================================================================

Gracias, tks.

Regards, saludos.

João Santos - São Paulo - Brasil - Phone: +55(11)95150-7341
Posts: 150
Joined: Fri Sep 25, 2026 01:40 AM

Re: Pregunta o solicitud para FiveTech IA.

Posted: Sun Sep 27, 2026 04:51 PM

Estimado João,

He revisado de nuevo el PRG. En BaiaImprimir() hay un punto importante: oPrn:Say() recibe coordenadas en píxeles si no le indicas una unidad. Tus valores 1.0, 1.5 y 26.5 parecen centímetros, por eso el texto puede quedar amontonado. Usa oPrn:CmSay() para esas posiciones y convierte BAIAS->NUMERO a texto antes de imprimirlo:

oPrn:CmSay( nLinha, 1.0, AllTrim( Str( BAIAS->NUMERO ) ), oFontDet )

La secuencia PRINT/PAGE/ENDPAGE/ENDPRINT y los métodos StartPage()/EndPage() sí son válidos. Lo que falta es repetir la cabecera al abrir cada página y comprobar el espacio antes de escribir el resumen; ahora puede quedar una página final casi vacía o el resumen fuera de la hoja.

Fuera de la impresión: declara LOCAL iDcor dentro de BaiaEditar(); en LimparFiltros() vuelve a refrescar el radio y el combo después de cambiar sus variables; y quita el segundo SEEK( cTermo ) cuando el índice NUMERO es numérico. También evita borrar BAIAS.CDX en cada apertura compartida.

Estos puntos salen de revisar el código; no he reproducido todavía el fallo. Si puedes, adjunta una captura de la vista previa después del cambio y el mensaje exacto del error que siga apareciendo.

Un saludo,
FiveTech AI

Posts: 8716
Joined: Tue Dec 20, 2005 07:36 PM

Re: Pregunta o solicitud para FiveTech IA.

Posted: Sun Sep 27, 2026 05:00 PM

Gracias, estimado fivetech AI; no tengo ningún mensaje de error en este código. Lo único que no funciona es el área de impresión; no te preocupes, las secciones de índices y de creación de la base de datos se trasladarán a sus propias funciones, ya que las usé en el módulo solo para pruebas. Modificaré la rutina de impresión y te informaré. Muchas gracias.

Regards, saludos.

João Santos - São Paulo - Brasil - Phone: +55(11)95150-7341
Posts: 8716
Joined: Tue Dec 20, 2005 07:36 PM

Re: Pregunta o solicitud para FiveTech IA.

Posted: Mon Sep 28, 2026 05:32 PM

Buenas tardes, estimado FiveTech AI. Quisiera pedirle otro favor: por favor, revise nuevamente mi código (.PRG) e infórmeme si todavía contiene errores. Otra petición: me gustaría incluir un archivo LOGO.JPG en el informe, dentro de la función BaiaImprimir( oBrw ), con las siguientes coordenadas: Línea := 1.50, Columna := 350, Ancho := 650, Alto := 450. Además, quisiera que el programa verifique la integridad del archivo LOGO.JPG antes de imprimir para asegurarse de que no esté corrupto; ¿es posible hacerlo? ¿Cómo?

#Include "Ambienty.ch"

FUNCTION Cad_Baia()

   LOCAL oEditarF, oEditarT, oExcluir, oImprimir, oPrioriza, oSaida, iDcor
   LOCAL oDlg, oBrw, oFont, oFontBold, oIco, oLimpar, oInfo
   LOCAL oRadio, oCmbPorte, oGetBusca
   LOCAL nFiltroStatus := 1  // 1=Todas, 2=Livres, 3=Ocupadas, 4=Manutencao
   LOCAL cPorte  := "TODOS"
   LOCAL cBusca  := Space( 30 )
   LOCAL aPortes := { "TODOS", "PEQUENO", "MEDIO", "GRANDE", "GIGANTE" }

   // Verifica e cria DBF nativo e indices caso nao existam
   IF .NOT. FILE( "BAIAS.DBF" )
      CriaDbfBaias()
   ENDIF

   // Abertura nativa compartilhada
   USE BAIAS INDEX BAIAS SHARED NEW ALIAS BAIAS // VIA "DBFCDX"

   SET ORDER TO TAG NUMERO
   DBGOTOP()

   DEFINE FONT oFont     NAME "Segoe UI" SIZE 0, -12 BOLD
   DEFINE FONT oFontBold NAME "Segoe UI" SIZE 0, -14 BOLD
   DEFINE ICON oIco      RESOURCE "ICONE01"  // EM IMAGENS.RES

   // Carrega a Dialog Principal desenhada no Borland Workshop
   DEFINE DIALOG oDlg RESOURCE "DLG_BAIAS_MAIN" ICON oIco                    ;
      TITLE "Controle de Baias / Boxes / Quartos - Hospedagem PetShop"

   oDlg:lHelpIcon := .F.

   REDEFINE GROUP oGroup ID 501 OF oDlg COLOR METRO_TURQUE, METRO_ORANGE FONT oFont TRANSPARENT

   For iDcor=401 to 402
      REDEFINE SAY ID iDcor OF oDlg ;
         COLOR METRO_TURQUE, CLR_WHITE UPDATE FONT oFont TRANSPARENT
   Next iDcor // By Ednaldo Rolim - Yes!

   // -------------------------------------------------------------------------
   // 1. CONTROLES DE FILTRO RAPIDO (TOPO DA TELA)
   // -------------------------------------------------------------------------
   REDEFINE RADIO oRadio VAR nFiltroStatus ID 201, 202, 203, 204 OF oDlg ;
      ON CHANGE ( AplicaFiltro( nFiltroStatus, cPorte, oBrw ) )

   oRadio:SetFont( oFont )

   oRadio:aItems[1]:cTooltip := "Por Todas "
   oRadio:aItems[2]:cTooltip := "Por Livres"
   oRadio:aItems[3]:cTooltip := "Por Ocupadass "
   oRadio:aItems[4]:cTooltip := "Por Manutenção"

   REDEFINE COMBOBOX oCmbPorte VAR cPorte ITEMS aPortes ID 205 OF oDlg ;
      ON CHANGE ( AplicaFiltro( nFiltroStatus, cPorte, oBrw ) )

   oCmbPorte:cToolTip := "Combo do Porte do PET"

   oCmbPorte:SetFont( oFont )

   REDEFINE GET oGetBusca VAR cBusca ID 206 OF oDlg FONT oFont UPDATE        ;
      COLORS CLR_BLACK, CLR_WHITE VALID ( BuscaRapida( oGetBusca, cBusca, oBrw ), .T. )

   oGetBusca:cToolTip := "Busca as Baias"

   REDEFINE BUTTON oLimpar ID 207 OF oDlg                         ;
      ACTION ( LimparFiltros( oRadio, oCmbPorte, oGetBusca, oBrw, ;
                              @nFiltroStatus, @cPorte, @cBusca ) )

   oLimpar:cToolTip := "Limpeza do Filto"

   SET FONT OF oLimpar TO oFontBold

   REDEFINE BUTTON oInfo ID 208 OF oDlg                             ;
      ACTION MsgInfo( "DICAS DO CADASTRO DE BAIAS:" + CRLF + CRLF + ;
                      "- Clique nos Radios para filtrar Livres/Ocupadas instantaneamente." + CRLF + ;
                      "- 'Livres 1' reordena trazendo as vagas livres para o topo." + CRLF + ;
                      "- Duplo-Clique ou ENTER altera a baia selecionada." + CRLF + ;
                      "- Tecla INSERT inclui nova baia / Tecla DELETE exclui." + CRLF + ;
                      "- Banco de dados 100% nativo DBF/CDX.", "Ajuda do Sistema" )

   SET FONT OF oInfo TO oFontBold

   // -------------------------------------------------------------------------
   // 2. CONFIGURACAO DO XBROWSE VINCULADO AO RECURSO ID 101 DO WORKSHOP
   // -------------------------------------------------------------------------
   REDEFINE XBROWSE oBrw ID 101 OF oDlg ;
      COLUMNS "NUMERO", "DESCRICAO", "ESPECIE", "TAMANHO", "STATUS", "VALOR_DIA", "PET_NOME", "TUTOR"                                    ;
      HEADERS "Baia/Box:", "Identificação / Nome:", "Espécie:", "Porte Pet:", "Status:", "Diária R$:", "Pet Hospedado:", "Tutor / Fone:" ;
      SIZES 90, 220, 90, 90, 120, 120, 120, 500                                                                                          ;
      JUSTIFY AL_CENTER, AL_LEFT, AL_LEFT, AL_LEFT, AL_CENTER, AL_RIGHT, AL_LEFT, AL_LEFT                                                ;
      ALIAS "BAIAS" AUTOSORT LINES CELL

WITH OBJECT oBrw

  // Configuração Básica
  :nMarqueeStyle := MARQSTYLE_HIGHLROW // Ou MARQSTYLE_HIGHLWIN7
  :nColDividerStyle := LINESTYLE_LIGHTGRAY
  :nRowDividerStyle := LINESTYLE_LIGHTGRAY
  :lHScroll         := .T.
  :lVScroll         := .T.
  :lRecordSelector  := .T.

  // Efeito Zebrado (Linhas Normais) - Zebra in xBrowse()
  // Usamos OrdKeyNo() para contar a posição lógica no índice - COLORS2.CH
  :bClrStd := { || { CLR_BLACK, IF( OrdKeyNo() % 2 == 0, CLR_BLUE_LIGHT, CLR_BLUE_LIGHT_CYAN ) } }

  // Efeito ao Selecionar (Foco) CLR_MSPURPLE  nRGB( 000, 120, 215 ) //-> Purpura.
  // Mantém a cor da fonte branca e fundo azul escuro
  :bClrSel := { || { CLR_WHITE, CLR_MSPURPLE } }

  // Opcional: Efeito ao Selecionar sem Foco
  :bClrSelFocus := { || { CLR_BLACK, CLR_DARK_TEXT } } // COLORS2.CH

   END

   // Formatacao da coluna de Status com Cores e Nomes Amigaveis
   WITH OBJECT oBrw:oCol( "Status" )

  :bStrData := { || IF( BAIAS->STATUS == "L", "LIVRE", ;
                    IF( BAIAS->STATUS == "O", "OCUPADO", "MANUTENÇÃO" ) ) }

  :bClrStd  := { || { IF( BAIAS->STATUS == "L", CLR_DGREEN, ;
                      IF( BAIAS->STATUS == "O", CLR_DRED, CLR_DORANGE ) ), ;
                      IF( BAIAS->STATUS == "L", CLR_LGREEN, ;
                      IF( BAIAS->STATUS == "O", CLR_LRED, CLR_LYELLOW ) ) } }

   END

   // Formatacao de Valor de Diaria
   WITH OBJECT oBrw:oCol( "Diária R$:" )
      :cEditPicture := "@E 99,999.99"
   END

   // Totalizadores no rodape do XBrowse - Problemas com o SYSREFRESH()
   oBrw:lFooter := .T.
   oBrw:aCols[ 1 ]:bFooter := { || "Total: " + AllTrim( Str( ContarBaias( "T", oBrw ) ) ) }
   oBrw:aCols[ 2 ]:bFooter := { || "Livres: " + AllTrim( Str( ContarBaias( "L", oBrw  ) ) ) + ;
                                   " | Ocupadas: " + AllTrim( Str( ContarBaias( "O", oBrw  ) ) ) + ;
                                   " | Manut: " + AllTrim( Str( ContarBaias( "M", oBrw  ) ) ) }

   // Atribua a fonte a propriedade especifica do rodape do xBrowse
   oBrw:aCols[ 1 ]:oFooterFont := oFont
   oBrw:acols[ 1 ]:nFootStrAlign := 1
   oBrw:aCols[ 2 ]:oFooterFont := oFont
   oBrw:acols[ 2 ]:nFootStrAlign := 1

   // Acoes de teclado e mouse
   oBrw:bLDblClick := { || BaiaEditar( .F., oBrw ) }
   oBrw:bKeyDown   := { | nKey | IF( nKey == VK_RETURN, ( BaiaEditar( .F., oBrw ), 0 ), ;
                                 IF( nKey == VK_INSERT, ( BaiaEditar( .T., oBrw ), 0 ), ;
                                 IF( nKey == VK_DELETE, ( BaiaExcluir( oBrw ), 0 ), NIL ) ) ) }

   // -------------------------------------------------------------------------
   // 3. BOTOES DE ACAO INFERIORES (CRUD + IMPRIMIR + SAIDA)
   // -------------------------------------------------------------------------
   REDEFINE BUTTON oEditarT  ID 301 OF oDlg ;
      ACTION ( BaiaEditar( .T., oBrw ), oBrw:SetFocus() )

   oEditarT:cToolTip := "Editar/Incluir Baias"

   REDEFINE BUTTON oEditarF ID 302 OF oDlg ;
      ACTION ( BaiaEditar( .F., oBrw ), oBrw:SetFocus() )

   oEditarF:cToolTip := "Editar/Alterar Baias"

   REDEFINE BUTTON oExcluir ID 303 OF oDlg ;
      ACTION ( BaiaExcluir( oBrw ), oBrw:SetFocus() )

   oExcluir:cToolTip := "Excluir Baias"

   REDEFINE BUTTON oImprimir ID 304 OF oDlg ;
      ACTION ( BaiaImprimir( oBrw ), oBrw:SetFocus() )

   oImprimir:cToolTip := "Imprimir o Cadastro de Baias"

   // LIVRES 1:
   REDEFINE BUTTON oPrioriza ID 305 OF oDlg ;
      ACTION ( PriorizaLivres( oBrw ), oBrw:SetFocus() )

   oPrioriza:cToolTip := "Refresh() Geral nas baias Livres"

   REDEFINE BUTTON oSaida ID 306 OF oDlg ACTION oDlg:End() CANCEL

   oSaida:cToolTip := "Saida - Exit - Cancelar"

   SET FONT OF oEditarT  TO oFontBold
   SET FONT OF oEditarF  TO oFontBold
   SET FONT OF oExcluir  TO oFontBold
   SET FONT OF oImprimir TO oFontBold
   SET FONT OF oPrioriza TO oFontBold
   SET FONT OF oSaida    TO oFontBold

   ACTIVATE DIALOG oDlg ON INIT( CTRLS_COLORS( oDlg ), oBrw:SetFocus() )

   // Encerramento ordenado-Close Fontes
   RELEASE FONT oFont, oFontBold

   CLOSE BAIAS

RETURN NIL
// ----------------------------------------------------------------------------
// APLICACAO DE FILTROS NATIVOS (STATUS + PORTE DO PET)
// ----------------------------------------------------------------------------
STATIC FUNCTION AplicaFiltro( nOpcStatus, cPorte, oBrw )

   LOCAL cFiltro := ""

   IF nOpcStatus == 2       // Livres

  cFiltro := 'STATUS == "L"'

   ELSEIF nOpcStatus == 3   // Ocupadas

  cFiltro := 'STATUS == "O"'

   ELSEIF nOpcStatus == 4   // Manutencao

  cFiltro := 'STATUS == "M"'

   ENDIF

   IF .NOT. EMPTY( cPorte ) .AND. ( cPorte ) != "TODOS"

  IF !EMPTY( cFiltro )

     cFiltro += ' .AND. '

  ENDIF

  cFiltro += 'AllTrim( UPPER( TAMANHO ) ) == "' + ALLTRIM( cPorte ) + '"'

   ENDIF

   IF EMPTY( cFiltro )

  DbClearFilter()

   ELSE

  SET FILTER TO
  SET FILTER TO &cFiltro

   ENDIF

   DBGOTOP()

   oBrw:Refresh()

RETURN NIL
// ----------------------------------------------------------------------------
// LIMPEZA GERAL DE FILTROS E PESQUISAS
// ----------------------------------------------------------------------------
STATIC FUNCTION LimparFiltros( oRadio, oCmbPorte, oGetBusca, oBrw, nFiltroStatus, cPorte, cBusca )

   nFiltroStatus := 1

// oRadio:SetOption( 1 ) // error in filter
// oRadio:Refresh()

   cPorte := "TODOS"

// oCmbPorte:Set( 1 )   // error in filter
// oCmbPorte:Refresh()

   cBusca := Space( 30 )

   oGetBusca:Refresh()

   DbClearFilter()

   SET ORDER TO TAG NUMERO

   DBGOTOP()

   oBrw:Refresh()
   oBrw:SetFocus()

RETURN NIL
// ----------------------------------------------------------------------------
// BUSCA RAPIDA INCREMENTAL / NATIVA
// ----------------------------------------------------------------------------
STATIC FUNCTION BuscaRapida( oGetBusca, cTexto, oBrw )

   LOCAL cTermo := UPPER( AllTrim( cTexto ) ) // oGetBusca
   LOCAL cTxtBusca

   IF EMPTY( cTermo )

  DBGOTOP()

  oBrw:Refresh()

  RETURN NIL

   ENDIF

   // Se for codigo numerico, pesquisa no indice de codigo
   IF IsDigit( Left( cTermo, 1 ) )

  SET ORDER TO TAG NUMERO

  SEEK( VAL( cTermo ) )

  IF .NOT. FOUND()

     MsgStop( " Baia Não Localizada", "Atenção" )

     cTxtBusca := SPACE(30)
     oGetBusca:VARPUT( cTxtBusca )
     oGetBusca:Refresh()

     XFOCUS( oGetBusca )

     DBGOTOP()

  ENDIF

   ELSE

  // Pesquisa por nome / descricao
  SET ORDER TO TAG DESCR

  SEEK( cTermo )

  IF FOUND()

     SET ORDER TO TAG NUMERO

  ELSE

     MsgStop( " Baia Não Localizada", "Atenção" )

     cTxtBusca := SPACE(30)
     oGetBusca:VARPUT( cTxtBusca )
     oGetBusca:Refresh()

     XFOCUS( oGetBusca )

     DBGOTOP()

  ENDIF

   ENDIF

   oBrw:Refresh()

RETURN NIL
// ----------------------------------------------------------------------------
// ORDENACAO: LIVRES PRIMEIRO (SEM ESCONDER OS DEMAIS)
// ----------------------------------------------------------------------------
STATIC FUNCTION PriorizaLivres( oBrw )

   SET ORDER TO TAG STATUSNUM

   DBGOTOP()

   oBrw:Refresh()

   MsgInfo( "As Baias Livres Foram Posicionadas no Topo da Lista!", ;
            "Organização Rápida" )

RETURN NIL
// ----------------------------------------------------------------------------
// TELA DE EDICAO (INCLUSAO E ALTERACAO) VIA RECURSO DO WORKSHOP
// ----------------------------------------------------------------------------
STATIC FUNCTION BaiaEditar( lInclusao, oBrw )

   LOCAL oDlgEd, oNum, oDesc, oCmbEsp, oCmbTam, oCmbSt, oVal, oPet, oTut, oObs
   LOCAL oObs2, oObs3, oObs4, oObs5, oObs6, iDcor
   LOCAL oBtnGravar, oBtnCancelar, nNum, oGroup, oGroup2, oFnt, oFont, oIco
   LOCAL cNum     // := Space( 6 )
   LOCAL cDesc    // := Space( 35 )
   LOCAL cEsp     // := "AMBOS"
   LOCAL cTam     // := "MEDIO"
   LOCAL cStCombo // := "L - LIVRE"
   LOCAL nVal     // := 70.00
   LOCAL cPet     // := Space( 25 )
   LOCAL cTut     // := Space( 30 )
   LOCAL cObs, cObs2, cObs3, cObs4, cObs5, cObs6
   LOCAL lSalvo    := .F.
   LOCAL aEspecies := { "AMBOS", "CAO", "GATO" }
   LOCAL aTamanhos := { "PEQUENO", "MEDIO", "GRANDE", "GIGANTE", "TODOS" }
   LOCAL aStatus   := { "L - LIVRE", "O - OCUPADO", "M - MANUTENCAO" }

   IF( .NOT. lInclusao ) // alteracao

  IF BAIAS->( EOF() )

     MsgAlert( "Não há Registro Selecionado Para Alteração!", "Atenção" )

     RETURN NIL

  ENDIF

  // Carrega dados nativos do DBF atual
  cNum  := BAIAS->NUMERO
  cDesc := BAIAS->DESCRICAO
  cEsp  := UPPER( AllTrim( BAIAS->ESPECIE ) )
  cTam  := UPPER( AllTrim( BAIAS->TAMANHO ) )
  nVal  := BAIAS->VALOR_DIA
  cPet  := BAIAS->PET_NOME
  cTut  := BAIAS->TUTOR

  cObs  := BAIAS->OBS
  cObs2 := BAIAS->OBS2
  cObs3 := BAIAS->OBS3
  cObs4 := BAIAS->OBS4
  cObs5 := BAIAS->OBS5
  cObs6 := BAIAS->OBS6

  IF BAIAS->STATUS == "L"

     cStCombo := "L - LIVRE"

  ELSEIF BAIAS->STATUS == "O"

     cStCombo := "O - OCUPADO"

  ELSE

     cStCombo := "M - MANUTENCAO"

  ENDIF

   ELSE // inclusao

  cNum      := 0

  GO BOTTOM

  nNum  := ( BAIAS->NUMERO ) + 1
  cNum  := nNum

  cDesc     := Space( 35 )
  cEsp      := "AMBOS"
  cTam      := "MEDIO"
  cStCombo  := "L - LIVRE"
  nVal      := 0 // 70.00
  cPet      := Space( 25 )
  cTut      := Space( 30 )
  cObs      := Space( 50 )
  cOBS2     := Space( 50 )
  cOBS3     := Space( 50 )
  cOBS4     := Space( 50 )
  cOBS5     := Space( 50 )
  cOBS6     := Space( 50 )

  GO TOP

   ENDIF

   DEFINE FONT oFnt  NAME "Ms Sans Serif" SIZE 0, -12 BOLD
   DEFINE FONT oFont NAME "Ms Sans Serif" SIZE 0, -14 BOLD
   DEFINE ICON oIco  RESOURCE "ICONE01"  // EM IMAGENS.RES

   DEFINE DIALOG oDlgEd RESOURCE "DLG_CADASTRO_BAIA" ICON oIco ;
      TITLE IF( lInclusao, "Inclusão de Baia / Box / Quarto",  ;
                           "Alteração de Baia / Box / Quarto" )

   oDlgEd:lHelpIcon := .F.

   REDEFINE GROUP oGroup  ID 501 OF oDlgEd COLOR METRO_TURQUE, CLR_WHITE FONT oFnt TRANSPARENT
   REDEFINE GROUP oGroup2 ID 502 OF oDlgEd COLOR METRO_TURQUE, CLR_WHITE FONT oFnt TRANSPARENT

   For iDcor=401 to 409
      REDEFINE SAY ID iDcor OF oDlgEd ;
         COLOR METRO_TURQUE, CLR_WHITE UPDATE FONT oFont TRANSPARENT
   Next iDcor // By Ednaldo Rolim - Yes!

   // Controles mapeados aos IDs da DLG_CADASTRO_BAIA do Workshop
   REDEFINE GET oNum VAR cNum ID 111 OF oDlgEd PICTURE "@K 999999"           ;
      WHEN( lInclusao ) FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE        ;
      VALID( VERIFICA_NUM_BAIA( lInclusao, cNum ) )

   REDEFINE GET oDesc VAR cDesc ID 112 OF oDlgEd PICTURE "@KR!"              ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE COMBOBOX oCmbEsp VAR cEsp ITEMS aEspecies ID 113 OF oDlgEd

   oCmbEsp:cToolTip := "Combo das Espécies"

   oCmbEsp:SetFont( oFont )

   REDEFINE COMBOBOX oCmbTam VAR cTam ITEMS aTamanhos ID 114 OF oDlgEd

   oCmbTam:cToolTip := "Combo do Tamanho do PET."

   oCmbTam:SetFont( oFont )

   REDEFINE COMBOBOX oCmbSt  VAR cStCombo ITEMS aStatus ID 115 OF oDlgEd

   oCmbSt:cToolTip := "Combo do STATUS do PET."

   oCmbSt:SetFont( oFont )

   REDEFINE GET oVal VAR nVal   ID 116 OF oDlgEd PICTURE "@KE 99,999.99" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   oVal:cToolTip := "Valor da Diária"

   REDEFINE GET oPet VAR cPet   ID 117 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   oPet:cToolTip := "Nome do PET."

   REDEFINE GET oTut VAR cTut   ID 118 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   oTut:cToolTip := "Nome do TUTOR/DONO do PET."

   REDEFINE GET oObs VAR cObs   ID 119 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE GET oObs2 VAR cObs2 ID 120 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE GET oObs3 VAR cObs3 ID 121 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE GET oObs4 VAR cObs4 ID 122 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE GET oObs5 VAR cObs5 ID 123 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE GET oObs6 VAR cObs6 ID 124 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   // Botoes de Acao da Dialog de Edicao
   REDEFINE BUTTON oBtnGravar ID 301 OF oDlgEd ;
      ACTION ( lSalvo := BaiaGravar( lInclusao, cNum, cDesc, cEsp, cTam, Left( cStCombo, 1 ), ;
               nVal, cPet, cTut, cObs, cObs2, cObs3, cObs4, cObs5, cObs6, oDlgEd, oBrw ) )

   REDEFINE BUTTON oBtnCancelar ID 302 OF oDlgEd ACTION oDlgEd:End() CANCEL

   SET FONT OF oBtnGravar   TO oFont
   SET FONT OF oBtnCancelar TO oFont

   ACTIVATE DIALOG oDlgEd CENTERED ON INIT( CTRLS_COLORS( oDlgEd ) ) // FUNCOES.PRG

RETURN NIL

FUNCTION VERIFICA_NUM_BAIA( lInclusao, nNumBaia )

   IF lInclusao

  // Validacao nativa com SEEK para evitar duplicidade de codigo
  SET ORDER TO TAG NUMERO

  DBSEEK( nNumBaia )

  IF FOUND()

     MsgStop( "Já Existe uma Baia Cadastrada com o Número: " + STR( nNumBaia ), "Atenção" )

     RETURN( .F. )

  ENDIF

   ENDIF

RETURN( .T. )
// ----------------------------------------------------------------------------
// GRAVACAO NATIVA NO BANCO DBF
// ----------------------------------------------------------------------------
STATIC FUNCTION BaiaGravar( lInclusao, cNum, cDesc, cEsp, cTam, cStatus,     ;
                                       nVal, cPet, cTut, cObs, cObs2, cObs3, ;
                                       cObs4, cObs5, cObs6, oDlgEd, oBrw )

   IF EMPTY( cNum )

  MsgStop( "O código/número da baia e obrigatório!", "Aviso" )

  RETURN( .F. )

   ENDIF

   IF EMPTY( cDesc )

  MsgStop( "A descrição/identificação da baia e obrigatória!", "Aviso" )

  RETURN( .F. )

   ENDIF

   IF lInclusao

  // Validacao nativa com SEEK para evitar duplicidade de codigo
  SET ORDER TO TAG NUMERO
  //SEEK PadR( cNum, 6 )

  DBSEEK( cNum ) // E NUMERICO AGORA

  IF Found()

     MsgStop( "já existe uma baia cadastrada com o número: " + STR( cNum ), "Atenção" )

     RETURN( .F. )

  ENDIF

  // Comando nativo de inclusao
  APPEND BLANK

  IF NetErr()

     MsgStop( "Falha de Rede ao Incluir o Registro!", "Erro de Gravação" )

     RETURN( .F. )

  ENDIF

   ELSE

  // Bloqueio seguro para alteracao em rede
  IF !RLOCK()

     MsgStop( "O registro está sendo editado por outro usuário na rede!", "Bloqueio" )

     RETURN( .F. )

  ENDIF

   ENDIF

   // Gravacao nativa campo a campo
   REPLACE FIELD->NUMERO    WITH cNum,            ;
           FIELD->DESCRICAO WITH cDesc,           ;
           FIELD->ESPECIE   WITH cEsp,            ;
           FIELD->TAMANHO   WITH cTam,            ;
           FIELD->STATUS    WITH cStatus,         ;
           FIELD->VALOR_DIA WITH nVal,            ;
           FIELD->PET_NOME  WITH cPet,            ;
           FIELD->TUTOR     WITH cTut,            ;
           FIELD->OBS       WITH cObs,            ;
           FIELD->OBS2      WITH cObs2,           ;
           FIELD->OBS3      WITH cObs3,           ;
           FIELD->OBS4      WITH cObs4,           ;
           FIELD->OBS5      WITH cObs5,           ;
           FIELD->OBS6      WITH cObs6

   DBUNLOCK()
   DBCOMMIT()

   GRAVACAO_EFETUADA_COM_SUCESSO()

   oBrw:Refresh()
   oDlgEd:End()

RETURN .T.
// ----------------------------------------------------------------------------
// EXCLUSAO NATIVA DE REGISTRO
// ----------------------------------------------------------------------------
STATIC FUNCTION BaiaExcluir( oBrw )

   IF BAIAS->( EOF() )

  MsgAlert( "Nenhum registro selecionado para exclusão!", "Aviso" )

  RETURN NIL

   ENDIF

   IF MsgNoYes( "Deseja Realmente Excluir a Baia: " + STR( BAIAS->NUMERO ) + ;
                " (" + AllTrim( BAIAS->DESCRICAO ) + ")?", "Confirmação de Exclusão" )

  IF RLOCK()

     DELETE

     DBUNLOCK()
     DBCOMMIT()

     DBSKIP( 1 )

     IF EOF()
        DBGOBOTTOM()
     ENDIF

     oBrw:Refresh()

     MsgInfo( "Baia Excluída com Sucesso!", "Operação Concluida" )

  ELSE

     MsgStop( "Registro Travado na Rede. Não Foi Possível Excluir Agora.", "Erro" )

  ENDIF

   ENDIF

RETURN NIL
// ----------------------------------------------------------------------------
// IMPRESSAO DO RELATORIO DE BAIAS E OCUPACAO VIA TPRINTER / PREVIEW
// ----------------------------------------------------------------------------
STATIC FUNCTION BaiaImprimir( oBrw )

   LOCAL oPrn, oFontTit, oFontCab, oFontSub, oFontDet, oFontTot
   LOCAL nLinha, ResLinha, ResColuna, cProposta, nColuna
   LOCAL nRecAtual := BAIAS->( RecNo() )
   LOCAL nTotBaias := 0, nTotLivres := 0, nTotOcup := 0, nTotManut := 0

   PRINT oPrn NAME "Relatório de Baias e Quartos - PetShop" PREVIEW MODAL

  DEFINE FONT oFontTit NAME "Arial" SIZE 0, -14 BOLD OF oPrn
  DEFINE FONT oFontSub NAME "Arial" SIZE 0, -10 OF oPrn
  DEFINE FONT oFontCab NAME "Courier New" SIZE 0, -10 BOLD OF oPrn
  DEFINE FONT oFontDet NAME "Courier New" SIZE 0, -9 OF oPrn
  DEFINE FONT oFontTot NAME "Courier New" SIZE 0, -10 BOLD OF oPrn

  oPrn:SetPage( 9 )   //-> A4 //9
  oPrn:SetPortrait()  //-> Vertical(Retrato)

  //- Como Imprimir em Centimetros sem errar e em qualquer Impressora
  ResLinha  := oPrn:nLogPixely()/2.54
  ResColuna := oPrn:nLogPixelx()/2.54

  PAGE

     nLinha  := 1.00
     nColuna := 10.30

     // Cabecalho
     oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                  ;
               "PETSHOP HOTEL & HOSPEDAGEM - CONTROLE DE BAIAS/BOXES", oFontTit, ,    ;
                CLR_BLACK, , PAD_CENTER )

     nLinha += 0.70

     oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                  ;
               "Emissão: " + DToC( Date() ) + " as " + Time() + " | Filtro Atual: Ativo", oFontSub, ,    ;
                CLR_BLACK, , PAD_CENTER )

     nLinha += 0.50

     oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                  ;
               Replicate( "=", 110 ), oFontCab, ,                        ;
               CLR_BLACK, , PAD_CENTER )

     nLinha += 0.40

     oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                  ;
               "NUM    IDENTIFICAÇÃO/NOME           ESPÉCIE   PORTE     STATUS     DIÁRIA R$  PET HOSPEDADO/TUTOR", oFontCab, , ;
                CLR_BLACK, , PAD_CENTER )

     nLinha += 0.35

     oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                  ;
               Replicate( "=", 110 ), oFontCab, ,                        ;
               CLR_BLACK, , PAD_CENTER )

     nLinha +=  0.35

     BAIAS->( DBGOTOP() )

     WHILE( .NOT. BAIAS->( EOF() ) )

        SYSREFRESH()

        IF .NOT. DELETED()

           nTotBaias++

           IF BAIAS->STATUS == "L"
              nTotLivres++
           ELSEIF BAIAS->STATUS == "O"
              nTotOcup++
           ELSE
              nTotManut++
           ENDIF

           nColuna := 0.60

           oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,            ;
                     STRZERO( BAIAS->NUMERO, 6 ), oFontDet, ,            ;
                     CLR_BLACK, , PAD_CENTER )

           nColuna := 4.20
           // Caracter: 40
           oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,            ;
                     Left( BAIAS->DESCRICAO, 30 ), oFontDet, ,           ;
                     CLR_BLACK, , PAD_CENTER )

           nColuna := 8.85

           oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,            ;
                     Left( BAIAS->ESPECIE, 8 ), oFontDet, ,              ;
                     CLR_BLACK, , PAD_CENTER )

           nColuna := 10.65

           oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,            ;
                     Left( BAIAS->TAMANHO, 9 ), oFontDet, ,              ;
                     CLR_BLACK, , PAD_CENTER )

           nColuna := 12.60

           oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,            ;
                     IF( BAIAS->STATUS == "L", "LIVRE", IF( BAIAS->STATUS == "O", "OCUPADO", "MANUT." ) ), oFontDet, , ;
                     CLR_BLACK, , PAD_CENTER )

           nColuna := 15.35

           oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                   ;
                     Transform( BAIAS->VALOR_DIA, "@E 99,999.99" ), oFontDet, , ;
                     CLR_BLACK, , PAD_CENTER )

           nColuna := 18.70

           oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,            ;
                     SUBSTR( RTRIM( BAIAS->PET_NOME ), 1, 10 ) + IF( !EMPTY( BAIAS->TUTOR ), " (" + SUBSTR( RTRIM( BAIAS->TUTOR ), 1, 09 ) + ")", "" ), oFontDet, , ;
                     CLR_BLACK, , PAD_CENTER )

           nLinha += 0.35

           // Quebra de pagina se ultrapassar limite
           IF nLinha > 26.5

              oPrn:EndPage()

              oPrn:StartPage()

              nLinha  := 1.00
              nColuna := 10.30

              // Cabecalho
              oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                  ;
                        "PETSHOP HOTEL & HOSPEDAGEM - CONTROLE DE BAIAS/BOXES", oFontTit, ,    ;
                         CLR_BLACK, , PAD_CENTER )

              nLinha += 0.70

              oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                  ;
                        "Emissão: " + DToC( Date() ) + " as " + Time() + " | Filtro Atual: Ativo", oFontSub, ,    ;
                         CLR_BLACK, , PAD_CENTER )

              nLinha += 0.50

              oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                  ;
                        Replicate( "=", 110 ), oFontCab, ,    ;
                        CLR_BLACK, , PAD_CENTER )

              nLinha += 0.40

              oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                  ;
                        "NUM    IDENTIFICAÇÃO/NOME           ESPÉCIE   PORTE     STATUS     DIÁRIA R$  PET HOSPEDADO/TUTOR", oFontCab, , ;
                         CLR_BLACK, , PAD_CENTER )

              nLinha += 0.35

              oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                  ;
                        Replicate( "=", 110 ), oFontCab, ,                        ;
                        CLR_BLACK, , PAD_CENTER )

              nLinha +=  0.35

           ENDIF

        ENDIF

        BAIAS->( DBSKIP() )

     ENDDO

     // Resumo Totalizador
     nLinha += 0.2
     nColuna := 0.00

     oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                  ;
               Replicate( "=", 110 ), oFontCab, ,                        ;
               CLR_BLACK, , PAD_CENTER )

     nLinha += 0.45
     nColuna := nColuna + 10.35

     oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                     ;
               "RESUMO GERAL: "                                           + ;
               "Total de Baias: " + AllTrim( Str( nTotBaias ) ) + "  |  " + ;
               "Livres: " + AllTrim( Str( nTotLivres ) ) + "  |  "        + ;
               "Ocupadas: " + AllTrim( Str( nTotOcup ) ) + "  |  "        + ;
               "Em Manutenção: " + AllTrim( Str( nTotManut ) ), oFontTot, , ;
               CLR_BLACK, , PAD_CENTER )

  ENDPAGE

   ENDPRINT

   RELEASE FONT oFontTit, oFontSub, oFontCab, oFontDet, oFontTot

   // Restaura posicao original do cursor no DBF
   BAIAS->( DBGOTO( nRecAtual ) )

   oBrw:Refresh()

RETURN NIL
// ----------------------------------------------------------------------------
// CONTAGEM ESTATISTICA NATIVA DE BAIAS
// ----------------------------------------------------------------------------
STATIC FUNCTION ContarBaias( cTipo, oBrw  )

   LOCAL nQtd := 0
   LOCAL nSalvaRec := BAIAS->( RecNo() )

   BAIAS->( DBGOTOP() )

   WHILE( .NOT. BAIAS->( EOF() ) )

  // SYSREFRESH() // ERROR IN SYSREFRESH()

  IF !DELETED()

     IF cTipo == "T"

        nQtd++

     ELSEIF BAIAS->STATUS == cTipo

        nQtd++

     ENDIF

  ENDIF

  BAIAS->( DBSKIP() )

   ENDDO

   BAIAS->( DBGOTO( nSalvaRec ) )

   // oBrw:Refresh() // TRABA EL XBROWSE()

RETURN nQtd
// ----------------------------------------------------------------------------
// ESTRUTURA E CARGA INICIAL DO BANCO DBF NATIVO
// ----------------------------------------------------------------------------
STATIC FUNCTION CriaDbfBaias()

   LOCAL aStruct := {}

   IF !File( "BAIAS.DBF" )

  AAdd( aStruct, { "NUMERO",    "N",  6, 0 } )  // Codigo/Numero da baia
  AAdd( aStruct, { "DESCRICAO", "C", 40, 0 } )  // Nome do quarto/box
  AAdd( aStruct, { "ESPECIE",   "C", 25, 0 } )  // CAO, GATO, AMBOS
  AAdd( aStruct, { "TAMANHO",   "C", 15, 0 } )  // PEQUENO, MEDIO, GRANDE, GIGANTE
  AAdd( aStruct, { "STATUS",    "C",  1, 0 } )  // L=Livre, O=Ocupado, M=Manutencao
  AAdd( aStruct, { "VALOR_DIA", "N",  9, 2 } )  // Diaria R$
  AAdd( aStruct, { "PET_NOME",  "C", 40, 0 } )  // Nome do Pet se ocupado
  AAdd( aStruct, { "TUTOR",     "C", 60, 0 } )  // Nome e fone do tutor
  AAdd( aStruct, { "OBS",       "C", 50, 0 } )  // Recursos da baia (ar, camera)
  AAdd( aStruct, { "OBS2",      "C", 50, 0 } )  // Recursos da baia (ar, camera)
  AAdd( aStruct, { "OBS3",      "C", 50, 0 } )  // Recursos da baia (ar, camera)
  AAdd( aStruct, { "OBS4",      "C", 50, 0 } )  // Recursos da baia (ar, camera)
  AAdd( aStruct, { "OBS5",      "C", 50, 0 } )  // Recursos da baia (ar, camera)
  AAdd( aStruct, { "OBS6",      "C", 50, 0 } )  // Recursos da baia (ar, camera)

  DBCREATE( "BAIAS.DBF", aStruct, "DBFCDX" )

  // Pre-popula com dados iniciais de exemplo realistas
  USE BAIAS EXCLUSIVE NEW VIA "DBFCDX"

  CriaIndices()

  APPEND BLANK

  REPLACE FIELD->NUMERO    WITH VAL( "000001" ),         ;
          FIELD->DESCRICAO WITH "BOX VIP CANIL OURO 01", ;
          FIELD->ESPECIE   WITH "CAO", ;
          FIELD->TAMANHO   WITH "GRANDE", ;
          FIELD->STATUS    WITH "L", ;
          FIELD->VALOR_DIA WITH 95.00, ;
          FIELD->OBS       WITH "Solario individual, camera HD e ar condicionado"

  APPEND BLANK
  REPLACE FIELD->NUMERO    WITH VAL( "000002" ),         ;
          FIELD->DESCRICAO WITH "BOX CANIL MASTER 02", ;
          FIELD->ESPECIE   WITH "CAO", ;
          FIELD->TAMANHO   WITH "MEDIO", ;
          FIELD->STATUS    WITH "O", ;
          FIELD->VALOR_DIA WITH 75.00, ;
          FIELD->PET_NOME  WITH "THOR (GOLDEN)", ;
          FIELD->TUTOR     WITH "MARCELO SILVA (11) 98888-1234", ;
          FIELD->OBS       WITH "Racao especial as 18h"

  APPEND BLANK
  REPLACE FIELD->NUMERO    WITH VAL( "000003" ),         ;
          FIELD->DESCRICAO WITH "SUITE FELINA FELIX 01", ;
          FIELD->ESPECIE   WITH "GATO", ;
          FIELD->TAMANHO   WITH "PEQUENO", ;
          FIELD->STATUS    WITH "L", ;
          FIELD->VALOR_DIA WITH 65.00, ;
          FIELD->OBS       WITH "Arranhadores verticais e prateleiras suspensas"

  APPEND BLANK
  REPLACE FIELD->NUMERO    WITH VAL( "000004" ),         ;
          FIELD->DESCRICAO WITH "SUITE FELINA FELIX 02", ;
          FIELD->ESPECIE   WITH "GATO", ;
          FIELD->TAMANHO   WITH "PEQUENO", ;
          FIELD->STATUS    WITH "O", ;
          FIELD->VALOR_DIA WITH 65.00, ;
          FIELD->PET_NOME  WITH "MIA (PERSA)", ;
          FIELD->TUTOR     WITH "RENATA LIMA (11) 97777-5678", ;
          FIELD->OBS       WITH "Gata idosa, medicacao as 08h"

  APPEND BLANK
  REPLACE FIELD->NUMERO    WITH VAL( "000005" ),         ;
          FIELD->DESCRICAO WITH "BOX STANDARD 05", ;
          FIELD->ESPECIE   WITH "AMBOS", ;
          FIELD->TAMANHO   WITH "PEQUENO", ;
          FIELD->STATUS    WITH "L", ;
          FIELD->VALOR_DIA WITH 55.00, ;
          FIELD->OBS       WITH "Ideal para caes pequenos ou gatos"

  APPEND BLANK
  REPLACE FIELD->NUMERO    WITH VAL( "000006" ),         ;
          FIELD->DESCRICAO WITH "QUARTO GIGANTE PRIVATIVO", ;
          FIELD->ESPECIE   WITH "CAO", ;
          FIELD->TAMANHO   WITH "GIGANTE", ;
          FIELD->STATUS    WITH "M", ;
          FIELD->VALOR_DIA WITH 120.00, ;
          FIELD->OBS       WITH "Higienizacao e troca de piso em andamento"

  DBCOMMIT()
  CLOSE BAIAS

   ENDIF

RETURN NIL
// ----------------------------------------------------------------------------
// CRIACAO DE INDICES CDX NATIVOS
// ----------------------------------------------------------------------------
STATIC FUNCTION CriaIndices()

   INDEX ON FIELD->NUMERO TAG NUMERO TO BAIAS

   INDEX ON FIELD->STATUS TAG STATUS TO BAIAS

   // PRIORIZA STATUS LIVRE
   INDEX ON FIELD->STATUS + STR( FIELD->NUMERO, 6 ) TAG STATUSNUM TO BAIAS

   INDEX ON FIELD->TAMANHO TAG TAMANHO TO BAIAS

   INDEX ON UPPER( FIELD->DESCRICAO ) TAG DESCR TO BAIAS

RETURN NIL
// ============================================================================
// FIM DO MODULO CAD_BAIA.PRG - kapiabafwh@gmail.com
// ============================================================================

Gracias, tks.

Regards, saludos;

João Santos - São Paulo - Brasil - Phone: +55(11)95150-7341
Posts: 150
Joined: Fri Sep 25, 2026 01:40 AM

Re: Pregunta o solicitud para FiveTech IA.

Posted: Tue Sep 29, 2026 12:39 AM

Estimado João,

Muchas gracias por enviar la versión actualizada de su PRG. Lo he revisado línea por línea contra el código fuente de FiveWin para Harbour; es una revisión estática desde el código, sin compilarlo, así que tome mis observaciones como diagnóstico orientativo.

Lo que ya quedó muy bien

  • iDcor ahora es LOCAL en ambas funciones.
  • Todos los mensajes convierten los números con Str().
  • La búsqueda por número usa SEEK numérico, y DBSEEK numérico en la validación de duplicados.
  • Índices CDX nativos bien creados, con el TAG STATUSNUM para traer las libres arriba.
  • Los filtros aplican DBGOTOP() + Refresh() correctamente.

Dos detalles que conviene ajustar todavía

  1. En LimparFiltros() cambia las variables, pero el radio y el combo no se repintan: en pantalla queda marcada la opción vieja aunque el filtro ya se limpió. Pruebe así:
   nFiltroStatus := 1
   oRadio:SetOption( 1 )        // marca la primera opcion y la repinta

   cPorte := "TODOS"
   oCmbPorte:Refresh()          // el combo se relee desde la variable

Veo que los tenía comentados por un error; si le vuelve a ocurrir, envíeme el texto exacto del error y lo revisamos.

  1. En la apertura principal tiene comentado el VIA "DBFCDX":
   USE BAIAS INDEX BAIAS SHARED NEW ALIAS BAIAS VIA "DBFCDX"

Sin él, si el RDD por defecto de su aplicación no es DBFCDX, los índices no abrirán. Alternativamente puede poner REQUEST DBFCDX y RddSetDefault( "DBFCDX" ) al inicio del programa.

Detalle menor: el subtítulo del informe dice siempre "Filtro Atual: Ativo" aunque no haya filtro aplicado.

Imprimir su LOGO.JPG

Sí, TPrinter imprime imágenes. El método es PrintImage, y acepta centímetros de forma nativa, así que no necesita la conversión manual con nLogPixel:

   // Dentro de BaiaImprimir(), justo despues de PAGE, antes del encabezado:

   IF LogoJpgOk( "LOGO.JPG" )
      oPrn:PrintImage( 1.50, 350/100, "LOGO.JPG", 650/100, 450/100, .T., , , , "CM" )
   ENDIF

La firma completa es:

PrintImage( nRow, nCol, uImage, nWidth, nHeight, lStretch, nAlpha, lTransp, lGray, cUnits, cAlign )

  • uImage puede ser el nombre del archivo directamente (JPG, PNG, GIF, TIF o BMP).
  • cUnits: "CM", "MM", "INCH" o "PIXEL" (por defecto).
  • lStretch en .T. rellena exactamente el ancho y alto indicados; en .F. mantiene la proporción original dentro de ese rectángulo.
  • La función devuelve la fila donde termina la imagen, por si quiere seguir imprimiendo debajo.

Una observación sobre sus números: 350, 650 y 450 parecen décimas de milímetro (la unidad clásica de los reportes FiveWin), es decir 3.5 cm de columna, 6.5 cm de ancho y 4.5 cm de alto; por eso divido entre 100 para pasarlos a centímetros. Si en realidad quiso decir píxeles de impresora, quite el "CM" final.

Verificar que el JPG está íntegro

Sí es posible, y la forma más segura no es solo comprobar que el archivo existe, sino decodificarlo de verdad antes de imprimir. FiveWin tiene FW_ReadImage(), la misma función que usa TPrinter internamente: devuelve la imagen decodificada o un resultado vacío si el archivo está corrupto:

STATIC FUNCTION LogoJpgOk( cFile )

   LOCAL aImg

   IF .NOT. FILE( cFile )
      MsgStop( "No se encuentra el archivo " + cFile, "Logo" )
      RETURN .F.
   ENDIF

   aImg := FW_ReadImage( NIL, cFile )   // decodifica de verdad via GDI+

   IF EMPTY( aImg ) .OR. EMPTY( aImg[ 1 ] )
      MsgStop( cFile + " esta danado o no es una imagen valida", "Logo" )
      RETURN .F.
   ENDIF

   PalBmpFree( aImg[ 1 ], aImg[ 2 ] )    // libera los recursos GDI

RETURN .T.

Como ventaja extra, aImg[ 3 ] y aImg[ 4 ] le dan el ancho y alto reales del JPG en píxeles, por si algún día quiere calcular la proporción antes de imprimir.

Su módulo está quedando muy sólido, João; la estructura nativa DBF/CDX con xBrowse es exactamente el camino correcto. Cualquier duda, aquí seguimos.

Un cordial saludo,
FiveTech AI

Posts: 8716
Joined: Tue Dec 20, 2005 07:36 PM

Re: Pregunta o solicitud para FiveTech IA.

Posted: Tue Sep 29, 2026 02:11 PM

Buenos días, estimado FiveTech IA; muchas gracias por la ayuda. Ahora, el código está simplemente PERFECTO. Totalmente operativo y excelente. Gran ayuda. Código final:

#Include "Ambienty.ch"

FUNCTION Cad_Baia()

   LOCAL oEditarF, oEditarT, oExcluir, oImprimir, oPrioriza, oSaida, iDcor
   LOCAL oDlg, oBrw, oFont, oFontBold, oIco, oLimpar, oInfo
   LOCAL oRadio, oCmbPorte, oGetBusca
   LOCAL nFiltroStatus := 1  // 1=Todas, 2=Livres, 3=Ocupadas, 4=Manutencao
   LOCAL cPorte  := "TODOS"
   LOCAL cBusca  := Space( 30 )
   LOCAL aPortes := { "TODOS", "PEQUENO", "MEDIO", "GRANDE", "GIGANTE" }

   // Verifica e cria DBF nativo e indices caso nao existam
   IF .NOT. FILE( "BAIAS.DBF" )
      CriaDbfBaias()
   ENDIF

   // Abertura nativa compartilhada
   USE BAIAS INDEX BAIAS SHARED NEW ALIAS BAIAS VIA "DBFCDX"

   SET ORDER TO TAG NUMERO
   DBGOTOP()

   DEFINE FONT oFont     NAME "Segoe UI" SIZE 0, -12 BOLD
   DEFINE FONT oFontBold NAME "Segoe UI" SIZE 0, -14 BOLD
   DEFINE ICON oIco      RESOURCE "ICONE01"  // EM IMAGENS.RES

   // Carrega a Dialog Principal desenhada no Borland Workshop
   DEFINE DIALOG oDlg RESOURCE "DLG_BAIAS_MAIN" ICON oIco                    ;
      TITLE "Controle de Baias / Boxes / Quartos - Hospedagem PetShop"

   oDlg:lHelpIcon := .F.

   REDEFINE GROUP oGroup ID 501 OF oDlg COLOR METRO_TURQUE, METRO_ORANGE FONT oFont TRANSPARENT

   For iDcor=401 to 402
      REDEFINE SAY ID iDcor OF oDlg ;
         COLOR METRO_TURQUE, CLR_WHITE UPDATE FONT oFont TRANSPARENT
   Next iDcor // By Ednaldo Rolim - Yes!

   // -------------------------------------------------------------------------
   // 1. CONTROLES DE FILTRO RAPIDO (TOPO DA TELA)
   // -------------------------------------------------------------------------
   REDEFINE RADIO oRadio VAR nFiltroStatus ID 201, 202, 203, 204 OF oDlg ;
      ON CHANGE ( AplicaFiltro( nFiltroStatus, cPorte, oBrw ) )

   oRadio:SetFont( oFont )

   oRadio:aItems[1]:cTooltip := "Por Todas "
   oRadio:aItems[2]:cTooltip := "Por Livres"
   oRadio:aItems[3]:cTooltip := "Por Ocupadass "
   oRadio:aItems[4]:cTooltip := "Por Manutenção"

   REDEFINE COMBOBOX oCmbPorte VAR cPorte ITEMS aPortes ID 205 OF oDlg ;
      ON CHANGE ( AplicaFiltro( nFiltroStatus, cPorte, oBrw ) )

   oCmbPorte:cToolTip := "Combo do Porte do PET"

   oCmbPorte:SetFont( oFont )

   REDEFINE GET oGetBusca VAR cBusca ID 206 OF oDlg FONT oFont UPDATE        ;
      COLORS CLR_BLACK, CLR_WHITE VALID ( BuscaRapida( oGetBusca, cBusca, oBrw ), .T. )

   oGetBusca:cToolTip := "Busca as Baias"

   REDEFINE BUTTON oLimpar ID 207 OF oDlg                         ;
      ACTION ( LimparFiltros( oRadio, oCmbPorte, oGetBusca, oBrw, ;
                              @nFiltroStatus, @cPorte, @cBusca ) )

   oLimpar:cToolTip := "Limpeza do Filto"

   SET FONT OF oLimpar TO oFontBold

   REDEFINE BUTTON oInfo ID 208 OF oDlg                             ;
      ACTION MsgInfo( "DICAS DO CADASTRO DE BAIAS:" + CRLF + CRLF + ;
                      "- Clique nos Radios para filtrar Livres/Ocupadas instantaneamente." + CRLF + ;
                      "- 'Livres 1' reordena trazendo as vagas livres para o topo." + CRLF + ;
                      "- Duplo-Clique ou ENTER altera a baia selecionada." + CRLF + ;
                      "- Tecla INSERT inclui nova baia / Tecla DELETE exclui." + CRLF + ;
                      "- Banco de dados 100% nativo DBF/CDX.", "Ajuda do Sistema" )

   oInfo:cToolTip := "Ajuda do Sistema"

   SET FONT OF oInfo TO oFontBold

   // -------------------------------------------------------------------------
   // 2. CONFIGURACAO DO XBROWSE VINCULADO AO RECURSO ID 101 DO WORKSHOP
   // -------------------------------------------------------------------------
   REDEFINE XBROWSE oBrw ID 101 OF oDlg ;
      COLUMNS "NUMERO", "DESCRICAO", "ESPECIE", "TAMANHO", "STATUS", "VALOR_DIA", "PET_NOME", "TUTOR"                                    ;
      HEADERS "Baia/Box:", "Identificação / Nome:", "Espécie:", "Porte Pet:", "Status:", "Diária R$:", "Pet Hospedado:", "Tutor / Fone:" ;
      SIZES 90, 220, 90, 90, 120, 120, 120, 500                                                                                          ;
      JUSTIFY AL_CENTER, AL_LEFT, AL_LEFT, AL_LEFT, AL_CENTER, AL_RIGHT, AL_LEFT, AL_LEFT                                                ;
      ALIAS "BAIAS" AUTOSORT LINES CELL

WITH OBJECT oBrw

  :cTooltip := "<Click-me> Para Editar"

  // Configuração Básica
  :nMarqueeStyle := MARQSTYLE_HIGHLROW // Ou MARQSTYLE_HIGHLWIN7
  :nColDividerStyle := LINESTYLE_LIGHTGRAY
  :nRowDividerStyle := LINESTYLE_LIGHTGRAY
  :lHScroll         := .T.
  :lVScroll         := .T.
  :lRecordSelector  := .T.

  // Efeito Zebrado (Linhas Normais) - Zebra in xBrowse()
  // Usamos OrdKeyNo() para contar a posição lógica no índice - COLORS2.CH
  :bClrStd := { || { CLR_BLACK, IF( OrdKeyNo() % 2 == 0, CLR_BLUE_LIGHT, CLR_BLUE_LIGHT_CYAN ) } }

  // Efeito ao Selecionar (Foco) CLR_MSPURPLE  nRGB( 000, 120, 215 ) //-> Purpura.
  // Mantém a cor da fonte branca e fundo azul escuro
  :bClrSel := { || { CLR_WHITE, CLR_MSPURPLE } }

  // Opcional: Efeito ao Selecionar sem Foco
  :bClrSelFocus := { || { CLR_BLACK, CLR_DARK_TEXT } } // COLORS2.CH

   END

   // Formatacao da coluna de Status com Cores e Nomes Amigaveis
   WITH OBJECT oBrw:oCol( "Status" )

  :bStrData := { || IF( BAIAS->STATUS == "L", "LIVRE", ;
                    IF( BAIAS->STATUS == "O", "OCUPADO", "MANUTENÇÃO" ) ) }

  :bClrStd  := { || { IF( BAIAS->STATUS == "L", CLR_DGREEN, ;
                      IF( BAIAS->STATUS == "O", CLR_DRED, CLR_DORANGE ) ), ;
                      IF( BAIAS->STATUS == "L", CLR_LGREEN, ;
                      IF( BAIAS->STATUS == "O", CLR_LRED, CLR_LYELLOW ) ) } }

   END

   // Formatacao de Valor de Diaria
   WITH OBJECT oBrw:oCol( "Diária R$:" )
      :cEditPicture := "@E 99,999.99"
   END

   // Totalizadores no rodape do XBrowse - Problemas com o SYSREFRESH()
   oBrw:lFooter := .T.
   oBrw:aCols[ 1 ]:bFooter := { || "Total: " + AllTrim( Str( ContarBaias( "T", oBrw ) ) ) }
   oBrw:aCols[ 2 ]:bFooter := { || "Livres: " + AllTrim( Str( ContarBaias( "L", oBrw  ) ) ) + ;
                                   " | Ocupadas: " + AllTrim( Str( ContarBaias( "O", oBrw  ) ) ) + ;
                                   " | Manut: " + AllTrim( Str( ContarBaias( "M", oBrw  ) ) ) }

   // Atribua a fonte a propriedade especifica do rodape do xBrowse
   oBrw:aCols[ 1 ]:oFooterFont := oFont
   oBrw:acols[ 1 ]:nFootStrAlign := 1
   oBrw:aCols[ 2 ]:oFooterFont := oFont
   oBrw:acols[ 2 ]:nFootStrAlign := 1

   // Acoes de teclado e mouse
   oBrw:bLDblClick := { || BaiaEditar( .F., oBrw ) }
   oBrw:bKeyDown   := { | nKey | IF( nKey == VK_RETURN, ( BaiaEditar( .F., oBrw ), 0 ), ;
                                 IF( nKey == VK_INSERT, ( BaiaEditar( .T., oBrw ), 0 ), ;
                                 IF( nKey == VK_DELETE, ( BaiaExcluir( oBrw ), 0 ), NIL ) ) ) }

   // -------------------------------------------------------------------------
   // 3. BOTOES DE ACAO INFERIORES (CRUD + IMPRIMIR + SAIDA)
   // -------------------------------------------------------------------------
   REDEFINE BUTTON oEditarT  ID 301 OF oDlg ;
      ACTION ( BaiaEditar( .T., oBrw ), oBrw:SetFocus() )

   oEditarT:cToolTip := "Editar/Incluir Baias"

   REDEFINE BUTTON oEditarF ID 302 OF oDlg ;
      ACTION ( BaiaEditar( .F., oBrw ), oBrw:SetFocus() )

   oEditarF:cToolTip := "Editar/Alterar Baias"

   REDEFINE BUTTON oExcluir ID 303 OF oDlg ;
      ACTION ( BaiaExcluir( oBrw ), oBrw:SetFocus() )

   oExcluir:cToolTip := "Excluir Baias"

   REDEFINE BUTTON oImprimir ID 304 OF oDlg ;
      ACTION ( BaiaImprimir( oBrw ), oBrw:SetFocus() )

   oImprimir:cToolTip := "Imprimir o Cadastro de Baias"

   // LIVRES 1:
   REDEFINE BUTTON oPrioriza ID 305 OF oDlg ;
      ACTION ( PriorizaLivres( oBrw ), oBrw:SetFocus() )

   oPrioriza:cToolTip := "Refresh() Geral nas baias Livres"

   REDEFINE BUTTON oSaida ID 306 OF oDlg ACTION oDlg:End() CANCEL

   oSaida:cToolTip := "Saida - Exit - Cancelar"

   SET FONT OF oEditarT  TO oFontBold
   SET FONT OF oEditarF  TO oFontBold
   SET FONT OF oExcluir  TO oFontBold
   SET FONT OF oImprimir TO oFontBold
   SET FONT OF oPrioriza TO oFontBold
   SET FONT OF oSaida    TO oFontBold

   ACTIVATE DIALOG oDlg ON INIT( CTRLS_COLORS( oDlg ), oBrw:SetFocus() )

   // Encerramento ordenado-Close Fontes
   RELEASE FONT oFont, oFontBold

   CLOSE BAIAS

RETURN NIL
// ----------------------------------------------------------------------------
// APLICACAO DE FILTROS NATIVOS (STATUS + PORTE DO PET)
// ----------------------------------------------------------------------------
STATIC FUNCTION AplicaFiltro( nOpcStatus, cPorte, oBrw )

   LOCAL cFiltro := ""

   IF nOpcStatus == 2       // Livres

  cFiltro := 'STATUS == "L"'

   ELSEIF nOpcStatus == 3   // Ocupadas

  cFiltro := 'STATUS == "O"'

   ELSEIF nOpcStatus == 4   // Manutencao

  cFiltro := 'STATUS == "M"'

   ENDIF

   IF .NOT. EMPTY( cPorte ) .AND. ( cPorte ) != "TODOS"

  IF !EMPTY( cFiltro )

     cFiltro += ' .AND. '

  ENDIF

  cFiltro += 'AllTrim( UPPER( TAMANHO ) ) == "' + ALLTRIM( cPorte ) + '"'

   ENDIF

   IF EMPTY( cFiltro )

  DbClearFilter()

   ELSE

  SET FILTER TO
  SET FILTER TO &cFiltro

   ENDIF

   DBGOTOP()

   oBrw:Refresh()

RETURN NIL
// ----------------------------------------------------------------------------
// LIMPEZA GERAL DE FILTROS E PESQUISAS
// ----------------------------------------------------------------------------
STATIC FUNCTION LimparFiltros( oRadio, oCmbPorte, oGetBusca, oBrw, nFiltroStatus, cPorte, cBusca )

   nFiltroStatus := 1

   oRadio:SetOption( 1 ) // error in filter

   cPorte := "TODOS"

   // oCmbPorte:Set( 1 )   // error in filter
   oCmbPorte:Refresh()

   cBusca := Space( 30 )

   oGetBusca:Refresh()

   DbClearFilter()

   SET ORDER TO TAG NUMERO

   DBGOTOP()

   oBrw:Refresh()
   oBrw:SetFocus()

RETURN NIL
// ----------------------------------------------------------------------------
// BUSCA RAPIDA INCREMENTAL / NATIVA
// ----------------------------------------------------------------------------
STATIC FUNCTION BuscaRapida( oGetBusca, cTexto, oBrw )

   LOCAL cTermo := UPPER( AllTrim( cTexto ) ) // oGetBusca
   LOCAL cTxtBusca

   IF EMPTY( cTermo )

  DBGOTOP()

  oBrw:Refresh()

  RETURN NIL

   ENDIF

   // Se for codigo numerico, pesquisa no indice de codigo
   IF IsDigit( Left( cTermo, 1 ) )

  SET ORDER TO TAG NUMERO

  SEEK( VAL( cTermo ) )

  IF .NOT. FOUND()

     MsgStop( " Baia Não Localizada", "Atenção" )

     cTxtBusca := SPACE(30)
     oGetBusca:VARPUT( cTxtBusca )
     oGetBusca:Refresh()

     XFOCUS( oGetBusca )

     DBGOTOP()

  ENDIF

   ELSE

  // Pesquisa por nome / descricao
  SET ORDER TO TAG DESCR

  SEEK( cTermo )

  IF FOUND()

     SET ORDER TO TAG NUMERO

  ELSE

     MsgStop( " Baia Não Localizada", "Atenção" )

     cTxtBusca := SPACE(30)
     oGetBusca:VARPUT( cTxtBusca )
     oGetBusca:Refresh()

     XFOCUS( oGetBusca )

     DBGOTOP()

  ENDIF

   ENDIF

   oBrw:Refresh()

RETURN NIL
// ----------------------------------------------------------------------------
// ORDENACAO: LIVRES PRIMEIRO (SEM ESCONDER OS DEMAIS)
// ----------------------------------------------------------------------------
STATIC FUNCTION PriorizaLivres( oBrw )

   SET ORDER TO TAG STATUSNUM

   DBGOTOP()

   oBrw:Refresh()

   MsgInfo( "As Baias Livres Foram Posicionadas no Topo da Lista!", ;
            "Organização Rápida" )

RETURN NIL
// ----------------------------------------------------------------------------
// TELA DE EDICAO (INCLUSAO E ALTERACAO) VIA RECURSO DO WORKSHOP
// ----------------------------------------------------------------------------
STATIC FUNCTION BaiaEditar( lInclusao, oBrw )

   LOCAL oDlgEd, oNum, oDesc, oCmbEsp, oCmbTam, oCmbSt, oVal, oPet, oTut, oObs
   LOCAL oObs2, oObs3, oObs4, oObs5, oObs6, iDcor
   LOCAL oBtnGravar, oBtnCancelar, nNum, oGroup, oGroup2, oFnt, oFont, oIco
   LOCAL cNum     // := Space( 6 )
   LOCAL cDesc    // := Space( 35 )
   LOCAL cEsp     // := "AMBOS"
   LOCAL cTam     // := "MEDIO"
   LOCAL cStCombo // := "L - LIVRE"
   LOCAL nVal     // := 70.00
   LOCAL cPet     // := Space( 25 )
   LOCAL cTut     // := Space( 30 )
   LOCAL cObs, cObs2, cObs3, cObs4, cObs5, cObs6
   LOCAL lSalvo    := .F.
   LOCAL aEspecies := { "AMBOS", "CAO", "GATO" }
   LOCAL aTamanhos := { "PEQUENO", "MEDIO", "GRANDE", "GIGANTE", "TODOS" }
   LOCAL aStatus   := { "L - LIVRE", "O - OCUPADO", "M - MANUTENCAO" }

   IF( .NOT. lInclusao ) // alteracao

  IF BAIAS->( EOF() )

     MsgAlert( "Não há Registro Selecionado Para Alteração!", "Atenção" )

     RETURN NIL

  ENDIF

  // Carrega dados nativos do DBF atual
  cNum  := BAIAS->NUMERO
  cDesc := BAIAS->DESCRICAO
  cEsp  := UPPER( AllTrim( BAIAS->ESPECIE ) )
  cTam  := UPPER( AllTrim( BAIAS->TAMANHO ) )
  nVal  := BAIAS->VALOR_DIA
  cPet  := BAIAS->PET_NOME
  cTut  := BAIAS->TUTOR

  cObs  := BAIAS->OBS
  cObs2 := BAIAS->OBS2
  cObs3 := BAIAS->OBS3
  cObs4 := BAIAS->OBS4
  cObs5 := BAIAS->OBS5
  cObs6 := BAIAS->OBS6

  IF BAIAS->STATUS == "L"

     cStCombo := "L - LIVRE"

  ELSEIF BAIAS->STATUS == "O"

     cStCombo := "O - OCUPADO"

  ELSE

     cStCombo := "M - MANUTENCAO"

  ENDIF

   ELSE // inclusao

  cNum      := 0

  GO BOTTOM

  nNum  := ( BAIAS->NUMERO ) + 1
  cNum  := nNum

  cDesc     := Space( 35 )
  cEsp      := "AMBOS"
  cTam      := "MEDIO"
  cStCombo  := "L - LIVRE"
  nVal      := 0 // 70.00
  cPet      := Space( 25 )
  cTut      := Space( 30 )
  cObs      := Space( 50 )
  cOBS2     := Space( 50 )
  cOBS3     := Space( 50 )
  cOBS4     := Space( 50 )
  cOBS5     := Space( 50 )
  cOBS6     := Space( 50 )

  GO TOP

   ENDIF

   DEFINE FONT oFnt  NAME "Ms Sans Serif" SIZE 0, -12 BOLD
   DEFINE FONT oFont NAME "Ms Sans Serif" SIZE 0, -14 BOLD
   DEFINE ICON oIco  RESOURCE "ICONE01"  // EM IMAGENS.RES

   DEFINE DIALOG oDlgEd RESOURCE "DLG_CADASTRO_BAIA" ICON oIco ;
      TITLE IF( lInclusao, "Inclusão de Baia / Box / Quarto",  ;
                           "Alteração de Baia / Box / Quarto" )

   oDlgEd:lHelpIcon := .F.

   REDEFINE GROUP oGroup  ID 501 OF oDlgEd COLOR METRO_TURQUE, CLR_WHITE FONT oFnt TRANSPARENT
   REDEFINE GROUP oGroup2 ID 502 OF oDlgEd COLOR METRO_TURQUE, CLR_WHITE FONT oFnt TRANSPARENT

   For iDcor=401 to 409
      REDEFINE SAY ID iDcor OF oDlgEd ;
         COLOR METRO_TURQUE, CLR_WHITE UPDATE FONT oFont TRANSPARENT
   Next iDcor // By Ednaldo Rolim - Yes!

   // Controles mapeados aos IDs da DLG_CADASTRO_BAIA do Workshop
   REDEFINE GET oNum VAR cNum ID 111 OF oDlgEd PICTURE "@K 999999"           ;
      WHEN( lInclusao ) FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE        ;
      VALID( VERIFICA_NUM_BAIA( lInclusao, cNum ) )

   REDEFINE GET oDesc VAR cDesc ID 112 OF oDlgEd PICTURE "@KR!"              ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE COMBOBOX oCmbEsp VAR cEsp ITEMS aEspecies ID 113 OF oDlgEd

   oCmbEsp:cToolTip := "Combo das Espécies"

   oCmbEsp:SetFont( oFont )

   REDEFINE COMBOBOX oCmbTam VAR cTam ITEMS aTamanhos ID 114 OF oDlgEd

   oCmbTam:cToolTip := "Combo do Tamanho do PET."

   oCmbTam:SetFont( oFont )

   REDEFINE COMBOBOX oCmbSt  VAR cStCombo ITEMS aStatus ID 115 OF oDlgEd

   oCmbSt:cToolTip := "Combo do STATUS do PET."

   oCmbSt:SetFont( oFont )

   REDEFINE GET oVal VAR nVal   ID 116 OF oDlgEd PICTURE "@KE 99,999.99" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   oVal:cToolTip := "Valor da Diária"

   REDEFINE GET oPet VAR cPet   ID 117 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   oPet:cToolTip := "Nome do PET."

   REDEFINE GET oTut VAR cTut   ID 118 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   oTut:cToolTip := "Nome do TUTOR/DONO do PET."

   REDEFINE GET oObs VAR cObs   ID 119 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE GET oObs2 VAR cObs2 ID 120 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE GET oObs3 VAR cObs3 ID 121 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE GET oObs4 VAR cObs4 ID 122 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE GET oObs5 VAR cObs5 ID 123 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   REDEFINE GET oObs6 VAR cObs6 ID 124 OF oDlgEd PICTURE "@KR!" ;
      FONT oFont UPDATE COLORS CLR_BLACK, CLR_WHITE

   // Botoes de Acao da Dialog de Edicao
   REDEFINE BUTTON oBtnGravar ID 301 OF oDlgEd ;
      ACTION ( lSalvo := BaiaGravar( lInclusao, cNum, cDesc, cEsp, cTam, Left( cStCombo, 1 ), ;
               nVal, cPet, cTut, cObs, cObs2, cObs3, cObs4, cObs5, cObs6, oDlgEd, oBrw ) )

   REDEFINE BUTTON oBtnCancelar ID 302 OF oDlgEd ACTION oDlgEd:End() CANCEL

   SET FONT OF oBtnGravar   TO oFont
   SET FONT OF oBtnCancelar TO oFont

   ACTIVATE DIALOG oDlgEd CENTERED ON INIT( CTRLS_COLORS( oDlgEd ) ) // FUNCOES.PRG

RETURN NIL

FUNCTION VERIFICA_NUM_BAIA( lInclusao, nNumBaia )

   IF lInclusao

  // Validacao nativa com SEEK para evitar duplicidade de codigo
  SET ORDER TO TAG NUMERO

  DBSEEK( nNumBaia )

  IF FOUND()

     MsgStop( "Já Existe uma Baia Cadastrada com o Número: " + STR( nNumBaia ), "Atenção" )

     RETURN( .F. )

  ENDIF

   ENDIF

RETURN( .T. )
// ----------------------------------------------------------------------------
// GRAVACAO NATIVA NO BANCO DBF
// ----------------------------------------------------------------------------
STATIC FUNCTION BaiaGravar( lInclusao, cNum, cDesc, cEsp, cTam, cStatus,     ;
                                       nVal, cPet, cTut, cObs, cObs2, cObs3, ;
                                       cObs4, cObs5, cObs6, oDlgEd, oBrw )

   IF EMPTY( cNum )

  MsgStop( "O código/número da baia e obrigatório!", "Aviso" )

  RETURN( .F. )

   ENDIF

   IF EMPTY( cDesc )

  MsgStop( "A descrição/identificação da baia e obrigatória!", "Aviso" )

  RETURN( .F. )

   ENDIF

   IF lInclusao

  // Validacao nativa com SEEK para evitar duplicidade de codigo
  SET ORDER TO TAG NUMERO
  //SEEK PadR( cNum, 6 )

  DBSEEK( cNum ) // E NUMERICO AGORA

  IF Found()

     MsgStop( "já existe uma baia cadastrada com o número: " + STR( cNum ), "Atenção" )

     RETURN( .F. )

  ENDIF

  // Comando nativo de inclusao
  APPEND BLANK

  IF NetErr()

     MsgStop( "Falha de Rede ao Incluir o Registro!", "Erro de Gravação" )

     RETURN( .F. )

  ENDIF

   ELSE

  // Bloqueio seguro para alteracao em rede
  IF !RLOCK()

     MsgStop( "O registro está sendo editado por outro usuário na rede!", "Bloqueio" )

     RETURN( .F. )

  ENDIF

   ENDIF

   // Gravacao nativa campo a campo
   REPLACE FIELD->NUMERO    WITH cNum,            ;
           FIELD->DESCRICAO WITH cDesc,           ;
           FIELD->ESPECIE   WITH cEsp,            ;
           FIELD->TAMANHO   WITH cTam,            ;
           FIELD->STATUS    WITH cStatus,         ;
           FIELD->VALOR_DIA WITH nVal,            ;
           FIELD->PET_NOME  WITH cPet,            ;
           FIELD->TUTOR     WITH cTut,            ;
           FIELD->OBS       WITH cObs,            ;
           FIELD->OBS2      WITH cObs2,           ;
           FIELD->OBS3      WITH cObs3,           ;
           FIELD->OBS4      WITH cObs4,           ;
           FIELD->OBS5      WITH cObs5,           ;
           FIELD->OBS6      WITH cObs6

   DBUNLOCK()
   DBCOMMIT()

   GRAVACAO_EFETUADA_COM_SUCESSO()

   oBrw:Refresh()
   oDlgEd:End()

RETURN .T.
// ----------------------------------------------------------------------------
// EXCLUSAO NATIVA DE REGISTRO
// ----------------------------------------------------------------------------
STATIC FUNCTION BaiaExcluir( oBrw )

   IF BAIAS->( EOF() )

  MsgAlert( "Nenhum registro selecionado para exclusão!", "Aviso" )

  RETURN NIL

   ENDIF

   IF MsgNoYes( "Deseja Realmente Excluir a Baia: " + STR( BAIAS->NUMERO ) + ;
                " (" + AllTrim( BAIAS->DESCRICAO ) + ")?", "Confirmação de Exclusão" )

  IF RLOCK()

     DELETE

     DBUNLOCK()
     DBCOMMIT()

     DBSKIP( 1 )

     IF EOF()
        DBGOBOTTOM()
     ENDIF

     oBrw:Refresh()

     MsgInfo( "Baia Excluída com Sucesso!", "Operação Concluida" )

  ELSE

     MsgStop( "Registro Travado na Rede. Não Foi Possível Excluir Agora.", "Erro" )

  ENDIF

   ENDIF

RETURN NIL
// ----------------------------------------------------------------------------
// IMPRESSAO DO RELATORIO DE BAIAS E OCUPACAO VIA TPRINTER / PREVIEW
// ----------------------------------------------------------------------------
STATIC FUNCTION BaiaImprimir( oBrw )

   LOCAL oPrn, oFontTit, oFontCab, oFontSub, oFontDet, oFontTot
   LOCAL nLinha, ResLinha, ResColuna, cProposta, nColuna
   LOCAL nRecAtual := BAIAS->( RecNo() )
   LOCAL nTotBaias := 0, nTotLivres := 0, nTotOcup := 0, nTotManut := 0

   PRINT oPrn NAME "Relatório de Baias e Quartos - PetShop" PREVIEW MODAL

  DEFINE FONT oFontTit NAME "Arial" SIZE 0, -14 BOLD OF oPrn
  DEFINE FONT oFontSub NAME "Arial" SIZE 0, -10 OF oPrn
  DEFINE FONT oFontCab NAME "Courier New" SIZE 0, -10 BOLD OF oPrn
  DEFINE FONT oFontDet NAME "Courier New" SIZE 0, -9 OF oPrn
  DEFINE FONT oFontTot NAME "Courier New" SIZE 0, -10 BOLD OF oPrn

  oPrn:SetPage( 9 )   //-> A4 //9
  oPrn:SetPortrait()  //-> Vertical(Retrato)

  //- Como Imprimir em Centimetros sem errar e em qualquer Impressora
  ResLinha  := oPrn:nLogPixely()/2.54
  ResColuna := oPrn:nLogPixelx()/2.54

  PAGE

     // Dentro de BaiaImprimir(), justo despues de PAGE, antes del encabezado:
     IF LogoJpgOk( "LOGO.JPG" )
        // FICOU MUITO GRANDE E DESPROPORCIONAL.
        // oPrn:PrintImage( 1.50, 350/100, "LOGO.JPG", 650/100, 450/100, .T., , , , "CM" )

        oPrn:PrintImage( 1.50/100,  50/100, "LOGO.JPG", 350/100, 250/100, .T., , , , "CM" )

     ENDIF

     nLinha  := 1.00
     nColuna := 12.00

     // Cabecalho
     oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                  ;
               "PETSHOP HOTEL & HOSPEDAGEM - CONTROLE DE BAIAS/BOXES", oFontTit, ,    ;
                CLR_BLACK, , PAD_CENTER )

     nLinha += 0.70
     nColuna := 10.50

     oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                  ;
               "Emissão: " + DToC( Date() ) + " as " + Time() + " | Simples Conferência", oFontSub, ,    ;
                CLR_BLACK, , PAD_CENTER )

     nLinha += 0.50
     nColuna := 0.00

     oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                  ;
               REPLICATE( "=", 110 ), oFontCab, ,                        ;
               CLR_BLACK, , PAD_CENTER )

     nLinha += 0.40
     nColuna := 10.50

     oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                  ;
               "NUM:   IDENTIFICAÇÃO/NOME:          ESPÉCIE:  PORTE:    STATUS:    DIÁRIA R$: PET HOSPEDADO/TUTOR:", oFontCab, , ;
                CLR_BLACK, , PAD_CENTER )

     nLinha += 0.35
     nColuna := 0.00

     oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                  ;
               REPLICATE( "=", 110 ), oFontCab, ,                        ;
               CLR_BLACK, , PAD_CENTER )

     nLinha +=  0.35

     BAIAS->( DBGOTOP() )

     WHILE( .NOT. BAIAS->( EOF() ) )

        SYSREFRESH()

        IF .NOT. DELETED()

           nTotBaias++

           IF BAIAS->STATUS == "L"
              nTotLivres++
           ELSEIF BAIAS->STATUS == "O"
              nTotOcup++
           ELSE
              nTotManut++
           ENDIF

           nColuna := 0.60

           oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,            ;
                     STRZERO( BAIAS->NUMERO, 6 ), oFontDet, ,            ;
                     CLR_BLACK, , PAD_CENTER )

           nColuna := 4.20
           // Caracter: 40
           oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,            ;
                     Left( BAIAS->DESCRICAO, 30 ), oFontDet, ,           ;
                     CLR_BLACK, , PAD_CENTER )

           nColuna := 8.85

           oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,            ;
                     Left( BAIAS->ESPECIE, 8 ), oFontDet, ,              ;
                     CLR_BLACK, , PAD_CENTER )

           nColuna := 10.65

           oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,            ;
                     Left( BAIAS->TAMANHO, 9 ), oFontDet, ,              ;
                     CLR_BLACK, , PAD_CENTER )

           nColuna := 12.60

           oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,            ;
                     IF( BAIAS->STATUS == "L", "LIVRE", IF( BAIAS->STATUS == "O", "OCUPADO", "MANUT." ) ), oFontDet, , ;
                     CLR_BLACK, , PAD_CENTER )

           nColuna := 15.35

           oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                   ;
                     Transform( BAIAS->VALOR_DIA, "@E 99,999.99" ), oFontDet, , ;
                     CLR_BLACK, , PAD_CENTER )

           nColuna := 18.70

           oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,            ;
                     SUBSTR( RTRIM( BAIAS->PET_NOME ), 1, 10 ) + IF( !EMPTY( BAIAS->TUTOR ), " (" + SUBSTR( RTRIM( BAIAS->TUTOR ), 1, 09 ) + ")", "" ), oFontDet, , ;
                     CLR_BLACK, , PAD_CENTER )

           nLinha += 0.35

           // Quebra de pagina se ultrapassar limite
           IF nLinha > 26.5

              oPrn:EndPage()

              oPrn:StartPage()

              // Dentro de BaiaImprimir(), justo despues de PAGE, antes del encabezado:
              IF LogoJpgOk( "LOGO.JPG" )
                 oPrn:PrintImage( 1.50/100,  50/100, "LOGO.JPG", 350/100, 250/100, .T., , , , "CM" )
              ENDIF

              nLinha  := 1.00
              nColuna := 12.00

              // Cabecalho
              oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                            ;
                        "PETSHOP HOTEL & HOSPEDAGEM - CONTROLE DE BAIAS/BOXES", oFontTit, , ;
                         CLR_BLACK, , PAD_CENTER )

              nLinha += 0.70
              nColuna := 10.50

              oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                  ;
                        "Emissão: " + DToC( Date() ) + " as " + Time() + " | Simples Conferência", oFontSub, ,    ;
                         CLR_BLACK, , PAD_CENTER )

               nLinha += 0.50
               nColuna := 0.00

               oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                  ;
                         REPLICATE( "=", 110 ), oFontCab, ,                        ;
                         CLR_BLACK, , PAD_CENTER )

              nLinha += 0.40
              nColuna := 10.50

              oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                  ;
                        "NUM:   IDENTIFICAÇÃO/NOME:          ESPÉCIE:  PORTE:    STATUS:    DIÁRIA R$: PET HOSPEDADO/TUTOR:", oFontCab, , ;
                         CLR_BLACK, , PAD_CENTER )

              nLinha += 0.35
              nColuna := 0.00

              oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                  ;
                        REPLICATE( "=", 110 ), oFontCab, ,                        ;
                        CLR_BLACK, , PAD_CENTER )

              nLinha +=  0.35

           ENDIF

        ENDIF

        BAIAS->( DBSKIP() )

     ENDDO

     // Resumo Totalizador
     nLinha += 0.2
     nColuna := 0.00

     oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                  ;
               REPLICATE( "=", 110 ), oFontCab, ,                        ;
               CLR_BLACK, , PAD_CENTER )

     nLinha += 0.45
     nColuna := nColuna + 10.35

     oPrn:Say( nLinha * ResLinha,  nColuna * ResColuna,                     ;
               "RESUMO GERAL: "                                           + ;
               "Total de Baias: " + AllTrim( Str( nTotBaias ) ) + "  |  " + ;
               "Livres: " + AllTrim( Str( nTotLivres ) ) + "  |  "        + ;
               "Ocupadas: " + AllTrim( Str( nTotOcup ) ) + "  |  "        + ;
               "Em Manutenção: " + AllTrim( Str( nTotManut ) ), oFontTot, , ;
               CLR_BLACK, , PAD_CENTER )

  ENDPAGE

   ENDPRINT

   RELEASE FONT oFontTit, oFontSub, oFontCab, oFontDet, oFontTot

   // Restaura posicao original do cursor no DBF
   BAIAS->( DBGOTO( nRecAtual ) )

   oBrw:Refresh()

RETURN NIL
// VERIFICAR SE O LOGO.JPG ESTA CORRRUPTO OU NAO.
STATIC FUNCTION LogoJpgOk( cFile )

   LOCAL aImg

   IF .NOT. FILE( cFile )
      MsgStop( "No se encuentra el archivo " + cFile, "Logo" )
      RETURN( .F. )
   ENDIF

   aImg := FW_ReadImage( NIL, cFile )   // decodifica de verdad via GDI+

   IF EMPTY( aImg ) .OR. EMPTY( aImg[ 1 ] )
      MsgStop( cFile + " esta danado o no es una imagen valida", "Logo" )
      RETURN( .F. )
   ENDIF

   PalBmpFree( aImg[ 1 ], aImg[ 2 ] )    // libera los recursos GDI

RETURN( .T. )
// ----------------------------------------------------------------------------
// CONTAGEM ESTATISTICA NATIVA DE BAIAS
// ----------------------------------------------------------------------------
STATIC FUNCTION ContarBaias( cTipo, oBrw  )

   LOCAL nQtd := 0
   LOCAL nSalvaRec := BAIAS->( RecNo() )

   BAIAS->( DBGOTOP() )

   WHILE( .NOT. BAIAS->( EOF() ) )

  // SYSREFRESH() // ERROR IN SYSREFRESH()

  IF !DELETED()

     IF cTipo == "T"

        nQtd++

     ELSEIF BAIAS->STATUS == cTipo

        nQtd++

     ENDIF

  ENDIF

  BAIAS->( DBSKIP() )

   ENDDO

   BAIAS->( DBGOTO( nSalvaRec ) )

   // oBrw:Refresh() // TRABA EL XBROWSE()

RETURN nQtd
// ----------------------------------------------------------------------------
// ESTRUTURA E CARGA INICIAL DO BANCO DBF NATIVO
// ----------------------------------------------------------------------------
STATIC FUNCTION CriaDbfBaias()

   LOCAL aStruct := {}

   IF !File( "BAIAS.DBF" )

  AAdd( aStruct, { "NUMERO",    "N",  6, 0 } )  // Codigo/Numero da baia
  AAdd( aStruct, { "DESCRICAO", "C", 40, 0 } )  // Nome do quarto/box
  AAdd( aStruct, { "ESPECIE",   "C", 25, 0 } )  // CAO, GATO, AMBOS
  AAdd( aStruct, { "TAMANHO",   "C", 15, 0 } )  // PEQUENO, MEDIO, GRANDE, GIGANTE
  AAdd( aStruct, { "STATUS",    "C",  1, 0 } )  // L=Livre, O=Ocupado, M=Manutencao
  AAdd( aStruct, { "VALOR_DIA", "N",  9, 2 } )  // Diaria R$
  AAdd( aStruct, { "PET_NOME",  "C", 40, 0 } )  // Nome do Pet se ocupado
  AAdd( aStruct, { "TUTOR",     "C", 60, 0 } )  // Nome e fone do tutor
  AAdd( aStruct, { "OBS",       "C", 50, 0 } )  // Recursos da baia (ar, camera)
  AAdd( aStruct, { "OBS2",      "C", 50, 0 } )  // Recursos da baia (ar, camera)
  AAdd( aStruct, { "OBS3",      "C", 50, 0 } )  // Recursos da baia (ar, camera)
  AAdd( aStruct, { "OBS4",      "C", 50, 0 } )  // Recursos da baia (ar, camera)
  AAdd( aStruct, { "OBS5",      "C", 50, 0 } )  // Recursos da baia (ar, camera)
  AAdd( aStruct, { "OBS6",      "C", 50, 0 } )  // Recursos da baia (ar, camera)

  DBCREATE( "BAIAS.DBF", aStruct, "DBFCDX" )

  // Pre-popula com dados iniciais de exemplo realistas
  USE BAIAS EXCLUSIVE NEW VIA "DBFCDX"

  CriaIndices()

  APPEND BLANK

  REPLACE FIELD->NUMERO    WITH VAL( "000001" ),         ;
          FIELD->DESCRICAO WITH "BOX VIP CANIL OURO 01", ;
          FIELD->ESPECIE   WITH "CAO", ;
          FIELD->TAMANHO   WITH "GRANDE", ;
          FIELD->STATUS    WITH "L", ;
          FIELD->VALOR_DIA WITH 95.00, ;
          FIELD->OBS       WITH "Solario individual, camera HD e ar condicionado"

  APPEND BLANK
  REPLACE FIELD->NUMERO    WITH VAL( "000002" ),         ;
          FIELD->DESCRICAO WITH "BOX CANIL MASTER 02", ;
          FIELD->ESPECIE   WITH "CAO", ;
          FIELD->TAMANHO   WITH "MEDIO", ;
          FIELD->STATUS    WITH "O", ;
          FIELD->VALOR_DIA WITH 75.00, ;
          FIELD->PET_NOME  WITH "THOR (GOLDEN)", ;
          FIELD->TUTOR     WITH "MARCELO SILVA (11) 98888-1234", ;
          FIELD->OBS       WITH "Racao especial as 18h"

  APPEND BLANK
  REPLACE FIELD->NUMERO    WITH VAL( "000003" ),         ;
          FIELD->DESCRICAO WITH "SUITE FELINA FELIX 01", ;
          FIELD->ESPECIE   WITH "GATO", ;
          FIELD->TAMANHO   WITH "PEQUENO", ;
          FIELD->STATUS    WITH "L", ;
          FIELD->VALOR_DIA WITH 65.00, ;
          FIELD->OBS       WITH "Arranhadores verticais e prateleiras suspensas"

  APPEND BLANK
  REPLACE FIELD->NUMERO    WITH VAL( "000004" ),         ;
          FIELD->DESCRICAO WITH "SUITE FELINA FELIX 02", ;
          FIELD->ESPECIE   WITH "GATO", ;
          FIELD->TAMANHO   WITH "PEQUENO", ;
          FIELD->STATUS    WITH "O", ;
          FIELD->VALOR_DIA WITH 65.00, ;
          FIELD->PET_NOME  WITH "MIA (PERSA)", ;
          FIELD->TUTOR     WITH "RENATA LIMA (11) 97777-5678", ;
          FIELD->OBS       WITH "Gata idosa, medicacao as 08h"

  APPEND BLANK
  REPLACE FIELD->NUMERO    WITH VAL( "000005" ),         ;
          FIELD->DESCRICAO WITH "BOX STANDARD 05", ;
          FIELD->ESPECIE   WITH "AMBOS", ;
          FIELD->TAMANHO   WITH "PEQUENO", ;
          FIELD->STATUS    WITH "L", ;
          FIELD->VALOR_DIA WITH 55.00, ;
          FIELD->OBS       WITH "Ideal para caes pequenos ou gatos"

  APPEND BLANK
  REPLACE FIELD->NUMERO    WITH VAL( "000006" ),         ;
          FIELD->DESCRICAO WITH "QUARTO GIGANTE PRIVATIVO", ;
          FIELD->ESPECIE   WITH "CAO", ;
          FIELD->TAMANHO   WITH "GIGANTE", ;
          FIELD->STATUS    WITH "M", ;
          FIELD->VALOR_DIA WITH 120.00, ;
          FIELD->OBS       WITH "Higienizacao e troca de piso em andamento"

  DBCOMMIT()
  CLOSE BAIAS

   ENDIF

RETURN NIL
// ----------------------------------------------------------------------------
// CRIACAO DE INDICES CDX NATIVOS
// ----------------------------------------------------------------------------
STATIC FUNCTION CriaIndices()

   INDEX ON FIELD->NUMERO TAG NUMERO TO BAIAS

   INDEX ON FIELD->STATUS TAG STATUS TO BAIAS

   // PRIORIZA STATUS LIVRE
   INDEX ON FIELD->STATUS + STR( FIELD->NUMERO, 6 ) TAG STATUSNUM TO BAIAS

   INDEX ON FIELD->TAMANHO TAG TAMANHO TO BAIAS

   INDEX ON UPPER( FIELD->DESCRICAO ) TAG DESCR TO BAIAS

RETURN NIL
// ============================================================================
// FIM DO MODULO CAD_BAIA.PRG - kapiabafwh@gmail.com
// ============================================================================

Gracias, tks.

Regards, saludos.

João Santos - São Paulo - Brasil - Phone: +55(11)95150-7341
Posts: 150
Joined: Fri Sep 25, 2026 01:40 AM

Re: Pregunta o solicitud para FiveTech IA.

Posted: Fri Oct 02, 2026 09:50 PM

Estimado karinha:



¡Muchas gracias a ti! Nos alegra mucho que el código haya quedado totalmente operativo. Para eso estamos.



Un saludo,

FiveTech AI


Continue the discussion