# Oficina e Stock — repartição, devolução e histórico Continuação SGF: [retirada e recusa de propostas](WORKSHOP_STOCK_PROPOSAL_CLOSURE.md), sem efeito físico, com decisões imutáveis, concorrência e histórico paginado. Implementação posterior; os números e hashes desta entrega inicial permanecem como prova histórica. Continuação posterior: [percurso nativo de devolução e observação SGF](NATIVE_WAREHOUSE_RETURN_DELIVERY.md) implementado e comprovado em base isolada. A limitação histórica abaixo sobre comando nativo foi superada nesse incremento, sem modificar esta prova anterior ou declarar composição operacional instalada. 02/11/2026. `WORKSHOP-MATERIAL-CYCLE-SIM-v1`. Continuação local sintética da [ligação integral a uma entrega](WORKSHOP_DELIVERY_LINK.md). Foram acrescentadas a repartição entre consumos distintos, a devolução física de material ainda não consumido e a consulta paginada do histórico. Não foram activadas demonstrações ou capacidades reais. ## Fluxo e responsabilidade O mesmo livro físico mantém entradas, saídas e devoluções; não há segunda tabela de saldos. O percurso comprovado é: saldo inicial 10 UN → saída física de 5 → saldo 5 → associação de 2 ao consumo, sem novo débito → entrada física de 3 devolvidas → saldo 8. A entrada inicial é uma fixture; a prova anterior de recepção nativa de Compras continua separada. Não se declara um ERP único instalado desde procurement até Oficina. `POST /api/workshop-stock/prepare-allocation` confere uma origem integral de consumo contra a quantidade ainda não associada de uma entrega. Vários consumos podem partilhar a entrega; uma origem não é fraccionada por várias entregas. Cada origem mantém decisão, fundamento, evidência, preparador/confirmador e versão próprios. A prévia mostra o saldo físico inalterado e a quantidade ainda não associada antes/depois. `POST /api/workshop-stock/prepare-return` exige uma ocorrência própria `returned`, material da empresa e verificação técnica independente. Não transforma um consumo em devolução. Limita a quantidade por **entregue − associado a consumo − já devolvido**. A confirmação exige outra identidade, fundamento e `received_in_warehouse=true`, declarado expressamente na interface. O relato técnico sozinho não gera entrada. A fotografia da operação conserva essa declaração e a origem/verificação/evidência. O escritor canónico `packages/inventory-return/src/DeliveryReturnWriter.php` participa na transacção do host, exige autorização, fotografa/revalida a operação e a entrega original, bloqueia armazém/artigo/operação/entrega, verifica revisão do livro e quantidade cumulativa devolvida e grava uma única entrada `workshop_return_in`. Repetições recuperam o movimento. Não faz commit independente. O host conserva a regra mais restritiva de quantidade ainda não consumida/associada. Artefacto local imutável preparado em Compras, `packages/inventory-return/releases/0.1.0`, manifesto SHA-256 `2850a4f5cb678acfe3a9dbc7a7d62eb233bc72722ad0de374681c2679c90557c`. **A existência do artefacto não equivale à integração do comando de devolução nativo de Compras**, que permanece por adaptar. O leitor comum consulta o mesmo livro e vê a entrada; não se alterou a sua consulta SQL nem se repetiu a carga da leitura. ## Integridade e concorrência `ws_allocations` e `ws_returns` são registos append-only do ensaio. Não alteram `ws_claims` nem as suas unicidades anteriores. Uma entrega já ligada integralmente não pode também ser repartida ou devolvida. A origem e proposta não podem ser usadas duas vezes. A soma de repartições e devoluções não excede a entrega. Todas as decisões voltam a validar contexto, direitos, origem/versão/verificação, mapeamento, elegibilidade, livro e quantidade restante. A confirmação de outra proposta torna a prévia anterior desactualizada. Desactivar novas repartições não apaga a protecção das origens já associadas. Estornos, ajustes, transferências, lotes, reservas, peças e entregas sem hash original íntegro continuam recusados neste recorte. A concorrência foi exercitada com dois processos PHP e o bloqueador identificado por `pg_blocking_pids`. Nas repartições concorrentes de 3+3 contra uma entrega de 5, apenas 3 ficam associados; a segunda proposta recusa 409 após a libertação. Duas devoluções concorrentes de 3 contra 5 igualmente produzem uma só entrada de 3. As falhas injectadas após inserir a associação/decisão fazem rollback integral; a retoma não duplica efeitos. ## Histórico e permissões `GET /api/workshop-stock` mantém páginas de 25 origens e acrescenta `proposal_page` e `status=all|pending|confirmed` para páginas de 25 propostas. Ordenação por ID decrescente, isolamento por tenant/empresa/unidade e associação conjunta dos movimentos da página. Confirmadas inclui os três livros de decisões; não se limita às últimas 25 propostas. Parâmetros desconhecidos são recusados. A interface tem filtros e navegação independentes das páginas de origens. Reutilizam-se `workshop_stock.view/prepare/confirm`, além de `workshop.view` e `stock.view`, no contexto de Oficina e unidade correcta. Não houve concessões reais nem direitos públicos novos. `partial_delivery_links` e `stock_returns` não são activados por omissão. A guarda sintética e os esquemas locais explicitamente elegíveis permanecem obrigatórios. As novas tabelas/índices foram criados **apenas nas fixtures novas da regressão**, sem migração/índice no destino. ## Evidência Resultados seleccionados, hashes e pós-ensaio: [workshop-material-cycle-20261102.json](proofs/workshop-material-cycle-20261102.json). As provas válidas foram reutilizadas. As alterações posteriores de declaração de recepção e paginação motivaram apenas a execução dos casos afectados. Uma expectativa antiga de saldo na helper de concorrência foi corrigida; a execução intermédia que a revelou não foi tratada como suite aprovada. Consolidação: **22 testes distintos / 820 asserções aprovadas**, escolhendo a prova mais recente por caso e sem contar repetições duas vezes. A prova identifica cada execução e cada caso seleccionado. Nenhuma suite nativa alheia foi repetida. Cobertura: saldo e quantidade restante, múltiplas origens, repetição, recusa de auto-confirmação, limite cumulativo, alteração concorrente, recuperação após falha, ocorrência/propriedade/verificação incompatíveis, direito revogado, contexto antigo, empresa distinta, apresentação conjunta de decisões e paginação/ordenação/filtros. O caso de devolução comprova ainda o replay do escritor comum e a observação do resultado na consulta de Stock. Build e render estático dos impactos aprovados. A verificação da caixa obrigatória e dos controlos de histórico é de fonte; não se declara ensaio de interacção ou revisão visual. Nenhum navegador foi usado. O pós-ensaio verifica zero concessões temporárias, constraint original e zero fontes operacionais configuradas. ## Limitações separadas - Não se implementou fraccionar a mesma origem por várias entregas, nem libertar automaticamente uma associação confirmada quando o apontamento é corrigido. - Material já consumido não é recuperado por este percurso. Compensação/correcção física desse material exige um circuito próprio e evidência distinta; não se confunde com devolução de excedente não consumido. - A aceitação física neste ensaio é de quantidade simples, sem classificação de qualidade/quarentena, lotes ou reservas. Não valida configuração/papéis de armazém de um cliente real. - A instalação operacional das tabelas/fontes, o comando nativo de devolução de Compras, a composição integral numa demonstração única, outros drivers e a revisão visual continuam pendentes. Não há medição nova de carga da escrita nem capacidade de implantação validada. Seis registos protegidos, cache bloqueada, demonstrações, credenciais e alterações alheias preservados. Nenhuma publicação, candidata activada, operação real, aceitação ou checkpoint presumido.