Pular para o conteúdo principal

Guia de Modelos de Avenças

Rota: /gateway/covenants-agreement

Autenticação: token Bearer (JWT) e contexto de tenant — ver Login Combinado

Visão Geral

Os Modelos de Avenças são templates de faturação recorrente pré-configurados. Definem tudo o que é necessário para gerar automaticamente documentos periódicos para Entidades — desde o tipo de documento e série de faturação até aos artigos/serviços, regras de preços e periodicidade.

Após a criação de um template, este pode ser associado a uma ou mais Entidades, cada uma com a sua data de início, data de fim e modo de pagamento. O sistema utiliza estas associações para gerar automaticamente faturas ou outros documentos nos intervalos configurados.

Quando Usar

  • ✅ Contratos mensais ou anuais de assistência técnica (ex.: contratos de suporte informático)
  • ✅ Acordos de manutenção recorrente
  • ✅ Faturação por subscrição de software ou hardware
  • ✅ Faturação periódica a preço fixo com artigos pré-definidos
  • ✅ Atribuição em massa do mesmo modelo de contrato a múltiplas Entidades

Características do Modelo

PropriedadeTipoDescrição
idstring (GUID)Identificador único — gerado pelo servidor, devolvido nas respostas GET
namestringNome do template (ex.: "Suporte Mensal TI")
descriptionstringDescrição detalhada
documentTypeintTipo de documento a gerar (ex.: Fatura)
documentSerieintSérie de documento a utilizar
documentTypeToConvertintTipo de documento de conversão/finalização
periodicityTypeintUnidade de periodicidade: 1=Diário, 2=Semanal, 3=Mensal, 4=Anual
periodicityValueintValor do intervalo de periodicidade — ver regras de validação
isGlobalboolSe true, aplica-se a todas as Entidades
priceTypeint?Tipo de tabela de preços a aplicar
withTaxbool?Se os preços incluem IVA
descriptionInDocumentboolIncluir a descrição do modelo no documento gerado
ignoreCustomerDiscountbool?Ignorar o desconto existente do cliente
itemsarrayLinhas de artigos incluídas na avença

Propriedades das Linhas de Artigos

PropriedadeTipoDescrição
referencestring (int)ID numérico do artigo/serviço, enviado como string (ex.: "42"). Deve existir no sistema.
descriptionstringDescrição da linha
quantitydecimalQuantidade (mín.: 1)
unitPricedecimalPreço unitário (mín.: 0)
discountdecimal?Desconto (opcional, mín.: 0)
netPricedecimalPreço líquido após desconto (mín.: 0)
taxIncludedPricedecimalPreço com IVA (mín.: 0)
itemAttributeCodestring?Código de atributo do artigo (opcional)
nota

O campo reference corresponde ao ID numérico do artigo registado no sistema. Apesar de o tipo ser string, o valor deve ser sempre um número inteiro (ex.: "1", "42", "150").


Criar Modelo de Avença

POST /gateway/covenants-agreement
Content-Type: application/json
Authorization: Bearer {token}

Exemplo Básico — Mensal

{
"name": "Suporte Mensal TI",
"description": "Contrato mensal de suporte e manutenção informática",
"documentType": 5,
"documentSerie": 1,
"documentTypeToConvert": 5,
"periodicityType": 3,
"periodicityValue": 1,
"isGlobal": false,
"priceType": 1,
"withTax": false,
"descriptionInDocument": true,
"ignoreCustomerDiscount": false,
"items": [
{
"reference": "1",
"description": "Serviço de Suporte Informático Mensal",
"quantity": 1,
"unitPrice": 150.00,
"discount": null,
"netPrice": 150.00,
"taxIncludedPrice": 184.50,
"itemAttributeCode": null
}
]
}

Resposta: 200 OK — devolve o GUID gerado para a avença criada.

"3fa85f64-5717-4562-b3fc-2c963f66afa6"

Exemplo com Múltiplos Artigos e Desconto — Anual

{
"name": "Pacote de Manutenção Anual TI",
"description": "Pacote anual de manutenção de hardware e software",
"documentType": 5,
"documentSerie": 2,
"documentTypeToConvert": 5,
"periodicityType": 4,
"periodicityValue": 1,
"isGlobal": false,
"priceType": 1,
"withTax": false,
"descriptionInDocument": true,
"ignoreCustomerDiscount": true,
"items": [
{
"reference": "2",
"description": "Manutenção de Hardware",
"quantity": 1,
"unitPrice": 500.00,
"discount": 10.00,
"netPrice": 450.00,
"taxIncludedPrice": 553.50,
"itemAttributeCode": null
},
{
"reference": "3",
"description": "Manutenção de Software e Licenciamento",
"quantity": 1,
"unitPrice": 300.00,
"discount": null,
"netPrice": 300.00,
"taxIncludedPrice": 369.00,
"itemAttributeCode": null
}
]
}

Exemplo de Avença Global — Mensal

{
"name": "Suporte Standard — Todas as Entidades",
"description": "Taxa de suporte standard aplicável a todas as Entidades",
"documentType": 5,
"documentSerie": 1,
"documentTypeToConvert": 5,
"periodicityType": 3,
"periodicityValue": 1,
"isGlobal": true,
"withTax": false,
"descriptionInDocument": false,
"ignoreCustomerDiscount": false,
"items": [
{
"reference": "1",
"description": "Taxa Mensal de Suporte Standard",
"quantity": 1,
"unitPrice": 50.00,
"discount": null,
"netPrice": 50.00,
"taxIncludedPrice": 61.50
}
]
}

Obter Modelo de Avença

Por ID

GET /gateway/covenants-agreement/{id}
Authorization: Bearer {token}
GET /gateway/covenants-agreement/3fa85f64-5717-4562-b3fc-2c963f66afa6

Resposta 200 OK:

{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "Suporte Mensal TI",
"description": "Contrato mensal de suporte e manutenção informática",
"documentType": 5,
"documentSerie": 1,
"documentTypeToConvert": 5,
"periodicityType": 3,
"periodicityValue": 1,
"isGlobal": false,
"priceType": 1,
"withTax": false,
"descriptionInDocument": true,
"ignoreCustomerDiscount": false,
"items": [...]
}

Exemplo de resposta com artigos expandidos:

{
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"name": "Pacote de Manutenção Anual TI",
"description": "Pacote anual de manutenção de hardware e software",
"documentType": 5,
"documentSerie": 2,
"documentTypeToConvert": 5,
"periodicityType": 4,
"periodicityValue": 1,
"isGlobal": false,
"priceType": 1,
"withTax": false,
"descriptionInDocument": true,
"ignoreCustomerDiscount": true,
"items": [
{
"reference": "2",
"description": "Manutenção de Hardware",
"quantity": 1,
"unitPrice": 500.00,
"discount": 10.00,
"netPrice": 450.00,
"taxIncludedPrice": 553.50,
"itemAttributeCode": null,
"lineOrder": 1
},
{
"reference": "3",
"description": "Manutenção de Software e Licenciamento",
"quantity": 1,
"unitPrice": 300.00,
"discount": null,
"netPrice": 300.00,
"taxIncludedPrice": 369.00,
"itemAttributeCode": null,
"lineOrder": 2
}
]
}
info

lineOrder representa a ordem de apresentação de cada artigo no documento gerado. É atribuído automaticamente pelo servidor com base na posição de cada artigo no array items — o primeiro artigo recebe lineOrder = 1, o segundo lineOrder = 2, e assim sucessivamente.


Listar Modelos de Avenças

GET /gateway/covenants-agreement
Authorization: Bearer {token}

Com Paginação

GET /gateway/covenants-agreement?page=1&pageSize=20
Authorization: Bearer {token}

Resposta 200 OK:

{
"totalCount": 12,
"pageSize": 20,
"currentPage": 1,
"totalPages": 1,
"data": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "Suporte Mensal TI",
"description": "Contrato mensal de suporte e manutenção informática",
"documentType": 5,
"documentTypeDescription": "Fatura",
"documentSerie": 1,
"documentSerieDescription": "FT 2026",
"documentTypeToConvert": 5,
"documentTypeToConvertDescription": "Fatura",
"periodicityType": 3,
"periodicityValue": 1,
"isGlobal": false,
"priceType": 1,
"withTax": false,
"descriptionInDocument": true,
"ignoreCustomerDiscount": false
}
]
}

Atualizar Modelo de Avença

PUT /gateway/covenants-agreement/{id}
Content-Type: application/json
Authorization: Bearer {token}
PUT /gateway/covenants-agreement/3fa85f64-5717-4562-b3fc-2c963f66afa6
Substituição completa de artigos

O array items substitui todos os artigos existentes da avença. Envie a lista completa desejada — qualquer artigo omitido será eliminado.

{
"name": "Suporte Mensal TI — Atualizado",
"description": "Contrato mensal de suporte informático atualizado",
"documentType": 5,
"documentSerie": 1,
"documentTypeToConvert": 5,
"periodicityType": 3,
"periodicityValue": 1,
"isGlobal": false,
"priceType": 1,
"withTax": false,
"descriptionInDocument": true,
"ignoreCustomerDiscount": false,
"items": [
{
"reference": "1",
"description": "Serviço de Suporte Informático Mensal",
"quantity": 1,
"unitPrice": 175.00,
"discount": null,
"netPrice": 175.00,
"taxIncludedPrice": 215.25,
"itemAttributeCode": null
}
]
}

Resposta: 204 No Content


Eliminar Modelo de Avença

DELETE /gateway/covenants-agreement/{id}
Authorization: Bearer {token}
DELETE /gateway/covenants-agreement/3fa85f64-5717-4562-b3fc-2c963f66afa6

Resposta: 204 No Content

Cuidado

A eliminação é permanente. Certifique-se de que a avença não tem associações ativas a Entidades antes de eliminar.


Gestão de Entidades Associadas

Após criar um modelo de avença, é necessário associá-lo às Entidades a que se aplica.

Listar Entidades Associadas

Obtém todas as Entidades atualmente associadas a um modelo de avença.

GET /gateway/covenants-agreement/{covenantId}/entities
Authorization: Bearer {token}
GET /gateway/covenants-agreement/3fa85f64-5717-4562-b3fc-2c963f66afa6/entities

Resposta 200 OK:

{
"hasAssignedEntities": true,
"assignedEntities": [
{
"entityKeyId": "1",
"entityName": "Acme Tecnologias, Lda"
},
{
"entityKeyId": "2",
"entityName": "TechVision Solutions"
}
]
}

Associar a Entidades

Associa um modelo de avença a um ou múltiplas Entidades de uma só vez.

POST /gateway/covenants-agreement/{covenantId}/assign-entities
Content-Type: application/json
Authorization: Bearer {token}
POST /gateway/covenants-agreement/3fa85f64-5717-4562-b3fc-2c963f66afa6/assign-entities
{
"entityKeyIds": ["1", "2", "3"],
"assignment": {
"initialDate": "2026-01-01T00:00:00",
"finalDate": "2026-12-31T00:00:00",
"nextDate": "2026-02-01T00:00:00",
"paymentMode": 1
}
}

Resposta 200 OK:

{
"totalSuccess": 2,
"totalFailed": 1,
"logLines": [
{
"entityKeyId": "1",
"entityName": "Acme Tecnologias, Lda",
"status": "Success",
"errorMessage": null
},
{
"entityKeyId": "2",
"entityName": "TechVision Solutions",
"status": "Success",
"errorMessage": null
},
{
"entityKeyId": "3",
"entityName": "Cliente Desconhecido",
"status": "Failed",
"errorMessage": "Entity not found."
}
]
}
Associação em Massa

O endpoint assign-entities processa todas as Entidades e devolve um log detalhado de sucessos e falhas. Mesmo que algumas associações falhem, as bem-sucedidas são confirmadas.


Ciclo de Vida

  1. Criar: Definir o template com tipo de documento, série, artigos e periodicidade
  2. Associar: Ligar o template a uma ou mais Entidades com datas de vigência
  3. Executar: O sistema gera automaticamente documentos em cada nextDate
  4. Avançar: nextDate avança pelo periodicityValue após cada geração
  5. Terminar: A faturação cessa quando finalDate é atingida (ou a associação é removida)

Validações Importantes

Campos Obrigatórios (Criar)

  • name — Nome do template (máx. 150 caracteres)
  • description — Descrição (máx. 250 caracteres)
  • documentType — ID de tipo de documento válido (> 0)
  • periodicityType — Unidade de periodicidade. Valores permitidos: 1 (Diário), 2 (Semanal), 3 (Mensal), 4 (Anual)
  • periodicityValue — Valor do intervalo — ver regras abaixo
  • items — Pelo menos uma linha de artigo
O campo id

No Criar, não envie o id — é gerado pelo servidor e devolvido na resposta.
No Atualizar, o id vai no path do URL (PUT /gateway/covenants-agreement/{id}), não no corpo do pedido.

Regras do PeriodicityValue

O significado de periodicityValue depende do periodicityType:

periodicityTypeSignificadoRegra do periodicityValue
1 — DiárioDias da semana para emissãoBitmask de dias úteis, intervalo 1–127 (Dom=1, Seg=2, Ter=4, Qua=8, Qui=16, Sex=32, Sáb=64)
2 — SemanalNúmero de semanas entre emissõesQualquer inteiro ≥ 1
3 — MensalNúmero de meses entre emissõesQualquer inteiro ≥ 1
4 — AnualNúmero de anos entre emissõesQualquer inteiro ≥ 1

Exemplos de bitmask para Diário:

DiasCálculoperiodicityValue
Segunda a Sexta2+4+8+16+3262
Apenas Segunda22
Todos os dias1+2+4+8+16+32+64127
Sábado e Domingo1+6465

Validações de Artigos

  • reference — Obrigatório, deve existir no sistema
  • description — Obrigatório (máx. 250 caracteres)
  • quantity — Mínimo 1
  • unitPrice, netPrice, taxIncludedPrice — Não podem ser negativos
  • discount — Não pode ser negativo (opcional)

Validações de Associação

  • paymentMode — Obrigatório, não pode ser 0
  • initialDate — Obrigatório, deve ser uma data válida
  • nextDate — Deve estar entre initialDate e finalDate
  • finalDate — Se fornecida, deve ser >= initialDate
Regra de Datas

nextDate deve estar dentro do intervalo [initialDate, finalDate]. Se finalDate for nulo, a associação funciona indefinidamente.

Respostas de Erro

Código HTTPCódigo de ErroSignificado
400CovenantAgreement.PeriodicityValueInvalidForDailyperiodicityValue não é um bitmask de dias válido (1–127) para o tipo Diário
400CovenantAgreement.ItemReferenceNotFoundUma ou mais referências de artigos não existem no sistema
400CovenantAgreement.PaymentModeRequiredpaymentMode é 0 ou não fornecido na associação
400CovenantAgreement.InvalidDateRangeIntervalo de datas inválido na associação
400CovenantAgreement.AssignmentOptionsInvalidOpções de associação inválidas
404CovenantsAgreement.NotFoundID da avença não encontrado
500CovenantAgreement.AssignmentDatabaseErrorErro de base de dados durante a associação

Boas Práticas

✅ Recomendado

  • Omitir o campo id no Criar — é gerado pelo servidor e devolvido na resposta
  • Definir sempre finalDate para contratos com prazo determinado
  • Verificar se o documentType e documentSerie estão ativos antes de criar
  • Usar os logLines da resposta de associação para detetar e rever falhas
  • Definir descriptionInDocument: true nos contratos em que o cliente deve ver a descrição da avença
  • No Atualizar, enviar a lista completa de artigos desejada — os artigos omitidos do array serão eliminados

❌ Evitar

  • Enviar o campo id no corpo do pedido de Criar (é ignorado e atribuído pelo servidor)
  • Definir paymentMode como 0 nas associações (bloqueado pela validação)
  • Definir nextDate fora do intervalo [initialDate, finalDate]
  • Eliminar uma avença que tem associações ativas
  • Definir periodicityValue como 0 ou negativo
  • Para o tipo Diário (periodicityType=1), usar periodicityValue fora do intervalo 1–127

Casos de Uso Comuns

Suporte Informático Mensal a Preço Fixo

Mensalidade fixa para horas de suporte ilimitadas.

{
"periodicityType": 3,
"periodicityValue": 1,
"items": [{ "reference": "1", "unitPrice": 200.00, ... }]
}

Contrato de Manutenção Anual

Documento anual único gerado uma vez por ano.

{
"periodicityType": 4,
"periodicityValue": 1,
"items": [{ "reference": "2", "unitPrice": 1200.00, ... }]
}

Faturação Trimestral para Múltiplas Entidades

Associar o mesmo template trimestral (a cada 3 meses) a um conjunto de Entidades.

{
"periodicityType": 3,
"periodicityValue": 3
}

Associação em massa:

{
"entityKeyIds": ["1", "2", "10", "11"],
"assignment": {
"initialDate": "2026-01-01T00:00:00",
"nextDate": "2026-04-01T00:00:00",
"paymentMode": 2
}
}

Emissão Diária — Segunda a Sexta

Emitir um documento em cada dia útil usando o bitmask de dias da semana.
Seg(2) + Ter(4) + Qua(8) + Qui(16) + Sex(32) = 62

{
"periodicityType": 1,
"periodicityValue": 62,
"items": [{ "reference": "5", "unitPrice": 10.00, ... }]
}

Integração com Outros Módulos

Documentos Gerados

O modelo de avença gera documentos de acordo com documentType e documentTypeToConvert. Estes seguem as mesmas regras que os documentos criados manualmente na Invoice API.

Contratos de Assistência

Os modelos de avenças funcionam em conjunto com o módulo de contratos do SAT. Um contrato pode referenciar um modelo de avença como o veículo de faturação para os serviços definidos no contrato.


Próximos Passos


Última actualização: 2 de junho de 2026