Árvore de páginas

Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.

...

Filtro Descrição
Filial*Seleção simples da filial a ser monitorada, a partir da lista das filiais disponíveis.
Produto

Seleção múltipla dos produtos a serem monitorados, a partir da informação do código ou da pesquisa dentre os produtos disponíveis para a filial.

RecursoSeleção múltipla dos recursos a serem monitorados, a partir da informação do código ou da pesquisa dentre os recursos disponíveis para a filial.
Motivos de Perda

Seleção múltipla dos motivos de perda a serem monitoradas, a partir da lista de motivos cadastrados através da rotina Motivo Refugo - SFCA003.
Obs.: como facilitador, já que o número de motivos possíveis depende do cadastro efetuado na rotina Motivo Refugo - SFCA003, caso não seja selecionado nenhum motivo, automaticamente todos serão considerados para o monitoramento.

Período*

Indica o tipo de período que será monitorado: Dia Atual, Semana Atual, Quinzena Atual, Mês Atual ou Personalizado.

Importante: as semanas compreendem os dados entre domingo e o sábado subsequente, a primeira quinzena compreende os dados entre os dias 01 e 15, enquanto a segunda quinzena compreende os dados entre os dias 16 e o último dia do mês.

Período personalizado (dias)

Indica o número de dias anteriores que serão monitorados, ou seja, o número de dias será considerado até a data atual, quando selecionado o tipo de período Personalizado.

* Filtro obrigatório


Nota
titleSeleção de Produtos - Unidades de Medida

Importante: Atenção ao selecionar os produtos que serão exibidos no monitor para que todos tenham a mesma unidade de medida padrão, evitando que seja impossível analisar os dados referentes às quantidades, já que não é realizada conversão entre diferentes unidades. A dica é incluir em suas visões pelo menos um monitor diferente para cada grupo de produtos com a mesma unidade de medida.

04. TAGS AUXILIARES

As Tags auxiliam na identificação dos filtros utilizados para delimitar o escopo de um monitor, sem necessidade de editá-los.

...

  • Visualização da quantidade de ordens de produção perdida referente a um status motivo específico:


  • Tags auxiliares:


  • Detalhes:

08. CÓDIGO FONTE

Dica

Segue abaixo o código fonte da classe responsável pelos dados deste monitor. Utilize este código como base para criar seus monitores exclusivos, alterando o nome da classe e adaptando à sua regra de negócio.

Bloco de código
languagecpp
themeMidnight
firstline1
titleStatusMotivoPerdas.prw
linenumberstrue
collapsetrue
#INCLUDE "PROTHEUS.CH"
#INCLUDE "TOPCONN.CH"
#INCLUDE "PCPMONITOR.CH"
#INCLUDE "PCPMONITORDEF.CH"

/*/{Protheus.doc} StatusMotivoPerdas
Classe para prover os dados do Monitor de Motivo de Perdas
@type Class
@author 
@since 
@version 
@return Nil
/*/
Class StatusMotivoPerdas FROM LongNameClass
    Static Method BuscaDados(oFiltros, cTipo, cSubTipo)
    Static Method BuscaDetalhes(oFiltros, nPagina)
    Static Method CargaMonitor()
    Static Method ValidaPropriedades(oFiltros)
EndClass

/*/{Protheus.doc} CargaMonitor
Realiza a carga do monitor no banco de dados, permitindo a exibição de um exemplo desse monitor para 
ser escolhido para uso na aplicação.
@type Class
@author 
@since 
@version 
@return lRet, logico, Define se a carga do Monitor foi realizada com sucesso
/*/
Method CargaMonitor() Class StatusMotivoPerdas
    Local aCategoria := {}
    Local aTags      := {}
    Local lRet       := .T.
    Local nPosTag    := 0
    Local oCarga     := PCPMonitorCarga():New()
    Local oSeries    := JsonObject():New()
        
    If !PCPMonitorCarga():monitorAtualizado("StatusMotivoPerdas")
        oSeries["FH"] := {1, COR_AMARELO}  //"Falha Humana"
        oSeries["FM"] := {2, COR_VERMELHO} //"Falha Mecânica"  
        oSeries["FP"] := {4, COR_LARANJA}  //"Falha Matéria Prima"
        oSeries["RB"] := {9, COR_CINZA}    //"Rebarba"

        PCPMonitorUtils():AdicionaTagMonitor(aTags,@nPosTag,"po-icon-calendar","01/02/2023 - 28/02/2023")
        PCPMonitorUtils():AdicionaTagMonitor(aTags,@nPosTag,"po-icon-star",STR0156+": 16") //"Perda"
        PCPMonitorUtils():AdicionaTagMonitor(aTags,@nPosTag,"po-icon-star-filled","5 "+STR0197) //"Apontamentos"

        oCarga:setaTitulo(STR0275) //"Motivos de Perda"
        oCarga:setaObjetivo(STR0276) //"Acompanhar o motivo das perdas registradas no sistema através da rotina de apontamento de perdas num determinado período."
        oCarga:setaAgrupador("PCP")
        oCarga:setaFuncaoNegocio("StatusMotivoPerdas")
        oCarga:setaTipoPadrao("chart")
        oCarga:setaTiposPermitidos("chart")
        oCarga:setaTiposGraficoPermitidos("pie;bar;column")
        oCarga:setaTipoGraficoPadrao("pie")
        oCarga:setaTipoDetalhe("detalhe")
        oCarga:setaExemploJsonGrafico(oSeries,aTags,aCategoria,"pie")
       
        oCarga:setaPropriedadeFilial("01_BC_FILIAL")
        oCarga:setaPropriedadeProduto("02_BC_PRODUTO",.T.)
        oCarga:setaPropriedadeRecurso("03_BC_RECURSO",.T.)
        oCarga:setaPropriedadeLookupTabela("04_BC_MOTIVO",STR0275,.T.,"CYO","CYO_CDRF","CYO_DSRF") //"Motivos de Perda"
        oCarga:setaPropriedadePeriodoAtual("05_TIPOPERIODO","D","06_PERIODO")
        
        If !oCarga:gravaMonitorPropriedades()
            lRet := .F.
        EndIf
        oCarga:Destroy()
    EndIf
    FwFreeArray(aCategoria)
    FwFreeArray(aTags)
    FreeObj(oSeries)
Return lRet


/*/{Protheus.doc} BuscaDados
Responsável por realizar a busca dos dados que serão exibidos no monitor (gráfico ou texto)
@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 StatusMotivoPerdas
    Local aNames     := {}
    Local cAliasQry  := GetNextAlias()
    Local cJsonDados := ""
    Local cQuery     := ""
    Local dDataIni   := dDataBase
    Local dDataFin   := dDataBase
    Local nIndice    := 0
    Local nPosTag    := 0
    Local nTotApont  := 0
    Local nTotQuant  := 0
    Local oDados     := JsonObject():New()
    Local oJsonRet   := JsonObject():New()

    oJsonRet["alturaMinimaWidget"] := "350px"
    oJsonRet["alturaMaximaWidget"] := "500px"
    oJsonRet["categorias"]         := {STR0275} //"Motivos de Perda"
    oJsonRet["series"]             := {}
    oJsonRet["tags"]               := {}
    oJsonRet["detalhes"]           := {}

    cQuery := montaQuery(oFiltros, @dDataIni, @dDataFin,1)
    dbUseArea(.T.,"TOPCONN",TcGenQry(,,cQuery),cAliasQry,.F.,.F.)

    nIndice := 0
    While (cAliasQry)->(!Eof())
        ++nIndice

        oDados[AllTrim((cAliasQry)->BC_MOTIVO)] := JsonObject():New()
        oDados[AllTrim((cAliasQry)->BC_MOTIVO)] := {(cAliasQry)->QT_PERDA, PCPMonitorUtils():RetornaCorSerie(nIndice)}

        nTotApont += (cAliasQry)->NR_APONT
        nTotQuant += (cAliasQry)->QT_PERDA

        (cAliasQry)->(dbSkip())
    End
    (cAliasQry)->(dbCloseArea())

    aNames := oDados:GetNames()
    For nIndice := 1 To Len(aNames)
        aAdd(oJsonRet["series"], JsonObject():New())	
        oJsonRet["series"][nIndice]["label"]   := IIF(AllTrim(aNames[nIndice])<>"",aNames[nIndice],"-")
        oJsonRet["series"][nIndice]["color"]   := oDados[aNames[nIndice]][2]
        oJsonRet["series"][nIndice]["tooltip"] := IIF(AllTrim(aNames[nIndice])<>"", aNames[nIndice] + " " + Capital(AllTrim(Posicione("CYO",1,xFilial("CYO",oFiltros["01_BC_FILIAL"])+aNames[nIndice], "CYO_DSRF"))), "- " + STR0286) + ": " + cValToChar(oDados[aNames[nIndice]][1])
        If cSubTipo <> 'pie'
            oJsonRet["series"][nIndice]["data"] := {}
            aAdd(oJsonRet["series"][nIndice]["data"], oDados[aNames[nIndice]][1])
        Else
            oJsonRet["series"][nIndice]["data"] := oDados[aNames[nIndice]][1]
        EndIf
    Next nIndice

    PCPMonitorUtils():AdicionaTagMonitor(oJsonRet["tags"],@nPosTag,"po-icon-calendar",dToC(dDataIni) + " - " + dToC(dDataFin))
    PCPMonitorUtils():AdicionaTagMonitor(oJsonRet["tags"],@nPosTag,"po-icon-star",STR0156 + ": " + cValToChar(nTotQuant)) //"Perda"
    PCPMonitorUtils():AdicionaTagMonitor(oJsonRet["tags"],@nPosTag,"po-icon-star-filled",cValToChar(nTotApont) + IIF(nTotApont > 1," "+STR0197," "+STR0280)) //"Apontamentos" //"Apontamento"

    If oFiltros:HasProperty("04_BC_MOTIVO") .And. ValType(oFiltros["04_BC_MOTIVO"]) == "A"
        For nIndice := 1 To Len(oFiltros["04_BC_MOTIVO"])
            PCPMonitorUtils():AdicionaTagMonitor(oJsonRet["tags"],@nPosTag,"po-icon-filter",oFiltros["04_BC_MOTIVO"][nIndice])
        Next nIndice
    EndIf

    If oFiltros:HasProperty("02_BC_PRODUTO") .And. ValType(oFiltros["02_BC_PRODUTO"]) == "A"
        For nIndice := 1 To Len(oFiltros["02_BC_PRODUTO"])
            PCPMonitorUtils():AdicionaTagMonitor(oJsonRet["tags"],@nPosTag,"po-icon-bar-code",oFiltros["02_BC_PRODUTO"][nIndice])
        Next nIndice
    EndIf

    If oFiltros:HasProperty("03_BC_RECURSO") .And. ValType(oFiltros["03_BC_RECURSO"]) == "A"
        For nIndice := 1 To Len(oFiltros["03_BC_RECURSO"])
            PCPMonitorUtils():AdicionaTagMonitor(oJsonRet["tags"],@nPosTag,"po-icon-manufacture",oFiltros["03_BC_RECURSO"][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 StatusMotivoPerdas
    Local cAliasQry  := GetNextAlias()
    Local cJsonDados := ""
    Local cQuery     := ""
    Local cRoteiro   := ""
    Local cSerie     := ""
    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

    If !Empty(oFiltros["SERIE"])
        cSerie := oFiltros["SERIE"]
    EndIf
    
    cQuery := montaQuery(oFiltros, @dDataIni, @dDataFin,2)
    dbUseArea(.T.,"TOPCONN",TcGenQry(,,cQuery),cAliasQry,.F.,.F.)

    oDados["items"]   := {}
    oDados["columns"] := bscColunas(lExpResult,cSerie)
    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",cSerie + " " + IIF(cSerie <> "-",Capital(AllTrim(Posicione("CYO",1,xFilial("CYO",oFiltros["01_BC_FILIAL"])+cSerie, "CYO_DSRF"))),STR0286))
    Else
        If oFiltros:HasProperty("04_BC_MOTIVO") .And. ValType(oFiltros["04_BC_MOTIVO"]) == "A"
            For nIndice := 1 To Len(oFiltros["04_BC_MOTIVO"])
                PCPMonitorUtils():AdicionaTagMonitor(oDados["tags"],@nPosTag,"po-icon-filter",oFiltros["04_BC_MOTIVO"][nIndice])
            Next nIndice
        EndIf
    EndIf

    If oFiltros:HasProperty("02_BC_PRODUTO") .And. ValType(oFiltros["02_BC_PRODUTO"]) == "A"
        For nIndice := 1 To Len(oFiltros["02_BC_PRODUTO"])
            PCPMonitorUtils():AdicionaTagMonitor(oDados["tags"],@nPosTag,"po-icon-bar-code",oFiltros["02_BC_PRODUTO"][nIndice])
        Next nIndice
    EndIf

    If oFiltros:HasProperty("03_BC_RECURSO") .And. ValType(oFiltros["03_BC_RECURSO"]) == "A"
        For nIndice := 1 To Len(oFiltros["03_BC_RECURSO"])
            PCPMonitorUtils():AdicionaTagMonitor(oDados["tags"],@nPosTag,"po-icon-manufacture",oFiltros["03_BC_RECURSO"][nIndice])
        Next nIndice
    EndIf

    If nPagina > 1
		nStart := ( (nPagina-1) * nTamPagina )
		If nStart > 0
			(cAliasQry)->(DbSkip(nStart))
		EndIf
	EndIf

	nPos := 0
    While (cAliasQry)->(!Eof())
        aAdd(oDados["items"], JsonObject():New())
        nPos++
        cRoteiro := IIF(!Empty((cAliasQry)->C2_ROTEIRO),(cAliasQry)->C2_ROTEIRO,IIF(!Empty((cAliasQry)->B1_OPERPAD),(cAliasQry)->B1_OPERPAD,"01"))

        oDados["items"][nPos]["BC_FILIAL"]  := (cAliasQry)->BC_FILIAL
        oDados["items"][nPos]["BC_TIPO"]    := (cAliasQry)->BC_TIPO
        oDados["items"][nPos]["BC_MOTIVO"]  := (cAliasQry)->BC_MOTIVO
        oDados["items"][nPos]["CYO_DSRF"]   := AllTrim(Posicione("CYO",1,xFilial("CYO",oFiltros["01_BC_FILIAL"])+(cAliasQry)->BC_MOTIVO, "CYO_DSRF"))
        oDados["items"][nPos]["BC_OP"]      := (cAliasQry)->BC_OP
        oDados["items"][nPos]["BC_OPERAC"]  := (cAliasQry)->BC_OPERAC
        oDados["items"][nPos]["G2_DESCRI"]  := AllTrim(Posicione("SG2",1,xFilial("SG2",oFiltros["01_BC_FILIAL"])+(cAliasQry)->BC_PRODUTO+cRoteiro+(cAliasQry)->BC_OPERAC,"G2_DESCRI"))
        oDados["items"][nPos]["BC_PRODUTO"] := (cAliasQry)->BC_PRODUTO
        oDados["items"][nPos]["B1_DESC"]    := (cAliasQry)->B1_DESC
        oDados["items"][nPos]["BC_LOCORIG"] := (cAliasQry)->BC_LOCORIG
        oDados["items"][nPos]["BC_QUANT"]   := (cAliasQry)->BC_QUANT
        oDados["items"][nPos]["B1_UM"]      := (cAliasQry)->B1_UM
        oDados["items"][nPos]["BC_OPERADO"] := (cAliasQry)->BC_OPERADO
        oDados["items"][nPos]["BC_DATA"]    := PCPMonitorUtils():FormataData((cAliasQry)->BC_DATA, 5)
        oDados["items"][nPos]["BC_RECURSO"] := (cAliasQry)->BC_RECURSO
        oDados["items"][nPos]["H1_DESCRI"]  := PCPMonitorUtils():RetornaDescricaoRecurso(oFiltros["01_BC_FILIAL"],(cAliasQry)->BC_RECURSO)

        (cAliasQry)->(dbSkip())

        //Verifica tamanho da página
        If !lExpResult .And. nPos >= nTamPagina
            Exit
        EndIf
    End
    oDados["hasNext"] := (cAliasQry)->(!Eof())
    (cAliasQry)->(dbCloseArea())
    cJsonDados := oDados:toJson()
    FreeObj(oDados)
Return cJsonDados

/*/{Protheus.doc} bscColunas
Cria array de objetos no formato poTableColumn com as colunas da table de detalhamento
@type Static Function
@author 
@since 
@version 
@param  lExpResult, logico, Indica se trata todas as colunas como visible
@param  cSerie    , caracter, Motivo selecionado para filtrar detalhes (quando selecionado)
@return aColumns, array objetos, Contém as definições das colunas da grid do monitor
/*/
Static Function bscColunas(lExpResult, cSerie)
    Local aColunas   := {}
    Local aLabels    := {}
    Local nIndice    := 0
    Local nIndLabels := 0

    PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"BC_FILIAL",STR0058,"string",lExpResult) //"Filial"
    PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"BC_MOTIVO",STR0159,"string",IIF(lExpResult .Or. cSerie == "",.T.,.F.)) //"Motivo"
    PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"CYO_DSRF", STR0160,"string",IIF(lExpResult .Or. cSerie == "",.T.,.F.)) //"Desc. Motivo"
    PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"BC_OP",STR0076,"string",.T.) //"OP"
    PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"BC_OPERAC",STR0077,"string",.T.) //"Operação"
    PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"G2_DESCRI" ,STR0078,"string",lExpResult) //"Desc. Oper"
    PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"BC_PRODUTO",STR0074,"string",.T.) //"Produto"
    PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"B1_DESC",STR0075,"string",lExpResult) //"Desc. Produto"
    PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"BC_LOCORIG",STR0277,"string",.T.) //"Armazém Origem"
    PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"BC_DATA",STR0278,"string",.T.) //"Data Perda"
    PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"BC_QUANT",STR0091,"string",.T.) //"Quantidade"
    PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"B1_UM",STR0180,"string",.T.) //"Un. Medida"
    PCPMonitorUtils():AdicionaLabelsColunaTabela(aLabels,@nIndLabels,"R",COR_VERMELHO,STR0282,COR_BRANCO) //"Refugo"
    PCPMonitorUtils():AdicionaLabelsColunaTabela(aLabels,@nIndLabels,"S",COR_AMARELO,STR0283,COR_PRETO) //"Scrap"
    PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"BC_TIPO",STR0146,"cellTemplate",.T.,.T.,aLabels) //"Tipo"
    PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"BC_OPERADO",STR0141,"string",.T.) //"Operador"
    PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"BC_RECURSO",STR0059,"string",.T.) //"Recurso"    
    PCPMonitorUtils():AdicionaColunaTabela(aColunas,@nIndice,"H1_DESCRI" ,STR0073,"string",lExpResult) //"Desc. Recurso"
Return aColunas

/*/{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 StatusMotivoPerdas
    Local aRetorno := {.T.,""}

    PCPMonitorUtils():ValidaPropriedadeFilial(oFiltros["01_BC_FILIAL"],aRetorno)

    If aRetorno[1] .And. oFiltros["05_TIPOPERIODO"] == "X"
        If !oFiltros:HasProperty("06_PERIODO") .Or. oFiltros["06_PERIODO"] == Nil .Or. Empty(oFiltros["06_PERIODO"])
            aRetorno[1] := .F.
            aRetorno[2] := STR0069 //"Deve ser informada a quantidade de dias para o período personalizado."
        EndIf
    EndIf
Return aRetorno

/*/{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
@param	nTipo   , numerico   , Data final do filtro
		1 - BuscaDados (dados agrupados)
		2 - BuscaDetalhes (colunas para consulta)
@return cQuery  , caracter   , Query utilizada para busca no banco de dados
/*/
Static Function montaQuery(oFiltros, dDataIni, dDataFin, nTipo)
    Local cMotivos  := ""
    Local cProdutos := ""
    Local cQuery    := ""
    Local cRecursos := ""
    Local nIndice   := 0

    cQuery := " SELECT "
    If nTipo == 1
        cQuery +=    " SBC.BC_FILIAL, SBC.BC_MOTIVO, COUNT(SBC.BC_FILIAL) NR_APONT, SUM(SBC.BC_QUANT) QT_PERDA"
    ElseIf nTipo == 2
        cQuery +=    " SBC.BC_FILIAL, SBC.BC_TIPO, SBC.BC_MOTIVO, SBC.BC_OP, SBC.BC_OPERAC, SBC.BC_PRODUTO, SB1.B1_DESC, SB1.B1_UM,"
        cQuery +=    " SBC.BC_LOCORIG, SBC.BC_QUANT, SBC.BC_OPERADO, SBC.BC_DATA, SBC.BC_RECURSO, SB1.B1_OPERPAD, SC2.C2_ROTEIRO"
    EndIf
    cQuery += " FROM " +RetSqlName("SBC")+ " SBC "

    If nTipo == 2
        cQuery += " LEFT JOIN "+RetSqlName("SB1")+" SB1 ON SB1.B1_FILIAL = '"+xFilial("SB1",oFiltros["01_BC_FILIAL"])+"' AND SB1.B1_COD = SBC.BC_PRODUTO AND SB1.D_E_L_E_T_ = ' ' " 
        cQuery += " LEFT JOIN "+RetSqlName("SC2")+" SC2 ON SC2.C2_FILIAL = '"+xFilial("SC2",oFiltros["01_BC_FILIAL"])+"' AND SC2.C2_NUM||SC2.C2_ITEM||SC2.C2_SEQUEN||SC2.C2_ITEMGRD = SBC.BC_OP AND SC2.D_E_L_E_T_ = ' ' "
    EndIf

    cQuery += " WHERE SBC.BC_FILIAL = '"+ xFilial("SBC", oFiltros["01_BC_FILIAL"])+"' "

    If oFiltros:HasProperty("02_BC_PRODUTO") .And. ValType(oFiltros["02_BC_PRODUTO"]) == "A"
        For nIndice := 1 To Len(oFiltros["02_BC_PRODUTO"])
            If Empty(cProdutos)
                cProdutos := "'" + oFiltros["02_BC_PRODUTO"][nIndice] + "'"
            Else
                cProdutos +=  ",'" + oFiltros["02_BC_PRODUTO"][nIndice] + "'"
            EndIf
        Next nIndice
    EndIf
    If !Empty(cProdutos)
        cQuery += " AND SBC.BC_PRODUTO IN ("+cProdutos+") "
    EndIf

    If oFiltros:HasProperty("03_BC_RECURSO") .And. ValType(oFiltros["03_BC_RECURSO"]) == "A"
        For nIndice := 1 To Len(oFiltros["03_BC_RECURSO"])
            If Empty(cRecursos)
                cRecursos := "'" + oFiltros["03_BC_RECURSO"][nIndice] + "'"
            Else
                cRecursos +=  ",'" + oFiltros["03_BC_RECURSO"][nIndice] + "'"
            EndIf
        Next nIndice
    EndIf
    If !Empty(cRecursos)
        cQuery += " AND SBC.BC_RECURSO IN ("+cRecursos+") "
    EndIf

    If !Empty(oFiltros["SERIE"])
        cMotivos := "'" + IIF(oFiltros["SERIE"] <> "-",oFiltros["SERIE"],"") + "'"
    Else
        If oFiltros:HasProperty("04_BC_MOTIVO") .And. ValType(oFiltros["04_BC_MOTIVO"]) == "A"
            For nIndice := 1 To Len(oFiltros["04_BC_MOTIVO"])
                If Empty(cMotivos)
                    cMotivos := "'" + oFiltros["04_BC_MOTIVO"][nIndice] + "'"
                Else
                    cMotivos +=  ",'" + oFiltros["04_BC_MOTIVO"][nIndice] + "'"
                EndIf
            Next nIndice
        EndIf
    EndIf
    If !Empty(cMotivos)
        cQuery += " AND SBC.BC_MOTIVO IN ("+cMotivos+") "
    EndIf

    dDataFin   := dDatabase
    dDataIni   := PCPMonitorUtils():RetornaPeriodoInicial(AllTrim(oFiltros["05_TIPOPERIODO"]),dDataFin,cValToChar(oFiltros["06_PERIODO"]))

    cQuery += " AND SBC.BC_DATA BETWEEN '"+dToS(dDataIni)+"' AND '"+dToS(dDataFin)+"' "
    cQuery += " AND SBC.D_E_L_E_T_ = ' ' "

    If nTipo == 1
        cQuery +=    " GROUP BY SBC.BC_FILIAL, SBC.BC_MOTIVO"
    EndIf

    cQuery := ChangeQuery(cQuery)
Return cQuery