Pular para o conteúdo principal

Guia de integração — Tabela de preços

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


Introdução

Este guia descreve como integrar com a API para gerir linhas de preços (tabelas de preços) no ecossistema SOBA. Uma linha de preços é composta por um cabeçalho (PriceTableDTO) e por linhas (PriceTableItemDTO), cada uma associada a um artigo (Item) ou a uma família de artigos (ItemGroup).

O modelo distingue dois tipos de tabela no campo priceTableType:

ValorNome (enum)Significado
0AbsolutePreços explícitos por artigo; pode incluir linhas do tipo família (ItemGroup) conforme o modelo; a API exige pelo menos uma linha em items.
1RelativeVariação em relação a uma linha absoluta de referência (absolutePriceLineId); regras adicionais aplicam-se na gravação.

Cada linha em items usa itemType:

ValorNome (enum)Significado
0ItemArtigo individual (itemKeyId = chave do artigo).
1ItemGroupFamília de artigos (itemKeyId tipicamente o identificador da família como texto).

O objetivo é apoiar integradores na utilização correta dos endpoints, na construção do corpo JSON e na antecipação de validações e erros devolvidos pelo servidor.


Regras de negócio e limites

As regras abaixo são aplicadas no serviço de aplicação antes de persistir dados. Incumprir uma delas devolve erro com o código indicado (formato típico da API — ver documentação de erros HTTP).

RegraDetalheCódigo de erro (exemplo)
Tabela relativaSe priceTableType é Relative (1), absolutePriceLineId não pode ser inválido (valor estritamente inferior a 0).PriceTableValidation.InvalidAbsolutePriceLine
Tabela absolutaSe priceTableType é Absolute (0), a lista items tem de existir e conter pelo menos um elemento.PriceTableValidation.AbsolutePriceLineRequiredItems
Intervalo de datasstartDate não pode ser posterior a endDate.PriceTableValidation.InvalidDateInterval
Identificadores 0–5Reservados no produto (preço de custo e linhas de preço 1 a 5). Para novas linhas configuráveis pelo integrador, prefira o identificador devolvido por GET /gateway/price-table/next-id (≥ 6).ver GET /gateway/price-table/next-id

Recomenda-se obter o próximo identificador com GET /gateway/price-table/next-id antes de criar uma nova linha, para evitar colisões e respeitar o mínimo configurado no servidor.


Obrigatoriedade e consistência do payload por priceTableType

O valor de priceTableType altera as validações do servidor e o conjunto de campos que devem estar coerentes no JSON.

Tabela absoluta (priceTableType = 0)

AspetoO que garantir
Obrigatório (API)items tem de existir e ter pelo menos um elemento. Caso contrário: PriceTableValidation.AbsolutePriceLineRequiredItems.
ConsistênciaPreencher discountPercentage1, discountPercentage2, discountPercentage3 no cabeçalho quando o modelo de negócio aplicar descontos globais; replicar ou complementar por linha em items conforme necessário.
ConsistênciaAlinhar isTaxIncludedPrice no cabeçalho com o critério de preço nas linhas: se o preço principal for com IVA, use taxIncludedPrice e isTaxIncludedPrice: true nas entradas relevantes; caso contrário privilegie netPrice e isTaxIncludedPrice: false.
DatasstartDate não pode ser posterior a endDate (validação comum a ambos os tipos).

Tabela relativa (priceTableType = 1)

AspetoO que garantir
Obrigatório (API)absolutePriceLineId não pode ser inferior a 0. Caso contrário: PriceTableValidation.InvalidAbsolutePriceLine. Na prática deve identificar uma linha de preços absoluta existente e válida no vosso contexto (referência para o cálculo relativo).
ConsistênciaDefinir percentageReference de acordo com o ajuste percentual global pretendido (valor e sinal conforme a vossa convenção de aumento ou desconto). O DTO expõe apenas percentageReference; não envie propriedades que não existam no contrato.
ConsistênciaEm items, cada artigo ou família (itemType) deve incluir os descontos em percentagem (discountPercentage13) e restantes campos exigidos pelo fluxo de preço relativo que implementam. Sem linhas, confirme no vosso analista de negócio se uma tabela relativa sem items é admitida no produto — a validação CanSave atual não exige linhas para o tipo relativo.
DatasMesma regra que na tabela absoluta (startDate / endDate).

Campos comuns aos dois tipos

id, description, startDate, endDate e priceTableType devem estar sempre definidos de forma válida no pedido. Os restantes campos do PriceTableDTO permanecem no contrato; valores por omissão (por exemplo 0) só são aceitáveis se forem semanticamente corretos para o caso de uso.


Endpoints disponíveis

Todos os caminhos abaixo assumem o prefixo público /gateway/price-table (Core API através do gateway).

MétodoURLDescrição resumida
GET/gateway/price-tableLista linhas de preços com paginação opcional.
GET/gateway/price-table/next-idDevolve o próximo identificador sugerido (mínimo 6).
GET/gateway/price-table/{id}Obtém uma linha por identificador, incluindo items.
POST/gateway/price-tableCria uma nova linha de preços. Resposta 201 Created em caso de sucesso.
PUT/gateway/price-table/{id}Atualiza a linha indicada. Resposta 204 No Content em caso de sucesso.
DELETE/gateway/price-table/{id}Elimina a linha indicada. Resposta 204 No Content em caso de sucesso.

Listar linhas de preços

URL: /gateway/price-table

Método: GET

Parâmetros de consulta (opcionais):

ParâmetroTipoDescrição
pageintNúmero da página (base 1), quando aplicável.
pageSizeintTamanho da página.

Comportamento: devolve uma listagem paginada das tabelas de preços.

Ver mais →


Obter o próximo identificador

URL: /gateway/price-table/next-id

Método: GET

Comportamento: devolve um inteiro com o próximo ID sugerido, não inferior a 6, para novas linhas de preços personalizadas.

Ver mais →


Obter uma linha por identificador

URL: /gateway/price-table/{id}

Método: GET

Parâmetro de rota:

ParâmetroTipoObrigatórioDescrição
idintSimIdentificador da linha de preços.

Comportamento: devolve PriceTableDTO com a coleção items preenchida quando existir.

Ver mais →


Criar linha de preços

URL: /gateway/price-table

Método: POST

Corpo: JSON no modelo PriceTableDTO (ver tabelas de campos abaixo).

Comportamento em sucesso: 201 Created (sem corpo de resposta no controlador atual).

Ver mais →


Atualizar linha de preços

URL: /gateway/price-table/{id}

Método: PUT

Parâmetros: id na rota; corpo PriceTableDTO.

Comportamento em sucesso: 204 No Content.

Ver mais →


Eliminar linha de preços

URL: /gateway/price-table/{id}

Método: DELETE

Comportamento em sucesso: 204 No Content.

Ver mais →


Estrutura do corpo (PriceTableDTO)

Campos mais relevantes para integração (outros campos de sincronização ou nuvem podem ser omitidos ou nulos consoante o caso de uso). As regras por tipo de tabela estão em Obrigatoriedade e consistência do payload por tipo.

CampoTipoObrigatório (API / validação)Descrição
idintSim na práticaIdentificador da linha.
descriptionstringSim (máx. 20 caracteres)Descrição curta.
priceTableTypeint (enum)Sim0 Absoluta, 1 Relativa.
startDatedate-timeSimInício de vigência.
endDatedate-timeSimFim de vigência (não pode ser anterior a startDate).
absolutePriceLineIdintCondiçãoObrigatório coerente para tipo relativa (referência a linha absoluta; na validação do servidor não pode ser negativo).
percentageReferencedecimalNãoReferência percentual global (sinal pode indicar aumento ou desconto consoante convenção do cliente).
discountPercentage1decimalNãoDesconto 1 (%).
discountPercentage2decimalNãoDesconto 2 (%).
discountPercentage3decimalNãoDesconto 3 (%).
isTaxIncludedPriceboolNãoSe os preços nas linhas são tratados com IVA incluído.
inactiveboolNãoLinha inativa.
itemsarrayCondiçãoObrigatório ter elementos para tipo absoluta.

Estrutura de cada linha (PriceTableItemDTO)

CampoTipoDescrição
priceLineIdintIdentificador da linha de preço no contexto da tabela.
itemKeyIdstringChave do artigo ou identificador usado para família, conforme itemType.
itemAttributeCodestringCódigo de atributo do artigo, quando aplicável.
itemTypeint0 Artigo, 1 Família.
descriptionstringDescrição apresentável.
percentageReferencedecimalReferência percentual ao nível da linha.
discountPercentage1decimalDesconto 1 (%).
discountPercentage2decimalDesconto 2 (%).
discountPercentage3decimalDesconto 3 (%).
netPricedecimalPreço líquido.
taxIncludedPricedecimalPreço com imposto incluído.
isTaxIncludedPriceboolSe o preço da linha inclui imposto.
itemPriceLineIdint?Linha de preço de referência por artigo (quando usado no produto).

Exemplo de pedido de criação (tabela absoluta)

Corpo JSON ilustrativo (valores de exemplo):

{
"id": 14,
"description": "Linha 14",
"startDate": "2026-05-13T10:15:58.222Z",
"endDate": "2026-05-14T10:15:58.222Z",
"priceTableType": 0,
"absolutePriceLineId": 0,
"percentageReference": 0,
"discountPercentage1": 1,
"discountPercentage2": 0,
"discountPercentage3": 0,
"isTaxIncludedPrice": true,
"inactive": false,
"items": [
{
"priceLineId": 14,
"itemKeyId": "1",
"itemAttributeCode": "",
"itemType": 0,
"description": "Dom Diogo (Arinto)",
"percentageReference": 0,
"discountPercentage1": 1,
"discountPercentage2": 0,
"discountPercentage3": 0,
"netPrice": 0,
"taxIncludedPrice": 0,
"isTaxIncludedPrice": true,
"itemPriceLineId": null
}
]
}

Exemplo de pedido de criação (tabela relativa)

{
"id": 15,
"description": "Linha 15",
"startDate": "2026-05-13T10:15:58.222Z",
"endDate": "2026-05-14T10:15:58.222Z",
"priceTableType": 1,
"absolutePriceLineId": 1,
"percentageReference": 10,
"discountPercentage1": 0,
"discountPercentage2": 0,
"discountPercentage3": 0,
"isTaxIncludedPrice": false,
"inactive": false,
"items": [
{
"priceLineId": 15,
"itemKeyId": "3",
"itemAttributeCode": "",
"itemType": 1,
"description": "Carnes",
"percentageReference": 0,
"discountPercentage1": 0,
"discountPercentage2": 0,
"discountPercentage3": 0,
"netPrice": 0,
"taxIncludedPrice": 0,
"isTaxIncludedPrice": false,
"itemPriceLineId": null
}
]
}

Notas sobre o payload (apenas API)

  • O integrador deve enviar JSON conforme PriceTableDTO e PriceTableItemDTO. As validações descritas neste guia aplicam-se a qualquer sistema cliente da API.
  • A secção Obrigatoriedade e consistência por tipo resume o que o integrador deve enviar ou alinhar por priceTableType, além das validações genéricas abaixo.
  • Em tabela relativa (priceTableType = 1), preencha absolutePriceLineId de forma coerente com a linha absoluta de referência (a API rejeita referência inválida segundo as regras do servidor).
  • Em tabela absoluta (priceTableType = 0), a lista items tem de ter pelo menos uma entrada.
  • Os campos discountPercentage1, discountPercentage2, discountPercentage3 e percentageReference existem no contrato no cabeçalho e nas linhas; podem ser utilizados consoante o vosso modelo de preços, desde que o conjunto respeite as validações do servidor.
  • Carga em massa: não há recurso dedicado para importação de ficheiros; construam items no vosso sistema e utilizem POST ou PUT.

Erros frequentes

CódigoTipo típicoSignificado e ação sugerida
PriceTable.NotFound404Identificador inexistente em consulta, atualização ou eliminação.
PriceTableCreate.Fail409 / falhaA persistência da criação falhou; rever dados e repetir; contactar suporte se persistir.
PriceTableUpdate.Fail409 / falhaA atualização falhou no armazenamento.
PriceTableDelete.Fail409 / falhaA eliminação falhou no armazenamento.
PriceTableValidation.InvalidAbsolutePriceLine400Tabela relativa com referência absoluta inválida (absolutePriceLineId negativo).
PriceTableValidation.AbsolutePriceLineRequiredItems400Tabela absoluta sem linhas em items.
PriceTableValidation.InvalidDateInterval400startDate posterior a endDate.

As respostas de erro seguem o padrão HTTP da API (Problem Details / HttpResponseError conforme versão). Valide sempre o código HTTP e o payload de erros.


Conclusão

A gestão de linhas de preços via Core API resume-se a operações CRUD sobre /gateway/price-table, com validações claras para tipos absoluto e relativo e para o intervalo de datas. Recomenda-se testar em ambiente de staging todos os cenários (criação com next-id, atualização parcial de items, tabelas relativas com referência válida e erros de validação) antes de produção.

Recursos relacionados


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