Files
Investidor-V2/docs/investmoz/simulations/data-contracts.md
T

104 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Contratos de dados do simulador
Estado: contrato tecnico interno. A API de conversão da Etapa 9 acrescenta metadados de execução ao snapshot económico cifrado existente. A migration `2026_10_02_120000` apenas ajusta RLS para suportar tombstones; não cria colunas nem altera snapshots armazenados.
## Princípios
- `personal_snapshot` contém identificação, contactos e atributos do promotor; `economic_snapshot` contém cenário, localização, actividade e valores do projecto. Os campos existentes mantêm-se como estão até uma migração de contrato deliberada.
- Montantes e taxas atravessam limites de API como strings decimais. O valor `"0"` é um valor conhecido, nunca um marcador de ausência. Não se deve converter dinheiro para `number` binário para calcular.
- Campo ausente ou `null` significa não fornecido. Uma lista vazia significa conhecida e vazia. “Não aplicável” e “indeterminado” são estados explícitos de um resultado, não valores numéricos.
- Moeda acompanha cada montante. Não se somam moedas diferentes sem taxa de câmbio, data, fonte e método aprovados.
- `referenceDate`, versão do motor, versão do conjunto de regras e cenário identificam a base temporal e reprodutível do resultado.
- Os campos actuais `investor_origin` e `tax_residency_country` não representam nacionalidade, residência migratória nem residência cambial. O contrato actual não infere esses contextos e ainda não os recolhe. Uma futura extensão deve armazenar cada declaração em campo próprio, com estado “não sei” distinto de um país.
- A moeda de cálculo e a moeda de apresentação são distintas. No plano financeiro, a conversão exploratória exige uma taxa na direcção `moeda de apresentação por 1 unidade da moeda de cálculo`, data efectiva e referência/fonte declaradas pelo utilizador. A interface e o CSV identificam-na como pressuposto não verificado; não é uma taxa oficial, fiscal, aduaneira ou contratual. Sem esses dados, os valores permanecem apenas na moeda de cálculo, que continua preservada no snapshot.
- Os formulários de oportunidade/investidor e o catálogo mantêm o montante na moeda de origem. O catálogo filtra/ordena por moeda e não converte montantes entre moedas; não precisa de taxa cambial para essa operação. Valores de várias moedas só podem ser somados depois de conversão com taxa, data, fonte e método apropriados.
- A taxa de câmbio aduaneira/fiscal não é fornecida pelo pressuposto do plano financeiro. Cálculos que dependam de câmbio oficial permanecem indeterminados até existir parâmetro versionado com fonte normativa/administrativa aplicável, âmbito e vigência confirmados.
- As calculadoras financeiras actuais limitam a entrada a moedas reconhecidas com duas casas decimais. Moedas com zero ou três casas não são aceites até os cálculos suportarem a precisão minoritária própria de cada código.
- `economic_snapshot.simulation_sources` e reservado ao servidor no snapshot cifrado. So o endpoint de conversao o escreve depois de verificar propriedade/token, execucao concluida e consentimento explicito; o cliente nao pode forjar ou editar a copia. A API apresenta a lista num campo separado para compatibilidade de clientes anteriores. Cada item conserva ID/versao, entradas permitidas, formula, resultado, relatorio, hashes e instante do consentimento, sem dados pessoais.
- A copia da execucao e uma referencia versionada no rascunho, nao um projecto submetido. Uma execucao com `legal_interpretation=false` continua aritmetica e nao pode ser apresentada como resultado fiscal aprovado. Se a pessoa mudar `reuse_simulation` para `no`, a copia e retirada do snapshot editavel.
- Resultados financeiros e resultados fiscais são linhas distintas. Uma ausência de parâmetros fiscais nunca é substituída por zero.
- `economic_snapshot.financial_tools_snapshot` guarda `financial-tools-v1`: período do orçamento, entradas do plano de empréstimo, ponto de equilíbrio, fontes de financiamento e linhas editáveis de receitas/despesas. O conteúdo é JSON versionado cifrado com o rascunho existente, limitado a 30 KB e sem campos pessoais; versões desconhecidas ou snapshots malformados são descartados para restauração segura. É um conjunto de pressupostos exploratórios, não uma oferta de crédito nem demonstração contabilística.
- A reconciliação do plano financeiro compara em cêntimos exactos usos iniciais (activos + fundo de maneio líquido) e fontes declaradas. O estado `balanced`, `shortfall` ou `surplus` acompanha o valor assinado da diferença; excedente não é rotulado como défice. A tesouraria inicial continua a considerar separadamente o caixa de abertura.
## Forma do resultado
`SimulationResult` tem `status` (`calculated`, `estimated`, `indeterminate`, `not_applicable`), `value`, `unit`, `explanation`, `missingInputs` e `sourceIds`. `calculated` e `estimated` exigem valor; `indeterminate` exige valor nulo e pelo menos uma entrada em falta; `not_applicable` exige valor nulo. Zero é aceite como valor calculado.
O contexto contém `contractVersion`, data de referência, moeda (nula quando não definida), identificador de cenário, versão do motor e versão do conjunto de regras (nula quando não existe regra publicada aplicável).
## Ciclo de vida e compatibilidade
Os snapshots existentes continuam a ser gravados pelo fluxo actual, separados e protegidos por controlo de acesso. `simulation_sources` nao e aceite pelo endpoint generico de actualizacao; a camada de servico preserva copias anexadas e remove-as perante consentimento revogado. A tipagem de resultados continua um contrato interno: nenhum endpoint generico passa a exigir `SimulationResult`. Uma futura alteracao de schema deve ser aditiva, versionada e acompanhada por compatibilidade de leitura e migration reversivel.
O tombstone de `simulation_form_drafts` continua visível sob RLS apenas ao utilizador/token proprietário, para permitir `UPDATE deleted_at` sem violar a policy PostgreSQL. Os endpoints `current`, `show`, `update`, `delete` e conversão filtram explicitamente `deleted_at IS NULL`; logo o rascunho eliminado não é restaurável nem recuperável pela API pública. A mudança da policy é aditiva e reversível; não altera dados.
`sourceIds` referencia fontes governadas quando existirem; texto explicativo não substitui fundamento legal validado. Até a aprovação das fontes e regras, qualquer linha fiscal permanece indeterminada e não é aconselhamento.
## Plano empresarial e existências
- Snapshot `business-plan-v9`: `monthlyUnitsByPeriod` opcional por produto, com agenda de ate 60 meses que deve cobrir o horizonte activo. Meses fora do horizonte ficam preservados e nao entram no calculo; se a agenda for ampliada, meses novos recebem `monthlyUnits` como quantidade-base. Sem agenda, `monthlyUnits` aplica-se a todo o horizonte. Preco e custo unitario sao constantes. Receitas, custos, consumo de existencias, cobrancas agendadas e cenarios usam os volumes mensais. Totais somam os periodos calculados em centimos; o CSV exporta a agenda em JSON. Snapshots v1-v8 mantem o modo constante.
- Snapshot `business-plan-v10`: acrescenta `unitPriceByPeriod` e `unitVariableCostByPeriod` opcionais por produto. Cada agenda monetaria cobre o horizonte activo, admite ate 60 meses, preserva meses ocultos na interface e usa o preco/custo base quando o utilizador amplia o horizonte. Sem agenda, o valor base aplica-se a todos os meses. Valores sao validados em centimos; receita, custo variavel, consumo de existencias, cobrancas agendadas e cenarios usam os valores de cada periodo. O CSV exporta as tres agendas em JSON. Leitores v1-v9 continuam a aceitar os seus contratos historicos, sem inferir agendas monetarias.
- Snapshot `business-plan-v11`: acrescenta agendas opcionais por mes para despesa operacional reconhecida, pagamento operacional, despesa de pessoal reconhecida e pagamento de pessoal. Cada agenda cobre o horizonte activo e admite ate 60 meses; sem agenda, o valor mensal base continua constante. Despesa reconhecida afecta resultado, enquanto pagamento afecta apenas tesouraria. As agendas sao validadas em centimos, preservadas em meses ocultos, ajustadas separadamente nos cenarios e exportadas em JSON no CSV. Leitores v1-v10 continuam compativeis e nao recebem agendas inferidas.
- Snapshot `business-plan-v12`: acrescenta uma agenda opcional de encomendas de existencias por mes, com montante decimal e prazo de entrega individual entre 0 e 12 meses. A agenda cobre o horizonte activo, preserva meses ocultos e pode ficar guardada enquanto o utilizador alterna entre o modo mensal constante e o modo por mes. Recepcao, stock em transito e falta sao reconciliados por mes; os pagamentos de compras continuam independentes. Os cenarios ajustam os montantes declarados e preservam prazos. Leitores v1-v11 mantem os pressupostos anteriores sem inferir uma agenda.
- Serializacao do plano empresarial respeita o limite de 60.000 caracteres aceite pelo request do rascunho. Acima do limite, o serializer rejeita a gravacao; a interface conserva a edicao em memoria, mostra erro e permite reduzir o plano antes de sincronizar. Um snapshot previamente maior que o limite nao e substituido por valores vazios/por defeito.
- Snapshot `business-plan-v4` acrescenta `salesCollectionLagMonths` opcional (nulo para o modo antigo/manual; 0–12 meses para agendar a cobrança da facturação) a `business-plan-v3`. Snapshot `business-plan-v5` acrescenta `salesCollectionPercent` (0–100%, até seis casas decimais), aplicado ao valor facturado no mês de vencimento; a parcela restante continua em contas a receber no fim do horizonte e não é reagendada. Snapshot `business-plan-v6` acrescenta o mês e percentagem declarados para uma única cobrança de valores a receber de abertura. Snapshot `business-plan-v7` acrescenta `openingReceivablesInstallments`, parcelas mensais expressas como percentagem do saldo inicial. A cobrança única legada e as parcelas detalhadas, em conjunto, não podem exceder 100%; montantes são arredondados ao cêntimo e limitados ao saldo disponível. Snapshot `business-plan-v8` acrescenta `salesRecoverySchedule`: eventos opcionais, com mês único dentro do horizonte e percentagem (0–100%) do saldo de facturas já vencidas que ainda está por receber. Primeiro ocorrem as cobranças previstas no vencimento; depois, a recuperação incide apenas nas facturas cujo vencimento seja anterior ao mês actual, das mais antigas para as mais recentes, arredondada a cêntimos e limitada ao saldo. Sem evento declarado, não se presume recuperação. Leitores v1–v7 continuam válidos e interpretam a nova agenda como vazia. Se as compras não estiverem informadas, a projecção de existências continua indeterminada.
- Saldo mensal simplificado: saldo inicial + recepções de encomendas − consumo calculado pelos produtos e quantidades planeadas. O prazo é um atraso fixo para todas as encomendas mensais; recepções e mercadoria em trânsito são expostas por período e no fecho do horizonte. Compras/encomendas e pagamentos continuam pressupostos separados; o primeiro altera stock e o segundo o fluxo de caixa.
- Uma falta de stock é apresentada separadamente e não reduz vendas automaticamente. O modelo não simula atrasos variáveis, stock por produto, devoluções, perdas ou reposição baseada em procura; os resultados continuam indicativos, não são contabilidade validada.
- No modo de cobrança por prazo, a percentagem declarada da facturação mensal é recebida no mês de vencimento (0 = no próprio mês). Facturação, cobrança calculada e saldo a receber dessa facturação permanecem separados; cobranças manuais adicionais são aditivas. A parte não recebida permanece em aberto até ao fim do horizonte, sem recuperação presumida. Valores a receber de abertura só são recebidos nos meses/percentagens explicitamente declarados; não é inferida maturidade.
## Ponte financeira-fiscal
- A ponte da Etapa 7 mantém receita, custo variável, despesas operacionais, pessoal, depreciação contabilística e juros reconhecidos em linhas separadas, com origem, montante por mês, total e tratamento fiscal por classificar.
- Resultado contabilístico antes de impostos reconcilia com essas linhas. Matéria colectável é sempre indeterminada até existirem classificação de dedutibilidade, ajustamentos, período e regra aprovada aplicáveis.
- Cobranças, pagamentos a fornecedores, pagamentos operacionais, pagamentos de pessoal, juros pagos e reembolsos de capital permanecem no calendário de caixa, fora das linhas de resultado contabilístico. Reembolso de capital não é despesa.
- Esta ponte não calcula imposto, não converte ausência em zero e não declara dedutibilidade fiscal.
- Antes do mapeamento, verifica que resultado e facturação reconciliam com os períodos, cobranças totais equivalem às suas origens discriminadas (vendas agendadas, recebíveis de abertura e outras/manuais), saldos de recebíveis evoluem segundo as cobranças declaradas e o caixa mensal/final reconcilia com entradas menos pagamentos. Uma divergência invalida a ponte.
- O CSV do plano repete estado da ponte, campos fiscais em falta, resultado contabilístico, totais e valores mensais por linha, além de manter o calendário de caixa em secção própria.
- A exportação da execução aritmética genérica só aceita estado concluído e inclui versões da execução/relatório, ID e SHA-256 do relatório quando válidos, datas, fórmula, entradas, resultado, moeda conhecida ou ausência explícita, fontes e limitações. O CSV local exclui perfil, contactos e outros campos pessoais.
- As exportações CSV serializam as células pelo utilitário comum `resources/js/lib/csv.ts`: texto cujo primeiro conteúdo significativo é `=`, `+`, `-` ou `@` recebe apóstrofo, sem alterar montantes negativos decimais válidos; aspas e delimitadores são escapados.
## Envelope versionado das execucoes aritmeticas da API
Snapshots concluidos da API mantêm `indicative_total`, `formula_version` e `legal_interpretation` e acrescentam `contract_version: 1`, `context` e `result`. O contexto usa a data de criação do cenário para não variar com o atraso da fila; moeda e versão de regras ficam nulas sem declaração/regra. `result.value` é a mesma string decimal do campo legado; `status: calculated` qualifica apenas a operação aritmética e a explicação exclui expressamente conclusão fiscal. Sem regra ou fonte legal aprovada, `ruleset_version` é nula e `source_ids` fica vazio. A entrada original permanece na tabela separada `simulation_result_sources`.
O contexto v1 inclui `scenario_version`, correspondente a `SimulationReport.version_no`. Na exportação, o cliente selecciona apenas um relatório pronto da mesma revisão, compara o snapshot do relatório com o resultado API em JSON canónico e exige um SHA-256 bem formado. Isto impede associar um relatório antigo ou divergente ao resultado actual; o hash é produzido e validado pelo backend.
- Snapshot `business-plan-v13`: adds an optional monthly cash-payment schedule for variable purchases. It is independent of inventory orders and receipts: it changes cash flow, not profit, consumption, or stock. Decimal amounts cover the active horizon, hidden months are preserved, and v1-v12 snapshots remain valid without an inferred schedule.
- Snapshot `business-plan-v14`: adds an explicit per-product inventory mode. Every product declares opening stock and monthly purchase amounts with independent lead times; opening stock must reconcile exactly to the plan's aggregate opening inventory. Receipts, consumption, transit and shortages are calculated separately for each product and then summed. Shortage on one product cannot be offset by another product's unused stock, and projected sales are not reduced automatically. The older aggregate inventory model and snapshots v1-v13 remain compatible.
- Snapshot `business-plan-v15`: adds an optional supplier payment mode for per-product purchase orders. Each order declares a 0-12 month payment lag from order date; cash payments replace the manual variable-purchase payment schedule while active, preventing double counting. Payments due after the forecast horizon are reported as outstanding supplier amounts; no supplier credit is presumed or confirmed. Snapshots v1-v14 retain their prior behavior.
- Snapshot `business-plan-v16`: supplier orders can declare up to 12 payment installments, each with a 0-12 month lag and a percentage of the order. Declared installment percentages cannot exceed 100%; cent rounding is capped at the unpaid order balance. Percentages below 100% leave an explicit unallocated amount due, and installments beyond the forecast horizon remain outstanding. Legacy v15 supplier terms are upgraded to one 100% installment when serialized; stored v1-v15 snapshots remain readable without changing their historical fields.
Novas execucoes identificam-se como `portal-arithmetic-v1`, para nao sugerir que o motor fiscal esta activo. Snapshots historicos com `portal-tax-arithmetic-v1` mantem os valores e continuam legiveis; resultados guardados nao sao reescritos.
- Snapshot `business-plan-v17`: adds `openingPayablesInstallments`, an optional schedule with month and percent of the original opening payable balance. Declared percentages sum to at most 100%; cent rounding is capped at the unpaid balance. Scheduled settlements reduce cash and opening payables, not profit or period expenses. Any unpaid amount remains a closing payable; an absent schedule assumes no settlement and leaves the full opening amount outstanding. Snapshots v1-v16 remain readable with an empty schedule; explicit resave produces v17.
- Execuções API concluídas só são aceites pelo consumidor se `result_snapshot` for um envelope `contract_version: 1` válido (incluindo consistência entre `result.value` e `indicative_total`) ou um snapshot legado legível com montante decimal. Estados concluídos sem snapshot, com snapshot malformado ou com versão v1 inválida são rejeitados na fronteira da API; estados não concluídos podem manter snapshot ausente/nulo. Snapshots históricos legíveis continuam compatíveis.
## IRPC normal — conferência anual opcional, versão de cálculo 2
O envelope de livros mantém `version:1`; `irpcNormal[opportunity]` aceita `profit` opcional (`version:1`, `completenessReference`, `lines`, `topics`). As linhas mantêm o código/origem financeira, estado `known|absent|''` e referência; os tópicos conservam separadamente estado, montante original e referência. `known` com montante zero não se torna `absent`; `''` não se torna zero. Tópicos de valor conhecido não zero sem regra implementada não são aplicados. Uma ausência incompatível com a origem ou com montante preenchido mantém pendência.
Sem `profit`, o cálculo/leitor/histórico `IRPC-normal-adjustments/1` mantém significado e chave anterior. Com conferência adicional, `IRPC-normal-adjustments/2` acrescenta `model.profit` congelado e pode produzir `taxableProfit` racional com sinal. `taxableBase` e `tax` continuam nulos. O cálculo só fecha no recorte anual/residente/MZN documentado, sujeito-exercício completo, receitas/custos ordinários qualificados, acréscimos resolvidos e demais efeitos expressamente ausentes ou zero conhecidos. A origem continua `projected`; não é demonstração contabilística nem confirmação AT. Depreciação positiva e juros financeiros remanescentes exigem tratamento próprio.
O fingerprint inclui os novos factos apenas quando presentes; alterações do plano ou da conferência desactualizam o resultado sem eliminar histórico. Os demais livros permanecem intactos no snapshot. Gravação e recuperação usam a API privada existente com ETag/If-Match; sem novo endpoint, schema, permissões ou activação de parâmetros. Matéria colectável/colecta/créditos anuais e M20/M22 não são inferidos de um lucro conhecido.
## IRPC normal — matéria colectável opcional, versão de cálculo3
O envelope de livros e entradas mantém `version:1`; `irpcNormal[opportunity].base` é opcional e versionado1. Conserva NUIT/suporte,método,situação/completude das perdas,manutenção da actividade,linhas anuais de perdas e estado/montante/referência dos benefícios à base. Os montantes apurados,utilizados anteriormente e propostos são stringsMZN,não negativos,até dois decimais;campos ausentes não recebem zero. Um saldo por sujeito/exercício;sem fusão de livros ou origens.
Sem `base`,as versões1/2 mantêm chaves e significado. Com `base`,`IRPC-normal-adjustments/3` acrescenta modelo congelado de elegibilidade/propostas/deduções/saldos e pode produzir `taxableBase` racional no recorte documentado;`tax` permanece nulo. O fingerprint inclui apenas as novas entradas quando presentes. Repetir cálculo não altera `previouslyUsed`;`remaining` é saldo aritmético desta simulação,não reporte/consumo oficial. Uma edição preserva os resultados anteriores no histórico e exige novo cálculo antes de exportar.
Estado conhecido zero,ausência suportada e informação em falta permanecem distintos. Benefício positivo,perda transmitida ou saldo/regime não correspondido não se convertem em dedução livre. Dados e resultado usam a APIprivada existente/ETag,sem schema,endpoints,permissões ou parâmetros novos. A matéria colectável simulada não é colecta nem imposto a pagar.
## IRPC normal — colecta opcional, versão de cálculo4
O envelope e o livro mantêm `version:1`; `irpcNormal[opportunity].assessment` opcional guarda `version:1`, `treatment:''|general_61_1|other` e referência do enquadramento. Sem esta entrada,versões/chaves1–3 mantêm o significado anterior. Com ela,o cálculo `IRPC-normal-adjustments/4` acrescenta modelo congelado `assessment` e `colecta` racional,sem reutilizar o campo legado `tax` como colecta ou saldo final.
A colecta corresponde à matéria colectável actual×32/100 no recorte2026/MZN/residente geral,após classificação e suporte expressos. O modelo identifica taxa32,art61(1),versão da regra e período anual. Informação em falta,período fora do recorte,moeda/âmbito distintos ou caso especial mantêm colecta nula;zero exige base conhecida zero. A fracção racional é conservada exactamente;`centExact:false` não autoriza arredondamento fiscal nem transcrição oficial.
`assessment.finalBalance` é sempre `scope:L8,status:not_calculated,payable:null,recoverable:null` nesta versão. Retenções,pagamentos e créditos anuais não entram na fórmula da colecta nem são subtraídos automaticamente. UI,HTML e dossier apresentam lucro tributável→matéria colectável→colecta→saldo final com esse limite. APIprivada/ETag existente conserva todo o snapshot e histórico,sem novos endpoints,schema,permissões ou migração dos resultados anteriores.