@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Services\SupplierPayables;
|
||||
use Tempo\Finance\Payables\SettlementHttp;
|
||||
|
||||
final class SupplierPaymentsController extends SettlementHttp
|
||||
{
|
||||
protected const MODE = 'compras';
|
||||
|
||||
protected const SERVICE = SupplierPayables::class;
|
||||
}
|
||||
@@ -120,6 +120,7 @@ final class SupplierPayables
|
||||
$engine = $this->engine($u);
|
||||
$d = $engine->listing(Invoice::query()->where('tenant_id', $u->tenant_id)->pluck('id')->all());
|
||||
$d['permissions'] = ['prepare' => $this->can($u, 'prepare'), 'validate' => $this->can($u, 'validate')];
|
||||
$d['payments_available'] = app()->environment('payable-testing') && Schema::hasTable('ps_payments') && $this->can($u, 'payments_view');
|
||||
$d['history_import_available'] = self::historyEnabled();
|
||||
$d['history_decisions_available'] = self::historyDecisionsEnabled();
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# Continuidade do desenvolvimento do SGC
|
||||
|
||||
**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).
|
||||
|
||||
|
||||
**Conferência posterior dos pendentes implementada, 29/10/2026:** confirmação/rejeição ligada ao núcleo comum com decisão imutável, saldo único e escrita original atómica. Provas SQLite e PostgreSQL descartável, incluindo dois pedidos simultâneos e reversão de falha, aprovadas. Ver [entrega](conferencia-pendentes-importados.md). Migração 000023 e opção de conferência preparadas, ainda não aplicadas/activadas em `compras_dev` ou 8005; importação local anterior preservada. Substitui a pendência de desenvolver esta conferência, sem novos pagamentos/transferências.
|
||||
|
||||
**Aplicação/activação histórica local concluída, 29/10/2026:** após «continue», 000022 aplicada em `compras_dev`, lote 23, e flag histórica activada, após backup/restauro das 72 tabelas. Registos/restrições preservados, duas tabelas novas vazias e dois triggers verificados. Activação auditada sem novas contas/concessões ou alteração de identidade; zero facturas/pagamentos/obrigações e nenhuma incorporação automática. Ver `historico-migracao-000022.json`, `historico-activacao-local.json` e [relatório](passagem-historico-pagamentos.md). Demo 8005 permanece sem esta migração/activação, confirmada em leitura; restantes demos e público preservados. Substitui apenas as indicações históricas de aplicação/activação pendentes abaixo. Novos pagamentos e decisão de pendentes depois da passagem continuam incremento próprio.
|
||||
|
||||
@@ -56,6 +56,7 @@ export function AppSidebar() {
|
||||
...(canReadPurchases
|
||||
? [
|
||||
{ title: 'Fornecedores', href: '/fornecedores', icon: Users },
|
||||
{ title: 'Avaliação de fornecedores', href: '/fornecedores/avaliacoes', icon: Users },
|
||||
{ title: 'Cotações', href: '/cotacoes', icon: Scale },
|
||||
{
|
||||
title: 'Ordens de compra',
|
||||
|
||||
@@ -113,6 +113,12 @@ export function procurementNavigation(
|
||||
path: '/fornecedores',
|
||||
roles: readers,
|
||||
},
|
||||
{
|
||||
id: 'supplier_evaluations',
|
||||
label: 'Avaliação de fornecedores',
|
||||
path: '/fornecedores/avaliacoes',
|
||||
roles: readers,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,39 @@
|
||||
import { Head } from '@inertiajs/react';
|
||||
import { useState } from 'react';
|
||||
import { PageTitle, Panel } from '@/components/procurement';
|
||||
import proposal from './evaluation-proposal';
|
||||
|
||||
const areas = [
|
||||
['Avaliações planeadas', 'Definir fornecedor, período, âmbito e responsáveis pela avaliação.'],
|
||||
['Nova avaliação', 'Identificar contratos e ordens abrangidas, escolher a grelha de bens ou serviços e reunir notas, justificações e evidências.'],
|
||||
['Rascunhos', 'Preparar a avaliação e completar evidências antes de submeter para revisão.'],
|
||||
['Avaliações em revisão', 'Conferência independente, com devolução para correcção ou aprovação documentada.'],
|
||||
['Avaliações aprovadas', 'Consultar versões aprovadas; rectificações devem gerar revisão identificável.'],
|
||||
['Histórico por fornecedor', 'Consultar a evolução, observações e contestações com decisão documentada. Comparar apenas âmbitos e grelhas equivalentes.'],
|
||||
['Planos de melhoria', 'Acompanhar acções, responsáveis, prazos, evidências de conclusão e validação de eficácia.'],
|
||||
['Relatórios de avaliação', 'Ficha por fornecedor e período, resultados por critério, ocorrências críticas e cobertura de evidências.'],
|
||||
];
|
||||
export default function SupplierEvaluations() {
|
||||
const [selected, setSelected] = useState(0);
|
||||
return <>
|
||||
<Head title="Avaliação de fornecedores" />
|
||||
<div className="space-y-6 p-4 md:p-8">
|
||||
<PageTitle eyebrow="Fornecedores" title="Avaliação de fornecedores" description="Acompanhamento da prestação da entidade fornecedora durante ou após o fornecimento." />
|
||||
<div className="rounded-xl border border-amber-300 bg-amber-50 p-4 text-sm text-amber-950">
|
||||
Proposta funcional para validação da organização. As áreas abaixo descrevem o circuito previsto; o registo e a aprovação de avaliações ainda não estão disponíveis. Pesos, escala e limiares são ilustrativos.
|
||||
</div>
|
||||
<nav aria-label="Áreas da avaliação de fornecedores" className="flex flex-wrap gap-2">
|
||||
{areas.map(([label], index) => <button key={label} type="button" aria-pressed={selected === index} onClick={() => setSelected(index)} className={`rounded-lg border px-4 py-2 text-sm ${selected === index ? 'bg-primary text-primary-foreground' : 'bg-card hover:bg-muted'}`}>{label}</button>)}
|
||||
</nav>
|
||||
<Panel title={areas[selected][0]} description={areas[selected][1]}>
|
||||
<p className="text-sm text-muted-foreground">Área prevista na proposta. Não são apresentados resultados de fornecedores reais.</p>
|
||||
</Panel>
|
||||
<Panel title="Proposta funcional completa" description="Qualificação verifica elegibilidade; avaliação analisa o cumprimento efectivo. Uma pontuação não suspende nem exclui automaticamente um fornecedor.">
|
||||
<details><summary className="cursor-pointer font-medium">Consultar campos, grelhas, evidências e regras propostas</summary>
|
||||
<div className="mt-4 whitespace-pre-wrap text-sm leading-7">{proposal}</div>
|
||||
</details>
|
||||
</Panel>
|
||||
</div>
|
||||
</>;
|
||||
}
|
||||
SupplierEvaluations.layout = { breadcrumbs: [{ title: 'Fornecedores', href: '/fornecedores' }, { title: 'Avaliação de fornecedores', href: '/fornecedores/avaliacoes' }] };
|
||||
@@ -41,7 +41,15 @@ Route::middleware(['auth', 'verified'])->group(function () {
|
||||
Route::post('empresa/iniciar', [CompanyController::class, 'store'])->name('company.store');
|
||||
|
||||
Route::middleware(EnsureCompanyIsConfigured::class)->group(function () {
|
||||
Route::get('fornecedores/avaliacoes', function (\Illuminate\Http\Request $request) {
|
||||
abort_unless(in_array($request->user()->purchasing_role, [\App\Enums\PurchasingRole::Admin, \App\Enums\PurchasingRole::Procurement, \App\Enums\PurchasingRole::Finance, \App\Enums\PurchasingRole::DepartmentHead]), 403);
|
||||
|
||||
return \Inertia\Inertia::render('suppliers/evaluations');
|
||||
})->name('suppliers.evaluations');
|
||||
Route::get('obrigacoes-fornecedores', [\App\Http\Controllers\SupplierPayablesController::class,'page']);
|
||||
Route::get('supplier-payments', [\App\Http\Controllers\SupplierPaymentsController::class,'page']);
|
||||
Route::get('api/supplier-payments', [\App\Http\Controllers\SupplierPaymentsController::class,'index']);
|
||||
Route::post('api/supplier-payments/{action}', [\App\Http\Controllers\SupplierPaymentsController::class,'command'])->whereIn('action',['payment-prepare','payment-decide','allocation-prepare','allocation-decide']);
|
||||
Route::get('api/supplier-payables', [\App\Http\Controllers\SupplierPayablesController::class,'index']);
|
||||
Route::post('api/supplier-payables/{action}', [\App\Http\Controllers\SupplierPayablesController::class,'command'])->whereIn('action',['prepare','validate','prepare_history','validate_history']);
|
||||
Route::get('politica-recomendacao', [FormalRecommendationController::class, 'policy'])->name('recommendations.policy');
|
||||
|
||||
Reference in New Issue
Block a user