import React,{useEffect,useState} from 'react'; import {billingSections,visibleBillingSections,filterBillingRows,loadBillingRows} from './billing-menu.js'; const emptyFilters={search:'',type:'',currency:'',series:'',state:'',author:'',from:'',to:''}; const BillingRegisterWorkspace=React.lazy(()=>import('./BillingRegisterWorkspace.jsx')); const value=v=>v===null||v===undefined||v===''?'Por determinar':String(v); export function BillingDocumentList({rows,filters,onFilter,onClear,onOpen}) { const filtered=filterBillingRows(rows,filters); const options=field=>[...new Set(rows.map(r=>r[field]).filter(v=>v!==null&&v!==undefined&&v!==''))].sort(); return

Lista de documentos

{['currency','series','state','author'].map(field=>)}
{filters.from&&filters.to&&filters.from>filters.to?

A data inicial deve ser anterior ou igual à data final.

:<>

{filtered.length} documento(s) nesta consulta.

{filtered.map(r=>)}
Número / referênciaTipoClienteEmissãoVencimentoTotalMoedaSaldo por receberEstadosAcções
{r.number}{r.name&&{r.name}}{r.version&&Versão {r.version}}{r.typeLabel}{value(r.client)}{r.nuit&&NUIT {r.nuit}}{r.type==='draft'?'Não emitido':value(r.issuedDate)}{r.type==='draft'?'Não aplicável':value(r.dueDate)}{r.type==='draft'?'Provisório — por determinar':value(r.total)}{r.base!==undefined&&r.base!==null&&Base aritmética: {r.base} (não é total fiscal)}{value(r.currency)}{r.type==='draft'?'Não aplicável':'Consultar percurso financeiro'}{r.state}Pagamento: {r.payment}
{!filtered.length&&

Nenhum documento corresponde aos filtros nas fontes disponíveis.

}}

Valores documentais preservados, sem recálculo. Não são somadas moedas diferentes. Ausência de saldo ou vencimento não significa zero, factura paga ou atraso. Filtros de emissão excluem rascunhos e datas desconhecidas.

; } export default function BillingMenuWorkspace({section,context,can,api,navigate}) { const unit=context.unit?.id??null; const [result,setResult]=useState(null),[loading,setLoading]=useState(false),[reload,setReload]=useState(0),[filters,setFilters]=useState(emptyFilters),[selected,setSelected]=useState(null); const active=billingSections.find(s=>s.id===section); useEffect(()=>{setSelected(null);},[section]); useEffect(()=>{ let current=true;setResult(null);setSelected(null); if(unit===null||active?.pending||(context.service_documents_enabled&&['billing_all','service_invoices'].includes(section)))return ()=>{current=false;}; setLoading(true); loadBillingRows(api,can,unit).then(r=>{if(current){setResult(r);setLoading(false);}}); return ()=>{current=false;}; },[context.token,section,reload]); if(!active)return null; if(context.service_documents_enabled&&['billing_all','service_invoices'].includes(section))return A abrir documentos…

}>
; const newDraft=()=>navigate('billing_drafts',null,true); const additional={billing_receipts:'receipt',billing_credit_notes:'credit_note',billing_invoice_receipts:'invoice_receipt'}[section]; if(additional&&context.service_documents_enabled&&unit&&can('service_documents.view',unit))return

COMERCIAL

{active.label}

Preparação, revisão distinta, prévia e emissão individual de teste. Os recibos usam afectações efectivas; o crédito exige decisão financeira própria.

Abrir {active.label.toLowerCase()}

Sem validade fiscal e sem movimento de dinheiro real.

; return

FACTURAÇÃO

{active.label}

Documentos comerciais no contexto de {context.company.name}{context.unit?` / ${context.unit.name}`:''}.

Demonstração — sem validade fiscal. A entrada e a consulta não habilitam emissão real. Documento, dívida e recebimento são factos distintos.

{!context.unit&&

Seleccione uma unidade

Escolha uma unidade autorizada para consultar os seus documentos.

} {active.pending?

Capacidade ainda não disponível

{active.pending}

{section==='billing_receipts'&&can('service_receivables.view',unit)&&}{section==='billing_credit_notes'&&can('service_invoices.view',unit)&&}

Este submenu identifica o âmbito previsto; não contém documentos simulados nem executa efeitos financeiros.

:context.unit&&<>
{can('billing_drafts.view',unit)&&can('billing_drafts.create',unit)&&}{can('service_invoices.view',unit)&&}

A criação reutiliza uma prestação existente e não emite automaticamente. Guardar rascunho, confirmar internamente, emitir em teste e receber mantêm os seus circuitos próprios.

{loading&&

A carregar documentos autorizados…

} {result?.sources.map(s=>s.error?

{s.label}: consulta indisponível. {s.error} Use Actualizar lista para tentar novamente.

:s.notice?

{s.label}: {s.notice}

:null)} {result&&!loading&&(result.sources.some(s=>!s.error&&!s.notice)?section!=='service_invoices'||r.type==='invoice')} filters={filters} onFilter={(k,v)=>setFilters(f=>({...f,[k]:v}))} onClear={()=>setFilters(emptyFilters)} onOpen={r=>r.type==='draft'?navigate('billing_drafts',r.id):setSelected(r)}/>:

Não há uma fonte documental disponível para esta consulta. Não é possível concluir que existam zero documentos.

)} {selected&&

{selected.number}

Factura de teste — fotografia preservada, sem edição directa.

{selected.detail.document_lines.map(([kind,text],i)=>kind==='title'?

{text}

:kind==='section'?

{text}

:

{text}

)}Descarregar PDF de teste

Pedidos de correcção

{selected.detail.corrections.length?selected.detail.corrections.map(c=>

#{c.id}: {c.reason} · {c.created_at} · Pendente, sem efeito fiscal.

):

Nenhum pedido registado.

}

Enviar ao cliente, duplicar documentos, exportar selecções e emitir notas de crédito ainda não estão disponíveis neste menu. Não existe emissão ou rectificação em massa.

} }
; }