Files
SGF/docs/COMMON_BUDGET_DELIVERY.md

14 KiB

Controlo orçamental comum — entrega técnica em verificação

Actualização posterior de 29/10/2026: extracção técnica aceite pela Tempo, com autorização de checkpoint exclusivamente local. Ver aceitação e pendências preservadas. A revisão visual de Compras continua pendente; SGF continua demonstrado apenas pelo adaptador QA, sem interface deste percurso; os dois testes MFA ignorados continuam pendentes. As menções abaixo a aceitação/checkpoint por realizar são históricas; não há activação operacional decorrente desta aceitação.

29/10/2026. COMMON-BUDGET-SYNTHETIC-v1. Implementação do primeiro incremento de desenho e transição. Sem aceitação presumida ou checkpoint de encerramento. Apenas provas isoladas; nenhuma migração, concessão ou operação nas bases de desenvolvimento/produção. Não houve publicação ou push.

Resultado e fronteira

Existe uma fonte única em packages/budget-control: Tempo\Finance\Budget\BudgetControl, contexto explícito BudgetContext e erro de domínio BudgetFailure. Foram retirados os algoritmos de movimentos/reforços/consumo de Compras; os percursos anteriores delegam neste núcleo. O núcleo grava dotação, aprovação, reforço, reserva, ajuste de adjudicação, compromisso, libertação permitida e consumo orçamental. Saldo/total aprovado também são calculados pelo núcleo.

Não chama auth(), sessão ou contexto global de uma aplicação, nem depende de Sales, recebimentos, contas a pagar, pagamentos, contabilidade ou de um SGF remoto. Usa Illuminate\Database\ConnectionInterface já disponibilizada pelos hosts, contexto imutável, tabelas por prefixo e callbacks locais de autorização/bloqueio/auditoria. A autorização é revalidada antes de qualquer replay; a auditoria participa na transacção do efeito.

O primeiro consumidor é Compras, nos seus percursos efectivos. O segundo é a composição reduzida de QA do SGF: bootstrap Laravel real, modelos de identidade/contexto/permissões reais e adaptador app/Modules/Purchasing/BudgetAdapter.php. O adaptador SGF recusa funcionar fora de budget-testing e de uma base descartável budget_core_sgf_<12 hex>, PostgreSQL local verificado. Não se declara instalado o módulo completo de Compras no SGF, nova interface visual ou circuito de procurement SGF completo. A origem SGF é uma referência sintética mapeada para testar o primeiro efeito comum; não é uma obrigação ou factura operacional.

Dependências e valores

  • Mantidos manifests/lockfiles: Laravel 13.39.0 / Brick Math 1.0.0 de Compras e Laravel 13.38.0 / Brick Math 0.14.8 do SGF. Nenhuma instalação, actualização ou substituição de dependências.
  • O núcleo usa os inteiros em centavos já gravados por Compras. Não calcula IVA, não converte câmbio e não introduz float. MZN é o recorte suportado; o adaptador Compras verifica a moeda empresarial antes/depois do bloqueio. Outras moedas permanecem explicitamente não suportadas.
  • Conversão decimal de entrada continua no Brick Math da aplicação Compras, exactamente pelos caminhos anteriores. Quantidades em milésimos, arredondamento HalfUp das linhas e cálculo cumulativo de facturas parciais permanecem em InvoiceWorkflow/serviços anteriores. Política SGF de truncagem do IVA de vendas não é aplicada a compras.
  • Não se recalcularam documentos nem se reescreveram valores históricos. O total inicial permanece imutável no percurso normal; apenas reforços aprovados contam para a dotação total.
  • A chave histórica (requisition_id, kind) continua a identificar o efeito. Replay idêntico não grava; o núcleo reconstrói o alvo monetário da entrada histórica para recusar replay com montante diferente, sem exigir hash ou migração retroactiva. Esta recusa é um reforço explícito: antes, o percurso de movimentos devolvia silenciosamente o efeito existente mesmo quando o montante pedido diferia. Não altera a história nem cria nova versão de documentos.

Adaptadores e responsabilidade

Ponto Papel nesta entrega
Compras app/Services/CommonBudget.php Confere sessão/actor, empresa, moeda e perfil actual; bloqueia empresa/actor; traduz erros; liga auditoria e elegibilidade do proponente
Compras BudgetWorkflow.php Conserva contrato dos chamadores, exigência de transacção exterior, vínculo da requisição e classificação corrente/investimento; delega o efeito
Compras BudgetReinforcementWorkflow.php Conserva conversão decimal/normalização de referência e retorno Eloquent; delega proposta/decisão
Compras BudgetController.php Conserva interface/validação/autorizações de origem; delega dotação, aprovação e saldos
Compras InvoiceWorkflow.php Conserva conferência de factura/preço/IVA/quantidades, actor distinto e auditoria invoice.validated; delega apenas consumo orçamental na mesma transacção
Compras Budget.php Mantém modelo/imutabilidade e usa a soma inteira comum do total aprovado
SGF app/Modules/Purchasing/BudgetAdapter.php Confere actor autenticado e contexto seleccionado, revalida membership/acções por unidade dentro do bloqueio e usa origens/centros explicitamente mapeados de QA
BudgetControl Único escritor do ledger/dotação/reforços dentro do recorte; não substitui elegibilidade de procurement ou conferência do documento

Compras continua a tratar o seu tenant_id como empresa. SGF usa separadamente tenant/empresa/unidade; o teste cria identificadores diferentes e um centro de compras próprio. Nenhum departamento ou lote industrial é convertido implicitamente em unidade/dotação. O orçamento industrial existente do SGF não foi alterado.

Fonte única e distribuição autónoma

O provider SGF carrega packages/budget-control/bootstrap.php. Compras procura o artefacto instalado em packages/budget-control, ou o caminho explícito config/common-budget.php / COMMON_BUDGET_PATH. Só em ambiente não produtivo existe fallback para a fonte canónica do checkout SGF vizinho. Não há chamadas remotas.

A prova autónoma empacota temporariamente apenas bootstrap e os três ficheiros de produção do núcleo, fora de ambos os projectos, e arranca Compras usando esse artefacto destacado. O teste exige que a classe efectivamente carregada venha do artefacto. O SGF carrega a fonte canónica. Os SHA-256 e traços normalizados coincidem. O artefacto temporário é eliminado no final, não constitui uma segunda fonte mantida. Para distribuição comercial, o artefacto local versionado terá de acompanhar Compras; não basta enviar o checkout sem o pacote. Automatização completa de releases/licenciamento não está incluída.

Provas executadas

Comando dos dois hosts, a partir de Compras:

& 'C:\Users\macbook\.config\investmoz\php-8.5.11\php.exe' tests/Concurrency/run-common-budget.php

O coordenador usa uma ligação administrativa à base de manutenção postgres exclusivamente para criar/eliminar duas bases novas. Não consulta ou migra bases de negócio. Em Compras aplica as migrações existentes apenas a compras_receipts_test_<12 hex> e usa as fixtures sintéticas existentes; no SGF aplica a fundação de identidade e o schema de QA apenas a budget_core_sgf_<12 hex>. Bases eliminadas no final. Configurações privadas são consumidas em processo, sem imprimir/versionar credenciais. Não se fez comparação de dados activos nem se reivindica checksum desses dados.

Evidência dirigida: dois hosts e concorrência. O relatório inclui hash do núcleo realmente carregado, igualdade dos traços, bases descartadas e ausência de revisão visual.

Sequência, em ambos os hosts Resultado em centavos
Dotação aprovada 100000; reserva 30000 repetida Reservado 30000; disponível 70000
Ajuste da adjudicação para 35000 repetido Reservado 35000; disponível 65000
Compromisso 35000 repetido Reservado 0; comprometido 35000; disponível 65000
Consumo parcial 10000 repetido Comprometido 25000; consumido 10000; disponível 65000
Reforço 20000 proposto Disponível permanece 65000
Aprovação distinta do reforço repetida Dotação total 120000; disponível 85000

Também passaram, nos dois hosts: recusa de aprovação própria; conflito de montante em replay; recusa de libertação já comprometida; isolamento de dotação entre empresas; libertação antes de compromisso uma única vez; base sem IVA usando subtotal original; falha SQL injectada na auditoria com rollback da reserva e retry sem duplicação; replay de decisão com permissão entretanto revogada. No SGF: origem de outra empresa recusada, unidade reservada recusada e contexto mudado após obter o serviço recusado.

Concorrência PostgreSQL: oito cenários aprovados, quatro por host. Duas ligações/processos PHP independentes, com dois waits de bloqueio observados em cada cenário: duas reservas acima do saldo conjunto; repetição da mesma reserva; repetição do mesmo compromisso; repetição da mesma libertação. No excesso apenas um efeito de 6000 cabe na dotação 10000; nos replays ambos os pedidos obtêm sucesso e o saldo só muda uma vez. Não é uma prova de todas as corridas possíveis ou teste de carga.

Regressões e compilação

  • Referência antes da alteração: 75 testes dirigidos / 317 asserções aprovados. Mesma bateria após extracção: 75 / 317, sem mudar expectativas existentes.
  • Regressão completa Compras: 498 aprovados, 2 ignorados, 4141 asserções, incluindo percursos/autorização existentes. Os dois ignorados são as limitações MFA anteriormente documentadas; não se declarou cobertura nova desses casos.
  • PHPStan Compras: zero erros. Pint dos ficheiros de produção alterados: aprovado. Sintaxe PHP 8.4 do pacote/adaptador/fixtures SGF: aprovada.
  • Compilação Compras: npm.cmd run build, aprovada; compilação SGF: scripts/sgf.ps1 npm run build, aprovada. Sem alterações de dependências; geração Wayfinder ocorreu pelo build habitual.
  • A suite destrutiva SGF normal não foi executada sobre sgf_tempo_test, para preservar a demonstração da equipa. O delta SGF foi verificado no host/bootstrap real com base descartável e nas verificações acima. Não se atribui regressão integral de todos os módulos SGF a esta prova.
  • Uma tentativa inicial com outro PHP existente falhou por falta do driver SQLite, sem asserções ou alteração de base. A bateria válida usou o executável já instalado com SQLite. O primeiro comando npm foi recusado pela política PowerShell; usou-se npm.cmd, sem mudar a política.

Ficheiros deste incremento

Fonte comum no SGF: packages/budget-control/bootstrap.php, README.md, src/BudgetContext.php, src/BudgetFailure.php, src/BudgetControl.php; provas reproduzíveis em tests/host-support.php, tests/run-host.php, tests/sgf-schema.php dentro do mesmo pacote.

SGF: app/Providers/AppServiceProvider.php, app/Modules/Purchasing/BudgetAdapter.php, este relatório, docs/proofs/common-budget-hosts.json e referências nos documentos/instruções existentes.

Compras: app/Providers/AppServiceProvider.php, config/common-budget.php, app/Services/CommonBudget.php, BudgetWorkflow.php, BudgetReinforcementWorkflow.php, InvoiceWorkflow.php, app/Models/Budget.php, app/Http/Controllers/BudgetController.php, tests/Concurrency/run-common-budget.php e referências nos relatórios existentes.

Alterações anteriores de oficinas/navegação, fontes e histórico SGF e documentação prévia de Compras foram preservadas, sem commit, reset ou checkout. Não são atribuídas a este incremento.

Migrações para desenvolvimento/produção — separadas e não executadas

Compras: o adaptador conserva as tabelas/colunas/índices existentes; esta extracção não necessita de migração SQL para os efeitos existentes. Não foram executadas migrações nessas bases. A distribuição tem de incluir o pacote e conservar os seus originais e lockfiles.

SGF: o único schema executado é a fixture packages/budget-control/tests/sgf-schema.php, que tem guarda QA e não está registada em database/migrations. Documenta cb_centres, cb_origins, cb_budgets, cb_budget_entries, cb_budget_consumptions, cb_budget_reinforcements, cb_audit e as sete acções purchasing_budget.*, mais a extensão da constraint de permissões na base nova. Nenhuma concessão real foi instalada.

A futura migração SGF terá de adaptar essas referências aos cadastros definitivos de Purchasing/Platform, completar constraints compostas de pertença e políticas de imutabilidade, conferir schema/permissões de destino e ser ensaiada com backup/restauro. Não apresentar esta fixture como migração operacional pronta nem retirar a guarda para apontar para sgf_tempo_dev. Não fundir tabelas/IDs/históricos existentes por igualdade numérica.

Limitações e próximos passos

Revisão visual não realizada; nenhum ecrã novo apresentado como aceite. SGF demonstra o efeito orçamental do primeiro incremento, não Compras integral instalado. O pacote não inclui obrigações, pagamentos ou contabilidade, emissão real, câmbio, novas reversões ou cancelamento de ordens já emitidas. A revogação/concessão de direitos reais permanece fora desta entrega.

Próximo passo dentro desta entrega: revisão do desenho/código/provas e dificuldades que a equipa identificar, sem presumir aceitação. Depois, preparar o empacotamento e os pontos de montagem do módulo completo nos dois produtos com os cadastros definitivos. T2 (obrigações), T3 (pagamentos) e restantes passos do plano não foram iniciados. As capacidades inexistentes continuam pendentes, sem motores fictícios ou reaproveitamento indevido de recebimentos de clientes/orçamento industrial.