Files
SGF/docs/SUPPLIER_ALLOCATION_REVERSAL_DELIVERY.md
2026-11-02 08:06:45 +02:00

12 KiB

Reversão integral de afectações — entrega técnica, 30/10/2026

Incremento COMMON-ALLOCATION-FULL-REVERSAL-SIM-v1, sobre os checkpoints aceites SGF e4f520092e8aa3261880b8b91fca0fdf789086ce e Compras 13a6cb9922af5004c636697c49f229d4a97f231c. Esses checkpoints e provas anteriores foram preservados. Esta entrega não presume aceitação e não cria novo checkpoint.

Responsabilidade e comportamento

Único motor: packages/payables/src/SupplierSettlements.php. O cálculo canónico de Payables continua a chamar allocated(), agora com afectações confirmadas menos compensações integrais confirmadas. O disponível do pagamento segue a mesma regra. Não se escreve um segundo saldo nem se alteram principal, impostos, documento, pagamento, afectação ou decisões originais.

  • reversal-prepare: recebe ID estável da afectação, versão da origem e motivo obrigatório. Cria uma proposta única por afectação, sem efeito monetário.
  • reversal-confirm: recebe ID da proposta e motivo obrigatório da decisão. Exige outra identidade e outra pessoa, revalida contexto, direitos e versão, e acrescenta o movimento compensatório integral ligado ao original. Não cancela o pagamento.
  • A nova afectação usa os comandos anteriores e uma nova referência. Revalida fornecedor, moeda, versão, saldo da obrigação e disponível do pagamento. A ligação original revertida não impede a nova ligação.
  • Referências antigas e suas repetições recuperam o resultado original, incluindo depois da reversão; não reaplicam o efeito revertido. Conteúdo incompatível gera conflito. Uma proposta com o mesmo plano pode existir num novo ciclo após reversão, sem confundir repetição com uma nova correcção.
  • O ciclo é por pagamento e corresponde à última compensação confirmada. Uma proposta de afectação ainda não decidida de um ciclo anterior não pode ser confirmada depois de uma reversão; exige nova preparação/referência. Decisões originais já confirmadas continuam recuperáveis sem novo efeito.
  • Motivo e autoria da preparação/confirmação ficam em registos imutáveis; eventos e outbox são gravados na mesma transacção dos comandos e movimentos. Confirmação concorrente recupera o mesmo movimento.

O motor continua a receber actor, pessoa, organização e callbacks explícitos. As permissões/contextos dos hosts continuam nos adaptadores existentes: SGF app/Modules/Purchasing/SupplierPayables.php; Compras app/Services/SupplierPayables.php. Não foram equiparados tenant, empresa ou unidade. Não há dependência de facturação de vendas ou de um SGF remoto.

Interfaces e direitos

SettlementHttp.php expõe a consulta das propostas/compensações e verifica o utilizador funcional do host. ui/settlements.php, a mesma página nas duas composições, acrescenta a secção «Reversão integral e nova afectação», com motivo, confirmação independente, montante integral, ligação ao original, histórico e explicação de que o pagamento continua confirmado. O formulário não permite indicar um montante de reversão. A consulta não recebe formulários de escrita. O servidor revalida tudo, mesmo que o cliente seja alterado.

As duas routes/web.php permitem apenas os dois novos comandos nos endpoints autenticados existentes. Novas capacidades explícitas: reversal_prepare e reversal_confirm; não derivam automaticamente dos direitos de afectação. Só foram outorgadas às identidades sintéticas de bases descartáveis pelo instalador de prova. Nenhum direito público, real ou das demonstrações persistentes foi modificado. Página inicial preservada sem cartões/resumos.

Actualização de esquema e preservação

src/ReversalSchema.php é uma actualização QA explícita e transaccional, não uma migração operacional registada:

  1. Acrescenta ps_reversal_proposals e ps_reversals, com unicidade por afectação, chaves estrangeiras e triggers append-only.
  2. Um trigger de integridade exige compensação do montante inteiro, pagamento/obrigação/contexto/versão correspondentes e confirmação por actor/pessoa diferentes do preparador.
  3. Acrescenta ps_proposals.allocation_cycle, com zero para os registos anteriores. Substitui a unicidade pagamento/plano por pagamento/plano/ciclo.
  4. Substitui a unicidade pagamento/obrigação da afectação pela unicidade decisão/obrigação. A regra de uma ligação activa por pagamento/obrigação mantém-se no motor, dentro do bloqueio organizacional e do pagamento. Só uma reversão confirmada permite nova ligação.

scripts/reversals-install.php recusa as bases das demonstrações persistentes, utiliza apenas settings de prova e compara todas as colunas anteriores das nove tabelas antes/depois. As linhas originais coincidiram nas duas composições. O código conserva compatibilidade com o esquema anterior, sem compensações: nesse caso a interface mostra que a actualização ainda não foi aplicada e não oferece os novos formulários.

Não aplicada em 8005/8006, desenvolvimento ou produção. Para esses destinos a mudança fica proposta separadamente: inventário e backup/restauro, conferência do esquema exacto, aplicação explícita e outorga dos dois direitos em contexto próprio. Não reverter o esquema simplesmente recriando as unicidades antigas depois de existirem novos ciclos; preservar o ledger e planear recuperação pelo backup ou correcção progressiva. Um binário antigo que desconheça compensações não pode calcular saldos de uma base que já tenha reversões: a versão do pacote e a do esquema têm de ser transportadas em conjunto. Os checkpoints anteriores continuam válidos para os seus esquemas/dados originais. Não há migração de dados reais nesta entrega.

Provas automáticas

Etapa Dívida Compras Dívida SGF Pagamento por afectar
Principal reconhecido 11 600 MZN 11 600 MZN —
Pagamento de 4 000 confirmado, antes de afectar 11 600 MZN 11 600 MZN 4 000 MZN
Afectação original de 4 000 confirmada 7 600 MZN 7 600 MZN 0 MZN
Reversão proposta 7 600 MZN 7 600 MZN 0 MZN
Reversão integral confirmada 11 600 MZN 11 600 MZN 4 000 MZN
Nova afectação de 3 000 proposta 11 600 MZN 11 600 MZN 4 000 MZN
Nova afectação de 3 000 confirmada 8 600 MZN 8 600 MZN 1 000 MZN

Vencimento e dias de atraso permanecem null; atraso indeterminado. Base 10 000, imposto documental 1 600 e principal 11 600 preservados, sem recálculo ou nova regra fiscal.

Evidências novas, sem substituir provas aceites:

  • proofs/supplier-reversals-baseline-20261030.json: percurso anterior HTTP/HTML no código actualizado e esquema anterior, nas duas composições.
  • proofs/supplier-reversals-20261030.json: compensação/correcção, repetição com mesma/nova chave, dupla reversão sem novo movimento, conteúdo incompatível, motivo em falta, payload parcial recusado, identidades e pessoas distintas, permissões, revogação durante espera, outra empresa, versão antiga/origem alterada, falha antes do evento e recuperação com a mesma chave, saldo disponível, novo ciclo e repetição das referências/decisões antigas, reentrada e histórico.
  • Quatro corridas PostgreSQL por host com dois processos e duas esperas observadas: preparação repetida, confirmação com revogação, confirmação repetida e nova afectação repetida. Não é prova de carga ou de todos os escalonamentos.
  • Integridade SQL: tentativas de update/delete dos dois novos tipos de registo recusadas; compensações com montante parcial, autor igual ou unidade incompatível recusadas. Originais de pagamento/decisão/afectação/principal comparados por hash. Um evento/outbox por acontecimento; um único movimento de reversão.
  • proofs/supplier-reversals-legacy-regression-20261030.json: regressão adversarial dos pagamentos/afectações anteriores, incluindo corridas, isolamento, limites e recuperação, sem regravar a prova aceite.
  • proofs/supplier-reversals-verification-20261030.json: resumo das verificações finais. Baseline no esquema antigo e regressão adversarial no esquema actualizado aprovados; os três artefactos correspondem ao SHA-256 final do mesmo núcleo 4a719ae1456df974877e2555dd6d559f26ebc40b90ae3ff7e11874cfbf2f106b. Oito corridas de reversão/correcção e doze de regressão financeira, com processos/ligações separados. Os runners terminaram com remoção das suas bases, roles e processos.

Regressões de Compras: 81 testes aprovados, 343 asserções, SQLite em memória, nos cinco ficheiros SupplierPayableIntegrationTest, ExternalPaymentTest, InvoiceTest, PayableHistoryImportTest e PayablePaymentDecisionTest. PHPStan das três classes comuns alteradas sem erros; Pint aprovado. Builds SGF e Compras aprovados. Regressão de navegação/página inicial aprovada. A suite SGF que recria a base persistente não foi executada: os comandos SGF foram exercitados nos hosts PostgreSQL descartáveis. Sem dependências novas ou alterações de versões.

Uma asserção antiga do script adversarial ainda esperava oferecer um pagamento totalmente afectado no formulário; foi ajustada para a regra de interface já entregue que o omite. Não se alterou o motor para satisfazer essa asserção.

Repetição e revisão local

Ficheiros alterados em SGF: packages/payables/bootstrap.php, src/SupplierSettlements.php, src/SettlementHttp.php, ui/settlements.php, routes/web.php, scripts/settlements-interface-run.py, settlements-interface-check.mjs, settlements-http-proof.mjs, settlements-probe.php e documentação. Novos: packages/payables/src/ReversalSchema.php, scripts/reversals-install.php, scripts/reversals-http-proof.mjs, este relatório e as quatro provas acima. Em Compras: routes/web.php, docs/desenvolvimento.md e docs/orientacoes-continuidade.md. Os adaptadores financeiros e o motor de obrigações Payables.php não foram duplicados nem alterados.

A comparação com o checkpoint e4f5200 confirmou que as três provas aceites supplier-settlements.json, supplier-settlements-interface-20261030.json e supplier-settlements-consolidation-20261030.json mantêm o conteúdo anterior. Alterações alheias de documentação/publicação de candidatos em Compras foram preservadas.

Na pasta SGF, executar com os binários existentes:

& 'C:/laragon/bin/python/python-3.10/python.exe' scripts/settlements-interface-run.py --reversals
& 'C:/laragon/bin/python/python-3.10/python.exe' scripts/settlements-interface-run.py --adversarial --upgraded

O runner exige 8007/8008 livres, cria apenas as suas bases/roles descartáveis e remove-as no finally. Não pára 8005/8006. Para manter as interfaces de prova abertas para revisão local, acrescentar --review ao primeiro comando; Compras http://127.0.0.1:8007/demo?next=payments, SGF http://127.0.0.1:8008/demo?next=payments. Ctrl+C termina os servidores e remove os dados dessa execução. As funções sintéticas são Preparação, Validação e Consulta. Depois das provas o cenário estará em 8 600/1 000; o histórico mostra as etapas. Não há credenciais no relatório.

Limitações separadas

Visual: pendente, sem tentativa de navegador nesta entrega, por instrução expressa. HTTP/HTML, sintaxe JS e VM não comprovam cliques, foco, scroll, legibilidade ou ecrã estreito. O bloqueio anterior de política de URL do navegador Windows não foi contornado.

MFA: os dois ignorados anteriores, users with two factor enabled are redirected to two factor challenge e security page is displayed, continuam pendentes. Não estão nos 81 testes afectados executados agora e não constituem falhas do cálculo financeiro provado.

Âmbito: apenas reversão integral de uma afectação confirmada e nova afectação. Sem reversão parcial, cancelamento do pagamento, operação bancária, contabilidade, reconciliação, stock/orçamento adicional, importação de históricos ou habilitação pública. A proposta de reversão fica pendente até confirmação; não foi acrescentado circuito de rejeição/cancelamento da proposta. As demonstrações persistentes não receberam a actualização QA. Sem publicação, push ou checkpoint de encerramento. Falta revisão/aceitação do responsável; não se presume aceitação visual ou técnica deste incremento.