Preserva demonstracao sintetica e aceitacao expressa. Aplicabilidade fiscal real permanece pendente, sem autorizacao de perfil real ou publicacao.
72 lines
10 KiB
Markdown
72 lines
10 KiB
Markdown
# Primeiro cálculo de serviço — entrega local delimitada
|
|
|
|
**Aceitação posterior em 26/10/2026:** o utilizador aceitou expressamente o cálculo de ensaio demonstrado e autorizou o checkpoint local, conforme [conferência e aceitação separadas](SERVICE_CALCULATION_SEPARATE_REVIEW.md). A aplicabilidade fiscal real continua pendente e a activação de perfil fiscal real não foi autorizada. O texto de entrega abaixo preserva o estado anterior a essa aceitação e não a revoga.
|
|
|
|
26/10/2026. Preservadas identidade, A, B1 (`8fcd52c`), preparação documental, pré-visualização e alterações posteriores existentes. Não constitui aceitação pelo utilizador nem autorização de emissão.
|
|
|
|
## Comportamento entregue
|
|
|
|
Uma linha, quantidade positiva, preço não negativo, moeda explícita e modo imposto acrescido (`added`). Aritmética Brick\Math já existente, sem dependências novas nem alterações de versões. Base e IVA exactos sem float ou truncagem intermédia. A política **`SGF-SERVICE-NET-VAT-TRUNCATE2-v1`** trunca apenas o IVA documental proposto a duas casas, conserva a diferença e calcula total proposto apenas quando a base é exactamente representável a duas casas. Caso contrário o total fica pendente, sem ajustar ou truncar a base.
|
|
|
|
Truncagem: decisão operacional expressa do utilizador, **não obrigação legal comprovada**. Fontes reutilizadas: ficha InvesteMoz `IVA-GERAL-BASE-LIQUIDA` v1.2, cadeia da Lei 22/2022 republicada/art. 17(1), CIVA art. 15 e acontecimentos arts. 7/8/17(2). A matriz e limites constam de [SERVICE_INVOICE_CALCULATION_SPEC.md](SERVICE_INVOICE_CALCULATION_SPEC.md). Não se repetiu investigação nem se copiou código do portal.
|
|
|
|
Separação confirmada: a classificação contabilística orienta contas; o enquadramento fiscal da operação determina tratamento e taxa de IVA. Nenhuma taxa é inferida da conta/classificação contabilística ou aplicada universalmente a serviços. Os 16% são exclusivamente parâmetro identificado dos ensaios deste incremento. Associações contabilísticas e lançamentos não foram implementados.
|
|
|
|
Perfis e resultados são imutáveis. Cada resultado conserva entradas, moeda, base exacta, IVA exacto, IVA proposto, diferença, total/pendência, política, perfil/versão/fontes e versões de rascunho, preparação e origem. Mudanças tornam o resultado anterior desactualizado na nova consulta; o histórico mantém os valores originais. A leitura não recalcula nem grava. A pré-visualização já aberta conserva a versão consultada e avisa de alterações pelo mecanismo existente, exigindo actualização explícita.
|
|
|
|
Execução por `POST /api/service-calculations/{id}` com contexto validado, sessão, CSRF e versões de rascunho/preparação/perfil. Sem campos arbitrários de taxa ou resultados enviados pelo navegador. Bloqueio fora de `testing`/`browser-testing`, seguido da guarda do destino efectivo `sgf_tempo_test`. O ensaio requer consulta e edição de rascunho já concedidas à identidade sintética; consulta não permite executar. Configurar aparência não dá esse acesso. Nenhuma concessão nova foi aplicada às contas reais e não existe via de activação de perfil real neste incremento.
|
|
|
|
Bloqueio transaccional da empresa serializa comandos com as alterações existentes. Revalida contexto/permissões, rejeita versões antigas e origem/preparação por rever, e garante uma única inserção por entrada/versionamento, com repetição devolvendo o mesmo resultado. Auditoria da criação na mesma transacção. Chaves compostas e trigger de inserção recusam associações cruzadas; triggers append-only impedem actualizações/transferências em massa e apagamentos de perfis/resultados. Não se apresenta isto como prova de RLS.
|
|
|
|
## Migração e preservação
|
|
|
|
Delta previamente apresentado: `2026_10_26_030000_create_service_calculations.php` cria `service_calculation_profiles`, `service_calculation_results`, índices, relações e triggers. Não altera B1, cadastros, permissões ou dados existentes; não tem rollback destrutivo automático.
|
|
|
|
Aplicada primeiro em `sgf_tempo_test` nas provas; depois em **`sgf_tempo_dev`**, por `scripts/sgf.ps1 migrate`, com proprietário separado. Antes de aplicar em desenvolvimento, o estado das migrações confirmou que apenas esta estava pendente. Verificação posterior: contagens e hashes do conteúdo das 14 tabelas existentes comparadas ficaram idênticos. Tabelas novas em desenvolvimento: **zero perfis, zero resultados**. [Prova de preservação](proofs/calculation-dev-preservation.json). Nenhum reset/fresh em desenvolvimento foi aplicado por este incremento.
|
|
|
|
## Provas
|
|
|
|
Regressões dirigidas: **53 testes, 743 asserções**, todos passados, abrangendo `ServiceCalculationTest`, `DocumentPreviewTest`, `InternalConfirmationTest`, `DocumentPreparationTest` e `DatabaseSafetyTest`. Execução exclusivamente em `sgf_tempo_test`. Compilação `npm run build` passou (Vite 8.3.5). Verificação de whitespace passou; nenhuma versão de ferramenta foi alterada.
|
|
|
|
Cobertura nova: três casos pedidos, zero explícito, fronteiras imediatamente abaixo/na/acima da truncagem, base com fracções adicionais, perfil/taxa/moeda ausentes ou incompatíveis, modo incluído recusado, repetição, versões antigas de rascunho/perfil, histórico desactualizado, leitor sem edição, revogação no pedido seguinte, unidade de perfil alheia, empresa irmã, tentativa de transferência em massa, bloqueio no ambiente normal e fotografia B1 preservada. Guardas existentes continuam a recusar desenvolvimento e sobreposição por URL e a verificar privilégios do papel de testes.
|
|
|
|
Concorrência separada, em dois processos PHP realmente sobrepostos: primeiro mantém bloqueio enquanto segundo entra; um resultado criado e um replay com o mesmo ID, sem duplicação. [Prova concorrente](proofs/calculation-concurrency.json).
|
|
|
|
Navegador Edge, **login real sintético**, com CSRF/sessão activos em `http://127.0.0.1:8001`, base `sgf_tempo_test`, sessões/cache isolados. Não se usou `actingAs` como demonstração de login. Taxa 16% apenas no perfil identificado `ENSAIO-MZN-16 v1`, moeda MZN explicitamente indicada:
|
|
|
|
| Base | IVA exacto | IVA truncado | Diferença | Total proposto | Prova |
|
|
| --- | --- | --- | --- | --- | --- |
|
|
| 100 | 16 | 16,00 | 0 | 116,00 | [Imagem](proofs/calculation-100.png) |
|
|
| 1000,03 | 160,0048 | 160,00 | 0,0048 | 1160,03 | [Imagem](proofs/calculation-1000.png) |
|
|
| 0,03 | 0,0048 | 0,00 | 0,0048 | 0,03 | [Imagem](proofs/calculation-small.png) |
|
|
| 0,0001 | 0,000016 | 0,00 | 0,000016 | Pendente | [Imagem](proofs/calculation-base-pending.png) |
|
|
|
|
Repetição do segundo caso no navegador conservou o mesmo resultado. Em todos: aviso permanente **RASCUNHO — SEM VALIDADE FISCAL**, identificação de ensaio, diferença preservada e pendências visíveis. [Registo da observação](proofs/calculation-browser-results.json). Separador decimal dos valores na interface é actualmente ponto; os valores são strings exactas, sem conversão de apresentação para float.
|
|
|
|
### Percurso exacto e repetição local da prova
|
|
|
|
1. Entrar como identidade sintética existente da fixture, com a credencial local criada aleatoriamente; nunca publicar a credencial. Seleccionar **Empresa Horizonte — Demonstração → Unidade Central — Demonstração**.
|
|
2. **Rascunhos de facturação → Ensaio base 100 → Pré-visualizar rascunho → Calcular ensaio · ENSAIO-MZN-16 v1**. Consultar os quatro valores e o total proposto.
|
|
3. **Voltar ao registo**, seleccionar os casos **Ensaio base 1000.03**, **Ensaio base 0.03** e **Ensaio base 0.0001**, repetir pré-visualização/cálculo. O segundo caso também foi calculado pela prova concorrente e a execução no navegador reutilizou o mesmo resultado.
|
|
4. Sair da sessão. A instância de prova é encerrada após a entrega; a aplicação normal não muda de ligação.
|
|
|
|
Para preparar outra prova, parar primeiro a instância com `scripts/browser-proof.ps1 stop`; executar apenas os testes dirigidos abaixo (recriam a base de testes, nunca desenvolvimento); arrancar novamente `scripts/browser-proof.ps1 start` e preparar os quatro rascunhos por `sgf.ps1 php scripts/calculation-fixture.php --env=testing`. O preparador de fixtures recusa uma base não vazia; não apaga dados para conseguir prosseguir. Depois, `sgf.ps1 php scripts/calculation-concurrency.php --env=testing` demonstra a concorrência antes do percurso no navegador. Não repetir o preparador de cálculo sobre a mesma fixture.
|
|
|
|
```powershell
|
|
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/sgf.ps1 test --stop-on-failure --filter="ServiceCalculationTest|DocumentPreviewTest|InternalConfirmationTest|DocumentPreparationTest|DatabaseSafetyTest"
|
|
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/sgf.ps1 npm run build
|
|
```
|
|
|
|
Os scripts PowerShell existentes podem precisar de `-ExecutionPolicy Bypass` apenas nesse processo; não se alterou política global. A execução recusa portas ocupadas, sem terminar processos de outro projecto.
|
|
|
|
## Ficheiros deste incremento
|
|
|
|
- Núcleo novo: `app/Modules/Services/ServiceCalculation.php`; migração nova acima; `tests/Feature/ServiceCalculationTest.php`.
|
|
- Integração: `DocumentPreview.php`, `Http/DocumentPreviewController.php`, `routes/web.php`, `resources/js/DocumentPreview.jsx`.
|
|
- Provas: `scripts/calculation-fixture.php`, `calculation-worker.php`, `calculation-concurrency.php`, `calculation-preservation.php` e ficheiros `docs/proofs/calculation-*`.
|
|
- Documentação: esta entrega, especificação de cálculo, README e AGENTS. Restantes alterações preexistentes foram preservadas; nenhum commit/checkpoint foi criado sem pedido.
|
|
|
|
## Condições para activação real
|
|
|
|
Continua por demonstrar a aplicabilidade concreta: regime, serviço/localização, tratamento, base tributável e acontecimento/exigibilidade. Activação requer incremento próprio com perfil real fundamentado/versionado e direitos fiscais especificamente aprovados, sem herdar poderes visuais. A decisão operacional de truncagem não comprova conformidade fiscal do montante documental. Representação de base/total com fracções adicionais fica pendente. Incluído e demais casos continuam excluídos. Não há número/data de emissão fiscal, emissão, PDF, recebimentos ou lançamentos; nenhum documento foi publicado.
|