La clase CoreDash ofrece un objeto utilizado en la construcción de Cards o Gráficos.
Este objeto puede utilizarse en la construcción de servicios REST utilizados en el Dashboard.
Servicio Cards
Pone a disposición una API REST en el Dashboard para visualizar un Card. Con el siguiente fuente (Ejemplo) se obtuvo el siguiente Card de ejemplo:
Para poner a disposición un card, es necesario que su API tenga 4 endpoints:
1. Un POST para cargar las informaciones que se mostrarán en los detalles de este card (Opción Detalles):
En el siguiente ejemplo, estas informaciones son devueltas por el endpoint /CardsCustomer/cards/itemsDetails.
El endpoint debe devolver la siguiente estructura json:
{ "header":[ { "showFilter": boolean, "property": string, "label":string } ], "items":[ { "property": <Valor devuelto por la query>, } ], "hasNext": boolean }
La propiedad header se refiere al encabezado de la tabla. Como la tabla utilizada por el dashboard es un componente de la biblioteca PO-UI (po-table), deben informarse las propiedades obligatorias a este componente: property (nombre identificador para la columna) y label (título para la columna). Para más informaciones, haga clic aquí.
La propiedad ítems se refiere a los valores que se mostrarán en las columnas de la tabla, es decir, para cada propiedad informada, la query devolverá un valor. Ejemplo: { "code": "000001" }. Este debe tener la propiedad "hasNext" para informar si existe una próxima página (true) o no (false).
{
"header": [
{
"showFilter": true,
"type": "link",
"property": "code",
"visible": true,
"label": "Código",
"action": "Enlace"
},
{
"showFilter": true,
"property": "store",
"visible": true,
"label": "Tienda"
},
{
"showFilter": true,
"property": "name",
"visible": true,
"label": "Nombre"
},
{
"showFilter": true,
"property": "fantasyName",
"visible": true,
"label": "Nombre fantasía"
},
{
"showFilter": true,
"property": "risk",
"visible": true,
"label": "Riesgo"
}
],
"items": [
{
"code": "API001",
"store": "01",
"name": "CLIENTE API INCLUSIÓN",
"fantasyName": "CLIENTE API INCLUSIÓN",
"risk": "A"
},
{
"code": "API002",
"store": "01",
"name": "CLIENTE API MODIFICACIÓN",
"fantasyName": "API MODIFICACIÓN",
"risk": "A"
},
{
"code": "API003",
"store": "01",
"name": "CLIENTE API BORRADO",
"fantasyName": "API BORRADO",
"risk": "A"
},
{
"code": "API005",
"store": "01",
"name": "API 005 MANUT.COMISIÓN MODIFICA",
"fantasyName": "API005",
"risk": "A"
},
{
"code": "API006",
"store": "01",
"name": "API006 MANUT.COMISIÓN BORRA",
"fantasyName": "API006",
"risk": "A"
},
{
"code": "API007",
"store": "01",
"name": "API007 - MATS030 - MODIFICAR",
"fantasyName": "API007 MATS030",
"risk": "A"
},
{
"code": "API008",
"store": "01",
"name": "API008 - MATS030 - BORRAR",
"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. Un GET para devolver los campos que pueden utilizarse en el filtro del card (Opción 'Filtrar' en la inclusión/modificación del card):
En el siguiente ejemplo, estas informaciones son devueltas por el endpoint /CardsCustomer/cards/cardFilter.
El endpoint debe devolver la siguiente estructura json:
{ "items": [ { "showFilter": boolean, "property": string, "label": string } ] }
La propiedad ítems se refiere al campo "Campo" de la inclusión de filtro. El property es el nombre identificador para la opción y el label es el título para la opción.
{ "items": [ { "showFilter": true, "property": "code", "label": "Código" }, { "showFilter": true, "property": "store", "label": "Tienda" }, { "showFilter": true, "property": "name", "label": "Nombre" }, { "showFilter": true, "property": "fantasyName", "label": "Nombre fantasía" }, { "showFilter": true, "property": "risk", "label": "Riesgo" } ] }
3. Un GET para devolver el valor de las informaciones que se mostrarán en el card (como máximo 4). Ejemplo: La información Total clientes riesgo A tiene el valor 197.
En el siguiente ejemplo, estas informaciones son devueltas por el endpoint /CardsCustomer/cards/cardInfo.
El endpoint debe devolver la siguiente estructura json:
{ "items": [ { "propriedad": "valor" } ], "hasNext": "false" }
La propiedad ítems debe traer todas las informaciones que podrán mostrarse en el card y su respectivo valor. En el ejemplo que tenemos anteriormente con la información de Total por cobrar, este se refiere a la propiedad "total" mostrada en esta devolución.
{ "items": [ { "risco_a": 197, "risco_b": 10, "risco_c": 1 } ], "hasNext": "false" }
4. Un GET para devolver los campos/propiedades que pueden utilizarse en la presentación del card:
En el siguiente ejemplo, estas informaciones son devueltas por el endpoint /CardsCustomer/cards/fieldsInfo.
El endpoint debe devolver la siguiente estructura json:
{ "items": [ { "value": string, "label": string } ] }
La propiedad ítems debe devolver la lista con todas las opciones que pueden aparecer en los campos Primera información, Segunda información, Tercera información y Cuarta información. Este campo es un componente de la biblioteca PO-ui (po-combo), por lo tanto, debe devolver las propiedades obligatorias para su implementación: label (título para la opción) y value (valor de aquella opción). Para más informaciones, haga clic aquí.
{ "items": [ { "value": "risco_a", "label": "Total clientes riesgo A: " }, { "value": "risco_b", "label": "Total clientes riesgo B: " }, { "value": "risco_c", "label": "Total clientes riesgo C: " } ] }
Ejemplo
Haga clic aquí para download del fuente de ejemplo.
#INCLUDE "TOTVS.CH" #INCLUDE "RESTFUL.CH" //------------------------------------------------------------------- /*/{Protheus.doc} WSCardsCustomer Ejemplo de API de integración de Cards @author Squad CRM & Facturación @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 "Activa los ítems utilizados para montaje del panel" ; WSSYNTAX "/cards/itemsDetails/{Order, Page, PageSize, Fields}" ; PATH "/cards/itemsDetails"; PRODUCES APPLICATION_JSON WSMETHOD GET cardFilter; DESCRIPTION "Pone a disposición los campos que podrán utilizarse en el filtro del Card" ; WSSYNTAX "/cards/cardFilter/" ; PATH "/cards/cardFilter"; PRODUCES APPLICATION_JSON WSMETHOD GET cardInfo; DESCRIPTION "Activa las informaciones del panel" ; WSSYNTAX "/cards/cardInfo/" ; PATH "/cards/cardInfo"; PRODUCES APPLICATION_JSON WSMETHOD GET fieldsInfo ; DESCRIPTION "Activa los campos que pueden utilizarse" ; WSSYNTAX "/cards/fieldsInfo/" ; PATH "/cards/fieldsInfo"; PRODUCES APPLICATION_JSON ENDWSRESTFUL //------------------------------------------------------------------- /*/{Protheus.doc} POST itemsDetails Activa los ítems utilizados para montaje del panel @author Squad CRM & Facturación @since 13/04/2022 @version 12.1.33 /*/ //------------------------------------------------------------------- WSMETHOD POST itemsDetails WSRECEIVE Order, Page, PageSize, Fields WSSERVICE CardsCustomer Local aHeader := {} Local aRet := {} Local cError := "Error en la requisición" 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 //Activa la función responsable por montar la expresión 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 la query estándar utilizada en el servicio 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 la query responsable por traer los ítems utilizados en el panel @param cCampos, Carácter, Campos que se devolverán en el SELECT @param cFiltro, Carácter, Filtro que se incluirá en la query @param cGroupBy, Carácter, Expresión group by que se incluirá en la query @author Squad CRM & Facturación @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 Efectúa la conversión entre los atributos objetos del Json y los campos utilizados en la Consulta @author Squad CRM & Facturación @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 devolver los datos que pueden mostrarse por el Card @author Squad CRM & Facturación @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() //Convierte los campos utilizados en la consulta a los campos utilizados en el card. oCoreDash:SetFields(DePara()) //Converte el filtro informado en el parámetro 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 Devuelve los datos que podrán mostrarse en el panel @author Squad CRM & Facturación @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 Devuelve los datos de acuerdo con el filtro @param cFiltro, Carácter, Filtro que se incluirá en la query @author Squad CRM & Facturación @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 Activa los campos que pueden utilizarse @author Squad CRM & Facturación @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 riesgo A: " }) aAdd(aItems, { "risco_b" , "Total clientes riesgo B: " }) aAdd(aItems, { "risco_c" , "Total clientes riesgo C: " }) /*Devuelve un objeto en el formato de Value y Label*/ oResponse["items"] := oCoreDash:SetPOCombo(aItems) Self:SetResponse( EncodeUtf8(oResponse:ToJson())) Return .T. //------------------------------------------------------------------- /*/{Protheus.doc} GET cardFilter Devuelve los campos que podrán filtrarse @author Squad CRM & Facturación @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" , "Tienda" },; {"name" , "Nombre" },; {"fantasyName", "Nombre fantasía"},; {"risk" , "Riesgo" }; } oResponse["items"] := oCoreDash:SetPOHeader(aFields) Self:SetResponse( EncodeUtf8(oResponse:ToJson())) Return .T. //------------------------------------------------------------------- /*/{Protheus.doc} RetHeader Devuelve los campos del encabezado de los detalles @author Squad CRM & Facturación @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" , "Tienda" ,,,,.T.},; {"name" , "Nombre" ,,,,.T.},; {"fantasyName", "Nombre fantasía",,,,.T.},; {"risk" , "Riesgo" ,,,,.T.}; } ElseIf cTable == "SC5" aHeader := {; {"num" , "Número Pedido" ,,,,.T.},; {"type" , "Tipo Pedido" ,,,,.T.},; {"payment" , "Condición de pago",,,,.T.},; {"emission", "Emisión" ,,,,.T.}; } EndIf Return aHeader
Pone a disposición una API REST en el Dashboard para visualizar un gráfico de Pizza o Polar. Con el siguiente fuente (Ejemplo) se obtuvo el siguiente Gráfico de ejemplo:
Para poner a disposición gráficos de pizza/polar, es necesario que la API tenga 3 endpoints:
1. Un GET para devolver el formulario de registro del gráfico:
En el siguiente ejemplo, estas informaciones son devueltas por el endpoint /Ejemplo2/charts/form.
Diferente de los cards, el gráfico tiene un formulario dinámico y es el servicio anteriormente mencionado que debe devolver los datos para el montaje del formulario de registro. En este ejemplo, este nos devolvió el formulario a partir de la línea 'Tipo de gráfico'. Todo lo que viene antes de esta línea, es estándar para todos los gráficos.
El endpoint debe devolver la siguiente estructura json:
{ "items": [ { "divider": string, "gridSmColumns": number, "type": string, "property": string, "gridColumns": number, "required": boolean, "label": string } ] }
La propiedad ítems debe devolver la lista con las configuraciones de todos los campos que deben mostrarse en el formulario. Para el montaje de este formulario, se utiliza el componente Dynamic Form del PO-ui, por lo tanto, para entender cada una de las propiedades que se devolverán en este servicio, haga clic aquí.
{ "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": "Fechas", "gridSmColumns": 12, "type": "date", "property": "datainicio", "gridColumns": 6, "required": true, "label": "De Fch. Emisión" }, { "gridSmColumns": 12, "type": "date", "property": "datafim", "gridColumns": 6, "required": true, "label": "A Fch. Emisión" } ] }
2. Un POST para cargar las informaciones del gráfico:
En el siguiente ejemplo, estas informaciones son devueltas por el endpoint /Ejemplo2/charts/retdados.
El endpoint debe devolver la siguiente estructura json:
{ "items": [ { "chartData": [ Lista de las informaciones que se mostrarán en el gráfico ], "chartLabels": [ Lista de los títulos de las informaciones ], "charttype": string - Tipo del gráfico, "title": string - Título del gráfico } ] }
La propiedad ítems debe devolver las informaciones del gráfico como valores que se mostrarán, títulos que representen estos valores, título del gráfico y máscara de valores que se utilizará.
{ "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": "Factura por Estado/Prov/Reg" } ] }
3. Un POST para cargar las informaciones que se mostrarán en los detalles del gráfico:
En el siguiente ejemplo, estas informaciones son devueltas por el endpoint /Ejemplo2/charts/itemsDetails.
El endpoint debe devolver la siguiente estructura json:
{ "header":[ { "showFilter": boolean, "property": string, "label":string } ], "items":[ { "property": <Valor devuelto por la query>, } ], "hasNext": boolean }
La propiedad header se refiere al encabezado de la tabla. Como la tabla utilizada por el dashboard es un componente de la biblioteca PO-UI (po-table), deben informarse las propiedades obligatorias a este componente: property (nombre identificador para la columna) y label (título para la columna). Para más informaciones, haga clic aquí.
La propiedad ítems se refiere a los valores que se mostrarán en las columnas de la tabla, es decir, para cada propiedad informada, la query devolverá un valor. Ejemplo: { "documentType": "N" }. Este debe tener la propiedad "hasNext" para informar si existe una próxima página (true) o no (false).
{ "header": [ { "showFilter": true, "type": "link", "property": "document", "label": "Documento", "action": "Enlace" }, { "showFilter": true, "property": "series", "label": "Serie" }, { "showFilter": true, "property": "state", "label": "ESTADO/PROV/REG" }, { "showFilter": true, "property": "documentType", "label": "Tipo" }, { "showFilter": true, "property": "dateOfIssue", "label": "Emisión" } ], "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 }
Haga clic aquí para download del fuente de ejemplo.
#INCLUDE "TOTVS.CH" #INCLUDE "RESTFUL.CH" //------------------------------------------------------------------------ /*/{Protheus.doc} Exemplo2 Ejemplo de API de integración de Gráficos de Pizza y/o Polar @author Squad CRM & Facturación @since 26/03/2020 @version 12.1.27 /*/ //------------------------------------------------------------------------ WSRESTFUL Ejemplo2 DESCRIPTION "Ejemplo de API - Gráfico Pizza y 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 Registro del gráfico" ; WSSYNTAX "/charts/form/" ; PATH "/charts/form"; PRODUCES APPLICATION_JSON WSMETHOD POST retdados ; DESCRIPTION "Devuelve las informaciones del gráfico" ; WSSYNTAX "/charts/retdados/{JsonFilter}" ; PATH "/charts/retdados"; PRODUCES APPLICATION_JSON WSMETHOD POST itemsDetails ; DESCRIPTION "Activa el detalle del gráfico" ; WSSYNTAX "/charts/itemsDetails/{JsonFilter}" ; PATH "/charts/itemsDetails"; PRODUCES APPLICATION_JSON ENDWSRESTFUL //------------------------------------------------------------------- /*/{Protheus.doc} GET form Devuelve los campos que se mostraron en el Registro del grafico. Debe seguir el formato del Dynamic Form del PO-UI. https://po-ui.io/tools/dynamic-form @author Squad CRM & Facturación @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("Fechas" , "datainicio" , 6 , "De Fch. Emisión" , .T., "date") oCoreDash:SetPOForm("" , "datafim" , 6 , "A Fch. Emisión" , .T., "date") oResponse := oCoreDash:GetPOForm() Self:SetResponse( EncodeUtf8(oResponse:ToJson())) Return .T. //------------------------------------------------------------------- /*/{Protheus.doc} POST retdados Devuelve un objeto JSON con las informaciones y valores del gráfico @author Squad CRM & Facturación @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 Devuelve los ítems utilizados en el Drilldown @author Squad CRM & Facturación @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 := "Error en la eequisición" 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 del Drilldown aHeader := {; {"document" , "Documento" ,"enlace" },; {"series" , "Serie" },; {"state" , ESTADO/PROV/REG" },; {"documentType" , "Tipo" },; {"dateOfIssue" , "Emisión" }; } 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 del Drilldown aHeader := {; {"D2_ITEM" , "Ítem" },; {"D2_COD" , "Cód. Producto", "enlace" },; {"B1_DESC" , "Desc. Producto " },; {"D2_PRCVEN", "Val.Unitario", "currency","BRL" },; {"D2_QUANT" , "Cantidad","number",'1.2-5' },; {"D2_TOTAL" , "Val. Total", "currency","BRL" },; {"D2_LOCAL" , "Almacén" }; } 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 del Drilldown aHeader := {; {"B1_COD" , "Cód. Producto" },; {"B1_DESC" , "Desc. Producto " },; {"B1_PRV1" , "Precio de venta", "currency","BRL" },; {"B1_TE" , "TES Entrada Est" },; {"B1_TS" , "TES Salida Est" }; } 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 el Drilldown del gráfico nivel 2 aHeader := {; {"document" , "Documento" },; {"series" , "Serie" },; {"state" , "ESTADO/PROV/REG" },; {"documentType" , "Tipo" },; {"dateOfIssue" , "Emisión" }; } 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 Devuelve los datos que podrán mostrarse en el grafico @author Squad CRM & Facturación @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*/,,"Factura por Estado/Prov/Reg")) 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","Cantidad de facturas 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, 'Facturas', 'bar', aCores[8][3] ) //Color utilizado: OrangeLht aAdd(aDataFim, oCoreDash:SetChart(aCab,,/*lCurrency*/,"bar","TOP 10 Clientes por tipo de factura")) Endif oResponse["items"] := aDataFim Return Nil //------------------------------------------------------------------- /*/{Protheus.doc} QuerySF2 Monta la query responsable por traer los registros de la factura @param cSelect, Carácter, Campos que se devolverán en el SELECT @param cFilter, Carácter, Filtro complementario utilizado en la cláusula WHERE @author Squad CRM & Facturación @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 la query responsable por traer los registros de la factura @param cSelect, Carácter, Campos que se devolverán en el SELECT @param cFilter, Carácter, Filtro complementario utilizado en la cláusula WHERE @author Squad CRM & Facturación @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 la query responsable por traer el documento del Reg. Producto @param cSelect, Carácter, Campos que se devolverán en el SELECT @param cFilter, Carácter, Filtro complementario utilizado en la cláusula WHERE @author Squad CRM & Facturación @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 Devuelve ESTADO/PROV/REG @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 Devuelve los tipos de factura @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.Precio/Cantidad') aAdd(aTipoNF, 'I=Compl.ICMS') aAdd(aTipoNF, 'P=Compl.IPI') aAdd(aTipoNF, 'D=Dev.Compras') aAdd(aTipoNF, 'B=Utiliza Proveedor') Return aTipoNF
Servicios gráficos de Barra/Línea
Pone a disposición una API REST en el Dashboard para visualizar un gráfico de Barra o Línea. Con el siguiente fuente se obtuvo el siguiente Gráfico de ejemplo:
Para poner a disposición gráficos en barra/línea, es necesario que la API tenga 3 endpoints:
1. Un GET para devolver el formulario de registro del gráfico:
En el siguiente ejemplo, estas informaciones son devueltas por el endpoint /Ejemplo/charts/form.
Diferente de los cards, el gráfico tiene un formulario dinámico y es el servicio que debe devolver el formulario de registro este. En este ejemplo, este nos devolvió el formulario a partir de la línea 'Tipo de gráfico'. Todo lo que viene antes de esta línea, es estándar para todos los gráficos.
El endpoint debe devolver la siguiente estructura json:
{ "items": [ { "divider": string, "gridSmColumns": number, "type": string, "property": string, "gridColumns": number, "required": boolean, "label": string } ] }
La propiedad ítems debe devolver la lista con las configuraciones de todos los campos que deben mostrarse en el formulario. Para el montaje de este formulario, se utiliza el componente Dynamic Form del PO-ui, por lo tanto, para entender cada una de las propiedades que se devolverán en este servicio, haga clic aquí.
{ "items": [ { "divider": "Tipo de gráfico", "gridSmColumns": 12, "options": [ { "value": "line", "label": "Línea" }, { "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": "Fecha inicial" }, { "gridSmColumns": 12, "type": "date", "property": "dateFim", "gridColumns": 6, "required": true, "label": "Fecha final" } ] }
2. Un POST para cargar las informaciones del gráfico:
En el siguiente ejemplo, estas informaciones son devueltas por el endpoint /Ejemplo3/charts/retdados.
El endpoint debe devolver la siguiente estructura json:
{ "items": [ { "chartData": [ { "data": [ Valores que se mostrarán ], "fill": false, "drillDown": true, "backgroundColor": "rgba(255,162, 54, 1)" - Color de la línea, "hoverBackgroundColor": "rgba(255,162, 54, 1)" - Color de la línea al pasar el mouse, "label": string - Título que representa el conjunto de información y que aparecerá en la leyenda, "lineTension": number - Tensión de la curva de la línea. Si fuera 0, la línea será recta } ], "chartLabels": [ Títulos correspondientes a los valores que se mostrarán ], "charttype": string - Tipo de gráfico, "title": string - Título del gráfico, "chartMask": string, "currencyMask": [ Máscaras utilizadas para mostrar valores ] } ] }
La propiedad ítems debe devolver las informaciones del gráfico como valores que se mostrarán, títulos que representen estos valores, título del gráfico y máscara de valores que se utilizará.
El gráfico utiliza la biblioteca chart.js. Para más información sobre sus propiedades, haga clic aquí.
{ "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": "Promedio", "lineTension": 0 } ], "chartLabels": [ "Enero", "Febrero", "Marzo" ], "charttype": "", "title": null, "chartMask": "currency", "currencyMask": [ { "maskFrac": "R$", "maxiFrac": 10, "miniFrac": 2 } ] } ] }
3. Un POST para cargar las informaciones que se mostrarán en los detalles del gráfico:
En el siguiente ejemplo, estas informaciones son devueltas por el endpoint /Ejemplo3/charts/itemsDetails.
El endpoint debe devolver la siguiente estructura json:
{ "header":[ { "showFilter": boolean, "property": string, "label":string } ], "items":[ { "property": <Valor devuelto por la query>, } ], "hasNext": boolean }
La propiedad header se refiere al encabezado de la tabla. Como la tabla utilizada por el dashboard es un componente de la biblioteca PO-UI (po-table), deben informarse las propiedades obligatorias a este componente: property (nombre identificador para la columna) y label (título para la columna). Para más informaciones, haga clic aquí.
La propiedad ítems se refiere a los valores que se mostrarán en las columnas de la tabla, es decir, para cada propiedad informada, la query devolverá un valor. Ejemplo: { "totalValor": }. Este debe tener la propiedad "hasNext" para informar si existe una próxima página (true) o no (false).
{ "header": [ { "showFilter": true, "type": "link", "property": "codigo", "label": "Código", "action": "Enlace" }, { "showFilter": true, "property": "nome", "label": "Nombre vendedor" }, { "showFilter": false, "format": "1.2-5", "type": "number", "property": "totalItens", "label": "Total de ítems" }, { "showFilter": false, "format": "BRL", "type": "currency", "property": "totalValor", "label": "Valor total" } ], "items": [ { "totalValor": 2000, "totalItens": 1, "nome": "10% COMIS 100%EMISIÓN", "codigo": "FIN058" }, { "totalValor": 2000, "totalItens": 1, "nome": "10% COMISIÓN 100% BAJA DESCUENTA IMPUESTOS", "codigo": "FIN056" }, { "totalValor": 2000, "totalItens": 1, "nome": "10% COMISIÓN 100% BAJA DESCUENTA IMPUESTOS", "codigo": "FIN060" }, { "totalValor": 2000, "totalItens": 1, "nome": "10% COMISIÓN 100% EMISIÓN DESCUENTA IMPUESTOS", "codigo": "FIN055" }, { "totalValor": 2000, "totalItens": 1, "nome": "10% COMISIÓN 100% EMISIÓN DESCUENTA IMPUESTOS", "codigo": "FIN059" }, { "totalValor": 5000, "totalItens": 4, "nome": "100% BAJA 10%COMISIÓN", "codigo": "FVEN10" }, { "totalValor": 1000, "totalItens": 1, "nome": "100%baja 0%comisión", "codigo": "FIN048" }, { "totalValor": 2000, "totalItens": 2, "nome": "100%emisión 0%comisión", "codigo": "FIN047" }, { "totalValor": 200000, "totalItens": 2, "nome": "5% COMISIÓN 100% BAJA", "codigo": "FIN600" }, { "totalValor": 1000, "totalItens": 1, "nome": "50 50 - 10%", "codigo": "FIN073" } ], "hasNext": true }
Haga clic aquí para download del fuente de ejemplo.
#INCLUDE "TOTVS.CH" #INCLUDE "RESTFUL.CH" //------------------------------------------------------------------------ /*/{Protheus.doc} Exemplo3 Ejemplo de API de integración de Gráficos de Barra y Línea @author Squad CRM & Facturación @since 28/07/2020 @version 12.1.27 /*/ //------------------------------------------------------------------------ WSRESTFUL Ejemplo3 DESCRIPTION "Ejemplo de API - Gráfico Barra y Línea" 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 Registro del gráfico" ; WSSYNTAX "/charts/form/" ; PATH "/charts/form"; PRODUCES APPLICATION_JSON WSMETHOD POST retDados ; DESCRIPTION "Debe devolver las informaciones mostradas en el gráfico." ; WSSYNTAX "/charts/retDados/{JsonFilter}" ; PATH "/charts/retDados"; PRODUCES APPLICATION_JSON WSMETHOD POST itemsDetails ; DESCRIPTION "Activa el detalle del gráfico" ; WSSYNTAX "/charts/itemsDetails/{JsonFilter}" ; PATH "/charts/itemsDetails"; PRODUCES APPLICATION_JSON ENDWSRESTFUL //------------------------------------------------------------------- /*/{Protheus.doc} GET form Devuelve los campos que se mostrarán en el formulario. El estándar del campo debe seguir o Dynamic Form del Portinari. @author Squad CRM & Facturación @since 27/03/2020 @version Protheus 12.1.27 /*/ //------------------------------------------------------------------- WSMETHOD GET form WSSERVICE Ejemplo3 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","Línea"}, {"bar","Barra"}})) oCoreDash:SetPOForm("Filtros" , "dateIni" , 6, "Fecha inicial" , .T., 'date' , , .T.) oCoreDash:SetPOForm("" , "dateFim" , 6, "Fecha final" , .T., 'date' , , .T.) oCoreDash:SetPOForm("" , "person" , 6, "Persona" , .F., 'string' , oCoreDash:SetPOCombo({{"F","Física"} , {"J","Jurídica"}}), .T.) oCoreDash:SetPOForm("" , "blocked" , 6, "¿Bloqueado?" , .F., 'string' , oCoreDash:SetPOCombo({{"1","Sí"} , {"2","No"}}) , .F.) oResponse := oCoreDash:GetPOForm() Self:SetResponse( EncodeUtf8(oResponse:ToJson())) Return .T. //------------------------------------------------------------------- /*/{Protheus.doc} POST retDados Devuelve los datos del gráfico @author Squad CRM & Facturación @since 27/03/2020 @version Protheus 12.1.27 /*/ //------------------------------------------------------------------- WSMETHOD POST retDados WSRECEIVE JsonFilter WSSERVICE Ejemplo3 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 Devuelve el valor de las Metas y el Valor vendido de acuerdo con parámetros informados @author Squad CRM & Facturación @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' } //######### Obtener los filtros del registro o del usuario y aplicar en la query ######### // Filtro por tipo da persona - Con Multiselección 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 de persona - con una única selección If oJson:HasProperty("blocked") .And. ValType(oJson["blocked"]) == "C" cFiltros += "AND SA1.A1_MSBLQL = '" + oJson["blocked"] + "'" EndIf //######### Final de la obtención de los filtros del registro o del usuario y aplicar en la 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, 'Riesgo A', , aCores[8][3] ) //Color utilizado: OrangeLht oCoreDash:SetChartInfo( aData2, 'Riesgo B', , aCores[1][3] ) //Color utilizado: GreenDk oCoreDash:SetChartInfo( aData3, 'Riesgo C', , aCores[6][3] ) //Color utilizado: YellowDk oCoreDash:SetChartInfo( aData4, 'Riesgo D', , aCores[15][3] ) //Color utilizado: 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, 'Promedio', "line", aCores[9][3] ,,.F.) //Color utilizado: BlueDk aDataFim := {} aAdd(aDataFim, oCoreDash:SetChart(aCab,,.F., ,"Cantidad de clientes por riesgo en cada Estado/Prov/Reg")) 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., ,"Mayores ventas - " + 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", "Mayores clientes - " + oJson["level"][2]["labelDataSet"] + " - " + oJson["level"][1]["label"])) EndIf oResponse["items"] := aDataFim Return //------------------------------------------------------------------- /*/{Protheus.doc} POST itemsDetails Método para devolver los datos del panel @author Squad CRM & Facturación @since 27/03/2020 @version Protheus 12.1.27 /*/ //------------------------------------------------------------------- WSMETHOD POST itemsDetails WSRECEIVE JsonFilter, drillDownFilter WSRESTFUL Ejemplo3 Local aHeader := {} Local aItems := {} Local aRet := {} Local cBody := DecodeUtf8(Self:GetContent()) Local cError := "Error en la requisición" 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 el nivel del gráfico If oJsonFilter:GetJsonText("level") == "null" .Or. Len(oJsonFilter["level"]) == 0 //Verifico el nivel del Drilldown If Len(oJsonDD) == 0 aHeader := {; {"codigo" , "Código" ,"enlace" },; {"nombre" , "Nombre vendedor" },; {"totalItens" , "Total de ítems","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 //Si quisiera tomar el nombre del nivel seleccionado : oJsonFilter["level"][1]["labelDataSet"] // Si fuese gráfico del tipo pizza: oJsonFilter["level"][1]["label"] aHeader := {; {"codigoPed" , "Código del pedido" },; {"codigoCli" , "Código del cliente" },; {"nome" , "Nombre" },; {"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]["código"] + "'") EndIf ElseIf Len(oJsonFilter["level"]) == 1 aHeader := {; {"codigoPed" , "Código del pedido" },; {"codigoCli" , "Código del cliente" },; {"nome" , "Nombre" },; {"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" , "Nombre vendedor" },; {"totalItens" , "Total de ítems","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 y el Total de los pedidos de venta @author Squad CRM & Facturación @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 la Query del Pedido de ventas realizando un filtro específo. @author Squad CRM & Facturación @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' " // Límite incluido para evitar lentitud en la devolución de la query en bases con una cantidad muy grande de pedidos de venta cGroup := " C5_NUM, C5_CLIENTE, SA1.A1_NOME " Return {cQuery, cWhere, cGroup} //------------------------------------------------------------------- /*/{Protheus.doc} RetRisco Devuelve el total de clientes de acuerdo con el riesgo informado en el filtro @param cFiltro, Carácter, Filtro que se incluirá en la query @author Squad CRM & Facturación @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 la query responsable por traer los clientes de acuerdo con el riesgo informado en el filtro @param cCampos, Carácter, Campos que se devolverán en el SELECT @param cFiltro, Carácter, Filtro que se incluirá en la query @param cGroupBy, Carácter, Expresión group by que se incluirá en la query @author Squad CRM & Facturación @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}
Pone a disposición una API REST en el Dashboard para visualizar un gráfico de Gauge. Con el siguiente fuente se obtuvo el siguiente Gráfico de ejemplo:
Para poner a disposición gráficos en gauge, es necesario que la API tenga 3 endpoints:
1. Un GET para devolver el formulario de registro del gráfico:
En el siguiente ejemplo, estas informaciones son devueltas por el endpoint /Ejemplo4/charts/form.
Diferente de los cards, el gráfico tiene un formulario dinámico y es el servicio que debe devolver el formulario de registro este. En este ejemplo, este nos devolvió el formulario a partir de la línea 'Tipo de gráfico'. Todo lo que viene antes de esta línea, es estándar para todos los gráficos.
El endpoint debe devolver la siguiente estructura json:
{ "items": [ { "divider": string, "gridSmColumns": number, "type": string, "property": string, "gridColumns": number, "required": boolean, "label": string } ] }
La propiedad ítems debe devolver la lista con las configuraciones de todos los campos que deben mostrarse en el formulario. Para el montaje de este formulario, se utiliza el componente Dynamic Form del PO-ui, por lo tanto, para entender cada una de las propiedades que se devolverán en este servicio, haga clic aquí.
{ "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": "De Fecha", "required": false, "type": "date", "gridSmColumns": 12 }, { "property": "datafim", "gridColumns": 6, "label": "A Fecha", "required": false, "type": "date", "gridSmColumns": 12 } ] }
2. Un POST para activar las informaciones del gráfico:
En el siguiente ejemplo, estas informaciones son devueltas por el endpoint /Ejemplo4/charts/retdados.
El endpoint debe devolver la siguiente estructura json:
{ "items": [ { "chartData": [ { <valor devuelto por la query>: number } ], "chartLabels": [ Título correspondiente al valor que se mostrará ], "charttype": string - Tipo de gráfico, "title": string - Título del gráfico, "chartMask": string } ] }
La propiedad ítems debe devolver las informaciones del gráfico como el valor que se mostrará, título que representará este valor, título del gráfico y máscara de valores que se utilizará.
El gráfico utiliza el componente gauge de la biblioteca PO-ui. Para más información sobre sus propiedades, haga clic aquí.
{ "items": [ { "chartLabels": [ "Cantidad de pedidos" ], "chartData": [ 45 ], "currencyMask": [ { "maskFrac": "R$", "maxiFrac": 10, "miniFrac": 2 } ], "charttype": "", "title": null } ] }
3. Un POST para activar las informaciones que se mostrarán en los detalles del gráfico:
En el siguiente ejemplo, estas informaciones son devueltas por el endpoint /Ejemplo4/charts/itemsDetails.
El endpoint debe devolver la siguiente estructura json:
{ "header":[ { "showFilter": boolean, "property": string, "label":string } ], "items":[ { "property": <Valor devuelto por la query>, } ], "hasNext": boolean }
La propiedad header se refiere al encabezado de la tabla. Como la tabla utilizada por el dashboard es un componente de la biblioteca PO-UI (po-table), deben informarse las propiedades obligatorias a este componente: property (nombre identificador para la columna) y label (título para la columna). Para más informaciones, haga clic aquí.
La propiedad ítems se refiere a los valores que se mostrarán en las columnas de la tabla, es decir, para cada propiedad informada, la query devolverá un valor. Ejemplo: { "totalValor": }. Este debe tener la propiedad "hasNext" para informar si existe una próxima página (true) o no (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": "Tienda cliente", "showFilter": true, "visible": true }, { "property": "C5_VEND1 ", "label": "Vendedor 1 ", "showFilter": true } ] }
Haga clic aquí para download del fuente de ejemplo.
#INCLUDE "TOTVS.CH" #INCLUDE "RESTFUL.CH" //------------------------------------------------------------------------ /*/{Protheus.doc} Ejemplo4 API - Ejemplo 4 - Gráfico de Gauge @author Squad CRM/Facturación @since 11/05/2022 @version 12.1.33 @return Json /*/ //------------------------------------------------------------------------ WSRESTFUL Ejemplo4 DESCRIPTION "Ejemplo 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 "Activa los campos que se mostrarán en el formulario" ; WSSYNTAX "/charts/form/" ; PATH "/charts/form"; PRODUCES APPLICATION_JSON WSMETHOD POST retdados ; DESCRIPTION "Activa los ítems" ; WSSYNTAX "/charts/retdados/{JsonFilter}" ; PATH "/charts/retdados"; PRODUCES APPLICATION_JSON WSMETHOD POST itemsDetails ; DESCRIPTION "Activa los ítems utilizados para montaje de los detalles" ; WSSYNTAX "/charts/itemsDetails/{JsonFilter}" ; PATH "/charts/itemsDetails"; PRODUCES APPLICATION_JSON ENDWSRESTFUL //------------------------------------------------------------------- /*/{Protheus.doc} GET form Devuelve los campos que se mostrarán en el formulario. El estándar del campo debe seguir el Dynamic Form del Portinari. @author Squad CRM & Facturamción @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 , "De Fecha" ; , .F., "date" ) oCoreDash:SetPOForm("" , "datafim" , 6 , "A Fecha" ; , .F., "date" ) oResponse := oCoreDash:GetPOForm() Self:SetResponse( EncodeUtf8(oResponse:ToJson())) Return .T. //------------------------------------------------------------------- /*/{Protheus.doc} POST retDados Devuelve los datos del gráfico @author Squad CRM & Facturación @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 devolver los datos detallados por ítems del gráfico @author Squad CRM & Facturación @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 := "Error en la requisición" 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" , "Tienda 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 Devuelve el valor de la cantidad de pedidos de acuerdo con parámetros informados @author Squad CRM & Facturación @since 16/05/2022 @version Protheus 12.1.33 /*/ //------------------------------------------------------------------- Static Function retDados(oResponse, oCoreDash, oJson, dDataIni, dDataFim) Local aData := {} Local aDataFim := {} Local aCab := {} aCab := {"Cantidade de pedidos"} oData := JsonObject():New() aData := { 45 /*Complete aquí con el valor devuelto por su query. Para el ejemplo está fijo 45*/ } aDataFim := {} aAdd(aDataFim, oCoreDash:SetChart(aCab, aData)) oResponse["items"] := aDataFim Return Nil //------------------------------------------------------------------- /*/{Protheus.doc} QuerySC5 Monta la query responsable por traer los ítems detallados utilizados en el gráfico @param cSelect, Caractere, Campos que se devolverán en el SELECT @param cFilter, Carácter, Filtro que se incluirá en la query @author Squad CRM & Facturación @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}
ATENCIÓN: Regla de paginación obligatoria
Para los servicios cuya devolución solicita la propiedad "hasNext", quiere decir que estos tienen paginación. La paginación con la utilización de la clase CoreDash es obligatoria y funciona por medio de los parámetros page (indica la página que se devolverá) y pageSize (indica cuántos registros de la página deben devolverse). Sus valores default son page = 1 e pageSize = 10.
Ejemplo de utilización: /Ejemplo1/cards/itemsDetails?page=2&pageSize=10
Sintaxis:
CoreDash():New()
Método construtor de la clase.
Local oCoreDash := CoreDash():New()
Sintaxis:
CoreDash():SetFields(aCampos)
Método que define los campos que se devolverán en el JSON del servicio.
Nombre | Tipo | Descripción | Default | Obligatorio | Referencia |
---|---|---|---|---|---|
aCampos | Array | Array que contiene el De / A de los campos que se mostrarán en el servicio | X |
Local oCoreDash := CoreDash():New() Local aCampos := {} Aadd(aCampos, {"code", "A1_CODIGO"}) Aadd(aCampos, {"name", "A1_NOME"}) oCoreDash:SetFields(aCampos)
Sintaxis:
CoreDash():SetQuery(cQuery)
Método que define la query que se utilizará en el servicio.
Nombre | Tipo | Descripción | Default | Obligatorio | Referencia |
---|---|---|---|---|---|
cQuery | Carácter | Recibe la query que se ejecutará. | X |
Local oCoreDash := CoreDash():New() Local cQuery := "" cQuery := " SELECT A1_COD, A1_NOME FROM " + RetSqlName("SA1") + " SA1 " oCoreDash:SetQuery(cQuery)
CoreDash():SetWhere(cWhere)
Método que define la cláusula where que será en el método SetQuery().
Nombre | Tipo | Descripción | Default | Obligatorio | Referencia |
---|---|---|---|---|---|
cWhere | Caractere | Where que se utilizará en la query enviada al 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)
CoreDash():SetIndexKey(cIndexFather)
Método que atribuye el orden del Alias principal.
Nombre | Tipo | Descripción | Estándar | Obligatorio | Referencia |
---|---|---|---|---|---|
cIndexFather | Carácter | Orden utilizado en el alias |
Local oCoreDash := CoreDash():New() //Ordenação Crescente (ASC) oCoreDash:SetIndexKey("A1_NOME") //Ordenação Decrescente (DESC) oCoreDash:SetIndexKey("-A1_NOME")
Sintaxis:
CoreDash():SetGroupBy(cGroup)
Método responsable por definir un agrupador en la query utilizada en el servicio.
Nombre | Tipo | Descripción | Estándar | Obligatorio | Referencia |
---|---|---|---|---|---|
cGroup | Carácter | Campos que deben componer el 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")
CoreDash():SetPage(nPage)
Método que atribuye el número de la página donde el usuario va a navegar.
Nombre | Tipo | Descripción | Estándar | Obligatorio | Referencia |
---|---|---|---|---|---|
nPage | Numérico | Número de la página que se mostrará al usuario | 1 |
Local oCoreDash := CoreDash():New() Local nPage := 8 oCoreDash:SetPage(nPage)
CoreDash():SetPageSize(nPageSize)
Método que atribuye la cantidad máxima de registros que se mostrarán por página.
Nombre | Tipo | Descripción | Estándar | Obligatorio | Referencia |
---|---|---|---|---|---|
nPageSize | Numérico | Cantidad máxima de registros mostrados por página al usuario. | 10 |
Local oCoreDash := CoreDash():New() Local nPageSize := 20 oCoreDash:SetPageSize(nPageSize)
CoreDash():DefFields(lConvProt, cField)
Método que efectúa la conversión entre campos del Objeto y Protheus
Nombre | Tipo | Descripción | Estándar | Obligatorio | Referencia |
---|---|---|---|---|---|
lConvProt | Lógico | Define si debe convertir los campos al estándar Protheus | .T. | ||
cField | Carácter | Campo que se convertirá |
Local oCoreDash := CoreDash():New() oCoreDash:DefFields(.T.,"CAMPO")
CoreDash():GetDataType(lConvProt, cField)
Devuelve el tipo del dato de un determinado campo.
Nombre | Tipo | Descripción | Estándar | Obligatorio | Referencia |
---|---|---|---|---|---|
lConvProt | Lógico | Define si debe convertir los campos al estándar Protheus | .T. | ||
cField | Caracteres | Campo que se convertirá |
Local oCoreDash := CoreDash():New() Local dData If oCoreDash:GetDataType(.T.,"CAMPO") == "D" dData := Date() Endif
CoreDash():SetFieldsFilt(cFields)
Método que define qué campos se devolverán por el servicio.
Nombre | Tipo | Descripción | Estándar | Obligatorio | Referencia |
---|---|---|---|---|---|
cFields | Carácter | Campos que se devolverán en el JSON. | X |
Local oCoreDash := CoreDash():New() Local cFields := "order, totValue, product" oCoreDash:SetFieldsFilt(cFields)
CoreDash():ToObjectJson()
Método que devuelve el JSON serializado.
Local oCoreDash := CoreDash():New() Local lRet := .T. Local cError := "Error en la requisición" If lRet Self:SetResponse( oCoreDash:ToObjectJson()) Else cError := oCoreDash:GetJsonError() SetRestFault( 500, EncodeUtf8(cError) ) EndIf
CoreDash():ToSingleObject()
Método que retorna un JSON serializado a solamente un objeto.
Se utiliza en requisiciones del tipo GET que devuelven informaciones de solamente un registro.
Local oCoreDash := CoreDash():New() Local cError := "Error en la requisición" Local lRet := .T. If lRet Self:SetResponse(oCoreDash:ToSingleObject()) Else cError := oCoreDash:GetJsonError() SetRestFault( 500, EncodeUtf8(cError) ) EndIf
Sintaxis:
CoreDash():GetJsonObject()
Método que devuelve el objeto JSON de la clase
Local oCoreDash := CoreDash():New() Local oJson oJson:= oCoreDash:GetJsonObject() If oJson["items"] != Nil ... Endif
CoreDash():SetApiQstring(aQueryString)
Método que define los campos (Devueltos por el JSON), page (página que se mostrará) y pagesize (Cantidad máxima de registros por página) y filtros.
Nombre | Tipo | Descripción | Estándar | Obligatorio | Referencia |
---|---|---|---|---|---|
aQueryString | Array | Recibe el filtro que se utilizará al devolver al JSON |
Local oCoreDash := CoreDash():New() Local aQueryString := {} aAdd(aQueryString, {"fields" , "order, totValue" }) aAdd(aQueryString, {"page" , 10 }) aAdd(aQueryString, {"pagesize" , 5 }) oCoreDash:SetApiQString(aQueryString)
CoreDash():SetApiFilter(aFilter)
Método que atribuye un filtro de búsqueda.
Nombre | Tipo | Descripción | Estándar | Obligatorio | Referencia |
---|---|---|---|---|---|
aFilter | Array | Array con expresiones de filtro que se utilizarán | X |
Local oCoreDash := CoreDash():New() Local aFilter := {} aAdd(aFilter, {"A1_COD = '000001'"}) oCoreDash:SetApiFilter(aFilter)
CoreDash():GetApiFilter()
Método que devuelve el filtro de búsqueda.
Local oCoreDash := CoreDash():New() oCoreDash:GetApiFilter()
CoreDash():BuildJson()
Local oCoreDash := CoreDash():New() Self:SetContentType("application/json") oCoreDash:SetQuery(cQuery) oCoreDash:SetWhere(cWhere) oCoreDash:SetFields(aCampos) oCoreDash:SetApiQstring(aQueryString) oCoreDash:BuildJson()
CoreDash():SetJson(lHasNext, aItems)
Método responsable por atribuir un objeto JSON, de acuerdo con el contrato establecido por TOTVS, conteniendo el [items] y el [hasNext].
Nombre | Tipo | Descripción | Estándar | Obligatorio | Referencia |
---|---|---|---|---|---|
lHasNext | Lógico | Indica si el objeto tiene próxima página. | .T. | ||
aItems | Array | Array con los valores del 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)
CoreDash():SetTable(cAlias)
Método que recibe el alias que será responsable por la generación del JSON.
Nombre | Tipo | Descripción | Estándar | Obligatorio | Referencia |
---|---|---|---|---|---|
cAlias | Carácter | Alias recibido para la generación del JSON. | X |
Local oCoreDash := CoreDash():New() Local cAlias := GetNextAlias() oCoreDash:SetTable(cAlias)
CoreDash():SetUpsertData(cAlias, cIndex, cBody)
Método que efectúa la inclusión o modificación de registros.
Nombre | Tipo | Descripción | Estándar | Obligatorio | Referencia |
---|---|---|---|---|---|
cAlias | Carácter | Alias recibido para la generación del JSON. | X | ||
cIndex | Carácter | Índice utilizado en la búsqueda. | |||
cBody | Carácter | JSON recibido en el Body del mensaje. | X |
Local oCoreDash := CoreDash():New() If oCoreDash:SetUpsertData(cAlias, Nil, cBody) Self:SetResponse( EncodeUtf8("Registro incluido con éxito")) Else SetRestFault( 500, EncodeUtf8("Falla al convertir el archivo.") ) Endif
CoreDash():Destroy()
Método responsable por destruir el objeto.
Local oCoreDash := CoreDash():New() If oCoreDash:SetUpsertData(cAlias, Nil, cBody) Self:SetResponse( EncodeUtf8("Registro incluido con éxito")) Else SetRestFault( 500, EncodeUtf8("Falla al convertir el archivo.") ) Endif oCoreDash:Destroy()
ATENCIÓN: El método estará a disposición en la expedición continua de Facturación.
Para se utilizar este método debe actualizar los fuentes con el paquete de expedición continua de FACTURACIÓN del día 06/05/2022.
CoreDash():GetJsonError()
Devuelve string con el mensaje de error del JSON.
Local oCoreDash := CoreDash():New() If oCoreDash:SetUpsertData(cAlias, Nil, cBody) Self:SetResponse( EncodeUtf8("Registro incluido con éxito")) Else SetRestFault( 500, oCoreDash:GetJsonError() ) Endif
Sintaxis:
CoreDash():SetPOHeader(aFields)
Método responsable por devolver un Array de acuerdo con lo esperado e la propiedad p-columns del componente Table de la biblioteca de componentes PO-UI
Nombre | Tipo | Descripción | Estándar | Obligatorio | Referencia |
---|---|---|---|---|---|
aFields | Array | Array de hasta seis dimensiones con los datos: aFields[n, 1] = Property - Nombre identificador (String) aFields[n, 2] = Label - Título de la columna mostrada en la tabla (String) aFields[n, 3] = Tipo del dato - Tipos aceptados actualmente: number, string, currency y link (String) aFields[n, 4] = Formato/máscara del dato (String) aFields[n, 5] = Indica si el campo podrá utilizarse en el filtro de los detalles (String 'false' o 'true') aFields[n, 6] = Indica si el campo será visible en la tabla (String 'false' o '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()))
CoreDash():SetPOCombo(aOptions)
Método responsable por devolver un Array de acuerdo con lo esperado en la propiedad p-options del componente Combo de la biblioteca de componentes PO-UI.
Nombre | Tipo | Descripción | Estándar | Obligatorio | Referencia |
---|---|---|---|---|---|
aOptions | Array | Array de dos dimensiones con las siguientes informaciones: aOptions[n, 1] = Valor (Value) aOptions[n, 2] = Rótulo (Label) | X |
Local oCoreDash := CoreDash():New() Local aOptions := {} aAdd(aOptions, {"phone" ,"Teléfono" }) aAdd(aOptions, {"cellPhone" ,"Celular" }) oCoreDash:SetPOCombo(aOptions)
CoreDash():SetPOForm(cDivider, cProperty, cGridColumns, cLabel, lRequired, cType, aOptions, loptionsMulti)
Método responsable por construir un Formulario utilizando como base el componente DynamicForm de la biblioteca de PO-UI.
Nombre | Tipo | Descripción | Estándar | Obligatorio | Referencia |
---|---|---|---|---|---|
cDivider | Carácter | Crea una división entre los campos, utilizando el nombre definido en la propiedad cDivider. | |||
cProperty | Carácter | Nombre de la propiedad. | |||
cGridColumns | Carácter | Número de columnas ocupado por el campo. | |||
cLabel | Carácter | Rótulo/Label del campo. | |||
lRequired | Lógico | Define si el campo es obligatorio. | |||
cType | Carácter | Tipo del campo. | |||
aOptions | Array | Lista de opciones del campo. | |||
loptionsMulti | Carácter | Define si el campo es 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 búsqueda" , .T., "string", oCoreDash:SetPOCombo({{"mensal","Mensal"},{"anual","Anual"}})) oCoreDash:SetPOForm("" , "datadereferencia", 6 , "Fecha de referencia" , .T., "date") oResponse := oCoreDash:GetPOForm() Self:SetResponse( EncodeUtf8(oResponse:ToJson()))
CoreDash():GetPOForm()
Método responsable por devolver el Formulario, construido por medio del 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 búsqueda" , .T., "string", oCoreDash:SetPOCombo({{"mensal","Mensal"},{"anual","Anual"}})) oCoreDash:SetPOForm("" , "datadereferencia", 6 , "Fecha de referencia" , .T., "date") oResponse := oCoreDash:GetPOForm() Self:SetResponse( EncodeUtf8(oResponse:ToJson()))
CoreDash():SetChartInfo(aDados, cLegenda, cTipo, cBgColor, lBackGround, lDrillDown)
Nombre | Tipo | Descripción | Estándar | Obligatorio | Referencia |
---|---|---|---|---|---|
aDados | Carácter | Array de Valores utilizados en el gráfico. | X | ||
cLegenda | Carácter | Leyenda Label de la serie del gráfico. | X | ||
cTipo | Carácter | Tipo de la serie en el gráfico. Ejemplos: bar, line | |||
cBgColor | Carácter | Color de la serie. | |||
lBackGround | Lógico | Define si el gráfico de líneas tendrá color de fondo. | .F. | ||
lDrillDown | Carácter | Define si la serie 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, "Promedio", "line", "rgba(255,240,210,0.0)", .F., .F.)
CoreDash():GetChartInfo()
Método responsable por devolver todos los gráficos incluidos por medio del método SetChartInfo.
Local aGraphic := {} Local oCoreDash := CoreDash():New() oCoreDash:SetChartInfo( aSaldo, "Promedio", "line", "rgba(23,132,175,0.59)", .F., .F.) aGraphic := oCoreDash:GetChartInfo()
CoreDash():SetChart( aLegenda, aDados, lCurrency, cType, cTitle, aMaskFrac ) Class CoreDash
Método responsable por devolver todas las informaciones de gráficos de Barra/Linha.
Nombre | Tipo | Descripción | Estándar | Obligatorio | Referencia |
---|---|---|---|---|---|
aLegenda | Array | Leyendas mostradas nen el Gráfico | X | ||
aDados | Array | Datos impresos en el Gráfico. Observación: Para gráficos del tipo barra/línea, puede utilizarse el propio GetChartInfo | |||
lCurrency | Lógico | Informa si la máscara devuelta será o no del tipo moneda | .F. | ||
cType | Carácter | Tipo de gráfico que será devuelto. | |||
cTitle | Carácter | Título mostrado en el gráfico. | |||
aMaskFrac | Array | Informa los formatos de máscara que pueden transferirse |
Atención
Para los gráficos del tipo Pizza y Polar no es posible realizar la máscara monetaria por medio de los parámetros lCurrency y 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,"Factura por Estado/Prov/Reg",aMask)
CoreDash():GetCposLGPD()
Método responsable por devolver array con los campos sensibles que deben tener exhibición restringida de acuerdo con el Usuario conectado.
Local oCoreDash := CoreDash():New() Local aCampos := {} Local aCposLGPD := {} Aadd(aCampos, {"code", "A1_CODIGO"}) Aadd(aCampos, {"name", "A1_NOME"}) oCoreDash:SetFields(aCampos) aCposLGPD := oCoreDash:GetCposLGPD()
CoreDash():GetColorChart()
Método responsable por devolver en un array todos los colores estandarizados para uso de gráficos DASH.
Si se transfiriera al método el ID del color, se devolverá solamente el color solicitado.
CoreDash():GetColorChart(X);
Donde X es el ID del color solicitado.
Parámetros:
Color (Variable) | Descripción del color | ID | Código RGBA | Situación Array | Ejemplo color |
---|---|---|---|---|---|
cGreenDk | Verde oscuro | 1 | rgba( 0,178,142, 1) | aArray[1][3] | |
cGreenLht | Verde claro | 2 | rgba( 0,201,161, 1) | aArray[2][3] | |
cRedDk | Rojo oscuro | 3 | rgba(198, 72, 64, 1) | aArray[3][3] | |
cRedLht | Rojo claro | 4 | rgba(227, 73, 64, 1) | aArray[4][3] | |
cYellDk | Amarillo oscuro | 5 | rgba(252,203, 76, 1) | aArray[5][3] | |
cYellLht | Amarillo claro | 6 | rgba(255,212,100, 1) | aArray[6][3] | |
cOrangeDk | Anaranjado oscuro | 7 | rgba(234,155, 62, 1) | aArray[7][3] | |
cOrangeLht | Anaranjado claro | 8 | rgba(255,162, 54, 1) | aArray[8][3] | |
cBlueDk | Azul oscuro | 9 | rgba( 0,120,255, 1) | aArray[9][3] | |
cBlueLht | Azul claro | 10 | rgba( 50,165,255, 1) | aArray[10][3] | |
cGreyDk | Gris oscuro | 11 | rgba(192,192,192, 1) | aArray[11][3] | |
cGreyLht | Gris claro | 12 | rgba(200,200,210, 1) | aArray[12][3] | |
cPurpleDk | Morado oscuro | 13 | rgba(128, 0,128, 1) | aArray[13][3] | |
cPurpleLht | Morado claro | 14 | rgba(185, 35,185, 1) | aArray[14][3] | |
cBrownDk | Marrón oscuro | 15 | rgba(128, 0, 0, 1) | aArray[15][3] | |
cBrownLht | Marrón claro | 16 | rgba(160, 80, 40, 1) | aArray[16][3] | |
cFuchsiaDk | Fucsia oscuro | 17 | rgba(255, 0,255, 1) | aArray[17][3] | |
cFuchsiaLht | Fucsia claro | 18 | rgba(255,120,255, 1) | aArray[18][3] | |
cMnightBlue | Azul media noche | 19 | rgba( 25, 25,112, 1) | aArray[19][3] | |
cMediumBlue | Azul medio | 20 | rgba( 0, 0,205, 1) | aArray[20][3] | |
cDGreen | Verde | 21 | rgba( 0,100, 0, 1) | aArray[21][3] | |
cFGreen | Verde selva | 22 | rgba( 34,139, 34, 1) | aArray[22][3] | |
cGreenYel | Verde limón | 23 | rgba(173,255, 47, 1) | aArray[23][3] | |
cSalmon | Salmón | 24 | rgba(250,128,114, 1) | aArray[24][3] | |
cTan | Rosado quemado | 25 | rgba(210,180,140, 1) | aArray[25][3] | |
cWheat | Rosado trigo | 26 | rgba(245,222,179, 1) | aArray[26][3] | |
cSlateGray | Gris pizarra | 27 | rgba(112,128,144, 1) | aArray[27][3] | |
cMistyRose | Rosa claro | 28 | rgba(255,228,225, 1) | aArray[28][3] |