environment('payable-testing') && $db->getDriverName() === 'pgsql' && $db->getConfig('host') === '127.0.0.1' && preg_match('/^(compras_receipts_test_|payable_sgf_)[a-f0-9]{12}$/D', $db->getDatabaseName()) && $db->selectOne('select current_database() as d')->d === $db->getDatabaseName(), 403); }; Route::middleware('web')->group(function () use ($guardDemo, $isSgf, $destination) { Route::get('/demo', function (Request $r) use ($guardDemo, $isSgf, $destination) { $guardDemo(); $next = $r->query('next') === 'payments' ? 'payments' : 'obligations'; $continue = $next === 'payments' ? '/supplier-payments' : $destination; $e = static fn ($v) => htmlspecialchars((string) $v, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); $title = $isSgf ? 'SGF — demonstração' : 'Compras — demonstração'; $html = ''.$title.'

'.$title.'

Entre para experimentar e identificar melhorias. Não precisa de conta nem de palavra-passe.

Escolha a função que quer experimentar

Todos os dados são sintéticos. A função escolhida determina as acções disponíveis.

'; foreach (['preparacao' => ['Preparar', 'Consultar a factura e propor a obrigação, o pagamento sintético ou a afectação.'], 'validacao' => ['Validar', 'Rever e decidir propostas preparadas por outra identidade sintética.'], 'consulta' => ['Consultar', 'Explorar valores, origem e histórico, sem alterar dados.']] as $role => [$label, $description]) { $html .= '
'.$description.'
'; } $html .= '

O que experimentar

Factura: base de 10 000 MZN + imposto documental de 1 600 MZN = 11 600 MZN. Preparar, trocar para validar e consultar o resultado. Repetir deve recuperar a mesma obrigação.

Depois, em Pagamentos e afectações: preparar 4 000 MZN, confirmar com outra identidade e conferir que a dívida continua em 11 600 MZN. Só a afectação confirmada de 4 000 MZN reduz o saldo para 7 600 MZN.

O vencimento permanece pendente e o atraso indeterminado. Não há execução bancária. Datas e referências do ensaio devem ser sintéticas; o cenário partilhado conserva as operações anteriores, sem reiniciar os valores a cada visita.

As funções usam identidades de demonstração partilhadas; não identificam a pessoa real que está a testar. O cenário e o histórico são partilhados e conservados entre visitas.

'; if ($r->user()) { $html .= '

Sessão actual: '.$e($r->user()->name).' · Continuar o percurso · Abrir a aplicação

'; } return response($html.'
')->header('Cache-Control', 'no-store')->header('X-Robots-Tag', 'noindex, nofollow'); }); Route::post('/demo/entrar', function (Request $r) use ($guardDemo, $isSgf, $destination) { $guardDemo(); $d = $r->validate(['role' => 'required|in:preparacao,validacao,consulta', 'next' => 'sometimes|in:payments,obligations']); abort_if(array_diff(array_keys($r->all()), ['role', '_token', 'next']) !== [], 422); // No arbitrary user identifier or permissions may be supplied by a visitor. $u = User::where('email', $d['role'].'-obrigacoes@example.test')->firstOrFail(); $grants = DB::table('pa_access')->where(['user_id' => $u->id, 'action' => 'view'])->get(); abort_unless($grants->count() === 1, 403); $g = $grants->first(); if ($isSgf) { app(\App\Shared\Context\CompanyContext::class)->selectFor($u->id, $g->tenant_id, $g->company_id, $g->unit_id); } else { abort_unless((int) $u->tenant_id === (int) $g->tenant_id && (int) $g->company_id === 0 && (int) $g->unit_id === 0, 403); } Auth::logout(); $r->session()->invalidate(); $r->session()->regenerateToken(); Auth::login($u, false); $r->session()->regenerate(); $r->session()->put('payables_demo_entry', true); if ($isSgf) { $r->session()->put('auth_version', (int) $u->auth_version); $r->session()->put('company_context', ['tenant_id' => (int) $g->tenant_id, 'company_id' => (int) $g->company_id, 'unit_id' => (int) $g->unit_id, 'token' => bin2hex(random_bytes(24))]); \App\Modules\Identity\Services\Audit::record('demo.entered', $u->id, $g->tenant_id, $g->company_id, $g->unit_id, details: ['role' => $d['role'], 'synthetic' => true]); } return redirect(($d['next'] ?? '') === 'payments' ? '/supplier-payments' : $destination); })->middleware('throttle:30,1'); Route::post('/demo/sair', function (Request $r) use ($guardDemo) { $guardDemo(); Auth::logout(); $r->session()->invalidate(); $r->session()->regenerateToken(); return redirect('/demo'); }); });