- Criado por Danilo Otavio Lima Salve, última alteração por Rafael Mota Previdi em 18 abr, 2023
1. VISÃO GERAL
A classe CoreDash fornece um objeto utilizado na construção de Cards ou Gráficos.
Este objeto pode ser utilizado na construção de serviços REST utilizados no Dashboard.
02. EXEMPLO DE UTILIZAÇÃO
Disponibiliza uma API REST no Dashboard para visualizar um Card. Com o fonte abaixo (Exemplo) foi obtido o seguinte Card de exemplo:
Para a disponibilização de um card, é necessário que sua API possua 4 endpoints:
1. Um POST para carregar as informações que serão apresentadas nos detalhes deste card (Opção Detalhes):
No exemplo abaixo, essas informações são retornadas pelo endpoint /CardsCustomer/cards/itemsDetails.
O endpoint deve retornar a seguinte estrutura json:
{ "header":[ { "showFilter": boolean, "property": string, "label":string } ], "items":[ { "property": <Valor retornado pela query>, } ], "hasNext": boolean }
A propriedade header refere-se ao cabeçalho da tabela. Como a tabela utilizada pelo dashboard é um componente da biblioteca PO-UI (po-table), deve-se informar as propriedades obrigatórias para este componente: property (nome identificador para a coluna) e label (título para a coluna). Para mais informações, clique aqui.
A propriedade items refere-se aos valores que serão apresentados nas colunas da tabela, ou seja, para cada propriedade informada, a query irá retornar um valor. Exemplo: { "code": "000001" }. Este deve ter a propriedade "hasNext" para informar se há próxima página (true) ou não (false).
{
"header": [
{
"showFilter": true,
"type": "link",
"property": "code",
"visible": true,
"label": "Código",
"action": "Link"
},
{
"showFilter": true,
"property": "store",
"visible": true,
"label": "Loja"
},
{
"showFilter": true,
"property": "name",
"visible": true,
"label": "Nome"
},
{
"showFilter": true,
"property": "fantasyName",
"visible": true,
"label": "Nome Fantasia"
},
{
"showFilter": true,
"property": "risk",
"visible": true,
"label": "Risco"
}
],
"items": [
{
"code": "API001",
"store": "01",
"name": "CLIENTE API INCLUSAO",
"fantasyName": "CLIENTE API INCLUSAO",
"risk": "A"
},
{
"code": "API002",
"store": "01",
"name": "CLIENTE API ALTERACAO",
"fantasyName": "API ALTERACAO",
"risk": "A"
},
{
"code": "API003",
"store": "01",
"name": "CLIENTE API EXCLUSAO",
"fantasyName": "API EXCLUSAO",
"risk": "A"
},
{
"code": "API005",
"store": "01",
"name": "API 005 MANUT.COMISSAO ALTERA",
"fantasyName": "API005",
"risk": "A"
},
{
"code": "API006",
"store": "01",
"name": "API006 MANUT.COMISSAO DELETA",
"fantasyName": "API006",
"risk": "A"
},
{
"code": "API007",
"store": "01",
"name": "API007 - MATS030 - ALTERAR",
"fantasyName": "API007 MATS030",
"risk": "A"
},
{
"code": "API008",
"store": "01",
"name": "API008 - MATS030 - DELETAR",
"fantasyName": "API008 MATS030",
"risk": "A"
},
{
"code": "BETIM",
"store": "01",
"name": "LOJA BETIM",
"fantasyName": "BETIM MG",
"risk": "A"
},
{
"code": "C16190",
"store": "01",
"name": "DSERFINR-16190",
"fantasyName": "16190",
"risk": "A"
},
{
"code": "CLIBH",
"store": "01",
"name": "CLIENTE BELO HORIZONTE",
"fantasyName": "BELO HORIZONTE",
"risk": "A"
}
],
"hasNext": true
}
2. Um GET para retornar os campos que poderão ser utilizados no filtro do card (Opção 'Filtrar' na inclusão/alteração do card):
No exemplo abaixo, essas informações são retornadas pelo endpoint /CardsCustomer/cards/cardFilter.
O endpoint deve retornar a seguinte estrutura json:
{ "items": [ { "showFilter": boolean, "property": string, "label": string } ] }
A propriedade items refere-se ao campo "Campo" da inclusão de filtro. O property é o nome identificador para a opção e o label é o título para a opção.
{ "items": [ { "showFilter": true, "property": "code", "label": "Código" }, { "showFilter": true, "property": "store", "label": "Loja" }, { "showFilter": true, "property": "name", "label": "Nome" }, { "showFilter": true, "property": "fantasyName", "label": "Nome Fantasia" }, { "showFilter": true, "property": "risk", "label": "Risco" } ] }
3. Um GET para retornar o valor das informações que serão apresentadas no card (no máximo 4). Exemplo: A informação Total clientes risco A possui o valor 197.
No exemplo abaixo, essas informações são retornadas pelo endpoint /CardsCustomer/cards/cardInfo.
O endpoint deve retornar a seguinte estrutura json:
{ "items": [ { "propriedade": "valor" } ], "hasNext": "false" }
A propriedade items deve trazer todas as informações que poderão ser apresentadas no card e seu respectivo valor. No exemplo que temos acima com a informação de Total a Receber, ele se refere à propriedade "total" apresentada neste retorno.
{ "items": [ { "risco_a": 197, "risco_b": 10, "risco_c": 1 } ], "hasNext": "false" }
4. Um GET para retornar os campos/propriedades que podem ser utilizados na apresentação do card:
No exemplo abaixo, essas informações são retornadas pelo endpoint /CardsCustomer/cards/fieldsInfo.
O endpoint deve retornar a seguinte estrutura json:
{ "items": [ { "value": string, "label": string } ] }
A propriedade items deve retornar a lista com todas as opções que podem aparecer nos campos Primeira Informação, Segunda Informação, Terceira Informação e Quarta Informação. Esse campo é um componente da biblioteca PO-ui (po-combo), portanto deve retornar as propriedades obrigatórias para sua implementação: label (título para a opção) e value (valor daquela opção). Para mais informações, clique aqui.
{ "items": [ { "value": "risco_a", "label": "Total clientes risco A: " }, { "value": "risco_b", "label": "Total clientes risco B: " }, { "value": "risco_c", "label": "Total clientes risco C: " } ] }
Clique aqui para download do fonte de exemplo.
#INCLUDE "TOTVS.CH" #INCLUDE "RESTFUL.CH" //------------------------------------------------------------------- /*/{Protheus.doc} WSCardsCustomer Exemplo de API de integração de Cards @author Squad CRM & Faturamento @since 13/04/2022 @version 12.1.33 /*/ //------------------------------------------------------------------- WSRESTFUL CardsCustomer DESCRIPTION "Cards de Clientes" WSDATA Fields AS STRING OPTIONAL WSDATA Order AS STRING OPTIONAL WSDATA Page AS INTEGER OPTIONAL WSDATA PageSize AS INTEGER OPTIONAL WSMETHOD POST itemsDetails ; DESCRIPTION "Carrega os Itens Utilizados para Montagem do Painel" ; WSSYNTAX "/cards/itemsDetails/{Order, Page, PageSize, Fields}" ; PATH "/cards/itemsDetails"; PRODUCES APPLICATION_JSON WSMETHOD GET cardFilter; DESCRIPTION "Disponibiliza os campos que poderão ser utilizados no filtro do Card" ; WSSYNTAX "/cards/cardFilter/" ; PATH "/cards/cardFilter"; PRODUCES APPLICATION_JSON WSMETHOD GET cardInfo; DESCRIPTION "Carrega as informações do Painel" ; WSSYNTAX "/cards/cardInfo/" ; PATH "/cards/cardInfo"; PRODUCES APPLICATION_JSON WSMETHOD GET fieldsInfo ; DESCRIPTION "Carrega os campos que podem que ser utilizados" ; WSSYNTAX "/cards/fieldsInfo/" ; PATH "/cards/fieldsInfo"; PRODUCES APPLICATION_JSON ENDWSRESTFUL //------------------------------------------------------------------- /*/{Protheus.doc} POST itemsDetails Carrega os Itens Utilizados para Montagem do Painel @author Squad CRM & Faturamento @since 13/04/2022 @version 12.1.33 /*/ //------------------------------------------------------------------- WSMETHOD POST itemsDetails WSRECEIVE Order, Page, PageSize, Fields WSSERVICE CardsCustomer Local aHeader := {} Local aRet := {} Local cError := "Erro na Requisição" Local lRet := .T. Local oCoreDash := CoreDash():New() Local aFilter := {} Local nQtdFilter := 0 Local cFilter := "" Local nX := 0 Local cBody := DecodeUtf8(Self:GetContent()) Local oBody := JsonObject():New() Local oJDetails := JsonObject():New() Local cCampos := "" Self:SetContentType("application/json") If !Empty(cBody) oBody:FromJson(cBody) If ValType(oBody["detailFilter"]) == "A" oJDetails := oBody["detailFilter"] EndIf EndIf If Len(oJDetails) == 0 aHeader := RetHeader("SA1") oCoreDash:SetFields(DePara("SA1")) oCoreDash:SetApiQstring(Self:aQueryString) aFilter := oCoreDash:GetApiFilter() nQtdFilter := Len(aFilter) If nQtdFilter > 0 For nX := 1 to nQtdFilter cFilter += " AND " + aFilter[nX][1] Next EndIf //Chama a função responsavel por montar a Expressão SQL aRet := MntQuery(, cFilter + " AND (SA1.A1_RISCO = 'A' OR SA1.A1_RISCO = 'B' OR SA1.A1_RISCO = 'C')",,"SA1") ElseIf Len(oJDetails) == 1 aHeader := RetHeader("SC5") oCoreDash:SetFields(DePara("SC5")) oCoreDash:SetApiQstring(Self:aQueryString) aFilter := oCoreDash:GetApiFilter() nQtdFilter := Len(aFilter) If nQtdFilter > 0 For nX := 1 to nQtdFilter cFilter += " AND " + aFilter[nX][1] Next EndIf cFilter := " AND SC5.C5_CLIENTE = '" + oJDetails[1]['code'] + "'" cCampos := "SC5.C5_NUM, SC5.C5_TIPO, SC5.C5_CONDPAG, SC5.C5_EMISSAO" aRet := MntQuery(cCampos, cFilter,,"SC5") EndIf //Define a Query padrão utilizada no Serviço oCoreDash:SetQuery(aRet[1]) oCoreDash:SetWhere(aRet[2]) If Len(aRet) >= 3 oCoreDash:SetGroupBy(aRet[3]) EndIf oCoreDash:BuildJson() lRet := ValType(oCoreDash:GetJsonObject()['items']) == "A" If lRet oCoreDash:SetPOHeader(aHeader) Self:SetResponse( oCoreDash:ToObjectJson()) Else SetRestFault(500, EncodeUtf8(cError)) EndIf oCoreDash:Destroy() aSize(aRet, 0) aSize(aHeader, 0) Return lRet //------------------------------------------------------------------- /*/{Protheus.doc} MntQuery Monta a query responsável por trazer os itens utilizados no Painel @param cCampos, Caractere, Campos que serão retornados no SELECT @param cFiltro, Caractere, Filtro a ser adicionado na query @param cGroupBy, Caractere, Expressão group by a ser adicionada na query @author Squad CRM & Faturamento @since 13/04/2022 @version 12.1.33 /*/ //------------------------------------------------------------------- Static Function MntQuery(cCampos, cFiltro, cGroupBy, cTable) Local cQuery Local cWhere Local cGroup Default cTable := "SA1" Default cCampos := "SA1.A1_COD, SA1.A1_LOJA, SA1.A1_NOME, SA1.A1_NREDUZ, SA1.A1_RISCO" If cTable == "SA1" cQuery := " SELECT " + cCampos + " FROM " + RetSqlName("SA1") + " SA1 " cWhere := " SA1.R_E_C_N_O_ <= 1000 AND SA1.A1_FILIAL = '" + xFilial("SA1") + "'" + cFiltro cWhere += " AND SA1.D_E_L_E_T_ = ' ' " ElseIf cTable == "SC5" cQuery := " SELECT " + cCampos + " FROM " + RetSqlName("SC5") + " SC5 " cWhere := " SC5.C5_FILIAL = '" + xFilial("SC5") + "'" + cFiltro cWhere += " AND SC5.D_E_L_E_T_ = ' ' " EndIf If !Empty(cGroupBy) cGroup := cGroupBy EndIf Return {cQuery, cWhere, cGroup} //------------------------------------------------------------------- /*/{Protheus.doc} DePara Efetua o Conversão entre os atributos objetos do Json e os campos utilizados na Consulta @author Squad CRM & Faturamento @since 13/04/2022 @version 12.1.33 /*/ //------------------------------------------------------------------- Static Function DePara(cTable) Local aCampos := {} Default cTable := "SA1" If cTable == "SA1" aCampos := {; {"code" , "SA1.A1_COD" },; {"store" , "SA1.A1_LOJA" },; {"name" , "SA1.A1_NOME" },; {"fantasyName", "SA1.A1_NREDUZ"},; {"risk" , "SA1.A1_RISCO" }; } ElseIf cTable == "SC5" aCampos := {; {"num" , "SC5.C5_NUM" },; {"type" , "SC5.C5_TIPO" },; {"payment" , "SC5.C5_CONDPAG" },; {"emission", "SC5.C5_EMISSAO"}; } EndIf Return aCampos //------------------------------------------------------------------- /*/{Protheus.doc} GET cardInfo Método para retornar os dados que podem ser apresentados pelo Card @author Squad CRM & Faturamento @since 13/04/2022 @version 12.1.33 /*/ //------------------------------------------------------------------- WSMETHOD GET cardInfo WSRESTFUL CardsCustomer Local aFilter := {} Local cWhere := "" Local nFiltro := 0 Local oCoreDash := CoreDash():New() Local oResponse := JsonObject():New() //Converte os campos utilizados na consulta para os campos utilizados no card. oCoreDash:SetFields(DePara()) //Converte o Filtro informado no parametro Query String. oCoreDash:SetApiQstring(Self:aQueryString) aFilter := oCoreDash:GetApiFilter() For nFiltro := 1 to Len(aFilter) cWhere += " AND " + aFilter[nFiltro][1] Next RetCardInfo(@oResponse, cWhere) self:SetResponse( EncodeUtf8(FwJsonSerialize(oResponse,.T.,.T.)) ) oResponse := Nil FreeObj( oResponse ) oCoreDash:Destroy() FreeObj( oCoreDash ) Return .T. //------------------------------------------------------------------- /*/{Protheus.doc} RetCardInfo Retorna os dados que poderão ser apresentados no painel @author Squad CRM & Faturamento @since 13/04/2022 @version 12.1.33 /*/ //------------------------------------------------------------------- Static Function RetCardInfo(oResponse, cApiFilter) Local oItem Local aItems := {} Default cApiFilter := "" oItem := JsonObject():New() oItem["risco_a"] := RetRisco(" AND SA1.A1_RISCO = 'A' " + cApiFilter) oItem["risco_b"] := RetRisco(" AND SA1.A1_RISCO = 'B' " + cApiFilter) oItem["risco_c"] := RetRisco(" AND SA1.A1_RISCO = 'C' " + cApiFilter) aAdd(aItems, oItem) oResponse['hasNext'] := 'false' oResponse["items"] := aItems Return Nil //------------------------------------------------------------------- /*/{Protheus.doc} RetRisco Retorna os dados de acordo com o filtro @param cFiltro, Caractere, Filtro a ser adicionado na query @author Squad CRM & Faturamento @since 13/04/2022 @version 12.1.33 /*/ //------------------------------------------------------------------- Static Function RetRisco(cFiltro) Local aQuery := MntQuery("COUNT(SA1.A1_COD) TOTAL_REGISTROS", cFiltro) Local cQuery := "" Local cTemp := GetNextAlias() Local xRet Default cWhere := "" Default cInfo := "" cQuery := aQuery[1] + " WHERE " + aQuery[2] DBUseArea( .T., "TOPCONN", TCGenQry( ,, cQuery ), cTemp, .T., .T. ) xRet := (cTemp)->TOTAL_REGISTROS (cTemp)->( DBCloseArea() ) Return xRet //------------------------------------------------------------------- /*/{Protheus.doc} GET fieldsInfo Carrega os campos que podem que ser utilizados @author Squad CRM & Faturamento @since 13/04/2022 @version 12.1.33 /*/ //------------------------------------------------------------------- WSMETHOD GET fieldsInfo WSSERVICE CardsCustomer Local aItems := {} Local oResponse := JsonObject():New() Local oCoreDash := CoreDash():New() aAdd(aItems, { "risco_a" , "Total clientes risco A: " }) aAdd(aItems, { "risco_b" , "Total clientes risco B: " }) aAdd(aItems, { "risco_c" , "Total clientes risco C: " }) /*Retorna um Objeto no formato de Value e Label*/ oResponse["items"] := oCoreDash:SetPOCombo(aItems) Self:SetResponse( EncodeUtf8(oResponse:ToJson())) Return .T. //------------------------------------------------------------------- /*/{Protheus.doc} GET cardFilter Retorna os campos que poderão ser filtrados @author Squad CRM & Faturamento @since 13/04/2022 @version 12.1.27 /*/ //------------------------------------------------------------------- WSMETHOD GET cardFilter WSSERVICE CardsCustomer Local aFields := {} Local oCoreDash := CoreDash():New() Local oResponse := JsonObject():New() aFields := {; {"code" , "Código" },; {"store" , "Loja" },; {"name" , "Nome" },; {"fantasyName", "Nome Fantasia"},; {"risk" , "Risco" }; } oResponse["items"] := oCoreDash:SetPOHeader(aFields) Self:SetResponse( EncodeUtf8(oResponse:ToJson())) Return .T. //------------------------------------------------------------------- /*/{Protheus.doc} RetHeader Retorna os campos do cabeçalho dos detalhes @author Squad CRM & Faturamento @since 18/04/2022 @version 12.1.33 /*/ //------------------------------------------------------------------- Static Function RetHeader(cTable) Local aHeader Default cTable := "SA1" If cTable == "SA1" aHeader := {; {"code" , "Código" , 'link',,,.T.},; {"store" , "Loja" ,,,,.T.},; {"name" , "Nome" ,,,,.T.},; {"fantasyName", "Nome Fantasia",,,,.T.},; {"risk" , "Risco" ,,,,.T.}; } ElseIf cTable == "SC5" aHeader := {; {"num" , "Número Pedido" ,,,,.T.},; {"type" , "Tipo Pedido" ,,,,.T.},; {"payment" , "Condição de Pagamento",,,,.T.},; {"emission", "Emissão" ,,,,.T.}; } EndIf Return aHeader
Disponibiliza uma API REST no Dashboard para visualizar um gráfico de Pizza ou Polar. Com o fonte abaixo (Exemplo) foi obtido o seguinte Gráfico de exemplo:
Para disponibilização de gráficos em pizza/polar, é necessário que a API possua 3 endpoints:
1. Um GET para retornar o formulário de cadastro do gráfico:
No exemplo abaixo, essas informações são retornadas pelo endpoint /Exemplo2/charts/form.
Diferente dos cards, o gráfico possui um formulário dinâmico e é o serviço acima mencionado que deve retornar os dados para a montagem do formulário de cadastro. Neste exemplo, ele nos retornou o formulário a partir da linha 'Tipo de Gráfico'. Tudo o que vem antes dessa linha, é padrão para todos os gráficos.
O endpoint deve retornar a seguinte estrutura json:
{ "items": [ { "divider": string, "gridSmColumns": number, "type": string, "property": string, "gridColumns": number, "required": boolean, "label": string } ] }
A propriedade items deve retornar a lista com as configurações de todos os campos que devem ser apresentados no formulário. Para a montagem deste formulário, é utilizado o componente Dynamic Form do PO-ui, portanto para entender cada uma das propriedades a serem retornadas neste serviço, clique aqui.
{ "items": [ { "divider": "Tipo de Gráfico", "gridSmColumns": 12, "options": [ { "value": "pie", "label": "Pizza" }, { "value": "polarArea", "label": "Polar" } ], "type": "string", "property": "charttype", "gridColumns": 6, "required": true, "label": "Tipo de Gráfico" }, { "divider": "Datas", "gridSmColumns": 12, "type": "date", "property": "datainicio", "gridColumns": 6, "required": true, "label": "Dt. Emissão De" }, { "gridSmColumns": 12, "type": "date", "property": "datafim", "gridColumns": 6, "required": true, "label": "Dt. Emissão Ate" } ] }
2. Um POST para carregar as informações do gráfico:
No exemplo abaixo, essas informações são retornadas pelo endpoint /Exemplo2/charts/retdados.
O endpoint deve retornar a seguinte estrutura json:
{ "items": [ { "chartData": [ Lista das informações a serem apresentadas no gráfico ], "chartLabels": [ Lista dos títulos das informações ], "charttype": string - Tipo do gráfico, "title": string - Título do gráfico } ] }
A propriedade items deve retornar as informações do gráfico como valores a serem apresentados, títulos a representarem esses valores, título do gráfico e máscara de valores a ser utilizada.
{ "items": [ { "chartData": [ 90, 470, 369, 150, 993, 488, 599, 539, 650, 5, 362, 346, 518, 983, 481, 34, 481, 377, 571, 127, 283, 898, 545, 279, 851, 844, 367, 971 ], "chartLabels": [ "AC", "AL", "AM", "AP", "BA", "CE", "DF", "ES", "EX", "GO", "MA", "MG", "MS", "MT", "PA", "PB", "PE", "PI", "PR", "RJ", "RN", "RO", "RR", "RS", "SC", "SE", "SP", "TO" ], "charttype": "", "title": "Nota fiscal por Estado" } ] }
3. Um POST para carregar as informações que serão apresentadas nos detalhes do gráfico:
No exemplo abaixo, essas informações são retornadas pelo endpoint /Exemplo2/charts/itemsDetails.
O endpoint deve retornar a seguinte estrutura json:
{ "header":[ { "showFilter": boolean, "property": string, "label":string } ], "items":[ { "property": <Valor retornado pela query>, } ], "hasNext": boolean }
A propriedade header refere-se ao cabeçalho da tabela. Como a tabela utilizada pelo dashboard é um componente da biblioteca PO-UI (po-table), deve-se informar as propriedades obrigatórias para este componente: property (nome identificador para a coluna) e label (título para a coluna). Para mais informações, clique aqui.
A propriedade items refere-se aos valores que serão apresentados nas colunas da tabela, ou seja, para cada propriedade informada, a query irá retornar um valor. Exemplo: { "documentType": "N" }. Este deve ter a propriedade "hasNext" para informar se há próxima página (true) ou não (false).
{ "header": [ { "showFilter": true, "type": "link", "property": "document", "label": "Documento", "action": "Link" }, { "showFilter": true, "property": "series", "label": "Serie" }, { "showFilter": true, "property": "state", "label": "UF" }, { "showFilter": true, "property": "documentType", "label": "Tipo" }, { "showFilter": true, "property": "dateOfIssue", "label": "Emissão" } ], "items": [ { "series": "004", "document": "000000001", "state": "SP", "documentType": "N", "dateOfIssue": "14/07/20" }, { "series": "133", "document": "000000001", "state": "SP", "documentType": "N", "dateOfIssue": "10/02/21" }, { "series": "3", "document": "000000001", "state": "SP", "documentType": "N", "dateOfIssue": "30/08/17" }, { "series": "317", "document": "000000001", "state": "MG", "documentType": "N", "dateOfIssue": "10/06/20" }, { "series": "626", "document": "000000001", "state": "SP", "documentType": "N", "dateOfIssue": "26/08/21" }, { "series": "FAT", "document": "000000001", "state": "SP", "documentType": "N", "dateOfIssue": "14/10/16" }, { "series": "MN", "document": "000000001", "state": "SP", "documentType": "N", "dateOfIssue": "02/09/21" }, { "series": "NF", "document": "000000001", "state": "SP", "documentType": "N", "dateOfIssue": "28/03/19" }, { "series": "3", "document": "000000002", "state": "SP", "documentType": "N", "dateOfIssue": "22/11/17" }, { "series": "317", "document": "000000002", "state": "MG", "documentType": "N", "dateOfIssue": "10/06/20" } ], "hasNext": true }
Clique aqui para download do fonte de exemplo.
#INCLUDE "TOTVS.CH" #INCLUDE "RESTFUL.CH" //------------------------------------------------------------------------ /*/{Protheus.doc} Exemplo2 Exemplo de API de integração de Graficos de Pizza e/ou Polar @author Squad CRM & Faturamento @since 26/03/2020 @version 12.1.27 /*/ //------------------------------------------------------------------------ WSRESTFUL Exemplo2 DESCRIPTION "Exemplo de API - Grafico Pizza e Polar" WSDATA JsonFilter AS STRING OPTIONAL WSDATA drillDownFilter AS STRING OPTIONAL WSDATA Page AS INTEGER OPTIONAL WSDATA PageSize AS INTEGER OPTIONAL WSMETHOD GET form ; DESCRIPTION "Form de Cadastro do Gráfico" ; WSSYNTAX "/charts/form/" ; PATH "/charts/form"; PRODUCES APPLICATION_JSON WSMETHOD POST retdados ; DESCRIPTION "Retorna as Informações do Gráfico" ; WSSYNTAX "/charts/retdados/{JsonFilter}" ; PATH "/charts/retdados"; PRODUCES APPLICATION_JSON WSMETHOD POST itemsDetails ; DESCRIPTION "Carrega o detalhamento do gráfico" ; WSSYNTAX "/charts/itemsDetails/{JsonFilter}" ; PATH "/charts/itemsDetails"; PRODUCES APPLICATION_JSON ENDWSRESTFUL //------------------------------------------------------------------- /*/{Protheus.doc} GET form Retorna os campos que apresentados no Cadastro do Grafico. Devera seguir o formato do Dynamic Form do PO-UI. https://po-ui.io/tools/dynamic-form @author Squad CRM & Faturamento @since 28/07/2020 @version 12.1.27 /*/ //------------------------------------------------------------------- WSMETHOD GET form WSSERVICE Exemplo2 Local oResponse := JsonObject():New() Local oCoreDash := CoreDash():New() oCoreDash:SetPOForm("Tipo de Gráfico" , "charttype" , 6 , "Tipo de Gráfico" , .T., "string",; oCoreDash:SetPOCombo({{"pie","Pizza"},{"polarArea","Polar"}})) oCoreDash:SetPOForm("Datas" , "datainicio" , 6 , "Dt. Emissão De" , .T., "date") oCoreDash:SetPOForm("" , "datafim" , 6 , "Dt. Emissão Ate" , .T., "date") oResponse := oCoreDash:GetPOForm() Self:SetResponse( EncodeUtf8(oResponse:ToJson())) Return .T. //------------------------------------------------------------------- /*/{Protheus.doc} POST retdados Retorna um objeto JSON com as informações e valores do Grafico @author Squad CRM & Faturamento @since 28/07/2020 @version 12.1.27 /*/ //------------------------------------------------------------------- WSMETHOD POST retdados WSRECEIVE JsonFilter WSSERVICE Exemplo2 Local oResponse := JsonObject():New() Local oCoreDash := CoreDash():New() Local oJson := JsonObject():New() oJson:FromJson(DecodeUtf8(Self:GetContent())) retDados(@oResponse, oCoreDash, oJson) Self:SetResponse( EncodeUtf8(oResponse:ToJson())) oResponse := Nil FreeObj( oResponse ) oCoreDash:Destroy() FreeObj( oCoreDash ) Return .T. //------------------------------------------------------------------- /*/{Protheus.doc} POST retdados Retorna os items utilizado no Drilldown @author Squad CRM & Faturamento @since 28/07/2020 @version 12.1.27 /*/ //------------------------------------------------------------------- WSMETHOD POST itemsDetails WSRECEIVE JsonFilter, drillDownFilter WSRESTFUL Exemplo2 Local aHeader := {} Local aItems := {} Local aRet := {} Local cBody := DecodeUtf8(Self:GetContent()) Local cError := "Erro na Requisição" Local cSelect := "" Local cWhere := "" Local lRet := .T. Local oCoreDash := CoreDash():New() Local oBody := JsonObject():New() Local oJsonFilter := JsonObject():New() Local oJsonDD := JsonObject():New() If !Empty(cBody) oBody:FromJson(cBody) If ValType(oBody["chartFilter"]) == "J" oJsonFilter := oBody["chartFilter"] EndIf If ValType(oBody["detailFilter"]) == "A" oJsonDD := oBody["detailFilter"] EndIf EndIf Self:SetContentType("application/json") If oJsonFilter:GetJsonText("level") == "null" .Or. Len(oJsonFilter["level"]) == 0 If Len(oJsonDD) == 0 //Nivel 1 do Drilldown aHeader := {; {"document" , "Documento" ,"link" },; {"series" , "Serie" },; {"state" , "UF" },; {"documentType" , "Tipo" },; {"dateOfIssue" , "Emissão" }; } aItems := {; {"document" , "F2_DOC" },; {"series" , "F2_SERIE" },; {"state" , "F2_EST" },; {"documentType" , "F2_TIPO" },; {"dateOfIssue" , "F2_EMISSAO" }; } cSelect := " F2_DOC, F2_SERIE, F2_EST, F2_TIPO, F2_EMISSAO, F2_TIPO " aRet := QuerySF2(cSelect) Elseif Len(oJsonDD) == 1 //Nivel 2 do Drilldown aHeader := {; {"D2_ITEM" , "Item" },; {"D2_COD" , "Cod. Produto", "link" },; {"B1_DESC" , "Desc. Produto " },; {"D2_PRCVEN", "Vlr.Unitario", "currency","BRL" },; {"D2_QUANT" , "Quantidade","number",'1.2-5' },; {"D2_TOTAL" , "Vlr. Total", "currency","BRL" },; {"D2_LOCAL" , "Armazem" }; } aItems := {; {"D2_ITEM" , "D2_ITEM"},; {"D2_COD" , "D2_COD"},; {"B1_DESC" , "B1_DESC"},; {"D2_PRCVEN" , "D2_PRCVEN"},; {"D2_QUANT" , "D2_QUANT"},; {"D2_TOTAL" , "D2_TOTAL"},; {"D2_LOCAL" , "D2_LOCAL"}; } cSelect := " D2_ITEM, D2_COD, B1_DESC, D2_PRCVEN, D2_QUANT, D2_TOTAL, D2_LOCAL " cWhere := " D2_DOC = '" + oJsonDD[1]['document'] + "' AND D2_SERIE = '" + oJsonDD[1]['series'] + "' " aRet := QuerySD2(cSelect, cWhere) Elseif Len(oJsonDD) == 2 //Nivel 3 do Drilldown aHeader := {; {"B1_COD" , "Cod. Produto" },; {"B1_DESC" , "Desc. Produto " },; {"B1_PRV1" , "Preço de Venda", "currency","BRL" },; {"B1_TE" , "TES Entrada Pad" },; {"B1_TS" , "TES Saída Pad" }; } aItems := {; {"B1_COD" , "B1_COD"},; {"B1_DESC" , "B1_DESC"},; {"B1_PRV1" , "B1_PRV1"},; {"B1_TE" , "B1_TE"},; {"B1_TS" , "B1_TS"}; } cSelect := " B1_COD, B1_DESC, B1_PRV1, B1_TE, B1_TS " cWhere := " B1_COD = '" + oJsonDD[2]['D2_COD'] + "' " aRet := QuerySB1(cSelect, cWhere) Endif Else //Monta o Drilldown do grafico nivel 2 aHeader := {; {"document" , "Documento" },; {"series" , "Serie" },; {"state" , "UF" },; {"documentType" , "Tipo" },; {"dateOfIssue" , "Emissão" }; } aItems := {; {"document" , "F2_DOC" },; {"series" , "F2_SERIE" },; {"state" , "F2_EST" },; {"documentType" , "F2_TIPO" },; {"dateOfIssue" , "F2_EMISSAO" }; } cSelect := " F2_DOC, F2_SERIE, F2_EST, F2_TIPO, F2_EMISSAO, F2_TIPO " aRet := QuerySF2(cSelect) EndIf oCoreDash:SetQuery(aRet[1]) oCoreDash:SetWhere(aRet[2]) oCoreDash:SetFields(aItems) oCoreDash:SetApiQstring(Self:aQueryString) oCoreDash:BuildJson() If lRet oCoreDash:SetPOHeader(aHeader) Self:SetResponse( oCoreDash:ToObjectJson() ) Else cError := oCoreDash:GetJsonError() SetRestFault( 500, EncodeUtf8(cError) ) EndIf oCoreDash:Destroy() FreeObj(oJsonDD) FreeObj(oJsonFilter) FreeObj(oBody) aSize(aRet, 0) aSize(aItems, 0) aSize(aHeader, 0) Return lRet //------------------------------------------------------------------- /*/{Protheus.doc} retDados Retorna os dados que poderão ser apresentados no Grafico @author Squad CRM & Faturamento @since 28/07/2020 @version 12.1.27 /*/ //------------------------------------------------------------------- Static Function retDados(oResponse, oCoreDash, oJson) Local aData := {} Local aDataFim := {} Local aCab := {} Local aCores := oCoreDash:GetColorChart() Local nLoop := 0 If oJson:GetJsonText("level") == "null" .Or. Len(oJson["level"]) == 0 aCab := GetUF() For nLoop := 1 To Len(aCab) aAdd(aData, Randomize(1,999) ) Next nLoop aDataFim := {} aAdd(aDataFim, oCoreDash:SetChart(aCab,aData,/*lCurrency*/,,"Nota fiscal por Estado")) ElseIf Len(oJson["level"]) == 1 aCab := GetTipoNF() For nLoop := 1 To Len(aCab) aAdd(aData, Randomize(1,999) ) Next nLoop aAdd(aDataFim, oCoreDash:SetChart(aCab,aData,/*lCurrency*/,"pie","Quantidade de Notas por Tipos")) ElseIf Len(oJson["level"]) == 2 aCab := GetTopCli() For nLoop := 1 To Len(aCab) aAdd(aData, Randomize(1, 999) ) Next nLoop oCoreDash:SetChartInfo( aData, 'Notas', 'bar', aCores[8][3] ) //Cor utilizada: OrangeLht aAdd(aDataFim, oCoreDash:SetChart(aCab,,/*lCurrency*/,"bar","TOP 10 Clientes por Tipo de Nota")) Endif oResponse["items"] := aDataFim Return Nil //------------------------------------------------------------------- /*/{Protheus.doc} QuerySF2 Monta a query responsável por trazer os registro da Nota fiscal @param cSelect, Caractere, Campos que serão retornados no SELECT @param cFilter, Caractere, Filtro complementar utilizado na clausula WHERE @author Squad CRM & Faturamento @since 28/07/2020 @version 12.1.27 /*/ //------------------------------------------------------------------- Static Function QuerySF2(cSelect, cFilter ) Local cQuery Local cWhere Default cSelect := " SF2.F2_DOC, SF2.F2_SERIE, SF2.F2_CLIENTE, SF2.F2_LOJA, SF2.F2_TIPO " Default cFilter := "" cQuery := " SELECT " + cSelect + " FROM " + RetSqlName("SF2") + " SF2 " cWhere := " SF2.F2_FILIAL = '" + xFilial("SF2") + "' " If !Empty(cFilter) cWhere += " AND " + cFilter Endif cWhere += " AND SF2.D_E_L_E_T_ = ' ' " Return { cQuery, cWhere } //------------------------------------------------------------------- /*/{Protheus.doc} QuerySD2 Monta a query responsável por trazer os registro da Nota fiscal @param cSelect, Caractere, Campos que serão retornados no SELECT @param cFilter, Caractere, Filtro complementar utilizado na clausula WHERE @author Squad CRM & Faturamento @since 28/07/2020 @version 12.1.27 /*/ //------------------------------------------------------------------- Static Function QuerySD2(cSelect, cFilter) Local cQuery Local cWhere Default cSelect := " SD2.D2_DOC, SD2.D2_ITEM, SD2.D2_COD " Default cFilter := "" cQuery := " SELECT " + cSelect + " FROM " + RetSqlName("SD2") + " SD2 " cQuery += " INNER JOIN " + RetSqlName("SB1") + " SB1 " cQuery += " ON B1_COD = D2_COD AND SB1.D_E_L_E_T_ = ' ' AND B1_FILIAL = '" + xFilial("SB1") + "' " cWhere := " SD2.D2_FILIAL = '" + xFilial("SD2") + "' " If !Empty(cFilter) cWhere += " AND " + cFilter Endif cWhere += " AND SD2.D_E_L_E_T_ = ' ' " Return {cQuery, cWhere} //------------------------------------------------------------------- /*/{Protheus.doc} QuerySB1 Monta a query responsável por trazer o registro do Cad. Produto @param cSelect, Caractere, Campos que serão retornados no SELECT @param cFilter, Caractere, Filtro complementar utilizado na clausula WHERE @author Squad CRM & Faturamento @since 08/06/2022 @version 12.1.33 /*/ //------------------------------------------------------------------- Static Function QuerySB1(cSelect, cFilter) Local cQuery Local cWhere Default cSelect := " SB1.B1_COD, SB1.B1_DESC " Default cFilter := "" cQuery := " SELECT " + cSelect + " FROM " + RetSqlName("SB1") + " SB1 " cWhere := " SB1.B1_FILIAL = '" + xFilial("SB1") + "' " If !Empty(cFilter) cWhere += " AND " + cFilter Endif cWhere += " AND SB1.D_E_L_E_T_ = ' ' " Return {cQuery, cWhere} //------------------------------------------------------------------- /*/{Protheus.doc} GetUF Retorna UF @author Aline Navarro @since 22/12/2020 @version 12.1.27 /*/ //------------------------------------------------------------------- Static Function GetUF() Local aUF := {} Local aUFX5 := {} Local nX := 0 Local nLenAUFX5 := 0 aUFX5 := FWGetSX5("12") nLenAUFX5 := Len(aUFX5) For nX := 1 To nLenAUFX5 aAdd(aUF,RTrim(aUFX5[nX,3])) //X5_CHAVE Next nX Return aUF //------------------------------------------------------------------- /*/{Protheus.doc} GetTipoNF Retorna os tipos de NF @author Rafael Mota Previdi @since 08/06/2022 @version 12.1.33 /*/ //------------------------------------------------------------------- Static Function GetTipoNF() Local aTipoNF := {} aAdd(aTipoNF, 'N=Normal') aAdd(aTipoNF, 'C=Compl.Preco/Quantidade') aAdd(aTipoNF, 'I=Compl.ICMS') aAdd(aTipoNF, 'P=Compl.IPI') aAdd(aTipoNF, 'D=Dev.Compras') aAdd(aTipoNF, 'B=Utiliza Fornecedor') Return aTipoNF
Disponibiliza uma API REST no Dashboard para visualizar um gráfico de Barra ou Linha. Com o fonte abaixo foi obtido o seguinte Gráfico de exemplo:
Para disponibilização de gráficos em barra/linha, é necessário que a API possua 3 endpoints:
1. Um GET para retornar o formulário de cadastro do gráfico:
No exemplo abaixo, essas informações são retornadas pelo endpoint /Exemplo/charts/form.
Diferente dos cards, o gráfico possui um formulário dinâmico e é o serviço que deve retornar o formulário de cadastro dele. Neste exemplo, ele nos retornou o formulário a partir da linha 'Tipo de Gráfico'. Tudo o que vem antes dessa linha, é padrão para todos os gráficos.
O endpoint deve retornar a seguinte estrutura json:
{ "items": [ { "divider": string, "gridSmColumns": number, "type": string, "property": string, "gridColumns": number, "required": boolean, "label": string } ] }
A propriedade items deve retornar a lista com as configurações de todos os campos que devem ser apresentados no formulário. Para a montagem deste formulário, é utilizado o componente Dynamic Form do PO-ui, portanto para entender cada uma das propriedades a serem retornadas neste serviço, clique aqui.
{ "items": [ { "divider": "Tipo de Gráfico", "gridSmColumns": 12, "options": [ { "value": "line", "label": "Linha" }, { "value": "bar", "label": "Barra" } ], "type": "string", "property": "charttype", "gridColumns": 6, "required": true, "label": "Tipo de Gráfico" }, { "divider": "Filtros", "gridSmColumns": 12, "type": "date", "property": "dateIni", "gridColumns": 6, "required": true, "label": "Data Inicial" }, { "gridSmColumns": 12, "type": "date", "property": "dateFim", "gridColumns": 6, "required": true, "label": "Data Final" } ] }
2. Um POST para carregar as informações do gráfico:
No exemplo abaixo, essas informações são retornadas pelo endpoint /Exemplo3/charts/retdados.
O endpoint deve retornar a seguinte estrutura json:
{ "items": [ { "chartData": [ { "data": [ Valores a serem apresentados ], "fill": false, "drillDown": true, "backgroundColor": "rgba(255,162, 54, 1)" - Cor da linha, "hoverBackgroundColor": "rgba(255,162, 54, 1)" - Cor da linha ao passar o mouse, "label": string - Título que representa o conjunto de informação e que irá aparecer na legenda, "lineTension": number - Tenão da curva da linha. Caso for 0, a linha será reta } ], "chartLabels": [ Títulos correspondentes aos valores que serão apresentados ], "charttype": string - Tipo de gráfico, "title": string - Título do gráfico, "chartMask": string, "currencyMask": [ Máscaras utilizadas para apresentar valores ] } ] }
A propriedade items deve retornar as informações do gráfico como valores a serem apresentados, títulos a representarem esses valores, título do gráfico e máscara de valores a ser utilizada.
O gráfico utiliza a biblioteca chart.js. Para mais informações sobre suas propriedades, clique aqui.
{ "items": [ { "chartData": [ { "data": [ 100006444, 100026546, 100015701 ], "fill": false, "drillDown": true, "backgroundColor": "rgba(255,162, 54, 1)", "hoverBackgroundColor": "rgba(255,162, 54, 1)", "label": "Vendedor 01", "lineTension": 0 }, { "data": [ 100009979, 100024524, 100029629 ], "fill": false, "drillDown": true, "backgroundColor": "rgba( 0,178,142, 1)", "hoverBackgroundColor": "rgba( 0,178,142, 1)", "label": "Vendedor 02", "lineTension": 0 }, { "data": [ 100023984, 100019381, 100026231 ], "fill": false, "drillDown": true, "backgroundColor": "rgba(255,212,100, 1)", "hoverBackgroundColor": "rgba(255,212,100, 1)", "label": "Vendedor 03", "lineTension": 0 }, { "data": [ 100028268, 100031184, 100010768 ], "fill": false, "drillDown": true, "backgroundColor": "rgba(128, 0, 0, 1)", "hoverBackgroundColor": "rgba(128, 0, 0, 1)", "label": "Vendedor 04", "lineTension": 0 }, { "data": [ 100017168.75, 100025408.75, 100020582.25 ], "type": "line", "fill": false, "drillDown": false, "backgroundColor": "rgba( 0,120,255, 1)", "hoverBackgroundColor": "rgba( 0,120,255, 1)", "label": "Média", "lineTension": 0 } ], "chartLabels": [ "Janeiro", "Fevereiro", "Março" ], "charttype": "", "title": null, "chartMask": "currency", "currencyMask": [ { "maskFrac": "R$", "maxiFrac": 10, "miniFrac": 2 } ] } ] }
3. Um POST para carregar as informações que serão apresentadas nos detalhes do gráfico:
No exemplo abaixo, essas informações são retornadas pelo endpoint /Exemplo3/charts/itemsDetails.
O endpoint deve retornar a seguinte estrutura json:
{ "header":[ { "showFilter": boolean, "property": string, "label":string } ], "items":[ { "property": <Valor retornado pela query>, } ], "hasNext": boolean }
A propriedade header refere-se ao cabeçalho da tabela. Como a tabela utilizada pelo dashboard é um componente da biblioteca PO-UI (po-table), deve-se informar as propriedades obrigatórias para este componente: property (nome identificador para a coluna) e label (título para a coluna). Para mais informações, clique aqui.
A propriedade items refere-se aos valores que serão apresentados nas colunas da tabela, ou seja, para cada propriedade informada, a query irá retornar um valor. Exemplo: { "totalValor": }. Este deve ter a propriedade "hasNext" para informar se há próxima página (true) ou não (false).
{ "header": [ { "showFilter": true, "type": "link", "property": "codigo", "label": "Código", "action": "Link" }, { "showFilter": true, "property": "nome", "label": "Nome Vendedor" }, { "showFilter": false, "format": "1.2-5", "type": "number", "property": "totalItens", "label": "Total de Itens" }, { "showFilter": false, "format": "BRL", "type": "currency", "property": "totalValor", "label": "Valor Total" } ], "items": [ { "totalValor": 2000, "totalItens": 1, "nome": "10% COMIS 100%EMISSAO", "codigo": "FIN058" }, { "totalValor": 2000, "totalItens": 1, "nome": "10% COMISSAO 100% BAIXA ABATE IMPOSTOS", "codigo": "FIN056" }, { "totalValor": 2000, "totalItens": 1, "nome": "10% COMISSAO 100% BAIXA ABATE IMPOSTOS", "codigo": "FIN060" }, { "totalValor": 2000, "totalItens": 1, "nome": "10% COMISSAO 100% EMISSAO ABATE IMPOSTOS", "codigo": "FIN055" }, { "totalValor": 2000, "totalItens": 1, "nome": "10% COMISSAO 100% EMISSAO ABATE IMPOSTOS", "codigo": "FIN059" }, { "totalValor": 5000, "totalItens": 4, "nome": "100% BAIXA 10%COMISSAO", "codigo": "FVEN10" }, { "totalValor": 1000, "totalItens": 1, "nome": "100%baixa 0%comissao", "codigo": "FIN048" }, { "totalValor": 2000, "totalItens": 2, "nome": "100%emissao 0%comissao", "codigo": "FIN047" }, { "totalValor": 200000, "totalItens": 2, "nome": "5% COMISSAO 100% BAIXA", "codigo": "FIN600" }, { "totalValor": 1000, "totalItens": 1, "nome": "50 50 - 10%", "codigo": "FIN073" } ], "hasNext": true }
Clique aqui para download do fonte de exemplo.
#INCLUDE "TOTVS.CH" #INCLUDE "RESTFUL.CH" //------------------------------------------------------------------------ /*/{Protheus.doc} Exemplo3 Exemplo de API de integração de Graficos de Barra e Linha @author Squad CRM & Faturamento @since 28/07/2020 @version 12.1.27 /*/ //------------------------------------------------------------------------ WSRESTFUL Exemplo3 DESCRIPTION "Exemplo de API - Grafico Barra e Linha" WSDATA JsonFilter AS STRING OPTIONAL WSDATA drillDownFilter AS STRING OPTIONAL WSDATA Fields AS STRING OPTIONAL WSDATA Order AS STRING OPTIONAL WSDATA Page AS INTEGER OPTIONAL WSDATA PageSize AS INTEGER OPTIONAL WSMETHOD GET form ; DESCRIPTION "Formulario de Cadastro do Gráfico" ; WSSYNTAX "/charts/form/" ; PATH "/charts/form"; PRODUCES APPLICATION_JSON WSMETHOD POST retDados ; DESCRIPTION "Deverá retornar as informações apresentadas no gráfico." ; WSSYNTAX "/charts/retDados/{JsonFilter}" ; PATH "/charts/retDados"; PRODUCES APPLICATION_JSON WSMETHOD POST itemsDetails ; DESCRIPTION "Carrega o detalhamento do gráfico" ; WSSYNTAX "/charts/itemsDetails/{JsonFilter}" ; PATH "/charts/itemsDetails"; PRODUCES APPLICATION_JSON ENDWSRESTFUL //------------------------------------------------------------------- /*/{Protheus.doc} GET form Retorna os campos que serão apresentados no formulário. O padrão do campo deve seguir o Dynamic Form do Portinari. @author Squad CRM & Faturamento @since 27/03/2020 @version Protheus 12.1.27 /*/ //------------------------------------------------------------------- WSMETHOD GET form WSSERVICE Exemplo3 Local oResponse := JsonObject():New() Local oCoreDash := CoreDash():New() oCoreDash:SetPOForm("Tipo de Gráfico", "charttype" , 6, "Tipo de Gráfico" , .T., "string" , oCoreDash:SetPOCombo({{"line","Linha"}, {"bar","Barra"}})) oCoreDash:SetPOForm("Filtros" , "dateIni" , 6, "Data Inicial" , .T., 'date' , , .T.) oCoreDash:SetPOForm("" , "dateFim" , 6, "Data Final" , .T., 'date' , , .T.) oCoreDash:SetPOForm("" , "person" , 6, "Pessoa" , .F., 'string' , oCoreDash:SetPOCombo({{"F","Física"} , {"J","Jurídica"}}), .T.) oCoreDash:SetPOForm("" , "blocked" , 6, "Bloqueado?" , .F., 'string' , oCoreDash:SetPOCombo({{"1","Sim"} , {"2","Não"}}) , .F.) oResponse := oCoreDash:GetPOForm() Self:SetResponse( EncodeUtf8(oResponse:ToJson())) Return .T. //------------------------------------------------------------------- /*/{Protheus.doc} POST retDados Retorna os dados do Gráfico @author Squad CRM & Faturamento @since 27/03/2020 @version Protheus 12.1.27 /*/ //------------------------------------------------------------------- WSMETHOD POST retDados WSRECEIVE JsonFilter WSSERVICE Exemplo3 Local oResponse := JsonObject():New() Local oCoreDash := CoreDash():New() Local oJson := JsonObject():New() oJson:FromJson(DecodeUtf8(Self:GetContent())) retDados(@oResponse, oCoreDash, oJson) Self:SetResponse( EncodeUtf8(oResponse:ToJson())) oResponse := Nil FreeObj( oResponse ) oCoreDash:Destroy() FreeObj( oCoreDash ) Return .T. //------------------------------------------------------------------- /*/{Protheus.doc} Function retDados Retorna o valor das Meta e o Valor Vendido de acordo com parâmetros informados @author Squad CRM & Faturamento @since 16/05/2022 @version Protheus 12.1.33 /*/ //------------------------------------------------------------------- Static Function retDados(oResponse, oCoreDash, oJson) Local aData := {} Local aDataFim := {} Local aData1 := {} Local aData2 := {} Local aData3 := {} Local aData4 := {} Local aData5 := {} Local aCab := {} Local aCores := oCoreDash:GetColorChart() Local aSaldo := {} Local nSaldo := 0 Local cPessoa := "" Local cFiltros := "" Local nFilter := 0 Local nCntFilt := 0 If oJson:GetJsonText("level") == "null" .Or. Len(oJson["level"]) == 0 aCab := {'SP', 'RJ', 'MG' } //######### Obter os filtros do cadastro ou de usuário e aplicar na query ######### // Filtro por tipo da pessoa - Com Multi-seleção If oJson:HasProperty("person") .And. ValType(oJson["person"]) == "A" cPessoa := oJson["person"] nCntFilt := Len(oJson["person"]) For nFilter := 1 To nCntFilt If nFilter == 1 cFiltros += " AND (" Else cFiltros += " OR " EndIf cFiltros += "SA1.A1_PESSOA = '" + oJson["person"][nFilter] + "' " If nFilter == nCntFilt cFiltros += ") " EndIf Next EndIf // Filtro por tipo da pessoa - com uma única seleção If oJson:HasProperty("blocked") .And. ValType(oJson["blocked"]) == "C" cFiltros += "AND SA1.A1_MSBLQL = '" + oJson["blocked"] + "'" EndIf //######### Fim da obtenção os filtros do cadastro ou de usuário e aplicar na query ######### aData1 := { RetRisco(cFiltros + " AND SA1.A1_RISCO = 'A' AND SA1.A1_EST = 'SP'"), RetRisco(cFiltros + " AND SA1.A1_RISCO = 'A' AND SA1.A1_EST = 'RJ'"), RetRisco(cFiltros + " AND SA1.A1_RISCO = 'A' AND SA1.A1_EST = 'MG'") } aData2 := { RetRisco(cFiltros + " AND SA1.A1_RISCO = 'B' AND SA1.A1_EST = 'SP'"), RetRisco(cFiltros + " AND SA1.A1_RISCO = 'B' AND SA1.A1_EST = 'RJ'"), RetRisco(cFiltros + " AND SA1.A1_RISCO = 'B' AND SA1.A1_EST = 'MG'") } aData3 := { RetRisco(cFiltros + " AND SA1.A1_RISCO = 'C' AND SA1.A1_EST = 'SP'"), RetRisco(cFiltros + " AND SA1.A1_RISCO = 'C' AND SA1.A1_EST = 'RJ'"), RetRisco(cFiltros + " AND SA1.A1_RISCO = 'C' AND SA1.A1_EST = 'MG'") } aData4 := { RetRisco(cFiltros + " AND SA1.A1_RISCO = 'D' AND SA1.A1_EST = 'SP'"), RetRisco(cFiltros + " AND SA1.A1_RISCO = 'D' AND SA1.A1_EST = 'RJ'"), RetRisco(cFiltros + " AND SA1.A1_RISCO = 'D' AND SA1.A1_EST = 'MG'") } oCoreDash:SetChartInfo( aData1, 'Risco A', , aCores[8][3] ) //Cor utilizada: OrangeLht oCoreDash:SetChartInfo( aData2, 'Risco B', , aCores[1][3] ) //Cor utilizada: GreenDk oCoreDash:SetChartInfo( aData3, 'Risco C', , aCores[6][3] ) //Cor utilizada: YellowDk oCoreDash:SetChartInfo( aData4, 'Risco D', , aCores[15][3] ) //Cor utilizada: BrowDk nSaldo := (aData1[1] + aData2[1] + aData3[1] + aData4[1] ) / 4 aAdd(aSaldo, nSaldo) nSaldo := (aData1[2] + aData2[2] + aData3[2] + aData4[2] ) / 4 aAdd(aSaldo, nSaldo) nSaldo := (aData1[3] + aData2[3] + aData3[3] + aData4[3] ) / 4 aAdd(aSaldo, nSaldo) oCoreDash:SetChartInfo( aSaldo, 'Média', "line", aCores[9][3] ,,.F.) //Cor utilizada: BlueDk aDataFim := {} aAdd(aDataFim, oCoreDash:SetChart(aCab,,.F., ,"Quantidade de Clientes por Risco em cada Estado")) ElseIf Len(oJson["level"]) == 1 aCab := {'Semana 1', 'Semana 2', 'Semana 3', 'Semana 4' } aData1 := { Randomize( 100000000.00, 999000000.00 ), Randomize( 100000000.00, 999000000.00 ), Randomize( 100000000.00, 999000000.00 ), Randomize( 100000000.00, 999000000.00 ), Randomize( 100000000.00, 999000000.00 )} aData2 := { Randomize( 100000000.00, 999000000.00 ), Randomize( 100000000.00, 999000000.00 ), Randomize( 100000000.00, 999000000.00 ), Randomize( 100000000.00, 999000000.00 ), Randomize( 100000000.00, 999000000.00 )} aData3 := { Randomize( 100000000.00, 999000000.00 ), Randomize( 100000000.00, 999000000.00 ), Randomize( 100000000.00, 999000000.00 ), Randomize( 100000000.00, 999000000.00 ), Randomize( 100000000.00, 999000000.00 )} aData4 := { Randomize( 100000000.00, 999000000.00 ), Randomize( 100000000.00, 999000000.00 ), Randomize( 100000000.00, 999000000.00 ), Randomize( 100000000.00, 999000000.00 ), Randomize( 100000000.00, 999000000.00 )} aData5 := { Randomize( 100000000.00, 999000000.00 ), Randomize( 100000000.00, 999000000.00 ), Randomize( 100000000.00, 999000000.00 ), Randomize( 100000000.00, 999000000.00 ), Randomize( 100000000.00, 999000000.00 )} oCoreDash:SetChartInfo( aData1, '00000101 - Cliente 000001',,aCores[8][3] ) //Cor utilizada: OrangeLht oCoreDash:SetChartInfo( aData2, '00000102 - Cliente 000002',,aCores[1][3] ) //Cor utilizada: GreenDk oCoreDash:SetChartInfo( aData3, '00543501 - Cliente 000003',,aCores[6][3] ) //Cor utilizada: YellowDk oCoreDash:SetChartInfo( aData4, '00543502 - Cliente 000004',,aCores[15][3] ) //Cor utilizada: BrowDk oCoreDash:SetChartInfo( aData5, '00543503 - Cliente 000005',,aCores[10][3] ) //Cor utilizada: BlueLht aDataFim := {} aAdd(aDataFim, oCoreDash:SetChart(aCab,,.T., ,"Maiores Vendas - " + oJson["level"][1]["labelDataSet"] + " - " + oJson["level"][1]["label"])) ElseIf Len(oJson["level"]) == 2 aCab := {"Pedido - 234323", "Pedido - 234322", "Pedido - 234456", "Pedido - 234533", "Pedido - 234222" } oData := JsonObject():New() aData := { 26589, 25000,23560,10000,35000} aDataFim := {} aAdd(aDataFim, oCoreDash:SetChart(aCab, aData, .T.,"pie", "Maiores Clientes - " + oJson["level"][2]["labelDataSet"] + " - " + oJson["level"][1]["label"])) EndIf oResponse["items"] := aDataFim Return //------------------------------------------------------------------- /*/{Protheus.doc} POST itemsDetails Método para retornar os dados do Painel @author Squad CRM & Faturamento @since 27/03/2020 @version Protheus 12.1.27 /*/ //------------------------------------------------------------------- WSMETHOD POST itemsDetails WSRECEIVE JsonFilter, drillDownFilter WSRESTFUL Exemplo3 Local aHeader := {} Local aItems := {} Local aRet := {} Local cBody := DecodeUtf8(Self:GetContent()) Local cError := "Erro na Requisição" Local lRet := .T. Local oCoreDash := CoreDash():New() Local oBody := JsonObject():New() Local oJsonFilter := JsonObject():New() Local oJsonDD := JsonObject():New() If !Empty(cBody) oBody:FromJson(cBody) If ValType(oBody["chartFilter"]) == "J" oJsonFilter := oBody["chartFilter"] EndIf If ValType(oBody["detailFilter"]) == "A" oJsonDD := oBody["detailFilter"] EndIf EndIf Self:SetContentType("application/json") //Verifico o Nivel do grafico If oJsonFilter:GetJsonText("level") == "null" .Or. Len(oJsonFilter["level"]) == 0 //Verifico o nivel do Drilldpwn If Len(oJsonDD) == 0 aHeader := {; {"codigo" , "Código" ,"link" },; {"nome" , "Nome Vendedor" },; {"totalItens" , "Total de Itens","number",'1.2-5',.F. },; {"totalValor" , "Valor Total" , "currency","BRL",.F.}; } aItems := {; {"codigo" , "SA3.A3_COD" },; {"nome" , "SA3.A3_NOME" },; {"totalItens" , "QTDITEM" },; {"totalValor" , "TOTAL","N" }; } aRet := MntQuery1() ElseIf Len(oJsonDD) == 1 //Caso eu queira pegar o nome do nível selecionado : oJsonFilter["level"][1]["labelDataSet"] // Se fosse gráfico do tipo pizza: oJsonFilter["level"][1]["label"] aHeader := {; {"codigoPed" , "Código do Pedido" },; {"codigoCli" , "Código do Cliente" },; {"nome" , "Nome" },; {"totalValor" , "TOTAL","currency","BRL",.F.}; } aItems := {; {"codigoPed" , "SC5.C5_NUM" },; {"codigoCli" , "SC5.C5_CLIENTE" },; {"nome" , "SA1.A1_NOME" },; {"totalValor" , "TOTAL","N" }; } aRet := MntQuery2("SC5.C5_VEND1 = '" + oJsonDD[1]["codigo"] + "'") EndIf ElseIf Len(oJsonFilter["level"]) == 1 aHeader := {; {"codigoPed" , "Código do Pedido" },; {"codigoCli" , "Código do Cliente" },; {"nome" , "Nome" },; {"totalValor" , "TOTAL","currency","BRL",.F.}; } aItems := {; {"codigoPed" , "SC5.C5_NUM" },; {"codigoCli" , "SC5.C5_CLIENTE" },; {"nome" , "SA1.A1_NOME" },; {"totalValor" , "TOTAL","N" }; } aRet := MntQuery2("SA1.A1_RISCO = '" + Right(oJsonFilter["level"][1]["labelDataSet"],1) + "' AND SA1.A1_EST = '" + oJsonFilter["level"][1]["label"] + "' ") ElseIf Len(oJsonFilter["level"]) == 2 aHeader := {; {"codigo" , "Código" },; {"nome" , "Nome Vendedor" },; {"totalItens" , "Total de Itens","number",'1.2-5',.F.},; {"totalValor" , "Valor Total", "currency","BRL",.F.}; } aItems := {; {"codigo" , "SA3.A3_COD" },; {"nome" , "SA3.A3_NOME" },; {"totalItens" , "QTDITEM" },; {"totalValor" , "TOTAL","N" }; } aRet := MntQuery1() EndIf oCoreDash:SetQuery(aRet[1]) oCoreDash:SetWhere(aRet[2]) oCoreDash:SetGroupBy(aRet[3]) oCoreDash:SetFields(aItems) oCoreDash:SetApiQstring(Self:aQueryString) oCoreDash:BuildJson() If lRet oCoreDash:SetPOHeader(aHeader) Self:SetResponse( oCoreDash:ToObjectJson() ) Else cError := oCoreDash:GetJsonError() SetRestFault( 500, EncodeUtf8(cError) ) EndIf oCoreDash:Destroy() FreeObj(oBody) FreeObj(oJsonFilter) FreeObj(oJsonDD) FreeObj(oCoreDash) aSize(aRet, 0) aSize(aItems, 0) aSize(aHeader, 0) Return( lRet ) //------------------------------------------------------------------- /*/{Protheus.doc} MntQuery1 Monta a Query o Total dos Pedidos de Venda @author Squad CRM & Faturamento @since 27/03/2020 @version Protheus 12.1.27 /*/ //------------------------------------------------------------------- Static Function MntQuery1() Local cQuery := "" Local cWhere := "" Local cGroup := "" cQuery := " SELECT SA3.A3_COD, SA3.A3_NOME, COUNT(C6_ITEM) QTDITEM, SUM(C6_VALOR) TOTAL " cQuery += " FROM " + RetSqlName("SC5") + " SC5 " cQuery += " INNER JOIN " + RetSqlName("SC6") + " SC6 ON SC6.C6_NUM = SC5.C5_NUM " cQuery += " INNER JOIN " + RetSqlName("SA3") + " SA3 ON SA3.A3_COD = SC5.C5_VEND1 " cWhere := " SC5.D_E_L_E_T_ = ' ' " cWhere += " AND SC6.D_E_L_E_T_ = ' ' " cWhere += " AND SA3.D_E_L_E_T_ = ' ' " cWhere += " AND SC5.C5_FILIAL = '" + xFilial("SC5") + "' " cWhere += " AND SC6.C6_FILIAL = '" + xFilial("SC6") + "' " cWhere += " AND SA3.A3_FILIAL = '" + xFilial("SA3") + "' " cWhere += " AND SC5.C5_EMISSAO >= '20220401' " cGroup := " SA3.A3_COD, SA3.A3_NOME " Return {cQuery, cWhere, cGroup} //------------------------------------------------------------------- /*/{Protheus.doc} MntQuery2 Monta Query do Pedido de vendas realizando um filtro específo. @author Squad CRM & Faturamento @since 27/03/2020 @version Protheus 12.1.27 /*/ //------------------------------------------------------------------- Static Function MntQuery2(cFilter) Local cQuery := "" Local cGroup := "" Local cWhere := "" Default cFilter := "" cQuery := " SELECT SC5.C5_NUM, SC5.C5_CLIENTE, SA1.A1_NOME, SUM(C6_VALOR) TOTAL " cQuery += " FROM " + RetSqlName("SC5") + " SC5 " cQuery += " INNER JOIN " + RetSqlName("SC6") + " SC6 ON SC6.C6_NUM = SC5.C5_NUM " cQuery += " INNER JOIN " + RetSqlName("SA1") + " SA1 ON SA1.A1_COD = SC5.C5_CLIENTE if !Empty(cFilter) cWhere += cFilter + " AND " EndIf cWhere += " SC5.D_E_L_E_T_ = ' ' " cWhere += " AND SC6.D_E_L_E_T_ = ' ' " cWhere += " AND SA1.D_E_L_E_T_ = ' ' " cWhere += " AND SC5.C5_FILIAL = '" + xFilial("SC5") + "' " cWhere += " AND SC6.C6_FILIAL = '" + xFilial("SC6") + "' " cWhere += " AND SA1.A1_FILIAL = '" + xFilial("SA1") + "' " cWhere += " AND SC5.C5_EMISSAO >= '20220401' " // Limite adicionado para evitar lentidao no retorno da query em bases com uma quantidade muito grande de pedidos de vendas cGroup := " C5_NUM, C5_CLIENTE, SA1.A1_NOME " Return {cQuery, cWhere, cGroup} //------------------------------------------------------------------- /*/{Protheus.doc} RetRisco Retorna o total de clientes de acordo com o risco informado no filtro @param cFiltro, Caractere, Filtro a ser adicionado na query @author Squad CRM & Faturamento @since 13/04/2022 @version 12.1.33 /*/ //------------------------------------------------------------------- Static Function RetRisco(cFiltro) Local aQuery := MntQuery3("COUNT(SA1.A1_COD) TOTAL_REGISTROS", cFiltro) Local cQuery := "" Local cTemp := GetNextAlias() Local xRet Default cWhere := "" Default cInfo := "" cQuery := aQuery[1] + " WHERE " + aQuery[2] DBUseArea( .T., "TOPCONN", TCGenQry( ,, cQuery ), cTemp, .T., .T. ) xRet := (cTemp)->TOTAL_REGISTROS (cTemp)->( DBCloseArea() ) Return xRet //------------------------------------------------------------------- /*/{Protheus.doc} MntQuery3 Monta a query responsável por trazer os clientes de acordo com o risco informado no filtro @param cCampos, Caractere, Campos que serão retornados no SELECT @param cFiltro, Caractere, Filtro a ser adicionado na query @param cGroupBy, Caractere, Expressão group by a ser adicionada na query @author Squad CRM & Faturamento @since 13/04/2022 @version 12.1.33 /*/ //------------------------------------------------------------------- Static Function MntQuery3(cCampos, cFiltro, cGroupBy) Local cQuery Local cWhere Local cGroup Default cTable := "SA1" Default cCampos := "SA1.A1_COD, SA1.A1_LOJA, SA1.A1_NOME, SA1.A1_NREDUZ, SA1.A1_RISCO" cQuery := " SELECT " + cCampos + " FROM " + RetSqlName("SA1") + " SA1 " cWhere := " SA1.A1_FILIAL = '" + xFilial("SA1") + "'" + cFiltro cWhere += " AND SA1.D_E_L_E_T_ = ' ' " If !Empty(cGroupBy) cGroup := cGroupBy EndIf Return {cQuery, cWhere, cGroup}
Disponibiliza uma API REST no Dashboard para visualizar um gráfico de Gauge. Com o fonte abaixo foi obtido o seguinte Gráfico de exemplo:
Para disponibilização de gráficos em gauge, é necessário que a API possua 3 endpoints:
1. Um GET para retornar o formulário de cadastro do gráfico:
No exemplo abaixo, essas informações são retornadas pelo endpoint /Exemplo4/charts/form.
Diferente dos cards, o gráfico possui um formulário dinâmico e é o serviço que deve retornar o formulário de cadastro dele. Neste exemplo, ele nos retornou o formulário a partir da linha 'Tipo de Gráfico'. Tudo o que vem antes dessa linha, é padrão para todos os gráficos.
O endpoint deve retornar a seguinte estrutura json:
{ "items": [ { "divider": string, "gridSmColumns": number, "type": string, "property": string, "gridColumns": number, "required": boolean, "label": string } ] }
A propriedade items deve retornar a lista com as configurações de todos os campos que devem ser apresentados no formulário. Para a montagem deste formulário, é utilizado o componente Dynamic Form do PO-ui, portanto para entender cada uma das propriedades a serem retornadas neste serviço, clique aqui.
{ "items": [ { "divider": "Tipo de Gráfico", "property": "charttype", "gridColumns": 6, "label": "Tipo de Gráfico", "required": true, "type": "string", "gridSmColumns": 12, "options": [ { "value": "gauge", "label": "Gauge" } ] }, { "divider": "Período", "property": "datainicio", "gridColumns": 6, "label": "Data de", "required": false, "type": "date", "gridSmColumns": 12 }, { "property": "datafim", "gridColumns": 6, "label": "Data até", "required": false, "type": "date", "gridSmColumns": 12 } ] }
2. Um POST para carregar as informações do gráfico:
No exemplo abaixo, essas informações são retornadas pelo endpoint /Exemplo4/charts/retdados.
O endpoint deve retornar a seguinte estrutura json:
{ "items": [ { "chartData": [ { <valor retornado pela query>: number } ], "chartLabels": [ Título correspondente ao valor que será apresentado ], "charttype": string - Tipo de gráfico, "title": string - Título do gráfico, "chartMask": string } ] }
A propriedade items deve retornar as informações do gráfico como o valor a ser apresentado, título a representar esse valor, título do gráfico e máscara de valores a ser utilizada.
O gráfico utiliza o componente gauge da biblioteca PO-ui. Para mais informações sobre suas propriedades, clique aqui.
{ "items": [ { "chartLabels": [ "Quantidade de pedidos" ], "chartData": [ 45 ], "currencyMask": [ { "maskFrac": "R$", "maxiFrac": 10, "miniFrac": 2 } ], "charttype": "", "title": null } ] }
3. Um POST para carregar as informações que serão apresentadas nos detalhes do gráfico:
No exemplo abaixo, essas informações são retornadas pelo endpoint /Exemplo4/charts/itemsDetails.
O endpoint deve retornar a seguinte estrutura json:
{ "header":[ { "showFilter": boolean, "property": string, "label":string } ], "items":[ { "property": <Valor retornado pela query>, } ], "hasNext": boolean }
A propriedade header refere-se ao cabeçalho da tabela. Como a tabela utilizada pelo dashboard é um componente da biblioteca PO-UI (po-table), deve-se informar as propriedades obrigatórias para este componente: property (nome identificador para a coluna) e label (título para a coluna). Para mais informações, clique aqui.
A propriedade items refere-se aos valores que serão apresentados nas colunas da tabela, ou seja, para cada propriedade informada, a query irá retornar um valor. Exemplo: { "totalValor": }. Este deve ter a propriedade "hasNext" para informar se há próxima página (true) ou não (false).
{ "hasNext": true, "items": [ { "C5_NUM": "CTFN40", "C5_CLIENTE": "FN4001", "C5_LOJACLI": "01", "C5_VEND1": "" }, { "C5_NUM": "pcpATW", "C5_CLIENTE": "000001", "C5_LOJACLI": "01", "C5_VEND1": "" }, { "C5_NUM": "pcpAU6", "C5_CLIENTE": "FAB004", "C5_LOJACLI": "01", "C5_VEND1": "" }, { "C5_NUM": "PCPATR", "C5_CLIENTE": "COMSIR", "C5_LOJACLI": "01", "C5_VEND1": "VENDIR" }, { "C5_NUM": "PCPATQ", "C5_CLIENTE": "COMSIR", "C5_LOJACLI": "01", "C5_VEND1": "VENDIR" }, { "C5_NUM": "PCPATO", "C5_CLIENTE": "COMISB", "C5_LOJACLI": "01", "C5_VEND1": "ICMPIA" }, { "C5_NUM": "PCPATH", "C5_CLIENTE": "COMIBX", "C5_LOJACLI": "01", "C5_VEND1": "CBX065" }, { "C5_NUM": "MN0039", "C5_CLIENTE": "MN0001", "C5_LOJACLI": "01", "C5_VEND1": "" }, { "C5_NUM": "FIN093", "C5_CLIENTE": "FIN462", "C5_LOJACLI": "01", "C5_VEND1": "" }, { "C5_NUM": "FIN092", "C5_CLIENTE": "FIN462", "C5_LOJACLI": "01", "C5_VEND1": "" } ], "header": [ { "property": "C5_NUM", "label": "Cód. Pedido ", "showFilter": true, "visible": true }, { "property": "C5_CLIENTE", "label": "Cód. Cliente", "showFilter": true }, { "property": "C5_LOJACLI", "label": "Loja Cliente", "showFilter": true, "visible": true }, { "property": "C5_VEND1 ", "label": "Vendedor 1 ", "showFilter": true } ] }
Clique aqui para download do fonte de exemplo.
#INCLUDE "TOTVS.CH" #INCLUDE "RESTFUL.CH" //------------------------------------------------------------------------ /*/{Protheus.doc} Exemplo4 API - Exemplo 4 - Gráfico de Gauge @author Squad CRM/Faturamento @since 11/05/2022 @version 12.1.33 @return Json /*/ //------------------------------------------------------------------------ WSRESTFUL Exemplo4 DESCRIPTION "Exemplo de Gráfico de Gauge" WSDATA JsonFilter AS STRING OPTIONAL WSDATA drillDownFilter AS STRING OPTIONAL WSDATA Page AS INTEGER OPTIONAL WSDATA PageSize AS INTEGER OPTIONAL WSMETHOD GET form ; DESCRIPTION "Carrega os campos que serão apresentados no formulário" ; WSSYNTAX "/charts/form/" ; PATH "/charts/form"; PRODUCES APPLICATION_JSON WSMETHOD POST retdados ; DESCRIPTION "Carrega os itens" ; WSSYNTAX "/charts/retdados/{JsonFilter}" ; PATH "/charts/retdados"; PRODUCES APPLICATION_JSON WSMETHOD POST itemsDetails ; DESCRIPTION "Carrega os Itens Utilizados para Montagem dos detalhes" ; WSSYNTAX "/charts/itemsDetails/{JsonFilter}" ; PATH "/charts/itemsDetails"; PRODUCES APPLICATION_JSON ENDWSRESTFUL //------------------------------------------------------------------- /*/{Protheus.doc} GET form Retorna os campos que serão apresentados no formulário. O padrão do campo deve seguir o Dynamic Form do Portinari. @author Squad CRM & Faturamento @since 16/05/2022 @version Protheus 12.1.33 /*/ //------------------------------------------------------------------- WSMETHOD GET form WSSERVICE Exemplo4 Local oResponse := JsonObject():New() Local oCoreDash := CoreDash():New() oCoreDash:SetPOForm("Tipo de Gráfico" , "charttype" , 6 , "Tipo de Gráfico" ; , .T., "string" , oCoreDash:SetPOCombo({{"gauge","Gauge"}})) oCoreDash:SetPOForm("Período" , "datainicio" , 6 , "Data de" ; , .F., "date" ) oCoreDash:SetPOForm("" , "datafim" , 6 , "Data até" ; , .F., "date" ) oResponse := oCoreDash:GetPOForm() Self:SetResponse( EncodeUtf8(oResponse:ToJson())) Return .T. //------------------------------------------------------------------- /*/{Protheus.doc} POST retDados Retorna os dados do Gráfico @author Squad CRM & Faturamento @since 16/05/2022 @version Protheus 12.1.33 /*/ //------------------------------------------------------------------- WSMETHOD POST retdados WSRECEIVE JsonFilter WSSERVICE Exemplo4 Local oResponse := JsonObject():New() Local oCoreDash := CoreDash():New() Local oJson := JsonObject():New() Local oJsonParam := JsonObject():New() Local dDataIni := FirstYDate(dDatabase) Local dDataFim := LastYDate(dDatabase) oJson:FromJson(DecodeUtf8(Self:GetContent())) If ValType(oJson["datainicio"]) == "C" .And. ValType(oJson["datafim"]) == "C" dDataIni := STOD(StrTran(oJson["datainicio"],'-','')) dDataFim := STOD(StrTran(oJson["datafim"],'-','')) Endif retDados(@oResponse, oCoreDash, oJson, dDataIni, dDataFim) Self:SetResponse( EncodeUtf8(oResponse:ToJson())) oResponse := Nil FreeObj( oResponse ) oCoreDash:Destroy() FreeObj( oCoreDash ) oJsonParam := Nil FreeObj(oJsonParam) Return .T. //------------------------------------------------------------------- /*/{Protheus.doc} POST itemsDetails Método para retornar os dados detalhados por items do gráfico @author Squad CRM & Faturamento @since 16/05/2022 @version Protheus 12.1.33 /*/ //------------------------------------------------------------------- WSMETHOD POST itemsDetails WSRECEIVE JsonFilter, drillDownFilter WSRESTFUL Exemplo4 Local aHeader := {} Local aItems := {} Local aRet := {} Local cBody := DecodeUtf8(Self:GetContent()) Local cError := "Erro na Requisição" Local cSelect := "" Local cFilter := "" Local lRet := .T. Local oCoreDash := CoreDash():New() Local oBody := JsonObject():New() Local oJsonFilter := JsonObject():New() Local oJsonDD := JsonObject():New() Local dDataIni := FirstYDate(dDatabase) Local dDataFim := LastYDate(dDatabase) If !Empty(cBody) oBody:FromJson(cBody) If ValType(oBody["chartFilter"]) == "J" oJsonFilter := oBody["chartFilter"] If ValType(oJsonFilter["datainicio"]) == "C" .And. ValType(oJsonFilter["datafim"]) == "C" dDataIni := STOD(StrTran(oJsonFilter["datainicio"],'-','')) dDataFim := STOD(StrTran(oJsonFilter["datafim"],'-','')) Endif EndIf If ValType(oBody["detailFilter"]) == "A" oJsonDD := oBody["detailFilter"] EndIf EndIf Self:SetContentType("application/json") If oJsonFilter:GetJsonText("level") == "null" .Or. Len(oJsonFilter["level"]) == 0 If Len(oJsonDD) == 0 aHeader := {; {"C5_NUM" , "Cód. Pedido " , , , .T. , .T. },; {"C5_CLIENTE" , "Cód. Cliente" },; {"C5_LOJACLI" , "Loja Cliente" , , , .T. , .T. },; {"C5_VEND1 " , "Vendedor 1 " } ; } aItems := {; {"C5_NUM" , "C5_NUM" },; {"C5_CLIENTE" , "C5_CLIENTE" },; {"C5_LOJACLI" , "C5_LOJACLI" },; {"C5_VEND1" , "C5_VEND1" } ; } cSelect := " SC5.C5_NUM,SC5.C5_CLIENTE, SC5.C5_LOJACLI, SC5.C5_VEND1 " cFilter := "C5_EMISSAO BETWEEN '" + DTos(dDataIni) + "' AND '"+ DTos(dDataFim) + "'" aRet := QuerySC5(cSelect, cFilter) Endif Endif oCoreDash:SetQuery(aRet[1]) oCoreDash:SetWhere(aRet[2]) oCoreDash:SetFields(aItems) oCoreDash:SetApiQstring(Self:aQueryString) oCoreDash:BuildJson() If lRet oCoreDash:SetPOHeader(aHeader) Self:SetResponse( oCoreDash:ToObjectJson() ) Else cError := oCoreDash:GetJsonError() SetRestFault( 500, EncodeUtf8(cError) ) EndIf oCoreDash:Destroy() FreeObj(oJsonDD) FreeObj(oJsonFilter) FreeObj(oBody) aSize(aRet, 0) aSize(aItems, 0) aSize(aHeader, 0) Return lRet //------------------------------------------------------------------- /*/{Protheus.doc} Function retDados Retorna o valor da quantidade de pedidos de acordo com parâmetros informados @author Squad CRM & Faturamento @since 16/05/2022 @version Protheus 12.1.33 /*/ //------------------------------------------------------------------- Static Function retDados(oResponse, oCoreDash, oJson, dDataIni, dDataFim) Local aData := {} Local aDataFim := {} Local aCab := {} aCab := {"Quantidade de pedidos"} oData := JsonObject():New() aData := { 45 /*Preencher aqui com o valor retornado pela sua query. Para o exemplo está fixo 45*/ } aDataFim := {} aAdd(aDataFim, oCoreDash:SetChart(aCab, aData)) oResponse["items"] := aDataFim Return Nil //------------------------------------------------------------------- /*/{Protheus.doc} QuerySC5 Monta a query responsável por trazer os itens detalhados utilizados no gráfico @param cSelect, Caractere, Campos que serão retornados no SELECT @param cFilter, Caractere, Filtro a ser adicionado na query @author Squad CRM & Faturamento @since 16/05/2022 @version 12.1.33 /*/ //------------------------------------------------------------------- Static Function QuerySC5(cSelect as Char, cFilter as Char) as Array Local cQuery as Char Local cWhere as Char Default cSelect := " SC5.C5_NUM,SC5.C5_CLIENTE, SC5.C5_LOJACLI,SC5.C5_VEND1 " Default cFilter := "" cQuery := " SELECT " + cSelect + " FROM " + RetSqlName("SC5") + " SC5 " cWhere := " SC5.C5_FILIAL = '" + xFilial("SC5") + "' " If !Empty(cFilter) cWhere += " AND " + cFilter Endif cWhere += " AND SC5.D_E_L_E_T_ = ' ' " Return {cQuery, cWhere}
ATENÇÃO: Regra de paginação obrigatória
Para os serviços cujo retorno solicita a propriedade "hasNext", quer dizer que eles possuem paginação. A paginação com a utilização da classe CoreDash é obrigatória e funciona através dos parâmetros page (indica a página ser retornada) e pageSize (indica quantos registros da página devem ser retornados). Seus valores default são page = 1 e pageSize = 10.
Exemplo de utilização: /Exemplo1/cards/itemsDetails?page=2&pageSize=10
03. MÉTODOS
Sintaxe:
CoreDash():New()
Descrição:
Método construtor da classe.
Local oCoreDash := CoreDash():New()
Sintaxe:
CoreDash():SetFields(aCampos)
Descrição:
Método que define os campos que serão retornados no JSON do serviço.
Parâmetros:
Nome | Tipo | Descrição | Default | Obrigatório | Referência |
---|---|---|---|---|---|
aCampos | Array | Array que contém o De / Para dos campos que serão apresentados no serviço | X |
Local oCoreDash := CoreDash():New() Local aCampos := {} Aadd(aCampos, {"code", "A1_CODIGO"}) Aadd(aCampos, {"name", "A1_NOME"}) oCoreDash:SetFields(aCampos)
Sintaxe:
CoreDash():SetQuery(cQuery)
Descrição:
Método que define a query que será utilizada no serviço.
Parâmetros:
Nome | Tipo | Descrição | Default | Obrigatório | Referência |
---|---|---|---|---|---|
cQuery | Caractere | Recebe a query que será executada. | X |
Local oCoreDash := CoreDash():New() Local cQuery := "" cQuery := " SELECT A1_COD, A1_NOME FROM " + RetSqlName("SA1") + " SA1 " oCoreDash:SetQuery(cQuery)
Sintaxe:
CoreDash():SetWhere(cWhere)
Descrição:
Método que define a clausula where que será no método SetQuery().
Parâmetros:
Nome | Tipo | Descrição | Default | Obrigatório | Referência |
---|---|---|---|---|---|
cWhere | Caractere | Where que será utilizado na query enviada para o método SetQuery() |
Local oCoreDash := CoreDash():New() Local cQuery := " SELECT A1_COD, A1_NOME FROM "+ RetSqlName("SA1") + " SA1 " Local cWhere := "" oCoreDash:SetQuery(cQuery) cWhere := " SA1.D_E_L_E_T = ' ' " oCoreDash:SetWhere(cWhere)
Sintaxe:
CoreDash():SetIndexKey(cIndexFather)
Descrição:
Método que atribui a ordenação do Alias principal.
Parâmetros:
Nome | Tipo | Descrição | Default | Obrigatório | Referência |
---|---|---|---|---|---|
cIndexFather | Caractere | Ordem utilizada no alias |
Local oCoreDash := CoreDash():New() //Ordenação Crescente (ASC) oCoreDash:SetIndexKey("A1_NOME") //Ordenação Decrescente (DESC) oCoreDash:SetIndexKey("-A1_NOME")
Sintaxe:
CoreDash():SetGroupBy(cGroup)
Descrição:
Método responsável por definir um agrupador na query utilizada no serviço.
Parâmetros:
Nome | Tipo | Descrição | Default | Obrigatório | Referência |
---|---|---|---|---|---|
cGroup | Caractere | Campos que devem compor o agrupador | X |
Local oCoreDash := CoreDash():New() Local cQuery := " SELECT tbl.CAMPO1, tbl.CAMPO2, COUNT(1) COUNT FROM TABLE tbl " Local cWhere := " WHERE FILIAL = 'valor' AND D_E_L_E_T_ = ' ' " oCoreDash:SetQuery(cQuery) oCoreDash:SetWhere(cWhere) oCoreDash:SetGroupBy(" tbl.CAMPO1, tbl.CAMPO2 ") oCoreDash:SetIndexKey("tbl.CAMPO1")
Sintaxe:
CoreDash():SetPage(nPage)
Descrição:
Método que atribui o número da página em que o usuário vai navegar.
Parâmetros:
Nome | Tipo | Descrição | Default | Obrigatório | Referência |
---|---|---|---|---|---|
nPage | Numérico | Número da página que será apresentada para o usuário | 1 |
Local oCoreDash := CoreDash():New() Local nPage := 8 oCoreDash:SetPage(nPage)
Sintaxe:
CoreDash():SetPageSize(nPageSize)
Descrição:
Método que atribui a quantidade máxima de registros que serão exibidos por página.
Parâmetros:
Nome | Tipo | Descrição | Default | Obrigatório | Referência |
---|---|---|---|---|---|
nPageSize | Numérico | Quantidade máxima de registros apresentados por página para o usuário. | 10 |
Local oCoreDash := CoreDash():New() Local nPageSize := 20 oCoreDash:SetPageSize(nPageSize)
Sintaxe:
CoreDash():DefFields(lConvProt, cField)
Descrição:
Método que efetua a conversão entre campos do Objeto e Protheus
Parâmetros:
Nome | Tipo | Descrição | Default | Obrigatório | Referência |
---|---|---|---|---|---|
lConvProt | Lógico | Define se deve converter os campos para padrão Protheus | .T. | ||
cField | Caractere | Campo que será convertido |
Local oCoreDash := CoreDash():New() oCoreDash:DefFields(.T.,"CAMPO")
Sintaxe:
CoreDash():GetDataType(lConvProt, cField)
Descrição:
Retorna o tipo do dado de um determinado campo.
Parâmetros:
Nome | Tipo | Descrição | Default | Obrigatório | Referência |
---|---|---|---|---|---|
lConvProt | Lógico | Define se deve converter os campos para padrão Protheus | .T. | ||
cField | Caracteres | Campo que será convertido |
Local oCoreDash := CoreDash():New() Local dData If oCoreDash:GetDataType(.T.,"CAMPO") == "D" dData := Date() Endif
Sintaxe:
CoreDash():SetFieldsFilt(cFields)
Descrição:
Método que define quais campos serão retornados pelo serviço.
Parâmetros:
Nome | Tipo | Descrição | Default | Obrigatório | Referência |
---|---|---|---|---|---|
cFields | Caractere | Campos que serão retornados no JSON. | X |
Local oCoreDash := CoreDash():New() Local cFields := "order, totValue, product" oCoreDash:SetFieldsFilt(cFields)
Sintaxe:
CoreDash():ToObjectJson()
Descrição:
Método que retorna o JSON serializado.
Local oCoreDash := CoreDash():New() Local lRet := .T. Local cError := "Erro na requisição" If lRet Self:SetResponse( oCoreDash:ToObjectJson()) Else cError := oCoreDash:GetJsonError() SetRestFault( 500, EncodeUtf8(cError) ) EndIf
Sintaxe:
CoreDash():ToSingleObject()
Descrição:
Método que retorna um JSON serializado para apenas um objeto.
Utilizado em requisições do tipo GET que retornam informações de apenas um registro.
Local oCoreDash := CoreDash():New() Local cError := "Erro na requisição" Local lRet := .T. If lRet Self:SetResponse(oCoreDash:ToSingleObject()) Else cError := oCoreDash:GetJsonError() SetRestFault( 500, EncodeUtf8(cError) ) EndIf
Sintaxe:
CoreDash():GetJsonObject()
Descrição:
Método que retorna o objeto JSON da classe
Local oCoreDash := CoreDash():New() Local oJson oJson:= oCoreDash:GetJsonObject() If oJson["items"] != Nil ... Endif
Sintaxe:
CoreDash():SetApiQstring(aQueryString)
Descrição:
Método que define os campos (Retornados pelo JSON), page (página que será apresentada) e pagesize (Quantidade máxima de registros por página) e filtros.
Parâmetros:
Nome | Tipo | Descrição | Default | Obrigatório | Referência |
---|---|---|---|---|---|
aQueryString | Array | Recebe o filtro a ser utilizado quando retornado o JSON |
Local oCoreDash := CoreDash():New() Local aQueryString := {} aAdd(aQueryString, {"fields" , "order, totValue" }) aAdd(aQueryString, {"page" , 10 }) aAdd(aQueryString, {"pagesize" , 5 }) oCoreDash:SetApiQString(aQueryString)
Sintaxe:
CoreDash():SetApiFilter(aFilter)
Descrição:
Método que atribui um filtro de pesquisa.
Parâmetros:
Nome | Tipo | Descrição | Default | Obrigatório | Referência |
---|---|---|---|---|---|
aFilter | Array | Array com expressões de filtro que serão utilizadas | X |
Local oCoreDash := CoreDash():New() Local aFilter := {} aAdd(aFilter, {"A1_COD = '000001'"}) oCoreDash:SetApiFilter(aFilter)
Sintaxe:
CoreDash():GetApiFilter()
Descrição:
Método que retorna o filtro de pesquisa.
Local oCoreDash := CoreDash():New() oCoreDash:GetApiFilter()
Sintaxe:
CoreDash():BuildJson()
Descrição:
Método que responsável por construir o objeto JSON.
Local oCoreDash := CoreDash():New() Self:SetContentType("application/json") oCoreDash:SetQuery(cQuery) oCoreDash:SetWhere(cWhere) oCoreDash:SetFields(aCampos) oCoreDash:SetApiQstring(aQueryString) oCoreDash:BuildJson()
Sintaxe:
CoreDash():SetJson(lHasNext, aItems)
Descrição:
Método que responsável por atribuir um objeto JSON, de acordo com o contrato estabelecido pela TOTVS, contento o [items] e o [hasNext].
Parâmetros:
Nome | Tipo | Descrição | Default | Obrigatório | Referência |
---|---|---|---|---|---|
lHasNext | Lógico | Indica se o objeto possui próxima página. | .T. | ||
aItems | Array | Array com os valores do objeto. |
Local aItems := {} Local lHasNext := .T. Local oCoreDash := CoreDash():New() Local oItem := JsonObject():New() If (cTemp)->(Eof()) lHasnext := .F. EndIf aAdd(aItems, oItem) oCoreDash:SetJson(lHasNext, aItems)
Sintaxe:
CoreDash():SetTable(cAlias)
Descrição:
Método que recebe o alias que será responsável pela geração do JSON.
Parâmetros:
Nome | Tipo | Descrição | Default | Obrigatório | Referência |
---|---|---|---|---|---|
cAlias | Caractere | Alias recebido para a geração do JSON. | X |
Local oCoreDash := CoreDash():New() Local cAlias := GetNextAlias() oCoreDash:SetTable(cAlias)
Sintaxe:
CoreDash():SetUpsertData(cAlias, cIndex, cBody)
Descrição:
Método que efetua a inclusão ou alteração de registros.
Parâmetros:
Nome | Tipo | Descrição | Default | Obrigatório | Referência |
---|---|---|---|---|---|
cAlias | Caractere | Alias recebido para a geração do JSON. | X | ||
cIndex | Caractere | Índice utilizado na busca. | |||
cBody | Caractere | JSON recebido no Body da mensagem. | X |
Local oCoreDash := CoreDash():New() If oCoreDash:SetUpsertData(cAlias, Nil, cBody) Self:SetResponse( EncodeUtf8("Registro incluído com sucesso")) Else SetRestFault( 500, EncodeUtf8("Falha ao converter o arquivo.") ) Endif
Sintaxe:
CoreDash():Destroy()
Descrição:
Método responsável por destruir o objeto.
Local oCoreDash := CoreDash():New() If oCoreDash:SetUpsertData(cAlias, Nil, cBody) Self:SetResponse( EncodeUtf8("Registro incluído com sucesso")) Else SetRestFault( 500, EncodeUtf8("Falha ao converter o arquivo.") ) Endif oCoreDash:Destroy()
ATENÇÃO: Método estará disponível na expedição contínua do Faturamento.
Para se utilizar deste método deve atualizar os fontes com o pacote da expedição contínua do FATURAMENTO do dia 06/05/2022.
Sintaxe:
CoreDash():GetJsonError()
Descrição:
Retorna string com a mensagem de erro do JSON.
Local oCoreDash := CoreDash():New() If oCoreDash:SetUpsertData(cAlias, Nil, cBody) Self:SetResponse( EncodeUtf8("Registro incluído com sucesso")) Else SetRestFault( 500, oCoreDash:GetJsonError() ) Endif
Sintaxe:
CoreDash():SetPOHeader(aFields)
Descrição:
Método responsável por retornar um Array conforme esperado na propriedade p-columns do componente Table da biblioteca de componentes PO-UI
Parâmetros:
Nome | Tipo | Descrição | Default | Obrigatório | Referência |
---|---|---|---|---|---|
aFields | Array | Array de até seis dimensões com os dados: aFields[n, 1] = Property - Nome identificador (String) aFields[n, 2] = Label - Título da coluna apresentada na tabela (String) aFields[n, 3] = Tipo do dado - Tipos aceitos hoje: number, string, currency e link (String) aFields[n, 4] = Formato/máscara do dado (String) aFields[n, 5] = Indica se o campo poderá ser usado no filtro dos detalhes (String 'false' ou 'true') aFields[n, 6] = Indica se o campo será visível na tabela (String 'false' ou 'true') | X |
Local aFields := {} Local aItems := {} Local oResponse := JsonObject():New() Local oCoreDash := CoreDash():New() aFields := {; {"num" , "Number" , 'number', /* format */, /* showFilter */, /* visible */ },; {"prefixo" , "Prefixo" , 'string', /* format */, 'false', 'false' },; {"parcela" , "String" , 'string', /* format */, /* showFilter */, /* visible */ },; {"valor" , "Valor" , 'currency', 'BRL', /* showFilter */, /* visible */ },; {"emissao" , "Data" , /* type */, /* format */, /* showFilter */, /* visible */ }; } aItems := oCoreDash:SetPOHeader(aFields) oResponse["items"] := aItems Self:SetResponse( EncodeUtf8(oResponse:ToJson()))
Sintaxe:
CoreDash():SetPOCombo(aOptions)
Descrição:
Método responsável por retornar um Array conforme esperado na propriedade p-options do componente Combo da biblioteca de componentes PO-UI.
Parâmetros:
Nome | Tipo | Descrição | Default | Obrigatório | Referência |
---|---|---|---|---|---|
aOptions | Array | Array de duas dimensões com as seguintes informações: aOptions[n, 1] = Valor (Value) aOptions[n, 2] = Rotulo (Label) | X |
Local oCoreDash := CoreDash():New() Local aOptions := {} aAdd(aOptions, {"phone" ,"Telefono" }) aAdd(aOptions, {"cellPhone" ,"Celular" }) oCoreDash:SetPOCombo(aOptions)
Sintaxe:
CoreDash():SetPOForm(cDivider, cProperty, cGridColumns, cLabel, lRequired, cType, aOptions, loptionsMulti)
Descrição:
Método responsável por construir um Formulário utilizando como base o componente DynamicForm do da biblioteca da PO-UI.
Parâmetros:
Nome | Tipo | Descrição | Default | Obrigatório | Referência |
---|---|---|---|---|---|
cDivider | Caractere | Cria uma divisória entre os campos, utilizando o nome definido na propriedade cDivider. | |||
cProperty | Caractere | Nome da Propriedade. | |||
cGridColumns | Caractere | Número de Colunas Ocupado pelo Campo. | |||
cLabel | Caractere | Rotulo/Label do Campo. | |||
lRequired | Lógico | Define se o campo é obrigatório. | |||
cType | Caractere | Tipo do Campo. | |||
aOptions | Array | Lista de opções do campo. | |||
loptionsMulti | Caractere | Define se o campo é MultSelect. |
Local oResponse := JsonObject():New() Local oCoreDash := CoreDash():New() oCoreDash:SetPOForm("Tipo de Gráfico", "graphictype" , 6 , "Tipo de Gráfico" , .T., "string", oCoreDash:SetPOCombo({{"pie","Pizza"},{"polarArea","Radar"}})) oCoreDash:SetPOForm("Filtros" , "typesearchcombo" , 12 , "Tipo de Pesquisa" , .T., "string", oCoreDash:SetPOCombo({{"mensal","Mensal"},{"anual","Anual"}})) oCoreDash:SetPOForm("" , "datadereferencia", 6 , "Data de Referência" , .T., "date") oResponse := oCoreDash:GetPOForm() Self:SetResponse( EncodeUtf8(oResponse:ToJson()))
Sintaxe:
CoreDash():GetPOForm()
Descrição:
Método responsável por retornar o Formulário, construído através do método SetPOForm.
Local oResponse := JsonObject():New() Local oCoreDash := CoreDash():New() oCoreDash:SetPOForm("Tipo de Gráfico", "graphictype" , 6 , "Tipo de Gráfico" , .T., "string", oCoreDash:SetPOCombo({{"pie","Pizza"},{"polarArea","Radar"}})) oCoreDash:SetPOForm("Filtros" , "typesearchcombo" , 12 , "Tipo de Pesquisa" , .T., "string", oCoreDash:SetPOCombo({{"mensal","Mensal"},{"anual","Anual"}})) oCoreDash:SetPOForm("" , "datadereferencia", 6 , "Data de Referência" , .T., "date") oResponse := oCoreDash:GetPOForm() Self:SetResponse( EncodeUtf8(oResponse:ToJson()))
Sintaxe:
CoreDash():SetChartInfo(aDados, cLegenda, cTipo, cBgColor, lBackGround, lDrillDown)
Descrição:
Método responsável por adicionar linhas e/ou colunas em um Gráfico de Barra ou Linha.
Parâmetros:
Nome | Tipo | Descrição | Default | Obrigatório | Referência |
---|---|---|---|---|---|
aDados | Caractere | Array de Valores utilizados no gráfico. | X | ||
cLegenda | Caractere | Legenda Label da série do gráfico. | X | ||
cTipo | Caractere | Tipo da série no gráfico. Exemplos: bar, line | |||
cBgColor | Caractere | Cor da série. | |||
lBackGround | Lógico | Define se o gráfico de linhas terá cor de fundo. | .F. | ||
lDrillDown | Caractere | Define se a série permite drilldown. | .T. |
Local oCoreDash := CoreDash():New() Local aHeader := {"2019","2020","2021"} Local aData1 := { Randomize(1,99), Randomize(1,99), Randomize(1,99) } Local aData2 := { Randomize(1,99), Randomize(1,99), Randomize(1,99) } Local aSaldo := {} Local nSaldo := 0 oCoreDash:SetChartInfo( aData1, 'Vendedor 01' ) oCoreDash:SetChartInfo( aData2, 'Vendedor 02' ) nSaldo := aData1[1] + aData2[1] aAdd(aSaldo, nSaldo) nSaldo := aData1[2] + aData2[2] aAdd(aSaldo, nSaldo) nSaldo := aData1[3] + aData2[3] aAdd(aSaldo, nSaldo) oCoreDash:SetChartInfo( aSaldo, "Média", "line", "rgba(255,240,210,0.0)", .F., .F.)
Sintaxe:
CoreDash():GetChartInfo()
Descrição:
Método responsável por retornar todos os gráficos adicionados através do método SetChartInfo.
Local aGraphic := {} Local oCoreDash := CoreDash():New() oCoreDash:SetChartInfo( aSaldo, "Média", "line", "rgba(23,132,175,0.59)", .F., .F.) aGraphic := oCoreDash:GetChartInfo()
Sintaxe:
CoreDash():SetChart( aLegenda, aDados, lCurrency, cType, cTitle, aMaskFrac ) Class CoreDash
Descrição:
Método responsável por retornar todas as informações de gráficos de Barra/Linha.
Parâmetros:
Nome | Tipo | Descrição | Default | Obrigatório | Referência |
---|---|---|---|---|---|
aLegenda | Array | Legendas apresentadas no Gráfico | X | ||
aDados | Array | Dados impressos no Gráfico. Observação: Para gráficos do tipo barra/linha, pode se usar o próprio GetChartInfo | |||
lCurrency | Lógico | Informa se a máscara retornada será ou não do tipo moeda | .F. | ||
cType | Caractere | Tipo de Gráfico que será retornado. | |||
cTitle | Caractere | Título apresentado no Gráfico. | |||
aMaskFrac | Array | Informa os formatos de máscara que podem ser passados |
Atenção
Para os gráficos do tipo Pizza e Polar não é possível realizar a máscara monetária através dos parâmetros lCurrency e aMaskFrac.
Local oCoreDash := CoreDash():New() Local aData := {} Local aCab := {} Local lCurrency := .T. Local aItem := {} Local aMask := {} Local cType := "bar" aMask := JsonObject():New() aItem['maskFrac'] := "R$" aItem['maxiFrac'] := 10 aItem['miniFrac'] := 2 AAdd(aMask,aItem) oCoreDash:SetChart(aCab,aData,lCurrency,cType,"Nota fiscal por Estado",aMask)
Sintaxe:
CoreDash():GetCposLGPD()
Descrição:
Método responsável por retornar array com os campos sensíveis que deverão ter exibição restrita de acordo com o Usuário logado.
Local oCoreDash := CoreDash():New() Local aCampos := {} Local aCposLGPD := {} Aadd(aCampos, {"code", "A1_CODIGO"}) Aadd(aCampos, {"name", "A1_NOME"}) oCoreDash:SetFields(aCampos) aCposLGPD := oCoreDash:GetCposLGPD()
Sintaxe:
CoreDash():GetColorChart()
Descrição:
Método responsável por retornar em um array todas as cores padronizadas para uso de gráficos DASH.
Se for passado ao metodo o ID da cor, será retornado somente a cor solicitada.
CoreDash():GetColorChart(X);
Onde X é o ID da cor solicitada.
Parâmetros:
Cor (Variável) | Descrição da Cor | ID | Código RGBA | Posição Array | Exemplo Cor |
---|---|---|---|---|---|
cGreenDk | Verde Escuro | 1 | rgba( 0,178,142, 1) | aArray[1][3] | |
cGreenLht | Verde Claro | 2 | rgba( 0,201,161, 1) | aArray[2][3] | |
cRedDk | Vermelho Escuro | 3 | rgba(198, 72, 64, 1) | aArray[3][3] | |
cRedLht | Vermelho Claro | 4 | rgba(227, 73, 64, 1) | aArray[4][3] | |
cYellDk | Amarelo Escuro | 5 | rgba(252,203, 76, 1) | aArray[5][3] | |
cYellLht | Amarelo Claro | 6 | rgba(255,212,100, 1) | aArray[6][3] | |
cOrangeDk | Laranja Escuro | 7 | rgba(234,155, 62, 1) | aArray[7][3] | |
cOrangeLht | Laranja Claro | 8 | rgba(255,162, 54, 1) | aArray[8][3] | |
cBlueDk | Azul Escuro | 9 | rgba( 0,120,255, 1) | aArray[9][3] | |
cBlueLht | Azul Claro | 10 | rgba( 50,165,255, 1) | aArray[10][3] | |
cGreyDk | Cinza Escuro | 11 | rgba(192,192,192, 1) | aArray[11][3] | |
cGreyLht | Cinza Claro | 12 | rgba(200,200,210, 1) | aArray[12][3] | |
cPurpleDk | Roxo Escuro | 13 | rgba(128, 0,128, 1) | aArray[13][3] | |
cPurpleLht | Roxo Claro | 14 | rgba(185, 35,185, 1) | aArray[14][3] | |
cBrownDk | Marron Escuro | 15 | rgba(128, 0, 0, 1) | aArray[15][3] | |
cBrownLht | Marron Claro | 16 | rgba(160, 80, 40, 1) | aArray[16][3] | |
cFuchsiaDk | Pink Escuro | 17 | rgba(255, 0,255, 1) | aArray[17][3] | |
cFuchsiaLht | Pink Claro | 18 | rgba(255,120,255, 1) | aArray[18][3] | |
cMnightBlue | Azul Meia Noite | 19 | rgba( 25, 25,112, 1) | aArray[19][3] | |
cMediumBlue | Azul Médio | 20 | rgba( 0, 0,205, 1) | aArray[20][3] | |
cDGreen | Verde | 21 | rgba( 0,100, 0, 1) | aArray[21][3] | |
cFGreen | Verde Floresta | 22 | rgba( 34,139, 34, 1) | aArray[22][3] | |
cGreenYel | Verde Limão | 23 | rgba(173,255, 47, 1) | aArray[23][3] | |
cSalmon | Salmão | 24 | rgba(250,128,114, 1) | aArray[24][3] | |
cTan | Rosa Queimado | 25 | rgba(210,180,140, 1) | aArray[25][3] | |
cWheat | Rosa Trigo | 26 | rgba(245,222,179, 1) | aArray[26][3] | |
cSlateGray | Cinza Ardósia | 27 | rgba(112,128,144, 1) | aArray[27][3] | |
cMistyRose | Rosa Claro | 28 | rgba(255,228,225, 1) | aArray[28][3] |
04. DEMAIS INFORMAÇÕES
- Não há.