import React, { useEffect, useState } from 'react';
const kinds={plan:'Plano da empresa',account:'Conta empresarial',category:'Categoria e regra-base',service_link:'Ligação do serviço à categoria',service_override:'Excepção explícita por serviço'};
const states={draft:'Proposta em preparação',submitted:'Submetida — aguarda validação',approved:'Aprovada — verificar vigência',refused:'Recusada'};
const labels={plan:'Plano',source_version:'Versão documental',plan_id:'Versão do plano aprovada',code:'Código da conta',name:'Designação',origin:'Origem da conta',movable:'Admite movimento após validação',evidence:'Fundamento e prova da conta empresarial',account_id:'Conta aprovada',conditions:'Condições e exclusões',service_id:'Serviço existente',category_id:'Categoria aprovada'};
function Decision({row,can,busy,act}) {
const [reason,setReason]=useState('');
if(row.state!=='submitted'||!can('catalogue_accounting.approve'))return null;
return
;
}
export default function CatalogueAccountingWorkspace({context,can,api,perform,busy}) {
const [list,setList]=useState(null),[error,setError]=useState(''),[kind,setKind]=useState('plan'),[data,setData]=useState({}),[previous,setPrevious]=useState(null),[replaces,setReplaces]=useState(''),[from,setFrom]=useState(''),[until,setUntil]=useState(''),[reason,setReason]=useState('');
const [service,setService]=useState(''),[date,setDate]=useState(''),[resolution,setResolution]=useState(null),[area,setArea]=useState('service_drafts'),[operations,setOperations]=useState([]),[operation,setOperation]=useState(''),[history,setHistory]=useState([]);
const prefix='/api/catalogue-accounting';
async function load(){setList(await api(prefix));}
useEffect(()=>{load().catch(e=>setError(e.message));},[context.token]);
async function act(path,body) {await perform(async()=>{await api(prefix+path,'POST',body,context.token,crypto.randomUUID());await load();},'Operação de classificação guardada; sem lançamentos.');}
function fresh(type){setKind(type);setData(type==='plan'?{plan:'PGC-NIRF',source_version:list.reference.source_version}:type==='account'?{origin:'enterprise',movable:false}:{});setPrevious(null);setReplaces('');setFrom('');setUntil('');setReason('');}
function revise(row){setKind(row.kind);setData({...row.data});setPrevious(row);setReplaces('');setFrom('');setUntil('');setReason('');}
if(!can('catalogue_accounting.view'))return
Categoria como regra-base; só uma excepção aprovada, vigente e compatível a substitui. Correcções e mudanças de categoria exigem nova versão e validação.
{error&&
{error}
}
Referências documentais disponíveis
{list.reference.source_version}
{list.reference.status}
{list.reference.accounts.map(a=>
{a.code} — {a.name} · referência agregadora, sem movimento
)}
Não há conta de movimento empresarial criada por omissão. Quem prepara propõe o desdobramento documentado; quem valida decide.
{can('catalogue_accounting.propose')&&
{previous?`Nova versão da proposta #${previous.id}`:'Preparar proposta'}
}
Propostas, submissões e decisões
{!rows.length&&
Nenhuma proposta nesta empresa.
}{[...rows].reverse().map(row=>
{title(row)}
{states[row.state]} · {row.valid_from} até {row.valid_until||'sem termo definido'} · Autor #{row.actor_id}
{Object.entries(row.data).map(([k,v])=>
{labels[k]||k}
{displayField(k,v)}
)}
Fundamento: {row.reason}
{row.replaces_id&&
Substitui explicitamente a versão aprovada #{row.replaces_id}, a partir do início da nova vigência.
}{row.decision&&
Decisão por #{row.decision.actor_id}: {row.decision.reason}