Files
Investidor-V2/resources/js/components/simulation-import-exemptions.tsx
T

51 lines
10 KiB
TypeScript

import { useState } from 'react';
import { importExemptionBook,importExemptionCurrent,importExemptionReportRows,importExemptionRules,importRuleSource,isImportService,isDevelopmentImport,importDevelopmentFields,newImportExemption,recordImportExemptions,saveImportExemptionBook,type ImportExemptionBook,type ImportExemptionRow } from '@/lib/iva-import-exemptions';
export function SimulationImportExemptions({draft,onChange}:{draft:Record<string,unknown>;onChange:(field:string,value:string)=>void}) {
const [error,setError]=useState('');
let book:ImportExemptionBook;
try {book=importExemptionBook(draft);}catch(cause){return <p role="alert">{String(cause)}</p>;}
const save=(next:ImportExemptionBook)=>{try {onChange('modelo_a_snapshot',saveImportExemptionBook(draft,next));setError('');}catch(cause){setError(String(cause));}};
const change=(id:string,patch:Partial<ImportExemptionRow>)=>save({...book,rows:book.rows.map(row=>row.id===id?{...row,...patch}:row)});
return <details className="space-y-3 rounded border p-3">
<summary>IVA na importação e serviços associados — enquadramentos disponíveis</summary>
<p>Oportunidade: {String(draft.context_opportunity||'entrada geral')}. Indique apenas importações relevantes: reimportação no mesmo estado, ouro pelo Banco de Moçambique, objectos de arte, veículo de combate a incêndios, embarcação/avião elegível ou objecto da sua exploração, bens em regime aduaneiro com isenção total de direitos, importação sob controlo alfandegário em zona/depósito/loja franca nas condições próprias, equipamento classe K para empreendimento autorizado, materiais/equipamentos para projecto de desenvolvimento ONU nas condições próprias, ou bens de abastecimento a bordo de embarcação/avião de navegação internacional. Escolha o ramo para apresentar as condições aplicáveis. Cobertura2026/MZN; as compras internas e os seus resultados conservam-se.</p>
<p>O valor declarado/previsional é conservado, sem o fixar como base aduaneira. A classificação não preenche o campo11 de dedução nem os totais do ModeloA. Uma condição não cumprida afasta só esta isenção; o imposto normal fica por enquadrar. Nas projecções, as respostas são pressupostos, sem certificação aduaneira.</p>
<p>Nos serviços associados, identifique a importação e a inclusão do valor na sua base, conforme o artigo16. O IVA do serviço é apresentado separadamente do IVA dos bens; o simulador não soma novamente esse valor à base.</p>
{error&&<p role="alert">{error}</p>}
<button type="button" className="underline" onClick={()=>save({...book,rows:[...book.rows,newImportExemption(crypto.randomUUID(),String(draft.currency??''))]})}>Acrescentar importação ou serviço relevante</button>
{book.rows.map(row=>{
const rule=importExemptionRules.find(item=>item.id===row.treatment);
return <details key={row.id} className="rounded border p-3"><summary>{row.description||'Importação por identificar'} — {row.period||'mês por indicar'}</summary>
<div className="grid gap-3 md:grid-cols-2">
<label>Ramo da importação<select className="block rounded border p-2" value={row.treatment} onChange={e=>change(row.id,{treatment:e.target.value})}><option value="">Por indicar</option>{importExemptionRules.map(item=><option key={item.id} value={item.id}>{item.label}</option>)}</select></label>
<label>Natureza dos dados<select className="block rounded border p-2" value={row.origin} onChange={e=>change(row.id,{origin:e.target.value as ImportExemptionRow['origin']})}><option value="projected">Projectados / pressupostos</option><option value="effective">Efectivos declarados</option></select></label>
{(['description','importer','declaredValue','goodsCode','originCountry','documentRef','documentDate','period','evidence'] as const).map((field,index)=>isImportService(row.treatment)&&['goodsCode','originCountry'].includes(field)?null:<label key={field}>{isImportService(row.treatment)&&field==='description'?'Serviço associado à importação':isImportService(row.treatment)&&field==='importer'?'Importador destinatário do serviço':isImportService(row.treatment)&&field==='declaredValue'?'Valor do serviço incluído na base (moeda indicada)':isImportService(row.treatment)&&field==='documentRef'?'Documento do serviço / referência da previsão':isImportService(row.treatment)&&field==='period'?'Mês do serviço':['Bens importados','Importador','Valor declarado / previsão (moeda indicada)','Código aduaneiro, se disponível','País de origem, se disponível','Documento aduaneiro / referência da previsão','Data do documento / prevista','Mês da importação','Fundamento factual das condições / pressupostos'][index]}<input className="block rounded border p-2" type={field==='documentDate'?'date':field==='period'?'month':'text'} value={row[field]} onChange={e=>change(row.id,{[field]:e.target.value})}/></label>)}
{isImportService(row.treatment)&&(['serviceImportRef','serviceBaseRef','serviceProvider'] as const).map((field,index)=><label key={field}>{['Importação de bens associada / documento ou previsão','Referência da base tributável que inclui o valor do serviço','Prestador do serviço, se disponível'][index]}<input className="block rounded border p-2" value={row[field]??''} onChange={e=>change(row.id,{[field]:e.target.value})}/></label>)}
{row.treatment==='accessory_service_first_destination'&&<label>Primeiro destino e documento de transporte ou primeira ruptura de carga<input className="block rounded border p-2" value={row.serviceFirstDestination??''} onChange={e=>change(row.id,{serviceFirstDestination:e.target.value})}/></label>}
{row.treatment==='authorized_investment_equipment'&&<>
<p className="md:col-span-2">A classe K e a autorização são condições distintas. O portal conserva a referência e o âmbito aplicável; apresentar um pedido não equivale a obter autorização. Numa projecção, identifique expressamente os pressupostos.</p>
<label>Autorização do empreendimento / pressuposto expresso<input className="block rounded border p-2" value={row.investmentAuthorizationRef??''} onChange={e=>change(row.id,{investmentAuthorizationRef:e.target.value})}/></label>
<label>Âmbito aplicável: bens, operação, período e condições<input className="block rounded border p-2" value={row.investmentScope??''} onChange={e=>change(row.id,{investmentScope:e.target.value})}/></label>
</>}
{isDevelopmentImport(row.treatment)&&<>
<p className="md:col-span-2">Pedido apresentado não equivale a despacho favorável nem a concessão aduaneira. Reutilize as referências dos documentos; numa projecção, identifique os pressupostos. O âmbito do despacho, lista e plano conserva-se nesta importação, sem o estender a outros bens ou operações.</p>
{importDevelopmentFields.map(([field,label])=><label key={field}>{label}<input className="block rounded border p-2" value={row[field]??''} onChange={e=>change(row.id,{[field]:e.target.value})}/></label>)}
{row.treatment==='un_development_reduction'&&<>
<p className="md:col-span-2">A redução de IVA acompanha a percentagem de redução de direitos, que não é a taxa aduaneira. Informe o IVA sem benefício já determinado ou expressamente assumido; o portal não presume taxa nem base aduaneira. Resultado decimal exacto, sem arredondamento fiscal presumido.</p>
<label>Redução dos direitos (% entre0e100, exclusiva)<input className="block rounded border p-2" value={row.developmentReductionPercent??''} onChange={e=>change(row.id,{developmentReductionPercent:e.target.value})}/></label>
<label>IVA desta importação sem benefício (moeda indicada)<input className="block rounded border p-2" value={row.developmentNormalVat??''} onChange={e=>change(row.id,{developmentNormalVat:e.target.value})}/></label>
<label>Referência documental / pressuposto do IVA sem benefício<input className="block rounded border p-2" value={row.developmentNormalVatRef??''} onChange={e=>change(row.id,{developmentNormalVatRef:e.target.value})}/></label>
</>}
</>}
<label>Moeda de origem<input className="block rounded border p-2" value={row.currency} onChange={e=>change(row.id,{currency:e.target.value})}/></label>
</div>
{rule?<><p>{importRuleSource(row.treatment)}</p><fieldset><legend>Condições de{rule.article}; respostas conservadas ao mudar de ramo</legend>{rule.conditions.map(([key,label])=><label className="block" key={key}>{label}<select className="block rounded border p-2" value={row.conditions[key]??''} onChange={e=>change(row.id,{conditions:{...row.conditions,[key]:e.target.value}})}><option value="">Por indicar</option><option value="yes">Sim</option><option value="no">Não</option></select></label>)}</fieldset></>:<p>Escolha o ramo para apresentar apenas as condições aplicáveis; as respostas anteriores mantêm-se.</p>}
<p>Editar não substitui o resultado anterior. Ao classificar novamente, a versão anterior passa ao histórico.</p>
</details>;
})}
{!!book.rows.length&&<button type="button" className="rounded bg-emerald-800 p-2 text-white" onClick={()=>{try {save(recordImportExemptions(draft,book));}catch(cause){setError(String(cause));}}}>{book.rows.some(row=>isImportService(row.treatment))?'Classificar importações e serviços e guardar versão':'Classificar importações e guardar versão'}</button>}
{book.result&&<><p role="status">{importExemptionCurrent(draft,book)?'Classificação correspondente às entradas guardadas.':'Entradas alteradas; classificação histórica preservada. Reveja e classifique novamente.'} {book.history?.length??0} versões anteriores.</p><dl>{importExemptionReportRows(draft).map(([,label,value,origin],index)=><div key={index}><dt className="font-semibold">{label}</dt><dd>{value}<small className="block">{origin}</small></dd></div>)}</dl></>}
</details>;
}