Pular para o conteúdo principal

Guia de integração — Configuração de pontos

Microserviço: XDPeople.Soba.WebAPI (Core API)
Autenticação: token Bearer (JWT) e contexto de tenant — ver Login Combinado


Introdução

Este guia descreve a integração com a API para gerir configurações de pontos (regras de atribuição de pontos por documento ou por linha).

O campo criteriaType (PointsConfigCriteriaType) define qual critério aninhado deve estar preenchido no pedido:

ValorNomeObjeto no JSON
0HeaderdefaultHeaderCriteria (regra ao nível do cabeçalho do documento).
1DefaultDetailsWithItemSearchCriteriadefaultDetailsItemCriteria (detalhes com pesquisa por artigo).
2DefaultDetailsWithFamilySearchCriteriadefaultDetailsFamilyCriteria (detalhes com pesquisa por família).

Os outros dois objetos de critério devem ser null ou omitidos, de forma a que apenas o ramo correspondente a criteriaType esteja definido no corpo.


Endpoints disponíveis

Prefixo público: /gateway/points-config.

MétodoURLDescrição resumida
GET/gateway/points-configLista configurações com paginação opcional (page, pageSize); ver regras de paginação.
GET/gateway/points-config/{id}Obtém uma configuração por Guid.
GET/gateway/points-config/next-orderDevolve o próximo número de ordem sugerido para uma nova entrada.
POST/gateway/points-configCria uma configuração; resposta 201 Created com Guid no corpo.
PUT/gateway/points-configAtualiza uma configuração existente; o id vai no corpo (PointsConfigDTO.Id); resposta 204 No Content.
DELETE/gateway/points-config/{id}Elimina por Guid; resposta 204 No Content.

Listar configurações

URL: /gateway/points-configMétodo: GET

Ver mais →

Obter por identificador

URL: /gateway/points-config/{id}Método: GET

Ver mais →

Próxima ordem

URL: /gateway/points-config/next-orderMétodo: GET

Ver mais →

Criar

URL: /gateway/points-configMétodo: POST

Ver mais →

Atualizar

URL: /gateway/points-configMétodo: PUT (identificador no corpo, não na rota)

Ver mais →

Eliminar

URL: /gateway/points-config/{id}Método: DELETE

Ver mais →


Estrutura do corpo (PointsConfigDTO)

CampoTipoDescrição
idGuid?Obrigatório em atualização; omitido ou vazio em criação.
orderintOrdem de apresentação / prioridade (validação: ver secção de validações).
descriptionstringDescrição (obrigatória no modelo).
activeboolConfiguração ativa.
cumulativeboolPermitir acumular com outras atribuições.
allowDecimalPointsboolPermitir pontos decimais.
startDatedate-timeInício de vigência.
endDatedate-timeFim de vigência.
criteriaTypeint (enum)Tipo de critério (tabela acima).
defaultHeaderCriteriaobjeto?Critério de cabeçalho; ver abaixo.
defaultDetailsItemCriteriaobjeto?Critério detalhe artigo; ver abaixo.
defaultDetailsFamilyCriteriaobjeto?Critério detalhe família; ver abaixo.

Campos auxiliares de listagem (StartDateHolder, EndDateHolder, ActiveHolder, IsPreCompiled, etc.) podem existir no contrato gerado; para integração REST concentre-se nos campos acima e nos critérios aninhados.

Base comum aos critérios (BaseCriteriaDTO)

Presente em qualquer critério não nulo:

CampoTipoDescrição
totalPointsdecimalTotal de pontos (modelo; frequentemente 0 à criação).
pointsBasedecimalBase de pontos (validação numérica no DTO).
eachYdecimalDenominador “Y” quando a fórmula é X por Y; caso contrário tipicamente 0.
formulaBaseint (enum)0 = XTimes, 1 = XForY.

defaultHeaderCriteria (DefaultHeaderCriteriaDTO)

Inclui os campos de BaseCriteriaDTO mais:

CampoTipoDescrição
documentFieldint (enum)Campo do documento usado na base do cálculo (total documento, líquido, impostos, valor pago, etc.).

defaultDetailsItemCriteria / defaultDetailsFamilyCriteria

Estendem BaseCriteriaDTO com:

CampoTipoDescrição
detailFieldint (enum)Campo da linha de detalhe (quantidade, preços, totais, etc.).
searchTypeint (enum)0 = lista, 1 = individual.
searchPoolarrayConjunto de referências; cada elemento segue DefaultDetailsItemDTO (artigo) ou DefaultDetailsFamilyDTO (família), conforme o critério.

Elementos de searchPool

CritérioDTO do elementoPropriedades
defaultDetailsItemCriteriaDefaultDetailsItemDTOid, description, keyId
defaultDetailsFamilyCriteriaDefaultDetailsFamilyDTOid, description, idParent (ascendente na hierarquia de famílias)

O campo searchType no critério de detalhe indica o modo de pesquisa (0 = lista, 1 = individual). O serviço de persistência valida sobretudo que searchPool não está vazio quando o critério correspondente está presente; mantenha searchType coerente com a intenção de negócio e com os consumidores do modelo.

Enums (valores numéricos no JSON)

Valores esperados no corpo JSON.

PointsConfigCriteriaType (criteriaType): 0 Cabeçalho, 1 Detalhe artigo, 2 Detalhe família.

FormulaBaseEnum (formulaBase nos critérios): 0 XTimes, 1 XForY.

SearchTypeEnum (searchType nos critérios de detalhe): 0 Lista, 1 Individual.

DocumentFieldsEnum (documentField em defaultHeaderCriteria):

ValorSignificado
0Total do documento
1Total líquido
2Total de impostos
3Valor pago

DetailFieldsEnum (detailField em critérios de detalhe):

ValorSignificado
0Quantidade
1Preço com IVA
2Total da linha com IVA
3Preço sem IVA
4Total da linha sem IVA

Obrigatoriedade e consistência do payload

Por criteriaType e formulaBase

criteriaTypeCritério a enviarsearchPooldocumentField / detailField
0 (Header)defaultHeaderCriteria preenchido; outros critérios null / omitidos.Não aplicável.documentField obrigatório no objeto de critério.
1 (Detalhe artigo)defaultDetailsItemCriteria preenchido; outros null.Lista não vazia quando o critério não é null (validação servidor).detailField obrigatório no objeto.
2 (Detalhe família)defaultDetailsFamilyCriteria preenchido; outros null.Lista não vazia quando o critério não é null (validação servidor).detailField obrigatório no objeto.
formulaBaseRequisito adicional (servidor + modelo)
0 (XTimes)eachY pode ser 0; foco em pointsBase.
1 (XForY)eachY tem de ser estritamente maior que zero (eachY > 0) sempre que o critério aninhado existir e for validado; valores 0 ou negativos falham com PointsConfig.InvalidEachY (no servidor a condição é eachY <= 0).

criteriaType desconhecido ou não mapeado

Se criteriaType tiver um valor não presente no dicionário interno de validadores do serviço, ValidateCriteria não executa nenhum dos validadores por tipo e devolve sucesso nessa fase (apenas a verificação de datas continua a aplicar-se). Para integrações válidas, use sempre 0, 1 ou 2 conforme o enum PointsConfigCriteriaType.

Intervalo de datas

  • startDate não pode ser posterior a endDate. Caso contrário: PointsConfig.InvalidDateRange.

Critério null no servidor

Se o objeto de critério correspondente ao criteriaType for null, o ramo específico de validação (pool vazio, eachY por tipo) não é executado e devolve sucesso nesse trecho. Para dados consistentes, envie sempre o critério alinhado ao criteriaType com as regras acima.


Validações:

Criação e atualização

Aplicado antes de persistir. Na atualização, se o id não existir em ConfigList, a api devolve PointsConfig.NotFound após carregar as definições e antes de gravar.

RegraCódigo de erro
startDate > endDatePointsConfig.InvalidDateRange
Tipo Header, critério não nulo, formulaBase == XForY e eachY <= 0PointsConfig.InvalidEachY
Tipo Detalhe artigo, critério não nulo, searchPool sem elementosPointsConfig.InvalidItemSearchPool
Tipo Detalhe artigo, critério não nulo, XForY e eachY <= 0PointsConfig.InvalidEachY
Tipo Detalhe família, critério não nulo, searchPool sem elementosPointsConfig.InvalidFamilySearchPool
Tipo Detalhe família, critério não nulo, XForY e eachY <= 0PointsConfig.InvalidEachY

Outros resultados de erro

CódigoQuando ocorre (resumo)
PointsConfig.NotFoundGET/PUT/DELETE com identificador inexistente na lista guardada.
PointsConfigCreate.FailExceção ou falha inesperada na criação.
PointsConfigUpdate.FailExceção ou falha inesperada na atualização.
PointsConfigDelete.FailExceção ou falha inesperada na eliminação.
PointsConfigSave.FailIConfigProvider.UpdateAsync devolveu false ao gravar definições.
PointsGetAll.FailFalha ao listar (ex.: exceção em GetAllAsync).
PointsGetById.FailFalha ao obter por id (ex.: exceção).
PointsGetNextOrder.FailFalha ao calcular a próxima ordem.
CreateDefaultSettingsFail.FailFalha ao criar definições por omissão quando ainda não existem.
Config.NotFoundConstante no módulo de erros; associada a configurações em falta em cenários de configuração.

Validações de listagem (GET)

Em GetAllAsync, os parâmetros de consulta são normalizados em memória:

ParâmetroComportamento
pageSe omitido ou menor que 1, usa-se página 1.
pageSizeSe omitido ou menor ou igual a 0, usa-se 20; caso contrário aplica-se o valor pedido até ao máximo 100 (MaxPageSize).

Exemplos de corpo (POST / PUT)

URL: POST /gateway/points-config (criação) ou PUT /gateway/points-config (atualização com id no corpo).
Propriedades em camelCase. Os outros dois critérios devem ser null (como abaixo) ou omitidos.

Cabeçalho — fórmula X vezes (criteriaType: 0, formulaBase: 0)

{
"order": 1,
"description": "Um ponto por euro no total do documento",
"active": true,
"cumulative": true,
"allowDecimalPoints": false,
"startDate": "2026-01-01T00:00:00",
"endDate": "2026-12-31T23:59:59",
"criteriaType": 0,
"defaultHeaderCriteria": {
"totalPoints": 0,
"pointsBase": 1,
"eachY": 0,
"formulaBase": 0,
"documentField": 0
},
"defaultDetailsItemCriteria": null,
"defaultDetailsFamilyCriteria": null
}

documentField: 0 total do documento, 1 total líquido, 2 total impostos, 3 valor pago.

Cabeçalho — fórmula X por Y (criteriaType: 0, formulaBase: 1)

eachY tem de ser maior que zero; caso contrário o servidor devolve PointsConfig.InvalidEachY.

{
"order": 2,
"description": "10 pontos por cada 50 € de total líquido",
"active": true,
"cumulative": false,
"allowDecimalPoints": false,
"startDate": "2026-01-01T00:00:00",
"endDate": "2026-12-31T23:59:59",
"criteriaType": 0,
"defaultHeaderCriteria": {
"totalPoints": 0,
"pointsBase": 10,
"eachY": 50,
"formulaBase": 1,
"documentField": 1
},
"defaultDetailsItemCriteria": null,
"defaultDetailsFamilyCriteria": null
}

Detalhe por artigo (criteriaType: 1, defaultDetailsItemCriteria)

searchPool não pode estar vazio quando o critério está preenchido (PointsConfig.InvalidItemSearchPool). Cada elemento: id, description, keyId (identificador do artigo no sistema).

Lista (searchType: 0) — pontos aplicáveis às linhas cujo artigo pertença ao conjunto definido.

{
"order": 3,
"description": "Um ponto por unidade de quantidade em artigos seleccionados",
"active": true,
"cumulative": true,
"allowDecimalPoints": false,
"startDate": "2026-01-01T00:00:00",
"endDate": "2026-12-31T23:59:59",
"criteriaType": 1,
"defaultHeaderCriteria": null,
"defaultDetailsItemCriteria": {
"totalPoints": 0,
"pointsBase": 1,
"eachY": 0,
"formulaBase": 0,
"detailField": 0,
"searchType": 0,
"searchPool": [
{ "id": 101, "description": "Artigo A", "keyId": "ART-001" },
{ "id": 102, "description": "Artigo B", "keyId": "ART-002" }
]
},
"defaultDetailsFamilyCriteria": null
}

Pesquisa individual (searchType: 1) — mesma estrutura; searchPool costuma ter um único artigo quando a regra de negócio é “um artigo em concreto”.

{
"order": 4,
"description": "2 pontos por euro no total da linha (IVA) — artigo único",
"active": true,
"cumulative": false,
"allowDecimalPoints": false,
"startDate": "2026-01-01T00:00:00",
"endDate": "2026-12-31T23:59:59",
"criteriaType": 1,
"defaultHeaderCriteria": null,
"defaultDetailsItemCriteria": {
"totalPoints": 0,
"pointsBase": 2,
"eachY": 0,
"formulaBase": 0,
"detailField": 2,
"searchType": 1,
"searchPool": [
{ "id": 200, "description": "Artigo premium", "keyId": "PREM-01" }
]
},
"defaultDetailsFamilyCriteria": null
}

Detalhe artigo com X por YformulaBase: 1 e eachY > 0.

{
"order": 5,
"description": "1 ponto por cada 5 € de preço com IVA nas linhas dos artigos listados",
"active": true,
"cumulative": true,
"allowDecimalPoints": false,
"startDate": "2026-01-01T00:00:00",
"endDate": "2026-12-31T23:59:59",
"criteriaType": 1,
"defaultHeaderCriteria": null,
"defaultDetailsItemCriteria": {
"totalPoints": 0,
"pointsBase": 1,
"eachY": 5,
"formulaBase": 1,
"detailField": 1,
"searchType": 0,
"searchPool": [
{ "id": 301, "description": "Refrigerante cola 33cl", "keyId": "BEB-001" }
]
},
"defaultDetailsFamilyCriteria": null
}

Detalhe por família (criteriaType: 2, defaultDetailsFamilyCriteria)

searchPool não pode estar vazio (PointsConfig.InvalidFamilySearchPool). Cada elemento: id, description, idParent (ascendente na hierarquia de famílias).

{
"order": 6,
"description": "Pontos por quantidade em linhas de famílias seleccionadas",
"active": true,
"cumulative": true,
"allowDecimalPoints": false,
"startDate": "2026-01-01T00:00:00",
"endDate": "2026-12-31T23:59:59",
"criteriaType": 2,
"defaultHeaderCriteria": null,
"defaultDetailsItemCriteria": null,
"defaultDetailsFamilyCriteria": {
"totalPoints": 0,
"pointsBase": 1,
"eachY": 0,
"formulaBase": 0,
"detailField": 0,
"searchType": 0,
"searchPool": [
{ "id": 10, "description": "Mercearia", "idParent": 0 },
{ "id": 11, "description": "Bebidas", "idParent": 10 }
]
}
}

Família com X por Y sobre total da linha sem IVA (detailField: 4):

{
"order": 7,
"description": "3 pontos por cada 2 € de total de linha sem IVA (famílias listadas)",
"active": true,
"cumulative": false,
"allowDecimalPoints": false,
"startDate": "2026-01-01T00:00:00",
"endDate": "2026-12-31T23:59:59",
"criteriaType": 2,
"defaultHeaderCriteria": null,
"defaultDetailsItemCriteria": null,
"defaultDetailsFamilyCriteria": {
"totalPoints": 0,
"pointsBase": 3,
"eachY": 2,
"formulaBase": 1,
"detailField": 4,
"searchType": 0,
"searchPool": [
{ "id": 20, "description": "Campânula promocional", "idParent": 0 }
]
}
}

Substitua id, keyId, idParent e descrições por valores válidos no vosso tenant.


Notas de integração

  • Use GET /gateway/points-config/next-order para preencher order em novas configurações.
  • Em atualização, envie id com o mesmo Guid que identifica o registo.
  • Mantenha um critério aninhado coerente com criteriaType; evite enviar os três objetos preenchidos se o produto espera exclusividade.
  • Recomenda-se order >= 1, em linha com [Range] em PointsConfigDTO e com o valor sugerido por GET .../next-order.

Conclusão

A gestão de configurações de pontos expõe CRUD sobre /gateway/points-config com validações dependentes de criteriaType, de formulaBase e do intervalo de datas. Teste em staging combinações de cabeçalho vs detalhe, lista vs conjunto mínimo em searchPool, e fórmulas XTimes vs XForY antes de produção.

Recursos relacionados


Última atualização: 14 de Maio de 2026