Classes
Visão geral
A API de Classes permite manipular dois recursos: as classes do sistema e as entidades das classes do sistema. Entidade no contexto desta API são os registros de uma classe ou das suas filhas. Por exemplo, a classe “Usuários” possui a entidade “administrator”.
O acesso às entidades por meio desta API é limitado às classes que fazem parte do cache local. Essa
API tem um propósito similar ao processo Admin > Explorer
, servindo como uma API não especializada
para consulta e alteração de dados cadastrais do sistema. Deve ser dada preferência às APIs mais
especializadas e otimizadas para acesso aos dados de uma classe caso elas existam.
Importante: a API de Classes potencialmente pode manipular todos os dados das classes cadastrais do sistema, no entanto essa funcionalidade requer que as definições de classes sejam revistas para utilizar o novo formato de definição de classes por meio dos arquivos x-model e x-view em vez dos arquivos x-class. Apesar de algumas classes de sistema terem sido revistas, a maior parte das classes relacionadas ao modelo do ERP encontram-se pendentes de revisão, que ocorrerá de forma gradual e sob demanda dos projetos de desenvolvimento. Lembramos também que as APIs HTTP encontram-se em caráter experimental e devem ser utilizadas com orientação do fornecedor do sistema. Caso deseje implementar algum processo de integração que requer acesso aos dados do sistema, entre em contato com o suporte para avaliarmos as revisões das definições de classes necessárias para atender o objetivo da integração.
Limitações conhecidas da API
Relações mestre-detalhe
A API atual não permite o consumo de registros detalhes a partir da mestre de uma forma simples, em apenas uma requisição. No entanto, pode-se obter informações dos registros detalhe consultando diretamente as entidades da classe de dados detalhe, filtrando pelo registro mestre. Exemplo:
- Requisição para obter o registro mestre. No exemplo abaixo estão sendo obtidos os dados de um cliente cuja chave é a 11658484.
GET /api/classes/v1/entities/11658484 HTTP/1.1
Host: localhost:8080
Accept: application/json
Authorization: Basic XXXXXXXXXXXXXXXXXXXXXXXXXX
Cache-Control: no-cache
- Requisição para obter os registros detalhes. No exemplo abaixo, estão sendo obtidos os endereços do cliente 11658484. A chave -1897047822 é a classe de Endereços.
GET /api/classes/v1/classes/-1897047822/entities?entidade=11658484 HTTP/1.1
Host: localhost:8080
Accept: application/json
Authorization: Basic XXXXXXXXXXXXXXXXXXXXXXXXXX
Cache-Control: no-cache
Classes
O modelo de dados do sistema é definido por uma hierarquia de classes única, onde algumas dessas classes definem tabelas da base dados. Uma vez associada uma classe a uma tabela da base de dados, o sistema passa a controlar os seus registros como entidades da classe, por meio de um mapeamento objeto-relacional.
Classes que não definem tabelas não terão entidades associadas a ela, por mais que uma classe seja hierarquicamente superior a outra que defina. Portanto, na hierarquia a seguir, as classes “Dados” e “Sistema” não tem entidades, servindo apenas para fins de agrupamento e reuso de definições comuns a todas as classes filhas. As classes “Engine” e “Grupos, papéis e usuários” definem tabelas na base de dados e portanto têm entidades/registros associadas a elas.
|-- Dados (-1898146248)
|-- Sistema (-1898146243)
|-- Engines (-1898145089): define a tabela iHost
|-- Grupos, papéis e usuários (-1898187811): define a tabela iGroupUser
|-- Grupos e Papéis (-1898141934)
|-- Usuários (-1898187809)
Tentar consultar as entidades de uma classe que não define uma tabela irá gerar um erro. Atualmente esta API também é limitada às classes que definem tabelas que fazem parte do cache local, ou seja, as que são replicadas e disponíveis em cada Engine.
Nas APIs HTTP, as entidades de uma classe são representadas por objetos cujas propriedades são os campos da classe, normalizados em caixa baixa. Exemplo do usuário “administrator”:
{
"iclass": -1898187809,
"iname": "administrator",
"istatus": -1898143909,
"ilastpasswdchg": "2019-01-14",
"ibegin": null,
"ibeginhour": null,
"iend": null,
"iendhour": null,
"iinformedfields": null,
"ikey": -1898186559,
"iversion": 591841,
"igroups": [
-1898186568
],
"isecuritypolicy": null,
"ifullname": "Administrador do Sistema",
"iemailaddress": null,
"ilanguage": -1898187416,
"ismtpserver": null,
"ichangeablelicenses": null,
"iissuablelicenses": null,
"ihomeprocess": null,
"ishortcuts": null,
"inavtreevisibilitymode": null
}
Um aspecto importante que sistemas de terceiros devem considerar ao utilizar as APIs HTTP é que as classes de dados evoluem e não é incomum o surgimento de novos campos. Por razões práticas, as APIs HTTPs não tem a sua versão alterada a cada campo criado, portanto os sistemas devem ser lenientes com propriedades a mais que as esperadas, evitando que se tornem incompatíveis com as atualizações do sistema.
GET /api/classes/v1/classes/<classKey>/schema
Obtém o esquema de dados de uma classe, no formato application/schema+json.
Parâmetros:
- Caminho do ponto de acesso:
- classKey: a chave da classe
- Query string: nenhum
- Corpo da requisição: nenhum
Exemplo de consumo:
curl -X GET -i https://<your_domain>:<port>/api/classes/v1/classes/-1898187811/schema -u '<user>:<pass>'
Resultado:
HTTP/1.1 200 OK
Content-Type: application/schema+json
{
"title": "Esquema da classe de dados \/Dados\/Sistema\/Grupos, Papéis e Usuários (-1898187811)",
"type": "object",
"required": [
"iclass",
"ifullname",
"iname",
"ikey"
],
"properties": {
"ishortcuts": {
"items": { "type": "integer" },
"type": "array"
},
"iversion": { "type": "integer" },
"iissuablelicenses": { "type": "string" },
"ikey": { "type": "integer" },
"isecuritypolicy": { "type": "integer" },
"igroups": {
"items": { "type": "integer" },
"type": "array"
},
"ifullname": { "type": "string" },
"iinformedfields": { "type": "string" },
"inavtreevisibilitymode": {
"enum": [ 0, 1, 2 ]
},
"iclass": { "type": "integer" },
"iemailaddress": { "type": "string" },
"ismtpserver": { "type": "integer" },
"iproduct": { "type": "string" },
"ihomeprocess": { "type": "integer" },
"ilanguage": { "type": "integer" },
"iname": { "type": "string" },
"ichangeablelicenses": { "type": "string" },
}
}
GET /api/classes/v1/classes/<classKey>/entities
Lista todas as entidades de uma classe, incluindo as das classes filhas.
Um aspecto importante a ser considerado quando listadas as entidades de uma classe com filhas é que as entidades retornadas podem ter estruturas distintas, visto que as classes filhas podem definir campos adicionais.
Parâmetros:
- Caminho do ponto de acesso:
- classKey: a chave da classe
- Query string: quaisquer campos da entidade podem ser utilizados como filtro. Ex:
?ikey=<chave-do-registro>
- Corpo da requisição: nenhum
Exemplo de consumo:
curl -X GET -i https://<domain.com>:<port>/api/classes/v1/classes/-1898187811/entities?ikey=-1898186562 -u '<user>:<pass>'
Resultado:
HTTP/1.1 200 OK
Content-Type: application/json
[
{
"ilanguage": null,
"iclass": -1898187810,
"inavtreevisibilitymode": null,
"ishortcuts": [
32145359
],
"ihomeprocess": null,
"iissuablelicenses": null,
"ichangeablelicenses": null,
"ipassword": null,
"ismtpserver": null,
"iemailaddress": "user@company.com",
"igroups": null,
"isecuritypolicy": null,
"ifullname": "Administrador de papel",
"iname": "Administrador de papel",
"iversion": 17138993,
"ikey": -1898186562,
"iinformedfields": null
}
]
GET /api/classes/v1/classes/<classKey>/children
Obtém as chaves das classes imediatamente filhas da classe informada.
Toda classe possui um campo chamado MAE ao qual referencia uma classe da mesma tabela. Basicamente serão retornadas todas as classes que possuem esse campo preenchido com a chave da classe informada.
Este método difere do classes.getChildren()
ao retornar apenas as classes filhas em vez de toda
a hierarquia de classes inferior à informada.
Parâmetros:
- Caminho do ponto de acesso:
- classKey: chave da classe
- Query string: nenhum
- Corpo da requisição: nenhum
Exemplo de consumo:
curl -X GET -i https://<domain.com>:<port>/api/classes/v1/classes/-1898187811/children -u '<user>:<pass>'
Resultado:
HTTP/1.1 200 OK
Content-Type: application/json
[
-1898187809,
-1898141934
]
GET /api/classes/v1/classes/<classKey>/descendants
Retorna todas as classes filhas na hierarquia, ou seja, todas as classes descendentes que podem ser filhas, netas, bisnetas, etc. incluindo as últimas classes que não possuem classes descendentes.
Diferente do método classes.getChildren()
, a classe informada não será retornada no resultado.
Parâmetros:
- Caminho do ponto de acesso:
- classKey: a chave da classe
- Query string: nenhum
- Corpo da requisição: nenhum
Exemplo de consumo:
curl -X GET -i https://<domain.com>:<port>/api/classes/v1/classes/-1898187811/descendants -u '<user>:<pass>'
Resposta:
HTTP/1.1 200 OK
Content-Type: application/json
[
-1898187810,
-1898187809,
-1898142007,
-1898141934
]
GET /api/classes/v1/classes/<classKey>/entities/<id>
Retorna a entidade da classe classKey
de chave id
.
Parâmetros:
- Caminho do ponto de acesso:
- classKey: chave da classe
- id: identificador ou chave da entidade
- Query string: nenhum
- Corpo da requisição: nenhum
Exemplo de consumo:
curl -X POST -i https://<domain.com>:<port>/api/classes/v1/classes/-1898187809/entities/-1898186559 -u '<user>:<pass>'
Resposta
HTTP/1.1 200 OK
Content-Type: application/json
{
"iendhour": null,
"iend": null,
"ibeginhour": null,
"ibegin": null,
"ilastpasswdchg": "2010-11-23",
"istatus": -1898143909,
"iname": "administrator",
"iclass": -1898187809,
"inavtreevisibilitymode": null,
"ishortcuts": null,
"ihomeprocess": null,
"iissuablelicenses": null,
"ichangeablelicenses": null,
"ismtpserver": null,
"ilanguage": -1898187416,
"iemailaddress": null,
"igroups": [
-1898186568
],
"isecuritypolicy": null,
"ifullname": null,
"iversion": 5377062,
"ikey": -1898186559,
"iinformedfields": null
}
POST /api/classes/v1/classes/<classKey>/entities
Cria uma nova entidade com os dados informados na classe classKey
. Será retornada a entidade
criada com todos os seus campos.
Parâmetros:
- Caminho do ponto de acesso:
- classKey: chave da classe
- Query string: nenhum
- Corpo da requisição: JSON válido com os dados referente a uma entidade
Exemplo de consumo:
curl -X POST -i https://<domain.com>:<port>/api/classes/v1/classes/-1898187810/entities
-u '<user>:<pass>'
-d '[{
"iclass": -1898187810,
"iemailaddress": "web@group.com.br",
"ifullname": "Gerentes de Projeto",
}]'
Resposta:
HTTP/1.1 201 Created
Content-Type: application/json
{
"ilanguage": null,
"iclass": -1898187810,
"inavtreevisibilitymode": null,
"ishortcuts": [ ],
"ihomeprocess": null,
"iissuablelicenses": null,
"ichangeablelicenses": null,
"ismtpserver": null,
"iemailaddress": "web@group.com.br",
"igroups": null,
"isecuritypolicy": null,
"ifullname": "Gerentes de Projeto",
"iname": "Novos Gerentes",
"iversion": 17121493,
"ikey": 1231235123,
"iinformedfields": null
}
POST /api/classes/v1/classes/<classKey>/entities/<id>
PATCH /api/classes/v1/classes/<classKey>/entities/<id>
PUT /api/classes/v1/classes/<classKey>/entities/<id>
Atualiza a entidade identificada pela chave id
de classe classKey
.
O POST e o PATCH devem ser utilizados para atualizações parciais de uma entidade. Nem todos os clientes HTTP suportam o método PATCH e por esse motivo os serviços de atualização também são disponibilizados via POST.
O PUT deveria ser utilizado quando o intuito da atualização é substituir todos os campos da entidade pelos valores informados. Aqueles que não forem informados e estiverem preenchidos deveriam ser apagados. No entanto, esse comportamento esperado do PUT não é aderente à realidade do sistema. O esquema de dados é dinâmico e potencialmente pode ser alterado a cada versão do sistema. Também é permitida a definição de campos adicionais customizados. Em termos práticos, seria muito arriscado o PUT sobrepor os valores dos campos não relacionados e, para os fins dessa API, os três métodos são equivalentes.
Parâmetros:
- Caminho do ponto de acesso:
- classKey: chave da classe
- id: identificador ou chave da entidade
- Query string: nenhum
- Corpo da requisição: JSON válido com os dados referentes a uma entidade ou mais entidades
Exemplo de consumo:
curl -X PATCH -i https://<domain.com>:<port>/api/classes/v1/classes/-1898187810/entities/1231235123
-u '<user>:<pass>'
-d '[{
"ifullname": "Alterando o nome do Grupo de Gerentes de Projeto",
}]'
Resposta:
HTTP/1.1 200 OK
Content-Type: application/json
{
"ilanguage": null,
"iclass": -1898187810,
"inavtreevisibilitymode": null,
"ishortcuts": [ ],
"ihomeprocess": null,
"iissuablelicenses": null,
"ichangeablelicenses": null,
"ipassword": null,
"ismtpserver": null,
"iemailaddress": "web@group.com.br",
"igroups": null,
"isecuritypolicy": null,
"ifullname": "Alterando o nome do Grupo de Gerentes de Projeto",
"iname": "Novos Gerentes",
"iversion": 17121493,
"ikey": 1231235123,
"iinformedfields": null
}
DELETE /api/classes/v1/classes/<classKey>/entities/<id>
Exclui a entidade id
da base de dados.
Parâmetros:
- Caminho do ponto de acesso:
- classKey: chave da classe
- id: identificador ou chave da entidade
- Query string: nenhum
- Corpo da requisição: nenhum
Exemplo de consumo:
curl -X POST -i https://<domain.com>:<port>/api/classes/v1/classes/-1898187810/entities/1231235123
-u '<user>:<pass>'
Resposta:
HTTP/1.1 200 OK
Content-Type: application/json
Entidades
As entidades das classes também podem ser lidas ou alteradas por rotas alternativas, que não a associam a uma classe de dados. Isso é possível pelo fato das entidades terem identificadores únicos perante todas as tabelas e classes do sistema. Essas URLs alternativas são úteis por não sofrerem modificação quando uma entidade muda de classe, sendo recomendadas como URLs estáveis para referenciar uma entidade em outros sistemas.
GET /api/classes/v1/entities/<id>
Retorna a entidade identificada por id
.
Parâmetros:
- Caminho do ponto de acesso:
- id: identificador ou chave da entidade
- Query string: nenhum
- Corpo da requisição: nenhum
Exemplo de consumo:
curl -X POST -i https://<domain.com>:<port>/api/classes/v1/entities/-1898186559 -u '<user>:<pass>'
Resposta:
HTTP/1.1 200 OK
Content-Type: application/json
{
"iendhour": null,
"iend": null,
"ibeginhour": null,
"ibegin": null,
"ilastpasswdchg": "2010-11-23",
"istatus": -1898143909,
"iname": "administrator",
"iclass": -1898187809,
"inavtreevisibilitymode": null,
"ishortcuts": null,
"ihomeprocess": null,
"iissuablelicenses": null,
"ichangeablelicenses": null,
"ismtpserver": null,
"ilanguage": -1898187416,
"iemailaddress": null,
"igroups": [
-1898186568
],
"isecuritypolicy": null,
"ifullname": null,
"iversion": 5377062,
"ikey": -1898186559,
"iinformedfields": null
}
POST /api/classes/v1/entities/<id>
PATCH /api/classes/v1/entities/<id>
PUT /api/classes/v1/entities/<id>
Atualiza a entidade identificada por id
.
Parâmetros:
- Caminho do ponto de acesso:
- id: identificador ou chave da entidade
- Query string: nenhum
- Corpo da requisição: nenhum
Exemplo de consumo:
curl -X PATCH -i https://<domain.com>:<port>/api/classes/v1/entities/1231235123
-u '<user>:<pass>'
-d '[{
"ifullname": "Alterando o nome do Grupo de Gerentes de Projeto",
}]'
Resposta:
HTTP/1.1 200 OK
Content-Type: application/json
{
"ilanguage": null,
"iclass": -1898187810,
"inavtreevisibilitymode": null,
"ishortcuts": [ ],
"ihomeprocess": null,
"iissuablelicenses": null,
"ichangeablelicenses": null,
"ipassword": null,
"ismtpserver": null,
"iemailaddress": "web@group.com.br",
"igroups": null,
"isecuritypolicy": null,
"ifullname": "Alterando o nome do Grupo de Gerentes de Projeto",
"iname": "Novos Gerentes",
"iversion": 17121493,
"ikey": 1231235123,
"iinformedfields": null
}
DELETE /api/classes/v1/entities/<id>
Exclui a entidade id
do sistema.
Parâmetros:
- Caminho para o ponto de acesso:
- id: identificador ou chave da Entidade
- Query string: nenhum
- Corpo da requisição: nenhum
Exemplo de consumo:
curl -X POST -i https://<domain.com>:<port>/api/classes/v1/entities/1231235123 -u '<user>:<pass>'
Resposta:
HTTP/1.1 200 OK
Content-Type: application/json