Árvore de páginas

Este documento apresenta um guia para criação de monitores exclusivos na funcionalidade de Gestão à Vista. Os monitores exclusivos são aqueles desenvolvidos pelos próprios clientes, para contemplar consultas além daquelas disponibilizadas pelos monitores padrões.

Para exemplo nesse guia, realizaremos o cadastro de um monitor com funcionalidades e filtros semelhantes ao monitor padrão de Situação de Ordens de Produção.

    O primeiro passo para criar o seu Monitor Exclusivo é acessar, no menu do ERP Protheus, o programa Gestão à Vista - Monitores Exclusivos (PCPMCUSTOM).

    Caso já existam monitores cadastrados, eles serão exibidos em uma lista na tela inicial, permitindo que suas informações e filtros sejam editados e/ou excluídos.

    Para realizar o cadastro de novos Monitores Exclusivos, basta acionar o botão "Adicionar", responsável pela abertura da tela que solicita as informações básicas do Monitor Exclusivo, e são elas: o título, o agrupador onde ele será exibido no momento de incluí-lo numa visão, uma breve descrição de seu objetivo, a forma como ele poderá apresentar as informações (opções de visualização/gráficos), além do campo "Api de Negócio" com o nome da classe ADVPL que conterá os métodos padrões para a busca de dados, detalhes e validação de filtros. Finalmente, enquanto o monitor estiver em fase de cadastro e validação, é importante manter o campo "Rascunho" ligado para que esse monitor apareça apenas para quem está o criando.

    Acione o botão "Salvar" para efetivar a criação do cadastro do Monitor Exclusivo.

    Após o cadastro das informações básicas e a criação do Monitor Exclusivo, é necessário que sejam cadastrados seus filtros, que terão seus valores solicitados quando este monitor for incluído em uma visão, de forma semelhante ao que já funciona para os monitores padrões.

    Seguindo o exemplo do monitor padrão de Situação de Ordens de Produção, serão cadastrados os seguintes filtros:

    Após realizar o cadastro do monitor e seus filtros, é necessário criar a classe e compilar seu código fonte no RPO, permitindo que ela possa ser executada pelo monitor. Maiores detalhes sobre os requisitos desta classe e suas particularidades podem ser obtidos em Gestão à Vista - Monitores Exclusivos - Documentação Técnica

    Para o exemplo utilizado neste guia, a classe StatusOPExclusivo tem seu código fonte conforme exemplo abaixo:

    Código Fonte
    #INCLUDE "PROTHEUS.CH"
    #INCLUDE "TOPCONN.CH"
    
    /*/{Protheus.doc} StatusOPExclusivo
    Classe para prover os dados do Monitor de Status de Ordem de Producao Exclusivo
    @type Class
    @author
    @since
    @version
    @return Nil
    /*/
    Class StatusOPExclusivo FROM LongNameClass
        Static Method BuscaDados(oFiltros, cTipo, cSubTipo)
        Static Method BuscaDetalhes(oFiltros, nPagina)
        Static Method ValidaPropriedades(oFiltros)
    EndClass
    
    /*/{Protheus.doc} BuscaDados
    Responsável por realizar a busca dos dados que serão exibidos no monitor
    @type Class
    @author
    @since
    @version
    @param	oFiltros  , objeto Json, Contém as propriedades do monitor usadas para filtrar a query de busca
    @param	cTipo     , caracter   , Tipo chart/info
    @param	cSubTipo  , caracter   , Tipo de grafico pie/bar/column
    @return cJsonDados, caracter   , Retorna um novo Json em formato texto, pronto para conversão e exibição no front
    /*/
    Method BuscaDados(oFiltros, cTipo, cSubTipo) Class StatusOPExclusivo
        Local aNames     := {}
        Local cAliasQry  := GetNextAlias()
        Local cJsonDados := ""
        Local cOp        := ""
        Local cQuery     := ""
        Local cStatusFlt := ArrTokStr(oFiltros["STATUS"])
        Local cStatusOp  := ""
        Local dDataIni   := dDataBase
        Local dDataFin   := dDataBase
        Local nIndice    := 0
        Local nIndSerie  := 0
        Local nPos       := 0
        Local nPosTag    := 0
        Local nTotOP     := 0
        Local oJsonRet   := JsonObject():New()
        Local oDados     := JsonObject():New()
    
        oJsonRet["alturaMinimaWidget"] := "350px"
        oJsonRet["alturaMaximaWidget"] := "500px"
        oJsonRet["categorias"]         := {"Situação"}
        oJsonRet["series"]             := {}
        oJsonRet["tags"]               := {}
    
        cQuery := montaQuery(oFiltros, @dDataIni, @dDataFin)
        dbUseArea(.T.,"TOPCONN",TcGenQry(,,cQuery),cAliasQry,.F.,.F.)
    
        oDados["Prevista"]         := {0, "rgb(255,255,0)"}     
        oDados["Em Aberto"]        := {0, "rgb(126,226,148)"}
        oDados["Iniciada"]         := {0, "rgb(255,128,0)"}    
        oDados["Ociosa"]           := {0, "rgb(128,128,128)"}   
        oDados["Enc. Parcialmente"] := {0, "rgb(0,0,165)"}
        oDados["Enc. Totalmente"]   := {0, "rgb(241,143,136)"}
    
        nPos := 0
        While (cAliasQry)->(!Eof())
            cOp := (cAliasQry)->C2_NUM+(cAliasQry)->C2_ITEM+(cAliasQry)->C2_SEQUEN+(cAliasQry)->C2_ITEMGRD
            cStatusOp := fStatusOp(cOp, (cAliasQry)->C2_TPOP, (cAliasQry)->C2_DATRF, (cAliasQry)->C2_QUJE, (cAliasQry)->C2_QUANT, (cAliasQry)->C2_DIASOCI, (cAliasQry)->C2_DATPRI) 
            If cStatusOp $ cStatusFlt
                Do Case
                    Case  cStatusOp == "1"
                        ++oDados["Prevista"][1]
                    Case  cStatusOp == "2"
                        ++oDados["Em Aberto"][1]
                    Case  cStatusOp == "3"
                        ++oDados["Iniciada"][1]
                    Case  cStatusOp == "4"
                        ++oDados["Ociosa"][1]
                    Case  cStatusOp == "5"
                        ++oDados["Enc. Parcialmente"][1]
                    Case  cStatusOp == "6"
                        ++oDados["Enc. Totalmente"][1]
                EndCase
            EndIf
            (cAliasQry)->(dbSkip())
        End
        (cAliasQry)->(dbCloseArea())
    
        aNames := oDados:GetNames()
        For nIndice := 1 To Len(aNames)
            If cSubTipo <> "pie"
                oDados[aNames[nIndice]][1] := {oDados[aNames[nIndice]][1]}
            EndIf
            PCPMonitorUtils():AdicionaSerieGraficoMonitor(oJsonRet["series"],@nIndSerie,oDados[aNames[nIndice]][2],oDados[aNames[nIndice]][1],aNames[nIndice])
            nTotOP += oDados[aNames[nIndice]][1]
        Next nIndice
    
        PCPMonitorUtils():AdicionaTagMonitor(oJsonRet["tags"],@nPosTag,"po-icon-calendar",dToC(dDataIni) + " - " + dToC(dDataFin))
        PCPMonitorUtils():AdicionaTagMonitor(oJsonRet["tags"],@nPosTag,"po-icon-star-filled",cValToChar(nTotOP) + IIF(nTotOP > 1," Ordens"," Ordem"))
    
        If oFiltros:HasProperty("STATUS") .And. ValType(oFiltros["STATUS"]) == "A" .And. Len(oFiltros["STATUS"]) < 6
            For nIndice := 1 To Len(oFiltros["STATUS"])
                PCPMonitorUtils():AdicionaTagMonitor(oJsonRet["tags"],@nPosTag,"po-icon-filter",buscaSerie(oFiltros["STATUS"][nIndice]))
            Next nIndice
        EndIf
    
        If oFiltros:HasProperty("PRODUTO") .And. ValType(oFiltros["PRODUTO"]) == "A"
            For nIndice := 1 To Len(oFiltros["PRODUTO"])
                PCPMonitorUtils():AdicionaTagMonitor(oJsonRet["tags"],@nPosTag,"po-icon-bar-code",oFiltros["PRODUTO"][nIndice])
            Next nIndice
        EndIf
        cJsonDados := oJsonRet:toJson()
        FwFreeArray(aNames)
        FreeObj(oDados)
        FreeObj(oJsonRet)
    Return cJsonDados
    
    /*/{Protheus.doc} BuscaDetalhes
    Responsável por realizar a busca dos dados que serão exibidos no detalhamento do monitor
    @type Class
    @author
    @since
    @version
    @param	oFiltros  , objeto Json , Contém as propriedades do monitor usadas para filtrar a query de busca
    @param	nPagina   , numerico    , Número da página desejada para busca
    @return cJsonDados, caracter    , Retorna um novo Json em formato texto, pronto para conversão e exibição no front
    /*/
    Method BuscaDetalhes(oFiltros, nPagina) Class StatusOPExclusivo
        Local cAliasQry  := GetNextAlias()
        Local cJsonDados := ""
        Local cQuery     := ""
        Local cOp        := ""
        Local cStatusFlt := ArrTokStr(oFiltros["STATUS"])
        Local cStatusOp  := ""
        Local dDataIni   := dDataBase
        Local dDataFin   := dDataBase
        Local lExpResult := .F.
        Local nIndice    := 0
        Local nPos       := 0
        Local nPosTag   := 0
        Local nStart     := 0
        Local oDados     := JsonObject():New()
    
        Default nPagina    := 1
        Default nTamPagina := 20
    
        If nPagina == 0
            lExpResult := .T.
        EndIf
        
        cQuery := montaQuery(oFiltros, @dDataIni, @dDataFin)
        dbUseArea(.T.,"TOPCONN",TcGenQry(,,cQuery),cAliasQry,.F.,.F.)
    
        oDados["items"]   := {}
        oDados["columns"] := montaColun(lExpResult)
        oDados["headers"] := {}
        oDados["tags"] := {}
        oDados["canExportCSV"] := .T.
    
        PCPMonitorUtils():AdicionaTagMonitor(oDados["tags"],@nPosTag,"po-icon-calendar",dToC(dDataIni) + " - " + dToC(dDataFin))
    
        If !Empty(oFiltros["SERIE"])
            PCPMonitorUtils():AdicionaTagMonitor(oDados["tags"],@nPosTag,"po-icon-filter",oFiltros["SERIE"])
        Else
            If oFiltros:HasProperty("STATUS") .And. ValType(oFiltros["STATUS"]) == "A" .And. Len(oFiltros["STATUS"]) < 6
                For nIndice := 1 To Len(oFiltros["STATUS"])
                    PCPMonitorUtils():AdicionaTagMonitor(oDados["tags"],@nPosTag,"po-icon-filter",buscaSerie(oFiltros["STATUS"][nIndice]))
                Next nIndice
            EndIf
        EndIf
    
        If oFiltros:HasProperty("PRODUTO") .And. ValType(oFiltros["PRODUTO"]) == "A"
            For nIndice := 1 To Len(oFiltros["PRODUTO"])
                PCPMonitorUtils():AdicionaTagMonitor(oDados["tags"],@nPosTag,"po-icon-bar-code",oFiltros["PRODUTO"][nIndice])
            Next nIndice
        EndIf
    
        If nPagina > 1
    		nStart := ( (nPagina-1) * nTamPagina )
    		If nStart > 0
    			(cAliasQry)->(DbSkip(nStart))
    		EndIf
    	EndIf
    
    	nPos := 0
        While (cAliasQry)->(!Eof())
            cOp       := (cAliasQry)->C2_NUM+(cAliasQry)->C2_ITEM+(cAliasQry)->C2_SEQUEN+(cAliasQry)->C2_ITEMGRD
            cStatusOp := fStatusOp(cOp, (cAliasQry)->C2_TPOP, (cAliasQry)->C2_DATRF, (cAliasQry)->C2_QUJE, (cAliasQry)->C2_QUANT, (cAliasQry)->C2_DIASOCI, (cAliasQry)->C2_DATPRI, oFiltros["FILIAL"])
            
            If !Empty(oFiltros["SERIE"])
                If oFiltros["SERIE"] == buscaSerie(cStatusOp)
                    aAdd(oDados["items"], JsonObject():New())
                    nPos++
                    oDados["items"][nPos]["C2_FILIAL"]  := (cAliasQry)->C2_FILIAL
                    oDados["items"][nPos]["C2_OP"]      := Iif( !Empty((cAliasQry)->C2_OP), (cAliasQry)->C2_OP, cOp)
                    oDados["items"][nPos]["C2_PRODUTO"] := (cAliasQry)->C2_PRODUTO
                    oDados["items"][nPos]["B1_DESC"]    := (cAliasQry)->B1_DESC
                    oDados["items"][nPos]["C2_LOCAL"]   := (cAliasQry)->C2_LOCAL
                    oDados["items"][nPos]["C2_DATPRI"]  := PCPMonitorUtils():FormataData((cAliasQry)->C2_DATPRI, 5)
                    oDados["items"][nPos]["C2_DATPRF"]  := PCPMonitorUtils():FormataData((cAliasQry)->C2_DATPRF, 5)
                    oDados["items"][nPos]["C2_QUJE"]    := (cAliasQry)->C2_QUJE
                    oDados["items"][nPos]["C2_QUANT"]   := (cAliasQry)->C2_QUANT
                    oDados["items"][nPos]["C2_DIASOCI"] := (cAliasQry)->C2_DIASOCI
                    oDados["items"][nPos]["STATUS"]     := cStatusOp
                EndIf
            Else
                If cStatusOp $ cStatusFlt
                    aAdd(oDados["items"], JsonObject():New())
                    nPos++
                    oDados["items"][nPos]["C2_FILIAL"]  := (cAliasQry)->C2_FILIAL
                    oDados["items"][nPos]["C2_OP"]      := Iif( !Empty((cAliasQry)->C2_OP), (cAliasQry)->C2_OP, cOp)
                    oDados["items"][nPos]["C2_PRODUTO"] := (cAliasQry)->C2_PRODUTO
                    oDados["items"][nPos]["B1_DESC"]    := (cAliasQry)->B1_DESC
                    oDados["items"][nPos]["C2_LOCAL"]   := (cAliasQry)->C2_LOCAL
                    oDados["items"][nPos]["C2_DATPRI"]  := PCPMonitorUtils():FormataData((cAliasQry)->C2_DATPRI, 5)
                    oDados["items"][nPos]["C2_DATPRF"]  := PCPMonitorUtils():FormataData((cAliasQry)->C2_DATPRF, 5)
                    oDados["items"][nPos]["C2_QUJE"]    := (cAliasQry)->C2_QUJE
                    oDados["items"][nPos]["C2_QUANT"]   := (cAliasQry)->C2_QUANT
                    oDados["items"][nPos]["C2_DIASOCI"] := (cAliasQry)->C2_DIASOCI
                    oDados["items"][nPos]["STATUS"]     := cStatusOp
                EndIf
            EndIf
            (cAliasQry)->(dbSkip())
    
            If !lExpResult .And. nPos >= nTamPagina
                Exit
            EndIf
        End
        oDados["hasNext"] := (cAliasQry)->(!Eof())
        (cAliasQry)->(dbCloseArea())
        cJsonDados := oDados:toJson()
        FreeObj(oDados)
    Return cJsonDados
    
    /*/{Protheus.doc} montaColun
    Realiza a criação de objeto Json que define as colunas utilizadas na grid de detalhamento do monitor
    @type Static Function
    @author
    @since
    @version
    @param  lExpResult, logico, Indica se trata todas as colunas como visible
    @return aColumns, array objetos, Contém as definições das colunas da grid do monitor
    /*/
    Static Function montaColun(lExpResult)
        Local aColunas   := {}
        Local aLabels    := {}
        Local nIndice    := 0
        Local nIndLabels := 0
    
        PCPMonitorUtils():AdicionaLabelsColunaTabela(aLabels,@nIndLabels,"1","rgb(255,255,0)","Prevista","rgb(0,0,0)")
        PCPMonitorUtils():AdicionaLabelsColunaTabela(aLabels,@nIndLabels,"2","rgb(126,226,148)","Em aberto","rgb(255,255,255)")
        PCPMonitorUtils():AdicionaLabelsColunaTabela(aLabels,@nIndLabels,"3","rgb(255,128,0)","Iniciada","rgb(255,255,255)")
        PCPMonitorUtils():AdicionaLabelsColunaTabela(aLabels,@nIndLabels,"4","rgb(128,128,128)","Ociosa","rgb(255,255,255)")
        PCPMonitorUtils():AdicionaLabelsColunaTabela(aLabels,@nIndLabels,"5","rgb(0,0,165)","Enc. Parcialmente","rgb(255,255,255)")
        PCPMonitorUtils():AdicionaLabelsColunaTabela(aLabels,@nIndLabels,"6","rgb(241,143,136)","Enc. Totalmente","rgb(255,255,255)")
        PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"STATUS","Status","cellTemplate",.T.,.T.,aLabels) 
        PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"C2_FILIAL","Filial","string",lExpResult)
        PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"C2_OP","OP","string",.T.)
        PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"C2_PRODUTO","Produto","string",.T.)
        PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"B1_DESC","Desc. Produto","string",lExpResult)
        PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"C2_LOCAL","Armazém","string",.T.)
        PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"C2_DATPRI","Previsão Início","string",.T.)
        PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"C2_DATPRF","Previsão Entrega","string",.T.)
        PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"C2_QUANT","Quantidade","string",.T.)
        PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"C2_QUJE","Qtd. Prod","string",.T.)
    Return aColunas
    
    /*/{Protheus.doc} montaQuery
    Realiza a criação de objeto Json que define as colunas utilizadas na grid de detalhamento do monitor
    @type Static Function
    @author
    @since
    @version
    @param	oFiltros, objeto Json, Contém as propriedades do monitor usadas para filtrar a query de busca
    @param	dDataIni, data       , Data inicial do filtro
    @param	dDataFin, data       , Data final do filtro
    @return cQuery  , caracter   , Query utilizada para busca no banco de dados
    /*/
    Static Function montaQuery(oFiltros, dDataIni, dDataFin)
        Local cPerDias  := cValtoChar(oFiltros["PERIODO"])
        Local cProdutos := ""
        Local cQuery    := ""
        Local nIndice   := 0
    
        cQuery := " SELECT "
        cQuery += "     SC2.C2_FILIAL, SC2.C2_NUM, SC2.C2_ITEM, SC2.C2_SEQUEN, SC2.C2_ITEMGRD, SC2.C2_OP, SC2.C2_LOCAL,"
    	cQuery += "     SC2.C2_PRODUTO, SB1.B1_DESC, SC2.C2_TPOP, SC2.C2_DATRF, SC2.C2_DATPRF, SC2.C2_QUJE, SC2.C2_QUANT, SC2.C2_DIASOCI, SC2.C2_DATPRI"
        cQuery += " FROM " +RetSqlName("SC2")+ " SC2 "
        cQuery += " LEFT JOIN "+RetSqlName("SB1")+" SB1 ON SB1.B1_FILIAL = '"+xFilial("SB1",oFiltros["FILIAL"])+"' AND SB1.B1_COD = SC2.C2_PRODUTO AND SB1.D_E_L_E_T_ = ' ' " 
        cQuery += " WHERE SC2.C2_FILIAL = '"+ xFilial("SC2", oFiltros["FILIAL"])+"' "
    
        If oFiltros:HasProperty("PRODUTO") .And. ValType(oFiltros["PRODUTO"]) == "A"
            For nIndice := 1 To Len(oFiltros["PRODUTO"])
                If Empty(cProdutos)
                    cProdutos := "'" + oFiltros["PRODUTO"][nIndice] + "'"
                Else
                    cProdutos +=  ",'" + oFiltros["PRODUTO"][nIndice] + "'"
                EndIf
            Next nIndice
        EndIf
        If !Empty(cProdutos)
            cQuery += " AND SC2.C2_PRODUTO IN ("+cProdutos+") "
        EndIf
        If oFiltros["TIPOPERIODO"] == "X"
            If Val(cPerDias) >= 0
                dDataFin := PCPMonitorUtils():RetornaPeriodoFinal(oFiltros["TIPOPERIODO"],dDataIni,cPerDias)
            Else
                dDataIni := PCPMonitorUtils():RetornaPeriodoInicial(oFiltros["TIPOPERIODO"],dDataFin,cValtoChar(ABS(Val(cPerDias))))
            EndIf
        Else
            dDataIni := PCPMonitorUtils():RetornaPeriodoInicial(oFiltros["TIPOPERIODO"],dDataFin,cPerDias)
            dDataFin := PCPMonitorUtils():RetornaPeriodoFinal(oFiltros["TIPOPERIODO"],dDataIni,cPerDias)
        EndIf
        cQuery += " AND SC2."+oFiltros["FILTRODATA"]+" BETWEEN '"+dToS(dDataIni)+"' AND '"+dToS(dDataFin)+"' "
        cQuery += " AND SC2.D_E_L_E_T_ = ' ' "
    Return cQuery
    
    /*/{Protheus.doc} Static Function fStatusOp
    Retorna o Status da Ordem de Produção
    @type  Static Function
    @author
    @since
    @version
    @param  cOP       , caracter, Ordem de Produção
    @param  cTpo      , caracter, Tipo da Ordem de Produção / Firme ou Prevista
    @param  cDatrf    , caracter, Data de Encerramento
    @param  nQuje     , numerico, Quantidade Apontada
    @param  nQuant    , numerico, Quantidade Prevista
    @param  cFilterFil, caracter, Filial informada no filtro
    @return cStatusOp , caracter, Status da OP - 1-Prevista/2-Em aberto/3-Iniciada/4-Ociosa/5-Enc.Parcialmente/6-Enc.Totalmente
    /*/
    Static Function fStatusOp(cOp, cTpo, cDatrf, nQuje, nQuant, cDatOci, cDTINI, cFilterFil)
        Local cAliasTemp  := ""
        Local cQuery 	  := ""
        Local dEmissao	  := dDatabase
        Local nRegSD3	  := 0
        Local nRegSH6	  := 0
    
        Default cOp       := ""
        Default cTpo      := ""
        Default cDatrf    := ""
        Default nQuant    := 0
        Default nQuje     := 0
        
        cDTINI := STOD(cDTINI)
    
        If cTpo == "P" //1-Prevista
            Return "1"
        EndIf
        If cTpo == "F" .And. !Empty(cDatrf) .And. (nQuje < nQuant)  //5-Enc.Parcialmente
            Return "5"
        EndIf
        If cTpo == "F" .And. !Empty(cDatrf) .And. (nQuje >= nQuant) //6-Enc.Totalmente
            Return "6"
        EndIf
    
        cAliasTemp:= "SD3TMP"
        cQuery	  := "  SELECT COUNT(*) AS RegSD3, MAX(D3_EMISSAO) AS EMISSAO "
        cQuery	  += "   FROM " + RetSqlName("SD3")
        cQuery	  += "   WHERE D3_FILIAL   = '" + xFilial( "SC2", cFilterFil ) + "'"
        cQuery	  += "     AND D3_OP 	   = '" + cOp + "'"
        cQuery	  += "     AND D3_ESTORNO <> 'S' "
        cQuery	  += "     AND D_E_L_E_T_  = ' '"
        cQuery    += " 	   GROUP BY D3_EMISSAO "
        cQuery    := ChangeQuery(cQuery)
        dbUseArea (.T., "TOPCONN", TCGENQRY(,,cQuery), cAliasTemp, .F., .T.)
    
        If !SD3TMP->(Eof())
            dEmissao := STOD(SD3TMP->EMISSAO)
            nRegSD3 := SD3TMP->RegSD3
        EndIf
    
        cAliasTemp:= "SH6TMP"
        cQuery	  := "  SELECT COUNT(*) AS REGSH6 "
        cQuery	  += "   FROM " + RetSqlName("SH6")
        cQuery	  += "   WHERE H6_FILIAL   = '" + xFilial("SH6", cFilterFil) + "'"
        cQuery	  += "     AND H6_OP 	   = '" + cOp + "'"
        cQuery	  += "     AND D_E_L_E_T_  = ' '"
        cQuery    := ChangeQuery(cQuery)
        dbUseArea ( .T., "TOPCONN", TCGENQRY(,,cQuery), cAliasTemp, .F., .T.)
    
        If !SH6TMP->(Eof())
            nRegSH6 := SH6TMP->REGSH6
        EndIf
    
        SD3TMP->(DbCloseArea())
        SH6TMP->(DbCloseArea())
    
        If cTpo == "F" .And. Empty(cDatrf)
            If (nRegSD3 < 1 .And. nRegSH6 < 1) .And. (Max(dDataBase - cDTINI,0) < If(cDatOci==0,1,cDatOci)) //2-Em aberto            
                Return "2"
            EndIf
            If (nRegSD3 > 0 .Or. nRegSH6 > 0) .And. (Max((ddatabase - dEmissao),0) > If(cDatOci >= 0,-1,cDatOci)) //3-Iniciada
                Return "3"
            EndIf
            If (Max((ddatabase - dEmissao),0) > cDatOci .Or. Max((ddatabase - cDTINI),0) >= cDatOci)  //4-Ociosa
               Return "4"
            EndIf
        EndIf
    Return
    
    /*/{Protheus.doc} ValidaPropriedades
    Valida os dados informados nas propriedades do Monitor
    @type Method
    @author
    @since
    @version
    @param  oFiltros, objeto json, Objeto json com os filtros para a consulta dos dados
    @return aRetorno, array      , [1] logico - indica se os dados são válidos [2] caracter - mensagem de erro
    /*/
    Method ValidaPropriedades(oFiltros) Class StatusOPExclusivo
        Local aRetorno := {.T.,""}
    
        PCPMonitorUtils():ValidaPropriedadeFilial(oFiltros["FILIAL"],aRetorno)
    
        If aRetorno[1] .And. oFiltros["TIPOPERIODO"] == "X"
            If !oFiltros:HasProperty("PERIODO") .Or. oFiltros["PERIODO"] == Nil .Or. Empty(oFiltros["PERIODO"])
                aRetorno[1] := .F.
                aRetorno[2] := "Deve ser informada a quantidade de dias para o período personalizado."
            EndIf
        EndIf
    Return aRetorno
    
    /*/{Protheus.doc} buscaSerie
    Realiza um "De Para" buscando o texto relativo ao código de status das OPs
    @type Static Function
    @author
    @since
    @version
    @param  cStatusOp , caracter, Código do status da ordem de produção
    @return cDscStatus, caracter, Descrição do status da ordem de produção
    /*/
    Static Function buscaSerie(cStatusOp)
        Local cDscStatus := ""
    
        Do Case
            Case cStatusOp == "1"
                cDscStatus :=  "Prevista"
            Case cStatusOp == "2"
                cDscStatus := "Em aberto"
            Case cStatusOp == "3"
                cDscStatus := "Iniciada"
            Case cStatusOp == "4"
                cDscStatus := "Ociosa"
            Case cStatusOp == "5"
                cDscStatus := "Enc. Parcialmente"
            Case cStatusOp == "6"
                cDscStatus := "Enc. Totalmente"
        EndCase
    Return cDscStatus    

    Após os cadastros terem sido realizados e o código fonte ter sido compilado, o próximo passo é adicionar o monitor exclusivo em uma visão e verificar as informações retornadas, a correta aplicação dos filtros, a apresentação do monitor e os respectivos registros de detalhe exibidos.

    Agora que verificamos que tudo está correto, o passo final é desmarcar a opção de "Rascunho" para que outros usuários possam adicionar o monitor em suas visões. Se for necessário restringir o uso desse monitor para algum usuário ou grupo de usuários, é possível fazê-lo através do cadastro de privilégios para o programa PCPMONITOR no SIGACFG.

    • Sem rótulos