Files
SGF/resources/js/AccountingMenuWorkspace.jsx
2026-11-11 09:00:17 +02:00

36 lines
8.7 KiB
React

import React,{useEffect,useState} from 'react';
import {accountingSections,visibleAccountingSections,accountingFunctions,accountingReports,filterAccountingReports} from './accounting-menu.js';
const ComposedAccountingWorkspace=React.lazy(()=>import('./ComposedAccountingWorkspace.jsx'));
export default function AccountingMenuWorkspace({section,context,can,navigate,api}) {
const [search,setSearch]=useState(''),[family,setFamily]=useState(''),[selected,setSelected]=useState(null);
useEffect(()=>{setSearch('');setFamily('');setSelected(null);},[context.token]);
if(!visibleAccountingSections(can).length)return <section className="panel"><h1>Contabilidade</h1><p>Sem contexto autorizado para esta consulta.</p></section>;
const active=accountingSections.find(s=>s.id===section);if(!active)return null;
const unit=context.unit?.id??null;
if(context.accounting?.single_book&&unit!==null&&can('general_ledger.view',unit))return <React.Suspense fallback={<p>A abrir Contabilidade…</p>}><ComposedAccountingWorkspace section={section} context={context} can={can} navigate={navigate} api={api}/></React.Suspense>;
const action=f=>f.target&&(!f.unit||unit!==null)&&can(f.permission,f.unit?unit:null)?<button onClick={()=>navigate(f.target)}>{f.action}</button>:null;
const functions=accountingFunctions.filter(f=>f.section===section);
const report=accountingReports.find(r=>r.id===selected);
return <div className="accounting-menu-workspace"><div className="page-title"><p className="eyebrow">CONTABILIDADE</p><h1>{active.label}</h1><p>{context.company.name}{context.unit?` / ${context.unit.name}`:''}</p></div>
<nav className="accounting-tabs" aria-label="Submenus de contabilidade">{visibleAccountingSections(can).map(s=><button key={s.id} aria-current={s.id===section?'page':undefined} onClick={()=>navigate(s.id)}>{s.label}</button>)}</nav>
<p className="alert home-notice">Navegação em preparação. Classificação contabilística, documentos, obrigações, liquidações e lançamentos têm responsabilidades distintas. Este menu não gera lançamentos ou declarações fiscais.</p>
{section==='accounting_panel'&&<>
<section className="panel"><h2>Trabalho contabilístico no contexto seleccionado</h2><p>Ainda não há fonte agregada de documentos por validar, contas por reconciliar ou estado do fecho. A indisponibilidade não é apresentada como zero pendências.</p><div className="accounting-routes">{accountingSections.filter(s=>s.id!==section).map(s=><button key={s.id} onClick={()=>navigate(s.id)}>{s.label}<span>Consultar percursos e disponibilidade →</span></button>)}</div></section>
<section className="panel"><h2>Percursos já disponíveis</h2><div className="actions">{can('catalogue_accounting.view')&&<button onClick={()=>navigate('catalogue_accounting')}>Classificação contabilística</button>}{can('service_fiscal.view')&&<button onClick={()=>navigate('service_fiscal')}>Perfis fiscais do serviço</button>}{unit!==null&&can('service_receivables.view',unit)&&<button onClick={()=>navigate('service_receivables')}>Recebimentos e reconciliação de teste</button>}</div><p>Estas ligações conservam os direitos e os limites dos respectivos módulos; não representam uma contabilidade geral já integrada.</p></section>
</>}
{context.accounting?.stock_valuation_read!==true&&unit!==null&&can('general_ledger.view',unit)&&<section className="panel"><h2>Primeiro lançamento contabilístico sintético</h2><p>Obrigação reconhecida → proposta → revisão independente → aplicação única. Duas contas e um período artificiais; sem utilização real, fecho ou contabilidade geral completa.</p><a href="/general-ledger">Abrir lançamento e extracto de ensaio</a></section>}
{context.accounting?.stock_valuation_read===true&&unit!==null&&can('stock.view',unit)&&can('general_ledger.view',unit)&&<section className="panel"><h2>Stock valorizado — consulta do livro de origem</h2><p>Quantidades físicas, valores contabilizados e pendências no mesmo livro QA. Esta consulta não executa movimentos ou lançamentos.</p><a href="/general-ledger/stock-valuation">Conferir stock e valorização</a></section>}
{functions.map(f=><section className="panel" key={f.id}><h2>{f.label}</h2><p>{f.description}</p><p><strong>Disponibilidade:</strong> {context.accounting?.stock_valuation_read===true&&['entries','balances'].includes(f.id)?'Consulta do mesmo livro de stock e valorização QA; confirmações e conferência completa na composição de origem.':unit!==null&&can('general_ledger.view',unit)&&['entries','balances'].includes(f.id)?'Primeiro percurso sintético de obrigação de fornecedor: lançamento equilibrado e extracto em duas contas artificiais. Não constitui contabilidade operacional, balancete legal, fecho ou demonstrações financeiras.':f.status}</p>{action(f)}</section>)}
{section==='accounting_daily'&&<section className="panel"><h2>Origem documental</h2><p>Documento recebido → preparação → classificação → conferência → validação → reconciliação → relatório → fecho. As etapas que ainda não têm implementação não são executadas por este menu.</p><div className="actions">{unit!==null&&can('billing_drafts.view',unit)&&<button onClick={()=>navigate('billing_drafts')}>Abrir rascunhos de facturação existentes</button>}{unit!==null&&can('supplier_payables.view',unit)&&<button onClick={()=>navigate('supplier_payables')}>Abrir obrigações a fornecedores de teste</button>}</div><p>Uma obrigação com principal reconhecido e vencimento desconhecido continua sem classificação automática de atraso. Preparar ou aprovar um pagamento não comprova execução bancária.</p></section>}
{section==='accounting_analysis'&&<section className="panel"><h2>Catálogo de relatórios previstos</h2><p>Catálogo para orientar a implementação. Não contém relatórios gerados, saldos, dados salariais ou bancários.</p><div className="form-grid"><label>Pesquisar relatório<input type="search" value={search} onChange={e=>setSearch(e.target.value)}/></label><label>Área<select value={family} onChange={e=>setFamily(e.target.value)}><option value="">Todas as áreas</option>{[...new Set(accountingReports.map(r=>r.family))].map(f=><option key={f}>{f}</option>)}</select></label></div>
<div className="accounting-report-list">{filterAccountingReports(search,family).map(r=><button key={r.id} aria-pressed={r.id===selected} onClick={()=>setSelected(r.id)}>{r.label}<small>{r.family} · Por implementar</small></button>)}</div>{!filterAccountingReports(search,family).length&&<p>Nenhuma definição de relatório corresponde à pesquisa. Isto não é uma consulta de movimentos.</p>}
{report&&<article className="accounting-report-detail"><h3>{report.label}</h3><p>{report.description}</p><p role="status"><strong>Relatório indisponível.</strong> Falta a fonte contabilística/auxiliar validada e a configuração aplicável. Não há geração, impressão ou exportação nesta página.</p><p>Filtros previstos: empresa, período ou data de referência, moeda e dimensões efectivamente aplicáveis. Os resultados e as exportações terão as mesmas restrições de acesso, com ligação aos documentos de origem.</p></article>}
<p>Não se misturam empresas, períodos ou moedas sem base consistente. Rascunhos, movimentos validados e previsões não são somados como se fossem equivalentes. As demonstrações serão reconciliadas com razão e balancete.</p>
</section>}
{section==='accounting_configuration'&&<section className="panel"><h2>Fiscalidade separada da entrada e da classificação</h2><p>O menu não adopta regras fiscais a partir de referências comerciais ou da comparação com outros produtos. Os perfis fiscais existentes mantêm as suas versões, decisões e bloqueios próprios.</p>{can('service_fiscal.view')&&<button onClick={()=>navigate('service_fiscal')}>Abrir perfis fiscais existentes</button>}</section>}
<section className="panel"><h2>Funções e responsabilidade</h2><p>Gestão acompanha e aprova dentro das suas alçadas; Contabilidade prepara, confere e valida conforme mandato; Tesouraria prepara operações e reconcilia dentro do seu âmbito. Estes nomes descrevem a organização proposta, não atribuem permissões à conta.</p><p>Preparação, aprovação, execução e revisão permanecem distintas. Administração técnica não substitui autorização financeira. Dados bancários, salários, custos e auditoria exigem consulta própria; não são carregados neste mapa.</p><p>Correcções e estornos preservam o original, com motivo e autorização. Nenhum modelo de relatório, menu ou comprovativo activa um cálculo, pagamento, fecho ou obrigação fiscal.</p></section>
</div>;
}