Bom dia, Criem um objeto de negocio para um relatorio no smart view, porem ao executar apresenta o erro abaixo:
connectors.native.failde-to-deserialize-O conteudo retornado pelo ERP TOTVS não condiz com o padrão esperado
Status:badRequest,System.Net.Http.Connection+ContentLegthReadStream
Como corrigir esse erro?
Segue o fonte abaixo:
#include “protheus.ch”
#include “msobject.ch”
#include “totvs.framework.treports.integratedprovider.th”
//*******************************************************************
//NameSpace;
//*******************************************************************
namespace custom.Interjornada.integratedprovider
//*******************************************************************
//Annotation;
//*******************************************************************
@totvsFrameworkTReportsIntegratedProvider(active=.T., team=“SIGAPON”, tables =“SPH”, name=“Interjornada”, country=“ALL”, initialRelease=“12.1.2410”)
//-------------------------------------------------------------------
/*{Protheus.doc} ProdTReportsBusinessObject
Classe (Objeto de Negócio) - Produtos para o TReports
@author Allax Souza
@since 23/10/2025
@version 1.0
*/
//-------------------------------------------------------------------
class IntTReportsBusinessObject from totvs.framework.treports.integratedprovider.IntegratedProvider
//*******************************************************************
//Assinatura de métodos públicos;
//*******************************************************************
public method new() as object
public method getData() as object
public method getSchema() as object
//*******************************************************************
//Assinatura de propriedades encapsuladas;
//*******************************************************************
protected data aFields as array
protected data aStruct as array
endclass
//-------------------------------------------------------------------
/*{Protheus.doc} new
Método construtor da classe
@author Allax Souza
@since 23/10/2025
@return object: self
@version 1.0
*/
//-------------------------------------------------------------------
method new() class IntTReportsBusinessObject
_Super:new()
self:appendArea(“Ponto Eletrônico”)
self:setDisplayName(“Interjornada”)
self:setDescription(“Relatório de Interjornada”)
self:aFields := {“PH_FILIAL”,“PH_CC”,“PH_MAT”,“RA_NOME”,“PH_DATE”,“PH_PD”,“P9_DESC”,“PH_QUANTIC”}
self:aStruct := getStruct(self:aFields)
//*******************************************************************
//Combobox
//*******************************************************************
//self:setIsCBoxLookup(.T.,.F.)
//*******************************************************************
//ele vai puxar os dados do schema com o Lookup
//*******************************************************************
//self:setIsLookup(.T.)
return self
//-------------------------------------------------------------------
/*{Protheus.doc} getData
Método para retorno dos dados para o objeto de negócio
@author Allax Souza
@since 23/10/2025
@param nPage, numérico, indica a página atual do relatório
@param oFilter, objeto, contém o filtro do TReports
@return object: self:oData
@version 1.0
*/
//-------------------------------------------------------------------
method getData(nPage as numeric, oFilter as object) as object class IntTReportsBusinessObject
local cQuery as character
local cAlias as character
local nSkip as numeric
local nCount as numeric
local nX as numeric
local jItems as json
local aPDFields as array
local lUseParams as logical
nCount := 0
cQuery := " SELECT " + CRLF
cQuery += " PH_FILIAL, " + CRLF
cQuery += " PH_CC, " + CRLF
cQuery += " PH_MAT, " + CRLF
cQuery += " RA_NOME, " + CRLF
cQuery += " PH_DATA, " + CRLF
cQuery += " PH_PD, " + CRLF
cQuery += " P9_DESC, " + CRLF
cQuery += " PH_QUANTC " + CRLF
cQuery += " FROM " + RetSQLName(“SPH”) + " AS SPH " + CRLF
cQuery += " INNER JOIN " + RetSQLName(“SRA”)+ " AS SRA " + CRLF
cQuery += " ON(SPH.D_E_L_E_T_=SRA.D_E_L_E_T_ AND SPH.PH_FILIAL=SRA.RA_FILIAL AND SPH.PH_MAT=SRA.RA_MAT) " + CRLF
cQuery += " INNER JOIN "+ RetSQLName(“SP9”)+ " AS SP9 " + CRLF
cQuery += " ON(SPH.D_E_L_E_T_=SP9.D_E_L_E_T_ AND SPH.PH_FILIAL=SP9.P9_FILIAL AND SPH.PH_PD=SP9.P9_CODIGO) " + CRLF
cQuery += " WHERE PH_PD IN(‘207’,‘219’) " + CRLF
cQuery += " ORDER BY FILIAL,MATRICULA " + CRLF
lUseParams := .T.
//Os filtros serão setados na interface do novo TReports
if oFilter:hasFilter()
cQuery += " AND " + oFilter:getSQLExpression()
endif
jParams := oFilter:getParameters() //metodo para retorno do json dos parâmetros
if ValType(jParams[“01”]) <> “A” .and. ValType(jParams[“02”]) <> “A” .and. ValType(jParams[“03”]) <> “A” .and. ValType(jParams[“04”]) <> “A”
lUseParams := .F.
endif
if lUseParams .and. !empty(jParams[“01”][1]) .and. !empty(jParams[“02”][1]).and. !empty(jParams[“03”][1]) .and. !empty(jParams[“04”][1])
cQuery += "AND PH_FILIAL BETWEEN " + jParams[‘01’][1] + " AND " + jParams[‘02’][1]
cQuery += "AND PH_DATA BETWEEN " + jParams[‘03’][1] + " AND " + jParams[‘04’][1]
endif
cAlias := MPSysOpenQuery(cQuery)
if nPage == 1
(cAlias)->(dbGoTop())
else
//Encontra a quantidade de itens que irá pular de acordo com a página atual
nSkip := ((nPage - 1) * self:getPageSize())
(cAlias)->(dbSkip(nSkip))
endif
//Verifica se precisa fazer o tratamento para LGPD
aPDFields := FwProtectedDataUtil():UsrAccessPDField(__cUserID, self:aFields)
lObfuscated := len( aPDFields ) != Len(self:aFields)
while !(cAlias)->(Eof())
jItems := JsonObject():new()
for nX := 1 To Len(self:aStruct)
if lObfuscated .and. aScan(aPDFields, self:aStruct[nX][5]) == 0
jItems[self:aStruct[nX][1]] := FwProtectedDataUtil():ValueAsteriskToAnonymize((cAlias)->&(self:aStruct[nX][5]))
else
jItems[self:aStruct[nX][1]] := (cAlias)->&(self:aStruct[nX][5])
endif
next nX
self:oData:appendData(jItems)
(cAlias)->(DBSkip())
nCount++
//Sai do loop quando chegar no tamanho de itens da página
if nCount == self:getPageSize()
exit
endif
enddo
//Se não for o último registro indica que terá próxima página
self:setHasNext(!(cAlias)->(Eof()))
(cAlias)->(DBCloseArea())
return self:oData
//-------------------------------------------------------------------
/*{Protheus.doc} getSchema
Retorna a estrutura dos campos
@return object: self:oSchema
@author Allax Souza
@since 23/10/2025
@version 1.0
*/
//-------------------------------------------------------------------
method getSchema() as object class IntTReportsBusinessObject
Local nX as numeric
for nX := 1 To Len(self:aStruct)
self:addProperty(self:aStruct[nX][1], self:aStruct[nX][2], self:aStruct[nX][3], self:aStruct[nX][4], self:aStruct[nX][5])
Next nX
self:addParameter(“01”, “Filial de” , “string”, .F.)
self:addParameter(“02”, “Filial até”, “string”, .F.)
self:addParameter(“03”, “Data de” , “date”, .F.)
self:addParameter(“04”, “Data até”, “date”, .F.)
//Consulta dos parâmetros
self:setCustomURL(“01”, “api/framework/v1/genericLookupService/smartview/SPH”, 2)
self:setCustomURL(“02”, “api/framework/v1/genericLookupService/smartview/SPH”, 2)
return self:oSchema
//-------------------------------------------------------------------
/*{Protheus.doc} getStruct
Prepara a estrutura dos campos
@param aFlds array: Array com os campos do relatório
@return array: Array com a estrutura dos campos
@author Allax Souza
@since 23/10/2025
@version 1.0
*/
//-------------------------------------------------------------------
Static function getStruct(aFlds)
Local aConvFld as array
Local aFldTmp as array
Local cCampo as character
Local cFldQry as character
Local cTipR as character
Local nPos as numeric
Local nC as numeric
aConvFld := {{“C”, “string”}, {“D”, “date”}, {“N”, “number”}, {“L”, “boolean”}, {“M”, “memo”}}
aFldTmp := {}
for nC := 1 to Len(aFlds)
cFldQry := aFlds[nC]
nPos := AT(“.”, aFlds[nC]) + 1
if nPos > 0
cCampo := Substr(cFldQry, nPos)
else
cCampo := cFldQry
endif
cTipo := GetSx3Cache(cCampo, "X3_TIPO")
if (nPos := aScan(aConvFld, {|c| c[01] = cTipo})) > 0
cTipR := aConvFld[nPos, 02]
else
cTipR := "string"
endif
AAdd(aFldTmp, {cCampo, FWSX3Util():GetDescription(cCampo), cTipR, FwX3Titulo(Upper(cCampo)), cCampo})
next nC
return (aFldTmp)