Contábil: Regras de Análise

Endpoints da WebApiAlcance para regras de análise (regra_analise) aplicadas sobre os balancetes importados do Domínio. Cada regra tem um tipo fixo que determina o formato esperado de params (conta virada, saldo negativo, soma de contas, limite de valor, fórmula, ou comparação com guias fiscais). Uma regra pode ser global (id_cliente nulo, aplicada a todos os clientes) ou de um cliente específico - na avaliação, as regras de cliente sempre se somam às globais.

Todos os endpoints exigem autenticação. Veja Autenticação para o fluxo de API Key. O Swagger oficial está em api.contabilidadealcance.com.br/docs.

Base path

/api/v1/regra-analise

Escopos necessários

  • regra_analise:read - listagem e busca por ID
  • regra_analise:write - criação, teste (dry-run), atualização e exclusão

O escopo é derivado do prefixo público da rota: /regra-analise vira o recurso regra_analise (hífen → underscore), e o método HTTP define a ação (read para GET, write para POST/PATCH/DELETE).

Envelope de resposta

{
  "status": "success",
  "message": "Mensagem em PT-BR",
  "data": {}
}

DELETE /regra-analise/{regra_id} responde 204 No Content, sem corpo.

Dois formatos de erro

Erros de regra de negócio (registro não encontrado, params/formula incompatíveis com o tipo da regra já persistida) respondem { "message": "<mensagem>" } no status HTTP correspondente. Já a validação do corpo de POST /regra-analise/ e de POST /regra-analise/testar (shape de params por tipo, sintaxe da formula) roda dentro do schema Pydantic e, quando falha, segue o formato padrão do FastAPI: { "detail": [...] }, sempre 422.

Endpoints

POST /regra-analise/

Cria uma regra global (id_cliente omitido ou null) ou de um cliente (id_cliente informado). O formato de params é validado de acordo com tipo - ver Parâmetros por tipo. Para tipo="formula", a sintaxe da fórmula também é validada (ast.parse) já na criação.

Parâmetros

Sem parâmetros de rota ou query - o corpo é um RegraAnaliseCreate.

Request

{
  "id_cliente": null,
  "tipo": "soma_total",
  "nome": "Soma do Ativo Circulante confere com o total do grupo 1",
  "params": {
    "contas": ["1.1.01", "1.1.02", "1.1.03"],
    "conta_total": "1.1",
    "tolerancia_cents": 100
  },
  "gravidade": "erro",
  "ativo": true
}

Response 201 Created

{
  "status": "success",
  "message": "Regra criada com sucesso",
  "data": {
    "id": 58,
    "id_usuario_created": 7,
    "id_cliente": null,
    "tipo": "soma_total",
    "nome": "Soma do Ativo Circulante confere com o total do grupo 1",
    "params": {
      "contas": ["1.1.01", "1.1.02", "1.1.03"],
      "conta_total": "1.1",
      "tolerancia_cents": 100
    },
    "formula": null,
    "gravidade": "erro",
    "ativo": true,
    "data_hora_criacao": "2026-08-10T09:00:00-03:00"
  }
}

Escopo: regra_analise:write

GET /regra-analise/

Lista regras globais + do cliente. Sem id_cliente, retorna apenas as regras globais; com id_cliente, retorna as globais e as daquele cliente.

Parâmetros de query

ParâmetroTipoObrigatórioObservações
id_clienteintnão> 0. Quando omitido, lista só as regras globais.

Request

GET /api/v1/regra-analise/?id_cliente=1234

Response 200 OK

{
  "status": "success",
  "message": "Regras recuperadas com sucesso",
  "data": [
    {
      "id": 58,
      "id_usuario_created": 7,
      "id_cliente": null,
      "tipo": "soma_total",
      "nome": "Soma do Ativo Circulante confere com o total do grupo 1",
      "params": {
        "contas": ["1.1.01", "1.1.02", "1.1.03"],
        "conta_total": "1.1",
        "tolerancia_cents": 100
      },
      "formula": null,
      "gravidade": "erro",
      "ativo": true,
      "data_hora_criacao": "2026-08-10T09:00:00-03:00"
    }
  ]
}

Lista vazia retorna 200 OK com data: [] e a mensagem "Nenhuma regra encontrada.".

Escopo: regra_analise:read

POST /regra-analise/testar

Executa um dry-run: avalia uma regra ad-hoc (não precisa existir no banco) contra os dados de um balancete já importado, sem persistir nada. Útil para validar uma regra antes de salvá-la.

Parâmetros

Sem parâmetros de rota ou query - o corpo é um TestarRegraRequest com regra (RegraAnaliseCreate) e id_balancete. Quando regra usa um tipo que lê guias fiscais (guia_vs_conta, guia_presente, guia_consistencia ou formula com guia(...)), as guias do mesmo cliente e período do balancete entram na avaliação.

Request

{
  "id_balancete": 771,
  "regra": {
    "id_cliente": 1234,
    "tipo": "guia_vs_conta",
    "nome": "DAS bate com a conta de tributos a pagar",
    "params": {
      "tipo_guia": "DAS",
      "componente": "principal",
      "operador": "=",
      "alvo": "conta",
      "codigos": ["2.1.05.001"],
      "tolerancia_cents": 100
    },
    "gravidade": "alerta"
  }
}

Response 200 OK

{
  "status": "success",
  "message": "Teste executado",
  "data": {
    "id_regra": 0,
    "nome": "DAS bate com a conta de tributos a pagar",
    "tipo": "guia_vs_conta",
    "gravidade": "alerta",
    "origem": "cliente",
    "status": "passou",
    "evidencia": "DAS/principal 1.245,00 = conta 1.245,00 (Δ 0,00)",
    "ocorrencias": []
  }
}

id_regra sempre vem 0 (regra rascunho, nunca persistida). origem é "cliente" quando id_cliente foi informado no corpo, senão "global". id_balancete inexistente retorna 404 com { "message": "Balancete nao encontrado." }.

Escopo: regra_analise:write

GET /regra-analise/{regra_id}

Busca uma regra pelo ID.

Parâmetros

ParâmetroTipoLocalObrigatórioDescrição
regra_idintrotasimID da regra.

Response 200 OK

{
  "status": "success",
  "message": "Regra encontrada",
  "data": {
    "id": 58,
    "id_usuario_created": 7,
    "id_cliente": null,
    "tipo": "soma_total",
    "nome": "Soma do Ativo Circulante confere com o total do grupo 1",
    "params": {
      "contas": ["1.1.01", "1.1.02", "1.1.03"],
      "conta_total": "1.1",
      "tolerancia_cents": 100
    },
    "formula": null,
    "gravidade": "erro",
    "ativo": true,
    "data_hora_criacao": "2026-08-10T09:00:00-03:00"
  }
}

ID inexistente retorna 404 com { "message": "Regra de analise nao encontrada." }.

Escopo: regra_analise:read

PATCH /regra-analise/{regra_id}

Atualiza campos mutáveis. tipo e id_cliente são imutáveis - ausentes do schema de atualização.

Parâmetros

regra_id na rota; corpo em RegraAnaliseUpdate.

params/formula revalidados contra o tipo já persistido

Se params ou formula forem enviados, são revalidados na borda contra o tipo já gravado da regra (a mesma checagem da criação). Enviar um params incompatível com o tipo responde 422 com { "message": "<motivo>" }, e não grava a alteração.

Request

{
  "params": {
    "contas": ["1.1.01", "1.1.02", "1.1.03", "1.1.04"],
    "conta_total": "1.1",
    "tolerancia_cents": 200
  },
  "ativo": false
}

Response 200 OK

{
  "status": "success",
  "message": "Regra atualizada",
  "data": {
    "id": 58,
    "id_usuario_created": 7,
    "id_cliente": null,
    "tipo": "soma_total",
    "nome": "Soma do Ativo Circulante confere com o total do grupo 1",
    "params": {
      "contas": ["1.1.01", "1.1.02", "1.1.03", "1.1.04"],
      "conta_total": "1.1",
      "tolerancia_cents": 200
    },
    "formula": null,
    "gravidade": "erro",
    "ativo": false,
    "data_hora_criacao": "2026-08-10T09:00:00-03:00"
  }
}

ID inexistente retorna 404 com { "message": "Regra de analise nao encontrada." }.

Escopo: regra_analise:write

DELETE /regra-analise/{regra_id}

Remove uma regra.

Parâmetros

ParâmetroTipoLocalObrigatórioDescrição
regra_idintrotasimID da regra.

Response 204 No Content

Sem corpo de resposta. ID inexistente retorna 404 com { "message": "Regra de analise nao encontrada." }.

Escopo: regra_analise:write

Parâmetros por tipo

O campo params (dict) tem um formato diferente para cada tipo, validado na criação e (quando enviado) na atualização:

tipoparams obrigatóriosparams opcionaisO que avalia
conta_viradaalvo ("grupo" | "conta"); grupo (1-4, se alvo="grupo") ou codigos (lista de classificações, se alvo="conta")natureza_esperada ("D" | "C")Linhas cuja natureza do saldo diverge da esperada pelo grupo contábil (1/3 = devedora, 2/4 = credora), ou da natureza_esperada informada.
saldo_negativoalvo ("grupo" | "conta") + grupo/codigos conforme alvo-Linhas com saldo bruto negativo (sinal cru: +devedor / -credor) dentro do escopo. Escopar por alvo é necessário - contas credoras (grupos 2 e 4) são negativas por construção.
soma_totalcontas (lista de classificações), conta_total (classificação)tolerancia_cents (default 0)Se a soma das contas bate com o saldo de conta_total.
limite_valorlimite_cents (int)base ("saldo_atual" default, "debito", "credito"), alvo/grupo/codigosLinhas cujo valor da base ultrapassa limite_cents.
formulaformula no nível da regra (mini-linguagem, não em params)-Expressão aritmética/comparação - ver Fórmula.
guia_vs_contatipo_guia, componente, alvo + grupo/codigos conforme alvooperador ("=" default, "<=", ">="), tolerancia_centsSoma de um componente de guia fiscal do tipo_guia no período vs. saldo das contas do escopo.
guia_presentetipo_guia-Passa se existir ao menos uma guia daquele tipo_guia no período do balancete/cliente.
guia_consistenciatipo_guiatolerancia_centsSe a soma dos componentes de cada guia do tipo_guia bate com o valor_total dela.

Fórmula

Para tipo="formula", o campo formula (string, até 2000 caracteres) aceita uma mini-linguagem restrita, validada por allow-list de nós (sem execução de código arbitrário):

  • Aritmética: +, -, *, / e parênteses.
  • Comparação (resultado booleano): ==, !=, <, <=, >, >=.
  • conta("codigo") - saldo atual (em reais) da classificação informada; 0.0 se ausente no balancete.
  • guia("tipo", "componente") - soma (em reais) do componente daquela guia fiscal no período; 0.0 se ausente.

Exemplo: conta("1.1.01") + conta("1.1.02") >= guia("DAS", "principal"). Sintaxe fora do permitido responde 422 com { "message": "Fórmula com sintaxe inválida." } (na criação) ou é rejeitada pelo schema ({ "detail": [...] }, quando a validação ocorre na borda do corpo).

Schemas

RegraAnaliseCreate

Corpo de POST /regra-analise/ e do campo regra em POST /regra-analise/testar.

CampoTipoObrigatórioObservações
id_clienteint | nullnãonull = regra global. Default null.
tipo"conta_virada" | "saldo_negativo" | "soma_total" | "limite_valor" | "formula" | "guia_vs_conta" | "guia_presente" | "guia_consistencia"simDefine o formato de params - ver tabela acima.
nomestr (1-200)simNome descritivo da regra.
paramsdictnãoFormato depende de tipo. Default {}.
formulastr (≤ 2000)condicionalObrigatória quando tipo="formula".
gravidade"erro" | "alerta"nãoDefault "erro".
ativoboolnãoDefault true.

RegraAnaliseUpdate

Corpo de PATCH /regra-analise/{regra_id}. Todos os campos são opcionais; apenas os enviados são atualizados. tipo, id_cliente, id e data_hora_criacao não fazem parte deste schema.

CampoTipoObservações
nomestr (1-200)Novo nome.
paramsdictRevalidado contra o tipo já persistido (ver Callout acima).
formulastr (≤ 2000)Revalidada contra o tipo já persistido.
gravidade"erro" | "alerta"-
ativoboolAtiva/inativa a regra.

RegraAnaliseRead

data de POST, GET /{regra_id}, GET / (itens da lista) e PATCH.

CampoTipoNotas
idintID da regra.
id_usuario_createdintUsuário que criou a regra.
id_clienteint | nullnull = regra global.
tipostrVer valores em RegraAnaliseCreate.
nomestrNome descritivo.
paramsdictFormato depende de tipo.
formulastr | nullPreenchido só quando tipo="formula".
gravidadestrerro | alerta.
ativoboolSe a regra é avaliada.
data_hora_criacaodatetimeLocalizado em America/Sao_Paulo.

ValidacaoResultado

data de POST /regra-analise/testar (resultado único, não uma lista).

CampoTipoNotas
id_regraintSempre 0 para regra ad-hoc (não persistida).
nomestr-
tipostr-
gravidadestrerro | alerta.
origem"global" | "cliente""cliente" quando id_cliente veio preenchido no corpo.
status"passou" | "falhou"Resultado da avaliação.
evidenciastrTexto legível com os valores comparados.
ocorrenciasList[Ocorrencia]Vazio quando status="passou".

Ocorrencia

Item de ocorrencias[] em ValidacaoResultado.

CampoTipoNotas
classificacaostrCódigo da conta envolvida (ou marcador como "(guia)").
descricaostrDescrição da conta ou do componente.
valor_centsintValor/diferença envolvida, em centavos.
detalhestrExplicação legível da ocorrência.

Notas

  • Ordem de rotas (FastAPI): POST /regra-analise/testar (path estático) é declarada antes de GET/PATCH/DELETE /regra-analise/{regra_id} (path dinâmico), para o match ocorrer na ordem correta.
  • Regras globais (id_cliente=null) valem para todos os clientes; na avaliação de um cliente, elas sempre se somam às regras específicas dele.
  • POST /regra-analise/testar não persiste nada - nem a regra testada, nem o resultado.
  • DELETE retorna 204 No Content, sem corpo.