diff --git a/README.md b/README.md index ecf1fd3..67b5e87 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ Este é o projecto activo em `C:\laragon\www\compras`. Preserve a conta existent ## Executar localmente +Durante o desenvolvimento, use `composer run dev` e abra **http://127.0.0.1:8005/avaliar**. Este é o ambiente persistente com os menus organizados e os processos em avaliação. Escolha **Entrar como proprietário** ou o perfil operacional pretendido. O arranque reutiliza a avaliação existente e inicia o Vite quando necessário, sem migrações, seeds ou alterações de contas. + Conferência dos pagamentos pendentes após importação: [entrega e provas](docs/conferencia-pendentes-importados.md). Implementada em testes, com migração 000023 e activação ainda por aplicar; demonstração actual preservada. ### Explorar a aplicação sem palavra-passe @@ -14,17 +16,19 @@ Na demonstração local isolada, abrir **http://127.0.0.1:8005/avaliar** e escol A entrada pertence exclusivamente à base QA local existente de obrigações, com empresa e exemplos sintéticos; não altera contas/dados da instalação normal em 8015. As regras de aprovação independente e de integridade permanecem. O proprietário tem o perfil administrativo e as três acções do ensaio de obrigações; os passos reservados a Procurement, Finanças ou Armazém usam os perfis de avaliação disponíveis. Não se declara que todos os percursos já tenham exemplos completos nesta base. -Retomar o servidor existente, sem apagar dados: `powershell -NoProfile -ExecutionPolicy Bypass -File C:\laragon\www\sgf-tempo\scripts\payables-demo.ps1 start`. Se já estiver activo, basta abrir a ligação. Verificação HTTP: `scripts/evaluation-access-check.mjs`; resultados em `docs/proofs/evaluation-access.json` (20 páginas, seis perfis, CSRF, recusa de identificadores arbitrários e saída; sem operações de negócio). A revisão visual do utilizador é separada. +Retomar a avaliação existente, sem apagar dados: `composer run dev`. Se já estiver activa, basta abrir a ligação. O comando não provisiona outra base nem reinicia o SGF. Verificação HTTP: `scripts/evaluation-access-check.mjs`; resultados em `docs/proofs/evaluation-access.json` (20 páginas, seis perfis, CSRF, recusa de identificadores arbitrários e saída; sem operações de negócio). A revisão visual do utilizador é separada. -Endereço local deste projecto: **http://127.0.0.1:8015**. Use `SERVER_PORT=8015`, `APP_URL=http://127.0.0.1:8015` e `SESSION_COOKIE=procuraflow_session` no `.env` para evitar colisões com outros projectos. O comando `php artisan serve` respeita `SERVER_PORT`. +Instalação habitual separada: **http://127.0.0.1:8015**, com autenticação e dados próprios, preservada no `.env`. O arranque antigo permanece disponível explicitamente como `composer run dev:standard`; não é a entrada de avaliação usada durante o desenvolvimento. -As dependências e o `.env` devem estar configurados. O projecto suporta a ligação PostgreSQL existente; os testes usam SQLite em memória. +### Preparação da instalação habitual, quando pretendida + +As dependências e o `.env` devem estar configurados. O projecto suporta a ligação PostgreSQL existente; os testes usam SQLite em memória. Esta preparação é separada da avaliação persistente usada no desenvolvimento. ```sh php artisan migrate npm install npm run build -composer dev +composer run dev:standard ``` Abra a aplicação, registe uma conta e configure a empresa no painel. A primeira conta torna-se administradora exclusivamente da empresa que cria. Em **Empresa e equipa**, adicione departamentos, centros de custo e utilizadores com os perfis necessários. Contas registadas publicamente não entram automaticamente numa empresa existente. diff --git a/composer.json b/composer.json index 2f3bcc6..4e7400e 100644 --- a/composer.json +++ b/composer.json @@ -52,6 +52,10 @@ "npm run build" ], "dev": [ + "Composer\\Config::disableProcessTimeout", + "@php scripts/dev-evaluation.php" + ], + "dev:standard": [ "Composer\\Config::disableProcessTimeout", "@php artisan dev" ], @@ -115,4 +119,4 @@ }, "minimum-stability": "stable", "prefer-stable": true -} \ No newline at end of file +} diff --git a/docs/desenvolvimento.md b/docs/desenvolvimento.md index 69b9320..b412eb4 100644 --- a/docs/desenvolvimento.md +++ b/docs/desenvolvimento.md @@ -1,5 +1,29 @@ # Desenvolvimento do SGC +## Paridade com o domínio pedida pela Tempo — 30 de Outubro de 2026 + +Requisito expresso: a versão vista localmente deve corresponder à de `www.compras.tempo.co.mz`, incluindo menus, dropdowns, visual e processos. A avaliação local passa a ser a referência da apresentação entregue; a aceitação exige conferir a mesma revisão e os assets, com diferenças de configuração/activação documentadas. Preservar dados e acessos de cada ambiente; não publicar os perfis sintéticos sem palavra-passe por consequência desta orientação. + +Conferência apenas de leitura: a pasta local está em main `4654268`, com as alterações de arranque e menu desta sessão ainda não enviadas/instaladas. Os documentos existentes distinguem pagamentos/afectações sintéticos em 8005/8006 da instalação habitual; `SupplierPayables` confirma guardas de ambiente/base para esses recortes. Logo, não há prova de equivalência funcional integral por partilhar os componentes React. O domínio com `www` não resolveu no DNS deste computador; o domínio sem `www` respondeu HTTP200 a curl (outra ferramenta recebeu HTTP403), sem inspecção autenticada ou identificação segura da revisão instalada. A pesquisa nos ficheiros consultados não identificou o instalador/acesso do servidor de Compras. Nenhuma publicação, alteração de DNS, flags remotas, contas ou dados foi feita. + +Para concluir a entrega equivalente: identificar o processo e acesso de instalação de Compras; comparar a revisão/schema/configuração/permissões e o âmbito dos fluxos hoje restritos à avaliação; preparar a candidata com as alterações locais; preservar o destino com backup/restauro antes da instalação; conferir assets/menus e percursos afectados no domínio. Resolver também o acesso ao nome `www`. A orientação está registada, mas a instalação e a paridade remota continuam pendentes. + +## Menu horizontal com dropdowns — 30 de Outubro de 2026 + +Pedido expresso: colocar o menu na horizontal, mantendo dropdowns e o visual. `SgcWorkspaceShell` passa a apresentar os grupos no topo em ecrãs grandes, com os componentes dropdown já existentes. Mantidos fundo escuro, identidade SGC, cores, ícones, destaque do destino activo, grupos, ordem, destinos e filtros por perfil. A pesquisa continua a filtrar as opções; os destinos de página completa conservam esse comportamento. A área de conteúdo deixa de reservar espaço para o menu lateral. Em ecrãs pequenos mantém-se o painel móvel; Aparência e Página inicial continuam acessíveis. + +Verificações dirigidas: TypeScript, lint do componente, formatação e `git diff --check` aprovados; módulo actualizado servido pelo Vite com HTTP200. Sem alterações de backend, processos ou permissões. Não foram repetidos testes de negócio por esta alteração de apresentação. Conferência visual do navegador não executada nesta passagem: o conector devolveu «The browser access host is unavailable». A alteração está disponível na avaliação 8005 com o Vite activo; não representa aceitação visual dos restantes processos. + +## Entrada de desenvolvimento na avaliação persistente — 30 de Outubro de 2026 + +Pedido expresso: durante o desenvolvimento, mostrar a versão de avaliação com os menus organizados e os processos avançados, não a instalação habitual sem acesso do utilizador. A comparação confirmou que os menus/processos estavam preservados no código; a diferença era a entrada 8015 versus a avaliação existente em 8005. + +`composer run dev` passa a executar `scripts/dev-evaluation.php`: confere a configuração QA existente, reutiliza a avaliação em 8005 ou retoma apenas esse servidor com o router existente, e inicia/reutiliza o Vite de Compras. Entrada apresentada: **http://127.0.0.1:8005/avaliar**, com «Entrar como proprietário» e os perfis existentes. O APP_URL do processo Vite é 8005, sem alterar o `.env`. Não inicia a fila habitual; não provisiona bases, aplica migrações, executa seeds, cria contas ou altera permissões. A instalação habitual permanece disponível explicitamente como `composer run dev:standard`. + +Verificações: sintaxe PHP, Pint dirigido, `composer validate --no-check-publish` e `git diff --check` aprovados. `--check` reconheceu a avaliação existente; arranque completo pelo Composer aprovado, reutilizando o servidor 8005 e iniciando o Vite em 127.0.0.1:5173. `/avaliar` e `/@vite/client` responderam HTTP200; terminal indica APP_URL8005. A sessão habitual iniciada nesta assistência foi terminada; nenhum processo alheio foi terminado e o servidor de avaliação existente foi preservado. O caminho de arranque com 8005 parado está implementado, mas não foi ensaiado interrompendo o servidor persistente do utilizador. + +Ficheiros: `composer.json`, `scripts/dev-evaluation.php`, README e orientações de continuidade. Sem alterações aos módulos funcionais, dados, credenciais ou ambiente do SGF. Esta conferência de arranque não substitui a avaliação visual e operacional dos processos. + ## Reforço da integração de obrigações — 29 de Outubro de 2026 Continuação do ensaio `COMMON-PAYABLE-SOURCE-SIM-v1`, descrito em diff --git a/docs/menus-benchmark-20261029.md b/docs/menus-benchmark-20261029.md index 6e18419..8484914 100644 --- a/docs/menus-benchmark-20261029.md +++ b/docs/menus-benchmark-20261029.md @@ -1,5 +1,7 @@ # Menus de Compras — primeira aplicação do benchmark +**Actualização de apresentação, 30/10/2026:** por pedido do proprietário, a navegação autenticada foi colocada na horizontal em ecrãs grandes, com dropdowns e o mesmo visual escuro, grupos, ícones, pesquisa e regras por perfil. O painel móvel mantém-se. Este estado substitui apenas a disposição lateral descrita no registo histórico abaixo; não altera os processos ou permissões. Tipos, lint, formatação e módulo Vite aprovados; conferência visual desta alteração ainda não executada por indisponibilidade do conector do navegador. + 29/10/2026. Pedido do proprietário: renovar os menus antes de retomar o trabalho funcional pendente. Referência fornecida: `referencias/benchmark-menus-20261029.txt`. Este incremento aplica a organização da navegação; não declara implementado todo o benchmark. ## Entregue diff --git a/docs/orientacoes-continuidade.md b/docs/orientacoes-continuidade.md index 3f10288..e3c2086 100644 --- a/docs/orientacoes-continuidade.md +++ b/docs/orientacoes-continuidade.md @@ -1,5 +1,9 @@ # Continuidade do desenvolvimento do SGC +**Paridade de versão local/domínio — decisão da Tempo, 30/10/2026:** a versão acompanhada pelo utilizador durante o desenvolvimento é a referência para `www.compras.tempo.co.mz`: mesmos menus horizontais/dropdowns, visual e implementação dos processos. Não apresentar uma interface antiga como entrega equivalente. Conferir revisão, assets, flags e dependências de cada percurso antes de declarar paridade; dados, identidades e permissões existentes de cada ambiente devem ser preservados. O acesso sem palavra-passe e os perfis sintéticos da avaliação local não foram autorizados no domínio por este pedido. Pagamentos e outros recortes limitados à avaliação exigem reconciliação explícita do âmbito, não mera cópia de flags ou de dados QA. As alterações locais desta sessão ainda não foram enviadas/instaladas e não há confirmação de paridade no servidor. Na leitura de 30/10, o nome com `www` não resolveu por DNS; o endereço sem `www` respondeu a curl, mas isso não confirma a revisão ou os percursos autenticados. O processo/acesso de instalação de Compras não está identificado nos ficheiros de entrega consultados; não reutilizar por inferência o instalador do InvesteMoz. + +**Entrada de desenvolvimento definida pela Tempo, 30/10/2026:** o utilizador quer acompanhar a avaliação persistente com menus organizados e processos avançados em **http://127.0.0.1:8005/avaliar**, com «Entrar como proprietário» e os perfis existentes. `composer run dev` usa agora essa avaliação e o Vite; não inicia a instalação habitual em 8015 nem a respectiva fila. Não voltar a apresentar 8015 como entrada normal de desenvolvimento. O arranque reutiliza os dados/configuração QA já existentes, sem provisionamento, migrações, seeds, alteração de contas ou reinício do SGF. A instalação habitual mantém-se separada e só arranca explicitamente com `composer run dev:standard`. Implementação em `scripts/dev-evaluation.php`; verificações e limites no registo de 30/10 em `desenvolvimento.md`. + **Pagamentos e afectações sintéticos, 29/10/2026:** percurso comum disponível apenas nas demonstrações isoladas 8005/8006, com preparação, confirmação independente e afectação explícita. Prova nas duas composições e preservação por hashes aprovadas; revisão visual/manual pendente. Sem migração habitual, utilização real ou novos pagamentos sobre importações históricas. Ver [relatório do núcleo comum](../../sgf-tempo/docs/SUPPLIER_SETTLEMENT_DELIVERY.md). diff --git a/resources/js/components/sgc-workspace-shell.tsx b/resources/js/components/sgc-workspace-shell.tsx index 64b3e92..54c1499 100644 --- a/resources/js/components/sgc-workspace-shell.tsx +++ b/resources/js/components/sgc-workspace-shell.tsx @@ -13,6 +13,7 @@ import { Button } from '@/components/ui/button'; import { DropdownMenu, DropdownMenuContent, + DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import { @@ -76,7 +77,7 @@ export function SgcWorkspaceShell({ children }: { children: ReactNode }) { SGC @@ -253,18 +254,13 @@ export function SgcWorkspaceShell({ children }: { children: ReactNode }) { ); return ( -
+
Saltar para o conteúdo - -
-
-
- -
-

- COMPRAS -

-

- {page.url.split('?')[0] === '/dashboard' - ? 'Painel inicial' - : (activeGroup?.label ?? - 'Espaço de trabalho')} -

-
-
- {searchField()} -
- - {user && ( - - - + + + {group.entries.map((entry) => ( + + {entry.fullPage ? ( + + {entry.label} + + ) : ( + + {entry.label} + + )} + + ))} + + + ))} + {query && + visibleGroups.length === 0 && + !normalize( + 'Painel inicial Visão geral', + ).includes(query) && ( +

+ Nenhuma opção encontrada. +

+ )} + +
+
+
+ +
+

+ COMPRAS +

+

+ {page.url.split('?')[0] === '/dashboard' + ? 'Painel inicial' + : (activeGroup?.label ?? + 'Espaço de trabalho')} +

+
+
+ {searchField()} +
+ + {user && ( + + + - - - - - - )} + + + + + + + + )} +
@@ -362,6 +460,15 @@ export function SgcWorkspaceShell({ children }: { children: ReactNode }) {
SGC · Sistema de Gestão de Compras + + Aparência + + + Página inicial +
diff --git a/scripts/dev-evaluation.php b/scripts/dev-evaluation.php new file mode 100644 index 0000000..c57c1d4 --- /dev/null +++ b/scripts/dev-evaluation.php @@ -0,0 +1,105 @@ + [ + 'timeout' => 3, 'follow_location' => 0, + ]])); +} + +try { + if (! is_file($settingsFile) || ! is_file($router)) { + throw new RuntimeException('A configuração da avaliação existente não está disponível. Nenhuma base foi criada ou alterada.'); + } + $settings = json_decode(file_get_contents($settingsFile), true, 32, JSON_THROW_ON_ERROR); + if (($settings['APP_ENV'] ?? '') !== 'payable-testing' + || ($settings['DB_HOST'] ?? '') !== '127.0.0.1' + || ! preg_match('/^compras_receipts_test_[a-f0-9]{12}$/D', $settings['DB_DATABASE'] ?? '') + || realpath($settings['HOST_ROOT'] ?? '') !== realpath($root)) { + throw new RuntimeException('A configuração não corresponde à avaliação isolada de Compras. Arranque cancelado.'); + } + + $response = evaluationResponse($entry); + if ($response === false || ! str_contains($response, 'Explorar Compras')) { + $port = @stream_socket_client('tcp://127.0.0.1:8005', $code, $message, 1); + if (is_resource($port)) { + fclose($port); + throw new RuntimeException('A porta 8005 está ocupada, mas não responde como avaliação de Compras. Nenhum processo foi terminado.'); + } + if (in_array('--check', $argv, true)) { + throw new RuntimeException('A avaliação não está em execução. Use composer run dev para a retomar.'); + } + $children['avaliação'] = new Process([PHP_BINARY, '-S', '127.0.0.1:8005', '-t', 'public', $router], $root, ['PAYABLE_SETTINGS_FILE' => $settingsFile], timeout: null); + $children['avaliação']->start(); + for ($attempt = 0; $attempt < 50; $attempt++) { + usleep(100000); + $response = evaluationResponse($entry); + if ($response !== false && str_contains($response, 'Explorar Compras')) { + break; + } + if (! $children['avaliação']->isRunning()) { + break; + } + } + if ($response === false || ! str_contains($response, 'Explorar Compras')) { + throw new RuntimeException('Não foi possível retomar a avaliação existente. Consulte o arranque local; os dados foram preservados.'); + } + } + + fwrite(STDOUT, "Compras — ambiente de desenvolvimento e avaliação\n$entry\nEscolha «Entrar como proprietário» ou um perfil de avaliação.\nMesma base persistente; sem migrações, seeds ou redefinição de contas.\n"); + if (! in_array('--check', $argv, true)) { + $hot = is_file($root.'/public/hot') ? trim(file_get_contents($root.'/public/hot')) : ''; + $host = parse_url($hot, PHP_URL_HOST); + $viteReady = in_array($host, ['127.0.0.1', 'localhost', '[::1]'], true) + && ($module = evaluationResponse($hot.'/resources/js/app.tsx')) !== false + && str_contains($module, 'SgcShell'); + if (! $viteReady) { + $children['vite'] = Process::fromShellCommandline('npm.cmd run dev -- --host 127.0.0.1', $root, ['APP_URL' => 'http://127.0.0.1:8005'], timeout: null); + $children['vite']->start(); + } else { + fwrite(STDOUT, "Vite de Compras já disponível; reutilizado.\n"); + } + if (function_exists('sapi_windows_set_ctrl_handler')) { + sapi_windows_set_ctrl_handler(function () use (&$stop): bool { + $stop = true; + + return true; + }); + } + while ($children && ! $stop) { + foreach ($children as $name => $process) { + fwrite(STDOUT, $process->getIncrementalOutput()); + fwrite(STDERR, $process->getIncrementalErrorOutput()); + if (! $process->isRunning()) { + $status = $process->getExitCode() ?? 1; + $stop = true; + } + } + usleep(100000); + } + } +} catch (Throwable $error) { + fwrite(STDERR, $error->getMessage()."\n"); + $status = 1; +} finally { + foreach ($children as $process) { + if ($process->isRunning()) { + $process->stop(2); + } + } +} +exit($status);