Implement P047 four remission families with scoped customs evidence and QA

This commit is contained in:
2026-10-25 11:43:00 +02:00
parent 4f28fac5d0
commit 6e1dc4104c
18 changed files with 538 additions and 2 deletions
@@ -24422,5 +24422,21 @@
],
"partial_QA_only": true,
"homologation_unchanged": "e38aa749"
},
"l1_p047_families_qa_20261025": {
"report": "docs/investmoz/simulations/iva-l1-p047-families-qa-20261025.json",
"delivered": 128,
"QA": [
"P047"
],
"pending": [
"P058",
"P084",
"P085",
"P001"
],
"partial_P058_preserved": true,
"homologation_unchanged": "e38aa749",
"active_writes": false
}
}
@@ -0,0 +1,231 @@
{
"status": "Concluído em QA no âmbito demonstrado de CIVA12(1)b; por disponibilizar em conjunto compatível",
"base": "4f28fac5",
"homologation_unchanged": "e38aa749",
"receipt_preserved": "9019f766",
"counts": {
"delivered": 128,
"QA": 1,
"functional_pending": 3,
"P001": 1,
"total": 133
},
"delivered_preserved": [
"AUD-SIM-L1-P002",
"AUD-SIM-L1-P003",
"AUD-SIM-L1-P004",
"AUD-SIM-L1-P005",
"AUD-SIM-L1-P006",
"AUD-SIM-L1-P007",
"AUD-SIM-L1-P008",
"AUD-SIM-L1-P009",
"AUD-SIM-L1-P010",
"AUD-SIM-L1-P011",
"AUD-SIM-L1-P012",
"AUD-SIM-L1-P013",
"AUD-SIM-L1-P014",
"AUD-SIM-L1-P015",
"AUD-SIM-L1-P016",
"AUD-SIM-L1-P017",
"AUD-SIM-L1-P018",
"AUD-SIM-L1-P019",
"AUD-SIM-L1-P020",
"AUD-SIM-L1-P021",
"AUD-SIM-L1-P022",
"AUD-SIM-L1-P023",
"AUD-SIM-L1-P024",
"AUD-SIM-L1-P025",
"AUD-SIM-L1-P026",
"AUD-SIM-L1-P027",
"AUD-SIM-L1-P028",
"AUD-SIM-L1-P029",
"AUD-SIM-L1-P030",
"AUD-SIM-L1-P031",
"AUD-SIM-L1-P032",
"AUD-SIM-L1-P033",
"AUD-SIM-L1-P034",
"AUD-SIM-L1-P035",
"AUD-SIM-L1-P036",
"AUD-SIM-L1-P037",
"AUD-SIM-L1-P038",
"AUD-SIM-L1-P039",
"AUD-SIM-L1-P040",
"AUD-SIM-L1-P041",
"AUD-SIM-L1-P042",
"AUD-SIM-L1-P043",
"AUD-SIM-L1-P044",
"AUD-SIM-L1-P045",
"AUD-SIM-L1-P046",
"AUD-SIM-L1-P048",
"AUD-SIM-L1-P049",
"AUD-SIM-L1-P050",
"AUD-SIM-L1-P051",
"AUD-SIM-L1-P052",
"AUD-SIM-L1-P053",
"AUD-SIM-L1-P054",
"AUD-SIM-L1-P055",
"AUD-SIM-L1-P056",
"AUD-SIM-L1-P057",
"AUD-SIM-L1-P059",
"AUD-SIM-L1-P060",
"AUD-SIM-L1-P061",
"AUD-SIM-L1-P062",
"AUD-SIM-L1-P063",
"AUD-SIM-L1-P064",
"AUD-SIM-L1-P065",
"AUD-SIM-L1-P066",
"AUD-SIM-L1-P067",
"AUD-SIM-L1-P068",
"AUD-SIM-L1-P069",
"AUD-SIM-L1-P070",
"AUD-SIM-L1-P071",
"AUD-SIM-L1-P072",
"AUD-SIM-L1-P073",
"AUD-SIM-L1-P074",
"AUD-SIM-L1-P075",
"AUD-SIM-L1-P076",
"AUD-SIM-L1-P077",
"AUD-SIM-L1-P078",
"AUD-SIM-L1-P079",
"AUD-SIM-L1-P080",
"AUD-SIM-L1-P081",
"AUD-SIM-L1-P082",
"AUD-SIM-L1-P083",
"AUD-SIM-L1-P086",
"AUD-SIM-L1-P087",
"AUD-SIM-L1-P088",
"AUD-SIM-L1-P089",
"AUD-SIM-L1-P090",
"AUD-SIM-L1-P091",
"AUD-SIM-L1-P092",
"AUD-SIM-L1-P093",
"AUD-SIM-L1-P094",
"AUD-SIM-L1-P095",
"AUD-SIM-L1-P096",
"AUD-SIM-L1-P097",
"AUD-SIM-L1-P098",
"AUD-SIM-L1-P099",
"AUD-SIM-L1-P100",
"AUD-SIM-L1-P101",
"AUD-SIM-L1-P102",
"AUD-SIM-L1-P103",
"AUD-SIM-L1-P104",
"AUD-SIM-L1-P105",
"AUD-SIM-L1-P106",
"AUD-SIM-L1-P107",
"AUD-SIM-L1-P108",
"AUD-SIM-L1-P109",
"AUD-SIM-L1-P110",
"AUD-SIM-L1-P111",
"AUD-SIM-L1-P112",
"AUD-SIM-L1-P113",
"AUD-SIM-L1-P114",
"AUD-SIM-L1-P115",
"AUD-SIM-L1-P116",
"AUD-SIM-L1-P117",
"AUD-SIM-L1-P118",
"AUD-SIM-L1-P119",
"AUD-SIM-L1-P120",
"AUD-SIM-L1-P121",
"AUD-SIM-L1-P122",
"AUD-SIM-L1-P123",
"AUD-SIM-L1-P124",
"AUD-SIM-L1-P125",
"AUD-SIM-L1-P126",
"AUD-SIM-L1-P127",
"AUD-SIM-L1-P128",
"AUD-SIM-L1-P129",
"AUD-SIM-L1-P130",
"AUD-SIM-L1-P131",
"AUD-SIM-L1-P132",
"AUD-SIM-L1-P133"
],
"families": {
"party": {
"source": "Lei7/91 art15(1)a/2,PDF11;Lei14/92 PDF23–24 não altera15",
"implemented": "Equipamento necessário ao funcionamento próprio; exclui actividade económica empresarial. Não acrescenta quota diplomática nem aprovação organizacional."
},
"patronage": {
"source": "Lei4/94 art7,PDF2;Decreto29/98 Regulamentoarts1–7,10/11,PDF7–9",
"implemented": "Livros culturais/científicos/escolares e insumos para produção nacional; percurso de liberalidade com comunicações,termo,incompatibilidades,irreversibilidade/confirmação da fonte. Outros bens apenas com disposição expressa,sem isenção por doação genérica. Não calcula incentivos ao rendimento."
},
"diplomatic": {
"source": "Decreto22/2021 arts2–9/11/12,PDF1–2/p425–426;revogação3/83 no13",
"implemented": "Sete categorias;reciprocidade,registo,pedido viaMINEC,limite próprio e histórico;quotas3/2/1,menor limite por reciprocidade,controlo conjunto e janela5anos;agências/organizações segundo acordo identificado,sem transplantar quotas."
},
"ipp": {
"source": "IPP22 Lei17/2022 PDF4–5;Lei8/2025 PDF2–3;Decreto37/2023 arts12(3),27/28/QuadroV;Decreto27/2026 art3PDF4",
"implemented": "30itens e disposição específica identificada;confirmação da correspondência e condições próprias,referências,pedido prévio,uso e decisão de âmbito. Taxa0%,redução e encargos suportados peloEstado não são tratados automaticamente como isenção. Competências pela data da decisão/previsão;transição31/07/2026,30dias após publicação;item30 anterior exige disposição de competência específica."
}
},
"examples": 42,
"verification": {
"frontend": {
"tests": 48,
"passed": 48
},
"API": {
"tests": 1,
"assertions": 208,
"guarded_database": "simulator_fiscal_delta_20261021_test:55441",
"rollback": true,
"all_previous_snapshot_members_equal": true
},
"types": "passed",
"build": "passed",
"UI": "Componente real: campos adaptados por família,quantidade oculta preservada,troca limpa confirmações,gravação/recuperação/relatório; ui-saved-state.json/report-dom.txt/P047-recovered-report.png"
},
"scope_limits": [
"Classifica IVA por remissão apenas com isenção de direitos demonstrada ou pressuposto expresso; não concede benefício aduaneiro.",
"Não automatiza classificação pautal nem todos os procedimentos de cada regime referido. Condições específicas ausentes permanecem indeterminadas.",
"Pedido apresentado não concede;deferimento previsto é apenas cenário condicionado.",
"Sem direitos,ICE,base aduaneira,dedução/campo11,alienação ou soma aos livros anteriores.",
"P058 quatro percursosQA4f28fac5 preservados;três questões residuais permanecem abertas.",
"P084/P085 procedimentoTempo entregue preservado;falta somente correspondência específica de formulário/instrução e mapeamento.",
"P001 limitado05/06 da edição recebida;sem renumeração a partir de outros modelos.",
"Formalidades digitais não automatizadas e cálculo fiscal restante de ramos com âmbito limitado conservados;L1aberto."
],
"source_records": [
{
"file": "docs/investmoz/simulations/source-archive/Lei-7-1991-Partidos-IFES.pdf",
"url": "https://www.ifes.org/sites/default/files/migrate/el00091.pdf",
"sha256": "6b783a0bb3330688ef10660a58060d9724aa2da6a873d234fe902f0eaaeda42d",
"pages": 21,
"origin": "Texto legislativo oficial; IFES reproduz exemplar da Assembleia, BR preservado nos demais."
},
{
"file": "docs/investmoz/simulations/source-archive/Lei-14-1992-BR42.pdf",
"url": "https://archive.gazettes.africa/archive/mz/1992/mz-government-gazette-series-i-supplement-dated-1992-10-14-no-42.pdf",
"sha256": "089fff7423e99a70a230a73ca379e4ea3a91d124703f91016e57ff82794b9e56",
"pages": 24,
"origin": "Texto legislativo oficial; IFES reproduz exemplar da Assembleia, BR preservado nos demais."
},
{
"file": "docs/investmoz/simulations/source-archive/Lei-4-1994-BR37-3-suplemento.pdf",
"url": "https://archive.gazettes.africa/archive/mz/1994/mz-government-gazette-series-i-supplement-no-3-dated-1994-09-13-no-37.pdf",
"sha256": "210df9db8980d0a5690cd187a6eeec7e37a900d743e39062c16f4e0d12215c7e",
"pages": 4,
"origin": "Texto legislativo oficial; IFES reproduz exemplar da Assembleia, BR preservado nos demais."
},
{
"file": "docs/investmoz/simulations/source-archive/Decreto-22-2021-BR70.pdf",
"url": "https://archive.gazettes.africa/archive/mz/2021/mz-government-gazette-series-i-dated-2021-04-14-no-70.pdf",
"sha256": "a8fac38dcfe08f9c7a8e46254cff10e1ec82fc4f7a8d88ad6e4fe7d91ffc21a5",
"pages": 4,
"origin": "Texto legislativo oficial; IFES reproduz exemplar da Assembleia, BR preservado nos demais."
},
{
"file": "docs/investmoz/simulations/source-archive/Decreto-29-1998-BR22-5-suplemento.pdf",
"url": "https://fracessoriasa.co.mz/wp-content/uploads/2021/10/53-Lei-do-Mecenato-Regulamento-patrocinios-e-doacoes.pdf",
"sha256": "6242cbe675faadf085f43f95ec8c7e8868aafe67c3b2ab2bb010992288f954f8",
"pages": 9,
"origin": "BR22-I 5.º suplemento09/06/1998, exemplar completo9p;Decreto29/98 nasp7–9"
}
],
"active_writes": false,
"proposed_group": {
"P047": "um ramo concluído emQA no âmbito acima",
"P058": "quatro percursos de bagagem emQA parcial;semfecho",
"requirements": "Integração compatível commain,preservação concorrente,backup/restauro autenticado e conferência só do delta;nenhuma entrega executada neste incremento."
}
}
@@ -1,5 +1,19 @@
# Rastreabilidade, utilização e formação
## 25/10/2026 — P047: quatro famílias em QA, entrega agrupada preparada
Inventário anterior aos testes:128fechos preservados,nenhuma perda confirmada;P058parcialQA4f28fac5 preservado.Homologaçãoe38aa749/recibo9019f766;nenhuma alteração no activo.
P047:partidos com equipamento necessário ao funcionamento próprio,excluindo actividade empresarial;mecenato com livro/insumos próprios e percurso regulamentar separado para liberalidades;veículos diplomáticos com reciprocidade,registo,pedido viaMINEC,limites e histórico;IPP30itens e disposição específica com condições próprias e isenção de direitos demonstradas.Pedido não concede;taxa0%,redução e encargo suportado peloEstado não equivalem automaticamente a isenção.Na projecção,o deferimento previsto é hipótese condicionada.A aplicação legal directa não recebe novo aprovador.
A competênciaIPP depende da data da decisão/previsão,não da importação.O Decreto27/2026,art3/PDF4/p1012(4),entra30dias após publicação01/07/2026:transição31/07/2026.O item30 anterior aessa data exige disposição de competência própria,sem retroagir a nova delegação.Datas,referências,bens,operação,período,condições e históricos ficam conservados.
QA:48testesfrontend;42exemplos;API1teste/208asserções comguarda de baseisolada55441 e rollback;tipos ecompilação aprovados.Interface:troca de família oculta campos sem apagar quantidades,limpa confirmações,guarda nova versão,recupera egera relatório da gravação.Sem direitos,ICE,baseaduaneira,dedução/campo11,alienação ou soma aos livros anteriores.Não automatiza todos os procedimentos dos regimes referidos.
Entrega compatível preparada:P047 concluído emQA no âmbito demonstrado;P058 apenas quatro percursos de bagagem emQAparcial,semfecho.P058mantém exactamente as três questões57(2)b,180dias e63(2).P084/P085mantêm procedimentoTempo entregue;pesquisa delimitada nesta ronda não demonstrou nova correspondência de formulário,logo não se importam condiçõesCBF nem se acrescentam aprovações.P001continua exclusivamente05/06da edição recebida.Sem renumeração por outro modelo.
Saldo:**128entregues+1QA(P047)+3funcionais pendentes(P058/P084/P085)+P001=133**.L1aberto.Formalidades digitais não automatizadas e cálculo fiscal restante dos ramos com âmbito limitado permanecem identificados.Evidência:`docs/investmoz/simulations/iva-l1-p047-families-qa-20261025.json`;inventário,hashes e provas em`outputs/iva-l1-p047-families-20261025/`.Não se repetem os128fechos.
## 25/10/2026 — impedimentos residuais e QA parcial de bagagem
128 fechos inventariados antes dos testes e preservados sem alterações nas respectivas linhas da matriz. Homologação e38aa749, recibo 9019f766; nenhuma alteração no activo.
File diff suppressed because one or more lines are too long
@@ -1,3 +1,4 @@
import { SimulationRemissionImports } from './simulation-remission-imports';
import { SimulationObjectiveImports } from './simulation-objective-imports';
import { SimulationMiners } from './simulation-miners';
import { SimulationReturnees } from './simulation-returnees';
@@ -118,6 +119,7 @@ export function SimulationMonthlyIva({draft, busy, onCalculate, onChange}: {
<SimulationImportExemptions draft={draft} onChange={onChange} />
<SimulationObjectiveImports draft={draft} onChange={onChange} />
<SimulationMiners draft={draft} onChange={onChange} />
<SimulationRemissionImports draft={draft} onChange={onChange} />
<SimulationReturnees draft={draft} onChange={onChange} />
<SimulationPublicAuthorityBase draft={draft} onChange={onChange} />
<SimulationCommissionBase draft={draft} onChange={onChange} />
@@ -0,0 +1,31 @@
import {useState} from 'react';
import {remissionBook,saveRemissionBook,newRemission,remissionFamilies,diplomaticRoles,ippItems,ippAuthority,remissionConditions,recordRemissions,remissionCurrent,remissionReportRows,remissionSource,type RemissionBook,type RemissionRow} from '@/lib/iva-remission-imports';
import {objectiveImportBook} from '@/lib/iva-objective-imports';
export function SimulationRemissionImports({draft,onChange}:{draft:Record<string,unknown>;onChange:(field:string,value:string)=>void}){
const[error,setError]=useState('');let book:RemissionBook;try{book=remissionBook(draft);}catch(e){return<p role="alert">{String(e)}</p>;}
const save=(b:RemissionBook)=>{try{onChange('modelo_a_snapshot',saveRemissionBook(draft,b));setError('');}catch(e){setError(String(e));}};
const change=(id:string,patch:Partial<RemissionRow>)=>save({...book,rows:book.rows.map(r=>r.id===id?{...r,...patch}:r)});
let sources:ReturnType<typeof objectiveImportBook>['rows']=[];try{sources=objectiveImportBook(draft).rows;}catch{/* Direct entry remains available; source originals stay untouched. */}
return<details className="rounded border p-3"><summary>Importações — quatro famílias de isenção por remissão (P047)</summary>
<p>Confirme o fundamento e o âmbito da isenção de direitos. Taxa pautal de 0%, redução e pedido apresentado são situações distintas. Uma previsão de deferimento produz apenas um cenário condicionado. O portal não concede benefícios aduaneiros nem calcula direitos, ICE ou dedução.</p>
{error&&<p role="alert">{error}</p>}<button type="button" onClick={()=>{const r=newRemission(crypto.randomUUID(),String(draft.currency??''));const known=book.rows.map(v=>v.importer).filter(Boolean);if(new Set(known).size===1)r.importer=known[0];save({...book,rows:[...book.rows,r]});}}>Acrescentar importação por remissão</button>
{book.rows.map(row=>{const text=(field:Exclude<keyof RemissionRow,'conditions'>,label:string,type='text')=><label className="block" key={field}>{label}<input type={type} value={row[field]} onChange={e=>change(row.id,{[field]:e.target.value})}/></label>;const select=(field:Exclude<keyof RemissionRow,'conditions'>,label:string,options:ReadonlyArray<readonly[string,string]>,clear=false)=><label className="block">{label}<select value={row[field]} onChange={e=>change(row.id,{[field]:e.target.value,...(clear?{conditions:{}}:{})})}><option value="">Por indicar</option>{options.map(([v,l])=><option key={v} value={v}>{l}</option>)}</select></label>;
return<details key={row.id}><summary>{row.description||'Importação por preparar'} — {row.period||'período por indicar'}</summary>
{sources.length>0&&<label>Reutilizar dados de importação preparada<select value="" onChange={e=>{const s=sources.find(v=>v.id===e.target.value);if(s)change(row.id,{description:row.description||s.description,importer:row.importer||s.importer,period:row.period||s.period,documentRef:row.documentRef||s.documentRef,evidence:row.evidence||s.evidence});}}><option value="">Preencher apenas campos em falta</option>{sources.map(s=><option key={s.id} value={s.id}>{s.description}</option>)}</select></label>}
{text('description','Bens identificados')}{text('importer','Importador / beneficiário')}{text('period','Período da importação','month')}{text('importDate','Data da importação ou previsão','date')}{select('origin','Natureza dos dados',[['projected','Pressupostos de projecção'],['effective','Factos efectivos declarados']])}{text('documentRef','Documentos disponíveis ou previsão')}{text('scope','Âmbito: bens, operação, período e condições')}{text('evidence','Factos ou pressupostos expressos')}
{select('family','Família legal',remissionFamilies,true)}
{row.family==='patronage'&&<>{select('patronagePath','Percurso do mecenato',[['book','Livro cultural/científico/escolar ou insumo de produção nacional — art7'],['donation','Liberalidade de livros/insumos no regulamento — arts10/11'],['specific','Outro fundamento expresso de isenção de direitos']],true)}{['donation','specific'].includes(row.patronagePath)&&text('specialRef',row.patronagePath==='donation'?'Acção/liberalidade: artigo4, documentos, comunicações, termo e confirmação nos termos do regulamento':'Disposição expressa, bens e âmbito: não basta doação genérica')}</>}
{row.family==='ipp'&&<>{select('ippItem','Item das IPP / Quadro V',[...ippItems.map(i=>[i.id,`${i.id} — ${i.label}`] as const),['specific','Outro artigo específico das IPP']],true)}{(row.ippItem==='specific'||(row.ippItem==='30'&&row.decisionDate<'2026-07-31'))&&text('ippArticle','Disposição, versão e trecho próprios; competência anterior a31/07 quando aplicável')}{text('decisionDate','Data da decisão ou previsão para determinar a competência','date')}{text('specialRef','Referências das condições/remissões e compromisso de uso; confirmação de tutela apenas quando prevista')}<p>Competência pela data da decisão/previsão: {row.decisionDate?ippAuthority(row.ippItem,row.decisionDate):'Data por indicar'}. A inclusão no quadro não concede isenção automaticamente. Itens28/30 com encargos suportados pelo Estado não equivalem, só por isso, a isenção de direitos.</p></>}
{row.family==='diplomatic'&&<>{select('role','Categoria diplomática',diplomaticRoles,true)}{['agency','organisation'].includes(row.role)?<>{text('agreementRef','Acordo de Sede ou específico: cláusula e âmbito')}{text('specialRef','Condições e limites próprios do acordo; sem quotas presumidas')}</>:row.role&&<>{text('quantity','Veículos desta linha','number')}{text('existingQuantity','Veículos já abrangidos no limite, fora destas linhas','number')}{text('limit',row.role==='mission'?'Limite fixado caso a caso pelo MINEC':'Limite aplicável pela reciprocidade, até ao máximo legal','number')}{text('limitRef','Referência do limite/reciprocidade e restrições aplicáveis')}{select('history','Importação anterior no mesmo direito',[['none','Nenhuma, segundo histórico identificado'],['known','Sim, data conhecida']])}{row.history==='known'&&text('previousDate','Data da importação anterior','date')}{text('historyRef','Histórico, incluindo operações fora deste dossier')}<p>Decreto22/2021: chefe até3; agente/cônsul de carreira até2; honorário e pessoal administrativo/técnico até1. A missão tem limite próprio. Nova importação após5anos; alienação e reexportação conservam regime próprio, sem cálculo neste percurso.</p></>}</>}
{remissionConditions(row).map(([key,label])=><label className="block" key={key}>{label}<select value={row.conditions[key]??''} onChange={e=>change(row.id,{conditions:{...row.conditions,[key]:e.target.value as ''|'yes'|'no'}})}><option value="">Por esclarecer</option><option value="yes">Sim, nos factos ou pressupostos identificados</option><option value="no">Não</option></select></label>)}
{row.family&&<>{select('rights','Situação dos direitos de importação',[['exempt','Isenção integral demonstrada ou pressuposto expresso'],['reduced','Redução parcial'],['zero','Taxa pautal de 0%'],['none','Sem isenção']])}{text('rightsRef','Fundamento exacto da isenção de direitos e âmbito ou pressuposto expresso')}
{(['ipp','diplomatic'].includes(row.family)||(row.family==='patronage'&&row.patronagePath==='donation'))&&text('requestRef',row.family==='diplomatic'?'Pedido caso a caso através do MINEC ou previsão':'Requerimento/comunicação prévia ou previsão')}
{select('decision','Situação da decisão / aplicação legal',[...((row.family==='party'||(row.family==='patronage'&&row.patronagePath!=='donation'))?[['not_required','Aplicação legal directa; não é criada aprovação adicional'] as const]:[]),['planned','Deferimento previsto — apenas cenário condicionado'],['requested','Pedido apresentado — benefício solicitado'],['approved','Decisão / confirmação recebida'],['denied','Indeferido']])}
{row.decision!=='not_required'&&text('decisionRef','Referência da decisão / pressuposto; entidade, data e âmbito abrangido')}
<p>Mudar família ou subpercurso conserva campos ocultos e limpa confirmações. Documentos e históricos permanecem guardados. A submissão e a decisão administrativas ocorrem fora do InvesteMoz.</p></>}
</details>;})}
{!!book.rows.length&&<button type="button" onClick={()=>{try{save(recordRemissions(draft,book));}catch(e){setError(String(e));}}}>Conferir quatro famílias e guardar versão</button>}
{book.result&&<><p role="status">{remissionCurrent(draft,book)?'Resultado corresponde às entradas guardadas.':'Entradas alteradas; resultado histórico conservado.'} {book.history?.length??0} versões anteriores.</p><dl>{remissionReportRows(draft).map(([,label,value,source],i)=><div key={i}><dt>{label}</dt><dd>{value}<small className="block">{source}</small></dd></div>)}</dl></>}
<details><summary>Fontes e limites de cobertura</summary><p>{remissionSource}</p><p>Avalia o IVA por remissão quando a isenção de direitos está demonstrada. Não substitui a classificação pautal nem automatiza todos os procedimentos dos regimes aduaneiros referidos. As condições específicas não identificadas permanecem indeterminadas. Sem cálculo de alienação, direitos, ICE ou dedução.</p></details>
</details>;
}
+122
View File
@@ -0,0 +1,122 @@
export const ippItems=[
{
"id": "1",
"label": "Bens destinados ao uso oficial das missões diplomáticas, postos consulares, organismos internacionais e suas agências acreditados em Moçambique, nos termos da legislação específica sobre a matéria."
},
{
"id": "2",
"label": "Os objectos destinados aos agentes diplomáticos ou consulares de carreira e funcionários internacionais, nos termos da legislação específica sobre a matéria."
},
{
"id": "3",
"label": "Amostras, isoladas ou em colecções, devidamente rotuladas, que de qualquer maneira apresentem as características que lhes são peculiares, sem valor comercial."
},
{
"id": "4",
"label": "Prémios ganhos em concursos públicos ou competições desportivas e Culturais."
},
{
"id": "5",
"label": "Bagagens, nos termos definidos por lei."
},
{
"id": "6",
"label": "Artigos de espólios que possam ser importados sob regime de bagagem, bem como féretros, coroas e emblemas funerários que os acompanhem."
},
{
"id": "7",
"label": "Objectos destinados aos mostruários dos museus de utilidade pública."
},
{
"id": "8",
"label": "Objectos considerados pelo Ministério da Cultura como obras de arte ou com valor histórico."
},
{
"id": "9",
"label": "Dádivas destinadas a prisioneiros de guerra nos termos do artigo 3 da Convenção de Genebra, assinada em 22 de Julho de 1929, relativa ao tratamento de prisioneiros de guerra."
},
{
"id": "10",
"label": "Filmes didácticos ou científicos, destinados aos Ministérios interessados."
},
{
"id": "11",
"label": "Material de guerra e de aquartelamento, fardamentos, destinados à utilização oficial das Forças de Defesa e Segurança."
},
{
"id": "12",
"label": "Mercadorias cujas isenções estejam previstas em Acordos e Tratados assinados ou reconhecidos pelo Governo da República de Moçambique."
},
{
"id": "13",
"label": "Produtos trazidos em pequenas quantidades dos países vizinhos pelas populações fronteiriças, para consumo pessoal ou familiar."
},
{
"id": "14",
"label": "Material e equipamento científico e didáctico ou de laboratório destinados à educação, ensino e investigação científico-técnica, devidamente confirmado pelo sector de tutela."
},
{
"id": "15",
"label": "Notas e moedas estrangeiras quando importadas por instituições bancárias devidamente autorizadas, para o efeito."
},
{
"id": "16",
"label": "Notas e moedas com curso legal no País quando importadas pelo Banco de Moçambique."
},
{
"id": "17",
"label": "Documentos de tráfego importados por companhias aéreas, empresas ferroviárias, companhias marítimas tais como carta de porte, documentos de embarque, bilhetes de passagem, etiqueta de bagagem."
},
{
"id": "18",
"label": "Documentos de trabalho, relatórios, proposta para concurso, planta e desenhos."
},
{
"id": "19",
"label": "Catálogos em papel ou em suporte magnético."
},
{
"id": "20",
"label": "Bens destinados a determinado uso industrial especificamente aprovado, regulado em legislação própria."
},
{
"id": "21",
"label": "Helicópteros, aviões e outros veículos aéreos, destinados a serviços comerciais de transporte público e à formação e capacitação de pessoal, em aeroclubes, embarcações para transporte público de passageiros, embarcações para investigação marinha, suas partes, acessórios e outros componentes para reposição, mediante confirmação do sector de tutela."
},
{
"id": "22",
"label": "Embarcações que se destinem ao exercício da actividade de transporte de cabotagem."
},
{
"id": "23",
"label": "Embarcações de pesca; equipamento de construção e reparação naval; motores para desenvolvimento de pesca de pequena escala; equipamento, sementes, reprodutores, rações e larvas de camarão para desenvolvimento de aquacultura; carrinhas frigoríficas para transporte de pescado; equipamento de laboratórios e reagentes."
},
{
"id": "24",
"label": "Artigos médicos, próteses e correlatos, importadas através do Serviço Nacional de Saúde."
},
{
"id": "25",
"label": "Produtos e micronutrientes de administração nos veículos alimentares de fortificação obrigatória, definidos e regulados em legislação própria, quando confirmados pelo Sector de tutela."
},
{
"id": "26",
"label": "Animais bravios, no âmbito do Programa de Repovoamento dos Parques Nacionais, devidamente confirmados pelo sector de tutela."
},
{
"id": "27",
"label": "Sistema de irrigação e seus acessórios, bem como produtos que se destinam à vedação com vista à protecção de animais no âmbito da actividade agro-pecuária, confirmados pelo sector de tutela."
},
{
"id": "28",
"label": "Equipamentos e materiais importados ao abrigo de Acordos celebrados pelo Governo, para implementação de projectos públicos, nos quais se prevê que a despesa relativa aos direitos e outros encargos aduaneiros é suportada pelo Estado Moçambicano."
},
{
"id": "29",
"label": "Bens, equipamentos e materiais importados pelo Estado, no âmbito da saúde, devidamente confirmado pelo Sector de tutela."
},
{
"id": "30",
"label": "Veículos automóveis 87.02/87.04 destinados a instituições do Estado ou acordos/tratados para projectos do Estado, com direitos e encargos suportados pelo Estado Moçambicano."
}
] as const;
+77
View File
@@ -0,0 +1,77 @@
import {acquisitionScope,readAcquisitionStore} from './iva-acquisitions.ts';
import {ippItems} from './iva-remission-catalog.ts';
export {ippItems};
export const remissionVersion='remission-imports/1';
export const remissionSource='P047 — CIVA12(1)b, redacção Lei22/2022 PDF2/p2252(26), mantida Lei10/2025 PDF13. Lei7/91 art15(1)a/2, exemplar Assembleia/IFES PDF11/p9; Lei14/92 BR42 suplemento PDF23–24 não altera15. Lei4/94 art7 PDF2 e Decreto29/98 BR22-I 5.º suplemento PDF7–9 arts1–7,10–12. Decreto22/2021 BR70-I PDF1–2/p425–426 arts2–9,11–14, revoga3/83. IPP Lei17/2022 BR250 PDF4–5/p2238–2239 art22; Lei8/2025 BR248 suplemento PDF2–3 acrescenta30; Decreto37/2023 arts12(3),27/28 e QuadroV; Decreto27/2026 altera competências desde31/07/2026,30dias após publicação01/07,art3/PDF4/p1012(4). Classificação IVA2026/MZN baseada em isenção de direitos demonstrada; não concede benefício aduaneiro, não calcula direitos, ICE, base ou dedução/campo11.';
export const remissionFamilies=[['party','Partido político — equipamento para funcionamento próprio'],['patronage','Mecenato — livros/insumos ou fundamento específico'],['diplomatic','Veículos diplomáticos/consulares — regime próprio'],['ipp','Instruções Preliminares da Pauta — fundamento e âmbito próprios']] as const;
export const diplomaticRoles=[['mission','Missão diplomática ou consular'],['head','Chefe de missão'],['agent','Agente diplomático/cônsul de carreira ou equiparado'],['honorary','Cônsul honorário acreditado'],['technical','Pessoal administrativo ou técnico'],['agency','Agência especializada das Nações Unidas'],['organisation','Organização equiparada ao nível de privilégios']] as const;
type Choice=''|'yes'|'no';
export type RemissionRow={id:string;family:string;description:string;importer:string;period:string;currency:string;origin:'projected'|'effective';importDate:string;scope:string;evidence:string;documentRef:string;rights:''|'exempt'|'reduced'|'zero'|'none';rightsRef:string;decision:''|'not_required'|'planned'|'requested'|'approved'|'denied';decisionRef:string;decisionDate:string;requestRef:string;specialRef:string;ippItem:string;ippArticle:string;patronagePath:''|'book'|'donation'|'specific';role:string;quantity:string;existingQuantity:string;limit:string;limitRef:string;history:''|'none'|'known';previousDate:string;historyRef:string;agreementRef:string;conditions:Record<string,Choice>};
export type RemissionLine={id:string;status:'exempt'|'not_applicable'|'indeterminate';importVat:string|null;deduction:null;source:string;reason:string};
type Result={version:string;revision:number;calculatedAt:string;sourceKey:string;inputs:RemissionRow[];rows:RemissionLine[]};
export type RemissionBook={rows:RemissionRow[];result?:Result;history?:Result[]};
export function newRemission(id:string,currency:string):RemissionRow{return{id,currency,family:'',description:'',importer:'',period:'',origin:'projected',importDate:'',scope:'',evidence:'',documentRef:'',rights:'',rightsRef:'',decision:'',decisionRef:'',decisionDate:'',requestRef:'',specialRef:'',ippItem:'',ippArticle:'',patronagePath:'',role:'',quantity:'',existingQuantity:'',limit:'',limitRef:'',history:'',previousDate:'',historyRef:'',agreementRef:'',conditions:{}};}
function store(draft:Record<string,unknown>){const s=readAcquisitionStore(draft.modelo_a_snapshot) as ReturnType<typeof readAcquisitionStore>&{remissionImports?:Record<string,RemissionBook>};const fields=Object.keys(newRemission('','')).filter(k=>k!=='conditions');if(s.remissionImports!==undefined&&(!s.remissionImports||typeof s.remissionImports!=='object'||Array.isArray(s.remissionImports)))throw Error('Importações por remissão não recuperáveis; originais preservados.');for(const b of Object.values(s.remissionImports??{}))if(!b||!Array.isArray(b.rows)||(b.history!==undefined&&!Array.isArray(b.history))||b.rows.some(r=>!r||fields.some(k=>typeof r[k as keyof RemissionRow]!=='string')||!r.conditions||typeof r.conditions!=='object'||Array.isArray(r.conditions)||Object.values(r.conditions).some(v=>!['','yes','no'].includes(v))))throw Error('Linhas por remissão não recuperáveis; originais preservados.');return s;}
export function remissionBook(draft:Record<string,unknown>):RemissionBook{return store(draft).remissionImports?.[acquisitionScope(draft)]??{rows:[]};}
export function saveRemissionBook(draft:Record<string,unknown>,book:RemissionBook):string{const s=store(draft),value=JSON.stringify({...s,remissionImports:{...s.remissionImports,[acquisitionScope(draft)]:book}});store({...draft,modelo_a_snapshot:value});return value;}
type Condition=readonly[string,string];
export function remissionConditions(r:RemissionRow):Condition[]{
const common:Condition[]=[['goods','Importação de bens abrangidos pelo fundamento identificado'],['scope','Beneficiário, bens, operação, período e condições coincidem com o âmbito da isenção de direitos']];
if(r.family==='party')return [...common,['party','Importador é o partido político identificado e legalmente constituído'],['equipment','Bens de equipamento necessários ao funcionamento próprio do partido — art15(1)a'],['nonBusiness','Não se destinam a actividades económicas de natureza empresarial — art15(2)']];
if(r.family==='patronage')return [...common,...(r.patronagePath==='specific'?[['specific','A disposição expressa identificada concede isenção de direitos a estes bens; não basta doação ou dedução ao rendimento'] as Condition]:[['books','Livros culturais, científicos ou escolares, ou insumos para a sua produção nacional — Lei4/94 art7'] as Condition]),...(r.patronagePath==='donation'?[['eligible','Acção/liberalidade elegível no art4 do Regulamento e destinatário nos termos da Lei4/94 art2'],['nonProselytism','Sem proselitismo confessional ou partidário nem proveito pecuniário/patrimonial directo'],['exclusive','Bens exclusivamente afectos à finalidade elegível — Lei4/94 art4'],['valuation','Apoio não monetário avaliado pela factura ou preço normal — Lei4/94 art5'],['communications','Comunicações aos beneficiários, tutela e Finanças nos termos do art5 do Regulamento'],['handover','Termo de entrega rubricado pelo representante da tutela, nos termos do art6; ou pressuposto expresso'],['unrelated','Sem pessoas vinculadas nos termos do art7, incluindo janela de12meses'],['irreversible','Liberalidade expressamente irreversível — art10(3)'],['confirmation','Confirmação de Finanças e entidade da área abrangida — art11; ou pressuposto expresso da projecção']] as Condition[]:[])];
if(r.family==='diplomatic')return [...common,['accredited','Beneficiário acreditado e abrangido pelos arts2/3 do Decreto22/2021'],['vehicle','Veículo automóvel para uso abrangido pelo regime diplomático identificado'],...(['agency','organisation'].includes(r.role)?[['agreement','Acordo de Sede/específico cobre a isenção e as condições desta importação — arts11/12'] as Condition]:[['reciprocity','Reciprocidade e razoabilidade verificadas, incluindo restrições do Estado acreditante — arts4/7'],['register','Registo no MINEC e na AT para controlo quantitativo — art5, ou pressuposto expresso'],['caseRequest','Isenção requerida caso a caso através do MINEC — art7(2), ou pressuposto expresso'],...(['agent','technical'].includes(r.role)?[['foreignNonResident','Não é nacional nem residente permanente em Moçambique — art3(3)'] as Condition]:[])] as Condition[])];
if(r.family==='ipp')return [...common,['ippGoods',ippItems.find(i=>i.id===r.ippItem)?.label??'Disposição IPP específica identificada e aplicável'],['ownConditions','Condições, limites e legislação específica referida neste item demonstrados; não basta seleccionar a categoria'],['priorRequest','Requerimento prévio à entidade competente — Decreto37/2023 art27(2)'],['use','Uso exclusivo para o fim/beneficiário; compromisso de uso art28(1–3) identificado ou previsto']];
return [];
}
export function ippAuthority(item:string,date:string){const n=Number(item),current=date>='2026-07-31';if(n===30&&!current)return 'Competência específica anterior a31/07/2026 por identificar; não retroagir Decreto27/2026';const groups=current?[[[9,11,15,16,21,22,28,29],'Ministro das Finanças'],[[2,8,12,14,20,23,24,25,27,30],'Presidente da Autoridade Tributária'],[[1,3,4,7,10,26],'Director-Geral das Alfândegas'],[[5,6,13,17,18,19],'Chefes das Estâncias Aduaneiras']]:[[[8,9,11,15,16,21,22,23,28,29],'Ministro das Finanças'],[[2,4,12,14,20,24,25,27],'Presidente da Autoridade Tributária'],[[1,7,26],'Director-Geral das Alfândegas'],[[3,10],'Director Regional'],[[5,6,13,17,18,19],'Chefes das Estâncias Aduaneiras']];return groups.find(([ids])=>(ids as number[]).includes(n))?.[1] as string||'Competência segundo disposição específica identificada';}
function date(v:string){const d=new Date(v+'T00:00:00Z');return /^\d{4}-\d{2}-\d{2}$/.test(v)&&Number.isFinite(d.getTime())&&d.toISOString().slice(0,10)===v;}
function years(v:string,n:number){const d=new Date(v+'T00:00:00Z'),m=d.getUTCMonth();d.setUTCFullYear(d.getUTCFullYear()+n);if(d.getUTCMonth()!==m)d.setUTCDate(0);return d.toISOString().slice(0,10);}
const positive=(v:string)=>/^[1-9]\d{0,5}$/.test(v),nonnegative=(v:string)=>/^(0|[1-9]\d{0,5})$/.test(v);
export function evaluateRemission(r:RemissionRow,currency:unknown):RemissionLine{
const result:RemissionLine={id:r.id,status:'indeterminate',importVat:null,deduction:null,source:remissionSource,reason:''};const stop=(reason:string,status:RemissionLine['status']='indeterminate')=>({...result,status,reason});
if(!remissionFamilies.some(([k])=>k===r.family))return stop('Escolha uma das quatro famílias documentadas.');
if(currency!=='MZN'||r.currency!==currency||!/^2026-(0[1-9]|1[0-2])$/.test(r.period)||!date(r.importDate)||r.importDate.slice(0,7)!==r.period)return stop('Indique moedaMZN e data/período2026 coerentes; não se presume conversão.');
if(!['projected','effective'].includes(r.origin)||![r.description,r.importer,r.scope,r.evidence,r.documentRef,r.rightsRef].every(v=>v.trim()))return stop('Identifique bens, importador, âmbito, documentos e fundamento da isenção de direitos ou pressupostos expressos.');
if(['reduced','zero','none'].includes(r.rights))return stop('Não demonstrada isenção integral de direitos nesta remissão. Redução, taxa pautal0% e não incidência são distintas de isenção — Decreto37/2023 art12(3). Outros fundamentos e eventual regime proporcional permanecem separados.','not_applicable');
if(r.rights!=='exempt')return stop('Situação dos direitos indeterminada; não equivale a IVAzero.');
const conditions=remissionConditions(r);if(conditions.some(([k])=>r.conditions[k]==='no'))return stop('Condição própria desta família não satisfeita; outros fundamentos não são excluídos.','not_applicable');if(conditions.some(([k])=>r.conditions[k]!=='yes'))return stop('Condições próprias por esclarecer; nenhuma confirmação é inferida de outra família.');
if(r.family==='patronage'&&!['book','donation','specific'].includes(r.patronagePath))return stop('Escolha livro/insumo, liberalidade ou disposição específica; doação genérica não concede isenção de importação.');
if(r.family==='patronage'&&['donation','specific'].includes(r.patronagePath)&&!r.specialRef.trim())return stop('Identifique acção/liberalidade e confirmação regulamentar ou disposição específica e âmbito.');
if(r.family==='ipp'){
if(!ippItems.some(i=>i.id===r.ippItem)&&!(r.ippItem==='specific'&&r.ippArticle.trim()))return stop('Escolha itemIPP ou identifique artigo específico; lista não classifica automaticamente os bens.');
if(!date(r.decisionDate))return stop('Indique data da decisão ou previsão para aplicar a competência vigente nesse acto; a data de importação não a substitui.');
if(r.ippItem==='30'&&r.decisionDate<'2026-07-31'&&!r.ippArticle.trim())return stop('Item30 antes de31/07/2026:identifique a disposição de competência aplicável; não retroagir Decreto27/2026.');
if(!r.requestRef.trim()||!r.specialRef.trim())return stop('Identifique requerimento prévio, condições/remissões e compromisso de uso. Confirmação de tutela apenas quando prevista no item.');
result.source+=';IPP22/item'+r.ippItem+';'+r.ippArticle+';entidade segundo data:'+ippAuthority(r.ippItem,r.decisionDate);
}
if(r.family==='diplomatic'){
if(!diplomaticRoles.some(([k])=>k===r.role))return stop('Identifique categoria diplomática; os limites não são iguais.');
if(['agency','organisation'].includes(r.role)){if(!r.agreementRef.trim()||!r.specialRef.trim())return stop('Identifique o Acordo de Sede/específico, cláusula e condições; não aplicar automaticamente quotas de pessoas às organizações.');}
else{
if(!r.requestRef.trim()||!r.historyRef.trim()||!r.limitRef.trim()||!positive(r.quantity)||!nonnegative(r.existingQuantity))return stop('Identifique pedido viaMINEC, histórico externo e reciprocidade/limite; informe quantidades inteiras.');
const statutory=({head:3,agent:2,honorary:1,technical:1} as Record<string,number>)[r.role];const limit=positive(r.limit)?(r.role==='mission'?Number(r.limit):Math.min(Number(r.limit),statutory)):null;
if(limit===null||limit===undefined)return stop('Limite da missão fixado caso a caso pelo MINEC; sem limite numérico presumido.');
if(Number(r.quantity)+Number(r.existingQuantity)>limit)return stop('Quantidade excede o limite desta categoria/reciprocidade — art9; separar bens abrangidos e excedentes, sem isentar toda a linha.','not_applicable');
if(r.history==='known'&&(!date(r.previousDate)||r.importDate<years(r.previousDate,5)))return stop('Nova importação antes de decorridos cinco anos ou data anterior por esclarecer — art9(3).');
if(!['none','known'].includes(r.history))return stop('Histórico por esclarecer; dossier vazio não demonstra ausência de importação anterior.');
}
}
const required=r.family==='ipp'||r.family==='diplomatic'||(r.family==='patronage'&&r.patronagePath==='donation');
if(r.decision==='denied')return stop('Pedido indeferido neste âmbito; não há isenção concedida.','not_applicable');
if(r.decision==='requested')return stop('Pedido apresentado conserva benefício solicitado; não é concessão.');
if(required&&!((r.decision==='approved'&&r.decisionRef.trim())||(r.origin==='projected'&&r.decision==='planned'&&r.decisionRef.trim())))return stop('Indique decisão/confirmação abrangente ou pressuposto expresso de deferimento na projecção; efectivo não usa deferimento previsto.');
if(!required&&!['not_required','approved','planned'].includes(r.decision))return stop('Registe aplicação legal directa ou a decisão/pressuposto identificado; não é criada nova aprovação.');
if(!required&&['approved','planned'].includes(r.decision)&&(!r.decisionRef.trim()||(r.origin==='effective'&&r.decision==='planned')))return stop('Decisão/pressuposto deve ter referência e natureza coerentes.');
return {...result,status:'exempt',importVat:'0.00',reason:'Isenção de IVA12(1)b: '+(remissionFamilies.find(([k])=>k===r.family)?.[1]??r.family)+', apenas no âmbito da isenção de direitos demonstrada. '+(r.origin==='projected'?'Cenário condicionado aos pressupostos expressos; não benefício concedido.':'Factos efectivos e âmbito declarados; o portal não emite concessão.')+' Sem direitos, ICE, dedução/campo11, soma aos livros internos ou cálculo de alienação; restrições de uso e alterações de destino mantêm o seu regime próprio.'};
}
function key(draft:Record<string,unknown>,book:RemissionBook){return JSON.stringify({version:remissionVersion,scope:acquisitionScope(draft),currency:draft.currency,location:draft.selection_labels??{},rows:book.rows});}
export function remissionCurrent(draft:Record<string,unknown>,book:RemissionBook){return !!book.result&&book.result.sourceKey===key(draft,book);}
export function recordRemissions(draft:Record<string,unknown>,book:RemissionBook):RemissionBook{if(!book.rows.length||new Set(book.rows.map(r=>r.id)).size!==book.rows.length)throw Error('Identifique linhas distintas; originais preservados.');const result:Result={version:remissionVersion,revision:(book.result?.revision??0)+1,calculatedAt:new Date().toISOString(),sourceKey:key(draft,book),inputs:structuredClone(book.rows),rows:book.rows.map(r=>evaluateRemission(r,draft.currency))};for(let i=0;i<book.rows.length;i++){const r=book.rows[i];if(r.family!=='diplomatic'||['agency','organisation'].includes(r.role)||result.rows[i].status!=='exempt')continue;const peers=book.rows.filter((p,j)=>j!==i&&p.family==='diplomatic'&&p.role===r.role&&p.importer===r.importer&&p.origin===r.origin&&evaluateRemission(p,draft.currency).status==='exempt');const statutory=({head:3,agent:2,honorary:1,technical:1} as Record<string,number>)[r.role]??Number(r.limit);const limit=Math.min(statutory,Number(r.limit),...peers.map(p=>Number(p.limit)));const quantity=Number(r.quantity)+peers.reduce((sum,p)=>sum+Number(p.quantity),0)+Math.max(Number(r.existingQuantity),...peers.map(p=>Number(p.existingQuantity)));if(quantity>limit||peers.some(p=>p.importDate!==r.importDate&&Math.max(Date.parse(p.importDate),Date.parse(r.importDate))<Date.parse(years(p.importDate<r.importDate?p.importDate:r.importDate,5))))result.rows[i]={...result.rows[i],status:'indeterminate',importVat:null,reason:'Linhas do mesmo beneficiário/categoria excedem o limite conjunto ou repetem importação em cinco anos; conferir histórico e bens abrangidos, sem dupla utilização.'};}const next={...book,result,history:[...(book.history??[]),...(book.result?[book.result]:[])]};saveRemissionBook(draft,next);return next;}
export function remissionReportRows(draft:Record<string,unknown>):Array<[string,string,string,string]>{try{const b=remissionBook(draft),v=b.result;if(!v)return[];return v.inputs.map((r,i)=>{
const context=[`Importador:${r.importer}`,`natureza:${r.origin==='projected'?'projecção condicionada':'factos efectivos'}`,`data:${r.importDate}`,`documentos:${r.documentRef}`,`âmbito:${r.scope}`,`factos:${r.evidence}`,`direitos:${r.rights};fundamento:${r.rightsRef}`,`decisão:${r.decision};data:${r.decisionDate};referência:${r.decisionRef}`];
if(r.family==='ipp')context.push(`IPP:${r.ippItem};artigo:${r.ippArticle};condições e uso:${r.specialRef};requerimento:${r.requestRef}`);
if(r.family==='patronage')context.push(`Mecenato:${r.patronagePath};referência:${r.specialRef}`);
if(r.family==='diplomatic')context.push(`Categoria:${diplomaticRoles.find(([k])=>k===r.role)?.[1]??r.role}`,`acordo:${r.agreementRef}`,`pedido:${r.requestRef}`,`condições:${r.specialRef}`,`quantidade:${r.quantity};já abrangidos:${r.existingQuantity};limite:${r.limit};referência:${r.limitRef}`,`histórico:${r.historyRef};anterior:${r.previousDate||r.history}`);
context.push(...remissionConditions(r).map(([k,label])=>`${label}:${r.conditions[k]==='yes'?'Sim':r.conditions[k]==='no'?'Não':'Por esclarecer'}`));
return ['IVA mensal',`P047 — ${r.period} — ${r.id}`,`${r.description};${v.rows[i].reason};IVA:${v.rows[i].importVat??'Indeterminado'};dedução:Não apurada`,`${v.rows[i].source};${remissionCurrent(draft,b)?'Resultado actual':'Entradas alteradas;resultado histórico conservado'};versão${v.revision};${v.calculatedAt};${context.join(';')}`];
});}catch(e){return[['IVA mensal','P047 — recuperação',String(e),'Originais preservados']];}}
+2
View File
@@ -1,3 +1,4 @@
import { remissionReportRows } from './iva-remission-imports.ts';
import { digitalReportRows } from './iva-digital.ts';
import { objectiveImportReportRows } from './iva-objective-imports.ts';
import { minerReportRows } from './iva-miners.ts';
@@ -669,6 +670,7 @@ export function buildProjectDossierRows(
rows.push(...digitalReportRows(draft));
rows.push(...objectiveImportReportRows(draft));
rows.push(...minerReportRows(draft));
rows.push(...remissionReportRows(draft));
rows.push(...returneeReportRows(draft));
rows.push(...travelReportRows(draft));
rows.push(...travelEventReportRows(draft));
+22
View File
@@ -0,0 +1,22 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;
final class IvaRemissionDraftTest extends TestCase
{
use DatabaseTransactions;
public function test_four_remission_families_recover_preserving128_accepted_books_and_partial_baggage():void
{
$target=DB::selectOne('select current_database() as name,inet_server_port() as port');$this->assertSame('simulator_fiscal_delta_20261021_test',$target->name);$this->assertSame(55441,(int)$target->port);
config(['investor-path.enabled'=>true,'suitecrm.enabled'=>false]);$this->actingAs(User::factory()->create(['email_verified_at'=>now()]));
$draft=json_decode(file_get_contents(base_path('tests/frontend/fixtures/iva-remission.json')),true,flags:JSON_THROW_ON_ERROR);
$id=$this->postJson('/api/v1/simulation-drafts',['personal_snapshot'=>[],'economic_snapshot'=>$draft],['Idempotency-Key'=>(string)Str::uuid()])->assertCreated()->json('data.id');$recovered=$this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk()->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'],$recovered['modelo_a_snapshot']);$this->assertSame('opportunity:367',$recovered['context_opportunity']);$s=json_decode($recovered['modelo_a_snapshot'],true,flags:JSON_THROW_ON_ERROR);$b=$s['remissionImports']['opportunity:367'];$this->assertCount(42,$b['rows']);$this->assertCount(1,$b['history']);$this->assertSame($b['rows'],$b['result']['inputs']);
foreach($b['result']['rows'] as $row){$this->assertSame('exempt',$row['status']);$this->assertSame('0.00',$row['importVat']);$this->assertNull($row['deduction']);$this->assertStringContainsString('CIVA12(1)b',$row['source']);}
$frozen=json_decode(file_get_contents(base_path('tests/frontend/fixtures/iva-remission-preserved.json')),true,flags:JSON_THROW_ON_ERROR);$prior=json_decode($frozen['modelo_a_snapshot'],true,flags:JSON_THROW_ON_ERROR);foreach($prior as $key=>$value)$this->assertSame($value,$s[$key]);
$path=base_path('outputs/iva-l1-p047-families-20261025');if(!is_dir($path))mkdir($path,0775,true);file_put_contents($path.'/recovered.json',json_encode($recovered,JSON_THROW_ON_ERROR|JSON_UNESCAPED_UNICODE));
}
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,17 @@
import test from 'node:test';import assert from 'node:assert/strict';import fs from 'node:fs';
import {newRemission,remissionConditions,evaluateRemission,ippItems,ippAuthority,diplomaticRoles,recordRemissions,saveRemissionBook,remissionBook,remissionCurrent,remissionReportRows} from '../../resources/js/lib/iva-remission-imports.ts';
import {objectiveImportBook} from '../../resources/js/lib/iva-objective-imports.ts';
const frozen=JSON.parse(fs.readFileSync('tests/frontend/fixtures/iva-remission-preserved.json','utf8')),prior=JSON.parse(frozen.modelo_a_snapshot),draft={...frozen,context_opportunity:'opportunity:367',project_title:'SYNTHETIC QA — P047 quatro famílias'};
function row(family,id,patch={}){const r={...newRemission(id??family,'MZN'),family,description:'SYNTHETIC QA bens '+(id??family),importer:'SYNTHETIC QA importador '+(id??family),period:'2026-10',importDate:'2026-10-15',scope:'SYNTHETIC QA bens/operação/período/condições',evidence:'SYNTHETIC QA pressupostos expressos',documentRef:'SYNTHETIC QA documentos',rights:'exempt',rightsRef:'SYNTHETIC QA isenção de direitos:fundamento e âmbito',decision:'planned',decisionRef:'SYNTHETIC QA deferimento previsto neste âmbito',decisionDate:'2026-10-01',requestRef:'SYNTHETIC QA requerimento prévio',specialRef:'SYNTHETIC QA cláusula,condições específicas/compromisso de uso',ippItem:'3',patronagePath:'book',role:'agent',quantity:'1',existingQuantity:'0',limit:'2',limitRef:'SYNTHETIC QA reciprocidade e limite',history:'none',historyRef:'SYNTHETIC QA histórico externo',agreementRef:'SYNTHETIC QA acordo e cláusula',...patch};r.conditions=Object.fromEntries(remissionConditions(r).map(([k])=>[k,'yes']));return r;}
const examples=[];
test('P047 partido: equipamento próprio; sem quota diplomática nem nova aprovação',()=>{const r=row('party','party',{decision:'not_required',decisionRef:'',requestRef:'',specialRef:'',limit:'',historyRef:''});assert.equal(evaluateRemission(r,'MZN').status,'exempt');for(const k of ['equipment','nonBusiness','party'])assert.equal(evaluateRemission({...r,conditions:{...r.conditions,[k]:'no'}},'MZN').status,'not_applicable');examples.push(r);});
for(const path of ['book','donation','specific'])test('P047 mecenato / '+path,()=>{const r=row('patronage','patronage-'+path,{patronagePath:path,decision:path==='donation'?'planned':'not_required'});const v=evaluateRemission(r,'MZN');assert.equal(v.status,'exempt');assert.equal(v.importVat,'0.00');assert.equal(v.deduction,null);assert.equal(remissionConditions(r).some(([k])=>k==='confirmation'),path==='donation');examples.push(r);});
for(const[role]of diplomaticRoles)test('P047 categoria diplomática / '+role,()=>{const r=row('diplomatic','diplomatic-'+role,{role,limit:role==='mission'?'8':role==='head'?'3':['honorary','technical'].includes(role)?'1':'2'});assert.equal(evaluateRemission(r,'MZN').status,'exempt');assert.equal(remissionConditions(r).some(([k])=>k==='foreignNonResident'),['agent','technical'].includes(role));examples.push(r);});
for(const item of ippItems)test('P047 IPP22 / '+item.id,()=>{const r=row('ipp','ipp-'+item.id,{ippItem:item.id});assert.equal(evaluateRemission(r,'MZN').status,'exempt');assert.match(evaluateRemission(r,'MZN').source,new RegExp('item'+item.id+';'));examples.push(r);});
test('P047 IPP lista exemplificada não substitui condições; outro artigo exige citação',()=>{const r=row('ipp','ipp-specific',{ippItem:'specific',ippArticle:'SYNTHETIC QA artigo específico e versão'});assert.equal(evaluateRemission(r,'MZN').status,'exempt');assert.equal(evaluateRemission({...r,ippArticle:''},'MZN').status,'indeterminate');assert.equal(evaluateRemission({...r,specialRef:''},'MZN').status,'indeterminate');assert.equal(evaluateRemission({...r,requestRef:''},'MZN').status,'indeterminate');assert.equal(evaluateRemission({...r,conditions:{...r.conditions,ownConditions:''}},'MZN').status,'indeterminate');examples.push(r);});
test('P047 IPP competência não retroage2026; taxa0 não é isenção; encargo do Estado não basta',()=>{assert.match(ippAuthority('3','2026-07-30'),/Director Regional/);assert.match(ippAuthority('3','2026-07-31'),/Director-Geral/);assert.match(ippAuthority('30','2026-07-30'),/por identificar/);assert.match(evaluateRemission(row('ipp','old-authority',{ippItem:'3',decisionDate:'2026-07-30'}),'MZN').source,/Director Regional/);assert.equal(evaluateRemission(row('ipp','missing-date',{decisionDate:''}),'MZN').status,'indeterminate');assert.equal(evaluateRemission(row('ipp','early30',{ippItem:'30',period:'2026-07',importDate:'2026-07-30',decisionDate:'2026-07-30'}),'MZN').status,'indeterminate');for(const item of ['28','30'])for(const rights of ['zero','none','reduced'])assert.equal(evaluateRemission(row('ipp',item,{ippItem:item,rights}),'MZN').status,'not_applicable');});
test('P047 pedido apresentado nunca concede; previsto apenas projecção; âmbito exacto',()=>{for(const family of ['party','patronage','diplomatic','ipp']){const r=row(family);assert.equal(evaluateRemission({...r,decision:'requested'},'MZN').status,'indeterminate');assert.equal(evaluateRemission({...r,decision:'denied'},'MZN').status,'not_applicable');assert.equal(evaluateRemission({...r,origin:'effective'},'MZN').status,'indeterminate');assert.equal(evaluateRemission({...r,origin:'effective',decision:'approved'},'MZN').status,'exempt');assert.equal(evaluateRemission({...r,decisionRef:'',decision:'approved'},'MZN').status,'indeterminate');assert.equal(evaluateRemission({...r,conditions:{...r.conditions,scope:'no'}},'MZN').status,'not_applicable');}});
test('P047 desconhecido/fonte ausente/data impossível não viram IVAzero',()=>{const r=row('party');for(const patch of [{rights:''},{rightsRef:''},{scope:''},{documentRef:''},{importer:''},{importDate:'2026-02-30'},{period:'2027-10'},{currency:'USD'},{conditions:{...r.conditions,equipment:''}}]){const v=evaluateRemission({...r,...patch},'MZN');assert.equal(v.status,'indeterminate');assert.equal(v.importVat,null);}assert.equal(evaluateRemission({...r,rights:'zero'},'MZN').status,'not_applicable');});
test('P047 veículos: quotas e reciprocidade inferiores,5anos,desconhecido; sem extensão de agentes a agências',()=>{const r=row('diplomatic');for(const patch of [{quantity:'3'},{quantity:'2',existingQuantity:'1'},{quantity:'2',limit:'1'}])assert.equal(evaluateRemission({...r,...patch},'MZN').status,'not_applicable');for(const patch of [{history:''},{limit:''},{history:'known',previousDate:'2021-10-16'},{limitRef:''},{quantity:'1.5'},{quantity:'-1'}])assert.equal(evaluateRemission({...r,...patch},'MZN').status,'indeterminate');assert.equal(evaluateRemission({...r,history:'known',previousDate:'2021-10-15'},'MZN').status,'exempt');const agency=row('diplomatic','agency',{role:'agency',limit:'',history:'',historyRef:'',quantity:'',existingQuantity:''});assert.equal(evaluateRemission(agency,'MZN').status,'exempt');assert.equal(evaluateRemission({...agency,agreementRef:''},'MZN').status,'indeterminate');});
test('P047 veículos:duas linhas do mesmo direito não duplicam limite nem janela5anos',()=>{const a=row('diplomatic','a',{quantity:'2'}),b={...a,id:'b'};assert.deepEqual(recordRemissions(draft,{rows:[a,b]}).result.rows.map(r=>r.status),['indeterminate','indeterminate']);const c={...b,quantity:'1',importDate:'2026-10-16'};assert.deepEqual(recordRemissions(draft,{rows:[{...a,quantity:'1'},c]}).result.rows.map(r=>r.status),['indeterminate','indeterminate']);});
test('P047 recuperação/histórico/relatório preservam128fechos e quatro percursosQA P058',()=>{let book=recordRemissions(draft,{rows:examples});assert.equal(examples.length,42);assert.equal(remissionCurrent(draft,book),true);const old=structuredClone(book.result);book={...book,rows:book.rows.map((r,i)=>i?r:{...r,scope:'SYNTHETIC QA novo âmbito'})};assert.equal(remissionCurrent(draft,book),false);assert.deepEqual(book.result,old);book=recordRemissions(draft,book);assert.deepEqual(book.history[0],old);draft.modelo_a_snapshot=saveRemissionBook(draft,book);assert.deepEqual(remissionBook(draft),book);const after=JSON.parse(draft.modelo_a_snapshot);for(const[k,v]of Object.entries(prior))assert.deepEqual(after[k],v);assert.equal(remissionBook({...draft,context_opportunity:'opportunity:999'}).rows.length,0);assert.match(remissionReportRows(draft)[0][3],/versão2/);assert.match(remissionReportRows(draft)[0][2],/IVA:0.00/);assert.throws(()=>saveRemissionBook(draft,{rows:[{...examples[0],rightsRef:{bad:true}}]}),/não recuperáveis/);assert.throws(()=>recordRemissions(draft,{rows:[examples[0],examples[0]]}),/distintas/);if(process.env.IVA_REMISSION_FIXTURE)fs.writeFileSync('tests/frontend/fixtures/iva-remission.json',JSON.stringify(draft));});