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 (discountPercentage1–3) 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