Files
Investidor-V2/resources/js/lib/iva-operations.ts
T

277 lines
56 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { acquisitionScope, readAcquisitionStore } from './iva-acquisitions.ts';
import { fundraisingError, type FundraisingContext } from './iva-fundraising.ts';
import { pharmaAnnexEntry, pharmaAnnexReference, pharmaAnnexSource, pharmaAnnexVersion } from './iva-pharma-annex.ts';
import { annexIEntry, annexIReference, annexISource, annexIVersion } from './iva-annex-i.ts';
import { productionOptionCheck, productionOptionVersion, type ProductionTaxOption } from './iva-production-option.ts';
import { temporaryBenefits, temporaryBenefit, temporaryBenefitNotice, temporaryBenefitVersion } from './iva-temporary-benefits.ts';
import { directExportTreatments } from './iva-export-operations.ts';
import { exportBeneficiaryTreatments } from './iva-export-beneficiaries.ts';
import { specialRegimeTreatments, specialRegimeIssue, specialRegimeOptions, isSpecialRegime, type SpecialRegime } from './iva-special-regimes.ts';
import { internationalAssetTreatments } from './iva-international-assets.ts';
import { exportServiceTreatments, isExportService } from './iva-export-services.ts';
import { onboardSupplyTreatments, onboardSupplyIssue, supplyCategories, isOnboardSupply, type SupplyCategory } from './iva-onboard-supplies.ts';
import { monthlySalesFromDraft, readMonthlyIvaSettings } from './monthly-iva.ts';
import { addFractions, decimalFraction, fraction, fractionLabel, fractionPresentation, type FiscalFraction } from './fiscal-rational.ts';
export const operationVersion = 'iva-operations-l1/2';
// The accepted v2 full-catalogue key predates scoped keys. Freeze its members
// so later, independent catalogue additions cannot invalidate those snapshots.
const legacyV2TreatmentIds = ['general','private_health','private_education','private_training','personal_lessons','export_goods','housing_rent','public_health','public_education','public_training','foreign_operation','other'];
const source2022 = 'Lei22/2022, BR250, 2.º suplemento, PDF1–4 (2252(25)–(28)); arts.1/2/6; efeitos01/01/2023';
const source2016 = 'CIVA republicado Lei13/2016, BR156, 10.º suplemento, PDF9–15 (1426(267)–(273))';
const source2025 = 'Lei10/2025, BR248, suplemento1, PDF14–15 (2180(14)–(15)); arts.1/2/3/5; efeitos01/01/2026';
const healthGoodsSource = 'CIVA republicado Lei13/2016, PDF9, p.1426(267), art.9(1)(b–f); PDF15, p.1426(273), art.19(1); Lei22/2022 art.1, PDF1, p.2252(25), mantém9(1)(b–f). Âmbito técnico2026/MZN';
const internalOperation = 'Operação interna localizada em Moçambique; não é importação nem operação localizada no estrangeiro';
export const modeloA06Correspondence = 'Exemplar recebido:06 é base de operações isentas, com remissão18(1)(b); nessa lei18(1)(b) trata IVA de importações, enquanto19(1)(b) enumera operações com direito. O mesmo exemplar já tem05 para vendas isentas com direito. O formulário antigo da AT usa03 para a remissão e06 para existências. Não há correspondência unívoca nem instrução aplicável que separe05/06 no acervo conferido: não atribuir06 automaticamente a operações no estrangeiro ou importar instruções antigas por número.';
export type OperationTreatment = {id:string; label:string; field:string|null; rate:number|null; article:string; source:string; conditions:string[];logicVersion?:string};
const nonprofitConditions = [
'Não distribui nem disponibiliza lucros; os corpos gerentes não têm interesse directo ou indirecto nos resultados, por si ou interposta pessoa',
'Escrituração abrange todas as actividades e está à disposição dos serviços fiscais para comprovação',
'Preços homologados pela autoridade competente ou, quando não susceptíveis de homologação, inferiores aos de operações análogas das empresas comerciais sujeitas a imposto',
'Não entra em concorrência directa com sujeitos passivos do imposto',
];
function socialTreatment(id:string,label:string,article:string,conditions:string[],nonprofit:boolean):OperationTreatment {
return {id,label,field:'07',rate:0,article:`CIVA arts.9(2)(${article}),10(${nonprofit?'2':'1'}),19(1)`,source:'CIVA republicado Lei13/2016, PDF9, p.1426(267), art.9(2)(a/c/d); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF2, p.2252(26),10(1–2). Âmbito técnico2026/MZN',conditions:[internalOperation,...(nonprofit?nonprofitConditions:['Entidade pública: órgão ou instituição da Administração Pública que desempenha funções administrativas do Estado, nos termos da legislação aplicável']),...conditions]};
}
const culturalSource = 'CIVA republicado Lei13/2016, PDF9, p.1426(267), art.9(2)(e–g); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF1, p.2252(25), mantém9(2)(e–g), e PDF2, p.2252(26),10(1–2). Âmbito técnico2026/MZN';
const culturalTreatments:OperationTreatment[] = ([false,true] as const).flatMap(nonprofit=>{
const suffix=nonprofit?'nonprofit':'public',entity=nonprofit?'organismo sem finalidade lucrativa':'entidade pública';
const make=(id:string,label:string,article:string,conditions:string[]):OperationTreatment=>({...socialTreatment(id,label,article,conditions,nonprofit),source:culturalSource});
return [
make(`cultural_visits_${suffix}`,`Visitas culturais/naturais — ${entity}`,'e',['Visita, guiada ou não, a museu, galeria de arte, monumento, parque, perímetro florestal, jardim botânico/zoológico ou similar pertencente ao Estado, a entidade pública ou a entidade sem finalidade lucrativa','Serviço efectuado pela própria entidade, por intermédio dos seus próprios agentes; organismo sem finalidade lucrativa devidamente autorizado quando aplicável','Se houver bens, são transmissões estreitamente conexas com essa visita; não venda autónoma nem serviço de intermediário']),
make(`religious_personnel_${suffix}`,`Cedência de pessoal religiosa/filosófica — ${entity}`,'f',['Cedência de pessoal efectuada por instituição religiosa ou filosófica identificada','Destino identificado: actividade isenta nos termos do CIVA, com fundamento específico, ou assistência espiritual; não qualquer fornecimento de mão-de-obra']),
];
});
culturalTreatments.push({id:'statutory_membership',label:'Serviços colectivos aos associados por quota estatutária',field:'07',rate:0,article:'CIVA arts.9(2)(g),10(2),19(1)',source:culturalSource,conditions:[internalOperation,...nonprofitConditions,'Serviços efectuados no interesse colectivo dos próprios associados por organismo sem finalidade lucrativa','Objectivos de natureza política, sindical, religiosa, patriótica, filantrópica, recreativa, desportiva, cultural, cívica ou de representação de interesses económicos, identificados','A única contraprestação é uma quota fixada nos respectivos estatutos; não pagamentos adicionais por serviços individuais']});
const listedGoodsTreatments:OperationTreatment[] = [
['maize','Milho','Bem transmitido identificado como milho'],
['maize_flour','Farinha de milho','Bem transmitido identificado como farinha de milho'],
['rice','Arroz','Bem transmitido identificado como arroz'],
['bread','Pão','Bem transmitido identificado como pão'],
['iodised_salt','Sal iodado','Sal identificado como iodado; não qualquer sal'],
['infant_powdered_milk','Leite em pó para lactente até um ano','Leite em pó identificado como destinado a lactente até um ano; não qualquer leite ou alimento infantil'],
['wheat','Trigo','Bem transmitido identificado como trigo'],
['wheat_flour','Farinha de trigo','Bem transmitido identificado como farinha de trigo'],
['fresh_chilled_tomato','Tomate fresco ou refrigerado','Tomate identificado como fresco ou refrigerado; não alargar automaticamente a conserva ou preparação'],
['potato','Batata','Bem transmitido identificado como batata'],
['onion','Cebola','Bem transmitido identificado como cebola'],
['frozen_horse_mackerel','Carapau congelado','Peixe identificado como carapau congelado; não qualquer espécie ou estado de conservação'],
['lighting_kerosene','Petróleo de iluminação','Produto identificado como petróleo de iluminação; não qualquer combustível'],
['domestic_lpg','Gás doméstico — GPL','Produto identificado como gás doméstico GPL; não qualquer gás industrial'],
['jet_fuel','Jet fuel','Produto identificado como jet fuel; não qualquer combustível de transporte'],
['eligible_bicycles','Bicicletas comuns e de ferro até 4 velocidades','Produto identificado na enumeração legal «bicicletas comuns e de ferro até 4 velocidades», com características sustentadas; não qualquer veículo'],
['condoms','Preservativos','Bem transmitido identificado como preservativo'],
['insecticides','Insecticidas','Bem transmitido identificado como insecticida; não qualquer produto químico'],
].map(([id,label,condition])=>({id:`listed_${id}`,label:`Lista legal — ${label}`,field:'05',rate:0,article:'CIVA arts.9(10),19(1)(b)(v), redacção Lei22/2022',source:'Lei22/2022 art.1, PDF2, p.2252(26),9(10); CIVA republicado Lei13/2016, PDF15, p.1426(273),19(1)(b)(v). Âmbito técnico2026/MZN',conditions:[internalOperation,'Transmissão do próprio bem enumerado, identificado; não um serviço autónomo nem extensão por sector, marca ou destino',condition]}));
export const operationTreatments:OperationTreatment[] = [
...exportServiceTreatments,
...onboardSupplyTreatments,
...internationalAssetTreatments,
...directExportTreatments,
...exportBeneficiaryTreatments,
...specialRegimeTreatments,
...temporaryBenefits.map(item=>({id:item.id,label:`Benefício terminado31/12/2025 — ${item.label}`,field:null,rate:null,article:`CIVA art.${item.article}`,source:`${item.source} CIVA republicado Lei13/2016,9(14),PDF10/p.1426(268),apenas para9(13)(b/f). Âmbito:cessação nas operações internas2026/MZN;sem cálculo histórico.`,conditions:[],logicVersion:temporaryBenefitVersion})),
{id:'annexI_goods',label:'Equipamento, sementes e outros bens do Anexo I — artigo9(12)(h)',field:'07',rate:0,logicVersion:annexIVersion,article:'CIVA arts.9(12)(h),19(1); Lei22/2022 art.3(1)',source:`CIVA republicado Lei13/2016, PDF10, p.1426(268),9(12)(h), e PDF15, p.1426(273),19(1); rectificação BR89/2017, PDF1, p.569; ${annexISource}. Âmbito técnico2026/MZN`,conditions:[internalOperation,'O bem transmitido corresponde ao código e à designação da posição escolhida no Anexo I; não basta a actividade agrícola, a marca ou uma indicação genérica de equipamento','Qualificadores expressos na posição conferidos e fundamentados, incluindo natureza, destino, certificação, peso, capacidade ou potência quando exigidos nessa linha; não acrescentar condições a linhas que não as exigem']},
{id:'pharma_manufacturing_inputs',label:'Bens do Anexo III para fabrico de medicamentos — estabelecimento integrado no SNS',field:'07',rate:0,logicVersion:pharmaAnnexVersion,article:'CIVA arts.9(1)(g),19(1); Lei22/2022 art.3(1)',source:`CIVA republicado Lei13/2016, PDF9, p.1426(267),9(1)(g), e PDF15, p.1426(273),19(1); rectificação BR89/2017, PDF1, p.569; ${pharmaAnnexSource}. Âmbito técnico2026/MZN`,conditions:[internalOperation,'Transmissão efectuada pelo próprio estabelecimento público ou privado identificado, integrado no Serviço Nacional de Saúde; não basta que o adquirente ou destino seja um hospital','Bens a utilizar como matérias-primas, produtos intermédios ou componentes para o fabrico de medicamentos, com utilização/fundamento identificados; não mera venda de produto acabado ou utilização genérica','Bem corresponde cumulativamente ao código e à designação da linha seleccionada no Anexo III; confirmar as especificações aplicáveis sem corrigir ou completar a pauta por suposição']},
...([false,true] as const).map(nonprofit=>({...socialTreatment(`fundraising_${nonprofit?'nonprofit':'public'}`,`Angariação ocasional de fundos — ${nonprofit?'organismo sem finalidade lucrativa':'entidade pública'}`,'h',['Actividade habitual isenta identificada:9(1)(a),9(2)(a/b/c/d/e/g) ou9(3)(a/b), com condições dessa isenção e fundamento identificados','Manifestação ocasional destinada à angariação de fundos em proveito exclusivo da entidade organizadora','Total anual declarado inclui esta manifestação e as realizadas fora deste dossier; não superior a oito no ano'],nonprofit),logicVersion:'fundraising/1',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(2)(h); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF1, p.2252(25),9(1–3), e PDF2, p.2252(26),10(1–2). Âmbito técnico2026/MZN'})),
...(['agriculture','forestry','livestock','fishing'] as const).flatMap((kind,index)=>{
const label=['Produção agrícola, avicultura e apicultura','Produção silvícola','Produção pecuária','Pesca'][index],letter=['a','b','c','d'][index];
const conditions=[internalOperation,'Operação no âmbito da própria produção identificada, utilizando os próprios recursos; não mera revenda/comércio','Se houver transformação, é acessória, pelo próprio produtor sobre produtos da sua produção, por meios geralmente utilizados nas respectivas explorações'];
const source=`CIVA republicado Lei13/2016, PDF10, p.1426(268),9(7)(${letter}); PDF11, p.1426(269),11; PDF15, p.1426(273),19(1)(b)(v); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(7). Âmbito técnico2026/MZN`;
const exempt:OperationTreatment={id:`production_${kind}`,label:`${label} — isenção`,field:kind==='agriculture'?'05':'07',rate:0,article:`CIVA arts.9(7)(${letter}),19(1)${kind==='agriculture'?'(b)(v)':',11'}`,source,conditions:[...conditions,...(kind==='agriculture'?[]:['Regime de isenção aplicável nesta operação: não existe opção de tributação eficaz do art.11 no período; fundamento/histórico identificado'])]};
return kind==='agriculture'?[exempt]:[exempt,{id:`production_${kind}_opted`,logicVersion:productionOptionVersion,label:`${label} — opção de tributação eficaz`,field:'01',rate:16,article:`CIVA arts.9(7)(${letter}),11,15(1),17(1),19(1)(a),34`,source:`${source}; ${source2022}; ${source2025}`,conditions:[...conditions,'Opção declarada à Direcção da Área Fiscal competente, na declaração adequada; se opção no início, consta da declaração de início da actividade','Operação no regime normal por opção eficaz; contraprestação completa, sem base especial do art.15(2) ou outro tratamento próprio']}];
}),
...listedGoodsTreatments,
{...socialTreatment('public_security','Bens e serviços ligados à segurança por entidade pública','b',['Transmissão de bens ou prestação ligada à segurança identificada e efectuada pela própria entidade pública; não presumir segurança social nem extensão a prestador privado contratado'],false),source:'CIVA republicado Lei13/2016, PDF9, p.1426(267),9(2)(b); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF1, p.2252(25), mantém9(2)(b); PDF2, p.2252(26),10(1). Âmbito técnico2026/MZN'},
{id:'official_military_supplies',label:'Fornecimentos oficiais militares/paramilitares elegíveis',field:'07',rate:0,article:'CIVA arts.9(11),19(1)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(11); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(11). Âmbito técnico2026/MZN',conditions:[internalOperation,'Bem/serviço no fornecimento de material de guerra e de aquartelamento ou fardamento militar/paramilitar, identificado','Destino de utilização oficial das Forças de Defesa e Segurança Nacional; actividade efectuada exclusivamente para aqueles serviços','Estabelecimento reconhecido pelo Ministério competente, com reconhecimento identificado; não basta o cliente ser militar']},
{id:'sisa_subject_operation',label:'Operação sujeita a SISA, ainda que dela isenta',field:'07',rate:0,article:'CIVA arts.9(12)(d),19(1)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(12)(d); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(12)(d). Âmbito técnico2026/MZN',conditions:[internalOperation,'Operação e fundamento de sujeição a SISA identificados, ainda que exista isenção desse imposto; não qualquer operação imobiliária','Esta linha corresponde à operação sujeita a SISA, não a locação, mediação ou outro serviço autónomo; este bloco não calcula SISA']},
{id:'exempt_activity_asset_sale',label:'Alienação de bem exclusivamente afecto a actividade isenta',field:'07',rate:0,article:'CIVA arts.9(12)(e),19(1)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(12)(e); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(12)(e). Âmbito técnico2026/MZN',conditions:[internalOperation,'Transmissão de bem identificado, com histórico de afectação disponível','Bem afecto exclusivamente a sector de actividade isento; não mera afectação parcial ou existência de alguma operação isenta na entidade']},
{id:'no_deduction_right_asset_sale',label:'Alienação de bem sem direito anterior à dedução',field:'07',rate:0,article:'CIVA arts.9(12)(e),19(1)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(12)(e); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(12)(e). Âmbito técnico2026/MZN',conditions:[internalOperation,'Transmissão de bem identificado, com histórico fiscal da aquisição/afectação disponível','Bem não foi objecto de direito à dedução, com fundamento identificado; não basta não ter exercido um direito existente nem desconhecer o histórico']},
{id:'excluded_deduction_asset_sale',label:'Alienação de bem adquirido com exclusão do artigo 20',field:'07',rate:0,article:'CIVA arts.9(12)(e),20,19(1)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(12)(e); PDF15, p.1426(273),19(1)/20(1); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(12)(e), e PDF3, p.2252(27),20(2–3). Âmbito técnico2026/MZN',conditions:[internalOperation,'Transmissão de bem identificado e aquisição correspondente documentada ou expressamente pressuposta','Aquisição feita com exclusão do direito à dedução nos termos do artigo20: identificar número/alínea aplicável e conferir as excepções do20(3); não assumir exclusão apenas por falta de documento ou dedução não exercida']},
{id:'special_tax_games',label:'Jogos e operações sujeitos ao imposto especial sobre o jogo',field:'07',rate:0,article:'CIVA arts.9(8),19(1)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(8); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(8). Âmbito técnico2026/MZN',conditions:[internalOperation,'Exploração/prática de jogo de fortuna ou azar ou diversão social nos termos da legislação própria, respectiva comissão, título de aposta ou bilhete de acesso/ingresso à área de jogo, identificado','Esta operação está sujeita ao imposto especial sobre o jogo, com fundamento identificado; não qualquer entretenimento ou serviço acessório autónomo; o imposto especial não é calculado neste bloco']},
{id:'stamped_values',label:'Transmissão de valores selados',field:'07',rate:0,article:'CIVA arts.9(12)(a),19(1), redacção Lei22/2022',source:'Lei22/2022 art.1, PDF2, p.2252(26),9(12)(a); CIVA republicado Lei13/2016, PDF15, p.1426(273),19(1). Âmbito técnico2026/MZN',conditions:[internalOperation,'Bem transmitido identificado como valor selado, com natureza sustentada pelo documento ou pressuposto da operação','A linha corresponde à transmissão do valor selado; comissão de venda ou serviço autónomo não é abrangido automaticamente por esta opção']},
{id:'public_passenger_transport',label:'Serviço de transporte público de passageiros',field:'07',rate:0,article:'CIVA arts.9(12)(j),19(1)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(12)(j); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(12)(j). Âmbito técnico2026/MZN',conditions:[internalOperation,'Serviço identificado como transporte público de passageiros, com natureza da prestação sustentada; não inferido apenas da natureza pública do prestador','A linha corresponde ao transporte de passageiros; não transporte de mercadorias, aluguer autónomo de veículo ou outro serviço acessório sem enquadramento próprio']},
{id:'industrial_feed',label:'Rações de produção industrial para animais elegíveis',field:'05',rate:0,article:'CIVA arts.9(12)(f),19(1)(b)(v)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(12)(f); PDF15, p.1426(273),19(1)(b)(v); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(12)(f). Âmbito técnico2026/MZN',conditions:[internalOperation,'Transmissão de bens resultantes de actividade industrial de produção de rações, identificada; não presumir isenção de qualquer alimento para animais','Rações destinadas à alimentação de animais de reprodução e abate para consumo humano, com destino identificado']},
{id:'industrial_feed_inputs',label:'Insumos enumerados para produção industrial de rações',field:'07',rate:0,article:'CIVA arts.9(12)(g),19(1)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(12)(g); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(12)(g). Âmbito técnico2026/MZN',conditions:[internalOperation,'Bem identificado na enumeração: grão de soja, bagaço de soja, soja integral, farinha de peixe, farinha de carne, pós de osso, monofosfato de cálcio, lisina ou metionina','Utilização como matéria-prima na actividade industrial de produção de rações destinadas à alimentação de animais de reprodução e abate para consumo humano, identificada']},
{id:'veterinary_goods',label:'Agulhas, seringas e medicamentos de uso veterinário',field:'07',rate:0,article:'CIVA arts.9(12)(i),19(1)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(12)(i); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(12)(i). Âmbito técnico2026/MZN',conditions:[internalOperation,'Transmissão de agulha, seringa ou medicamento identificado; não qualquer equipamento ou serviço veterinário','Uso veterinário identificado para os bens da operação']},
{id:'agricultural_services',label:'Serviços agrícolas de canais, regadio, drenagem e pulverização',field:'07',rate:0,article:'CIVA arts.9(15),19(1)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(15); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(15). Âmbito técnico2026/MZN',conditions:[internalOperation,'Serviço identificado: abertura de canais, ceifa, drenagem, fornecimento de água para irrigação, limpeza de valas de drenagem ou pulverização da terra','Serviço efectuado no âmbito da actividade agrícola, com afectação identificada; não qualquer obra, limpeza ou fornecimento de água']},
{id:'author_rights',label:'Direitos de autor pelo autor, herdeiro ou legatário',field:'07',rate:0,article:'CIVA arts.9(9)(a),19(1)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(9)(a); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(9). Âmbito técnico2026/MZN',conditions:[internalOperation,'Operação identificada como transmissão de direitos de autor ou autorização para utilização de obra intelectual','Efectuada pelo próprio autor, seu herdeiro ou legatário, com qualidade identificada; não presumir isenção de revenda/intermediação por terceiro']},
{id:'cultural_publications',label:'Jornais, revistas e livros de natureza elegível',field:'07',rate:0,article:'CIVA arts.9(9)(b),19(1)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(9)(b); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(9). Âmbito técnico2026/MZN',conditions:[internalOperation,'Transmissão de jornal, revista ou livro identificado; não qualquer material escolar, serviço editorial ou fornecimento autónomo','Natureza cultural, educativa, técnica ou recreativa da publicação identificada e sustentada; não inferida apenas do nome do fornecedor ou sector']},
...culturalTreatments,
{id:'general',label:'Operação interna geral',field:'01',rate:16,article:'CIVA arts.1,6,15(1),17(1–2); art.34 (Lei10/2025)',source:`${source2016}; ${source2022}; ${source2025}`,conditions:['Operação localizada e tributável em Moçambique, no regime normal','Contraprestação completa; sem base especial do art.15(2), isenção ou taxa reduzida']},
{id:'private_health',label:'Serviços médicos e sanitários privados',field:'03',rate:5,article:'CIVA arts.15(10),17-A(a)',source:source2022,conditions:['Serviço médico/sanitário ou operação estreitamente conexa','Prestador hospitalar privado, clínica, dispensário ou similar']},
{id:'private_education',label:'Ensino privado reconhecido',field:'03',rate:5,article:'CIVA arts.15(10),17-A(b)',source:source2022,conditions:['Ensino ou bens/serviços conexos prestados pelo estabelecimento','Estabelecimento privado integrado no Sistema Nacional de Ensino e reconhecido pelo Ministério competente']},
{id:'private_training',label:'Formação profissional privada',field:'03',rate:5,article:'CIVA arts.15(10),17-A(c)',source:source2022,conditions:['Formação profissional ou fornecimentos conexos pelo prestador, não venda autónoma de materiais','Prestador privado']},
{id:'personal_lessons',label:'Lições ministradas a título pessoal',field:'03',rate:5,article:'CIVA arts.15(10),17-A(d)',source:source2022,conditions:['Lições ministradas a título pessoal','Matérias de ensino escolar ou superior']},
{id:'export_goods',label:'Exportação de bens pelo vendedor',field:'05',rate:0,article:'CIVA arts.13(1)(a),19(1)(b)(i)',source:source2016,conditions:['Bens expedidos/transportados para o estrangeiro pelo vendedor ou terceiro por sua conta','Saída documentada, ou pressuposto expresso da projecção; não mera venda a cliente estrangeiro']},
{id:'housing_rent',label:'Locação de imóvel para habitação',field:'07',rate:0,article:'CIVA art.9(5), redacção Lei22/2022; art.19(1)',source:source2022,conditions:['Locação de imóvel para fins de habitação','Não é hospedagem nem locação comercial/industrial ou serviço autónomo']},
{id:'public_health',label:'Serviços médicos e sanitários públicos',field:'07',rate:0,article:'CIVA arts.9(1)(a),10(1),19(1)',source:source2022,conditions:['Serviço médico/sanitário ou operação estreitamente conexa','Estabelecimento hospitalar público, dispensário ou similar; natureza pública confirmada']},
{id:'public_education',label:'Ensino público reconhecido',field:'07',rate:0,article:'CIVA arts.9(3)(a),10(1),19(1)',source:source2022,conditions:['Ensino ou fornecimentos conexos pelo estabelecimento','Estabelecimento público integrado no Sistema Nacional de Ensino e reconhecido pelo Ministério competente']},
{id:'public_training',label:'Formação profissional pública',field:'07',rate:0,article:'CIVA arts.9(3)(b),10(1),19(1)',source:source2022,conditions:['Formação profissional ou fornecimentos conexos pelo prestador','Prestador público']},
{id:'financial_stamp',label:'Operação bancária/financeira sujeita a Selo',field:'07',rate:0,article:'CIVA art.9(4), redacção Lei22/2022; art.19(1)',source:`${source2022}; ${source2016}`,conditions:['A operação é bancária ou financeira, não um serviço acessório autónomo','Sujeição a Imposto do Selo identificada para esta operação; não depende de calcular o Selo neste bloco']},
{id:'insurance_stamp',label:'Seguro/resseguro ou mediação conexa sujeitos a Selo',field:'07',rate:0,article:'CIVA art.9(6), redacção Lei22/2022; art.19(1)',source:`${source2022}; ${source2016}`,conditions:['Seguro/resseguro ou serviço conexo efectuado por corrector ou outro mediador de seguros','Sujeição a Imposto do Selo identificada para esta operação']},
{id:'public_waste',label:'Remoção de lixo pública ou por entidade contratada',field:'07',rate:0,article:'CIVA art.9(12)(b), redacção Lei22/2022; art.19(1)',source:`${source2022}; ${source2016}`,conditions:['Prestação de serviço de remoção de lixo, não qualquer serviço de limpeza','Efectuada por entidade pública ou por entidade por ela contratada, com relação identificada']},
{id:'public_funeral',label:'Serviços funerários/cremação públicos e bens acessórios',field:'07',rate:0,article:'CIVA art.9(12)(c), redacção Lei22/2022; art.19(1)',source:`${source2022}; ${source2016}`,conditions:['Serviço funerário/cremação ou transmissão de bem acessório a esse serviço','Efectuado por entidade pública; não aplicar automaticamente a funerária privada']},
{id:'health_assistive',label:'Bens de compensação da deficiência, próteses e braille',field:'07',rate:0,article:'CIVA arts.9(1)(b),19(1)',source:healthGoodsSource,conditions:[internalOperation,'Bem identificado na enumeração: cadeira de rodas/veículo semelhante, aparelho/máquina/impressora braille, prótese ou material de compensação','Destino documentado conforme a categoria: deficiência, substituição de membro/órgão, fractura, pessoa invisual ou correcção da audição; não qualquer equipamento médico']},
{id:'human_materials',label:'Órgãos, sangue e leite humanos',field:'07',rate:0,article:'CIVA arts.9(1)(c),19(1)',source:healthGoodsSource,conditions:[internalOperation,'Transmissão de órgãos, sangue ou leite de origem humana, identificada; não produto de origem animal nem serviço autónomo']},
{id:'patient_transport',label:'Transporte de doentes/feridos por organismo autorizado',field:'07',rate:0,article:'CIVA arts.9(1)(d),19(1)',source:healthGoodsSource,conditions:[internalOperation,'Transporte de doente ou ferido em ambulância ou outro veículo apropriado','Organismo que efectua o transporte devidamente autorizado, com autorização identificada; não basta o destino hospitalar']},
{id:'mosquito_nets',label:'Transmissão de redes mosquiteiras',field:'07',rate:0,article:'CIVA arts.9(1)(e),19(1)',source:healthGoodsSource,conditions:[internalOperation,'Bem identificado como rede mosquiteira; não extensão automática a outros produtos de prevenção']},
{id:'medicines',label:'Medicamentos e artigos terapêuticos/profilácticos elegíveis',field:'07',rate:0,article:'CIVA arts.9(1)(f),19(1)',source:healthGoodsSource,conditions:[internalOperation,'Medicamento/especialidade farmacêutica ou produto farmacêutico exclusivamente terapêutico/profiláctico; ou pasta, gaze, algodão hidrófilo, tira/penso adesivo ou análogo','Finalidade elegível identificada: terapêutica/profiláctica nos produtos farmacêuticos; higiénica, medicinal ou cirúrgica nos artigos enumerados, mesmo impregnados/revestidos; não qualquer produto vendido por farmácia']},
...([false,true] as const).flatMap(nonprofit=>{
const suffix=nonprofit?'nonprofit':'public',entity=nonprofit?'organismo sem finalidade lucrativa':'entidade pública';
return [
socialTreatment(`social_assistance_${suffix}`,`Assistência social — ${entity}`,'a',['Prestação de assistência social ou transmissão de bens estreitamente conexa, identificada','Fins e objecto da entidade reconhecidos pelas autoridades competentes, com fundamento identificado'],nonprofit),
socialTreatment(`social_care_${suffix}`,`Equipamentos sociais/creches/lares — ${entity}`,'c',['Prestação ou bem estreitamente conexo no exercício da actividade habitual de creche, jardim de infância, centro de tempos livres, lar ou outro equipamento social enumerado no art.9(2)(c)','Equipamento pertencente à entidade e fins/objecto reconhecidos pelas autoridades competentes; não qualquer alojamento ou empresa de cuidados'],nonprofit),
socialTreatment(`activity_facilities_${suffix}`,`Prática artística/desportiva/recreativa — ${entity}`,'d',['Serviço efectuado pela própria entidade que explora o estabelecimento ou instalação','Instalação destinada à prática artística, desportiva, recreativa ou de educação física e serviço prestado a quem a pratica; não isenção automática de bilhetes para espectadores'],nonprofit),
];
}),
{id:'foreign_operation',label:'Operação no estrangeiro — analisar territorialidade',field:null,rate:null,article:'CIVA art.6: localização por natureza da operação; art.19(1)(b)(ii) não determina sozinho a caixa06 do formulário',source:source2016,conditions:[]},
{id:'other',label:'Outra operação / enquadramento ainda desconhecido',field:null,rate:null,article:'Fundamento específico ainda necessário; não presumir taxa ou isenção',source:'Sem fonte operacional determinada para esta linha',conditions:[]},
];
export type SalesOperation = {id:string;period:string;description:string;establishment:string;amount:string;basis:''|'net'|'included';treatment:string;confirmed:number[];evidence:string;sourceAmount:string|null;sourcePeriod:string;sourceCurrency:string;source:string;taxOption?:ProductionTaxOption;fundraiser?:FundraisingContext;pharmaAnnexItem?:string;annexIItem?:string;annexIOnly?:boolean;temporaryBenefitOrigin?:string;relatedExport?:{id:string;description:string;treatment:string};supplyCategory?:SupplyCategory;specialRegime?:SpecialRegime; splitSource?:{id:string;amount:string|null;period:string;currency:string;basis:string}};
export type SalesBook = {currency:string;rows:SalesOperation[];periods:Array<{period:string;complete:boolean}>; result?:SalesResult; history?:SalesResult[]};
export type SalesLineResult = {id:string;field:string|null;net:string|null;vat:string|null;gross:string|null;rate:number|null;status:'calculated'|'exempt'|'indeterminate';reason:string;article:string;source:string;exact?:{net:FiscalFraction;vat:FiscalFraction;gross:FiscalFraction}};
export type SalesResult = {version:string;revision:number;calculatedAt:string;opportunity:string;location:string;currency:string;key:string;inputs:SalesOperation[];rows:SalesLineResult[];periods:Array<{period:string;fields:Record<string,string|null>;exactFields?:Record<string,FiscalFraction|null>;reasons:string[]}>;rounding:string};
type Store = ReturnType<typeof readAcquisitionStore> & {salesOperations?:Record<string,SalesBook>};
export function newSalesOperation(id:string,period:string,currency:string):SalesOperation {return {id,period,description:'',establishment:'',amount:'',basis:'',treatment:'other',confirmed:[],evidence:'',sourceAmount:null,sourcePeriod:period,sourceCurrency:currency,source:'Introdução directa; projecção, não declaração submetida'};}
export function continueAnnexIOperation(row:SalesOperation,targetId:string):SalesOperation {
const entry=annexIEntry(row.annexIItem),target=operationTreatments.find(t=>t.id===targetId);
if(row.treatment!=='annexI_goods'||!entry?.relatedTreatments?.includes(targetId)||!target)throw new Error('O tratamento de continuidade não corresponde à posição escolhida; dados conservados.');
return {...row,treatment:targetId,confirmed:[],annexIOnly:false,source:`${row.source}; continuidade expressamente escolhida a partir de ${annexIReference(entry)} para ${target.label}; rever condições do tratamento, sem alterar montante/moeda/contexto`};
}
export function continueTemporaryOperation(row:SalesOperation,targetId:string):SalesOperation {
const benefit=temporaryBenefit(row.treatment),target=operationTreatments.find(item=>item.id===targetId);
if(!benefit||!target||temporaryBenefit(targetId))throw new Error('Escolha um enquadramento actual distinto do benefício terminado; dados conservados.');
return {...row,treatment:targetId,confirmed:[],temporaryBenefitOrigin:benefit.id,source:`${row.source}; continuidade expressamente escolhida de ${benefit.id}/${benefit.branch}, CIVA art.${benefit.article}, termo31/12/2025, ${temporaryBenefitVersion}, para ${target.label}; ${benefit.source}; montante/moeda/período conservados; rever condições, sem cálculo automático`};
}
export function referenceExportOperation(row:SalesOperation,related:SalesOperation):SalesOperation {
if(!isExportService(row.treatment)||row.id===related.id)throw new Error('Escolha outra operação para referenciar neste serviço; dados conservados.');
return {...row,relatedExport:{id:related.id,description:related.description,treatment:related.treatment},confirmed:[]};
}
export function salesBook(draft:Record<string,unknown>):SalesBook {
const store=readAcquisitionStore(draft.modelo_a_snapshot) as Store;
if(store.salesOperations!==undefined&&(!store.salesOperations||typeof store.salesOperations!=='object'||Array.isArray(store.salesOperations)))throw new Error('Formato das operações IVA não recuperável; dados preservados, sem substituição.');
const book=store.salesOperations?.[acquisitionScope(draft)];
if(!book)return {currency:String(draft.currency??''),rows:[],periods:[]};
if(typeof book.currency!=='string'||!Array.isArray(book.rows)||!Array.isArray(book.periods)||book.rows.some(r=>!r||Object.keys(newSalesOperation('','','')).some(k=>k==='confirmed'?!Array.isArray(r.confirmed)||r.confirmed.some(c=>!Number.isInteger(c)):k==='sourceAmount'?!(r.sourceAmount===null||typeof r.sourceAmount==='string'):typeof r[k as keyof SalesOperation]!=='string'))||book.periods.some(p=>!p||!/^\d{4}-\d{2}$/.test(p.period)||typeof p.complete!=='boolean'))throw new Error('Operações IVA não recuperáveis; os dados originais foram preservados.');
return book;
}
export function saveSalesBook(draft:Record<string,unknown>,book:SalesBook):string {const store=readAcquisitionStore(draft.modelo_a_snapshot) as Store;return JSON.stringify({...store,salesOperations:{...store.salesOperations,[acquisitionScope(draft)]:book}});}
export function reuseSales(draft:Record<string,unknown>,book:SalesBook):SalesBook {
const source=monthlySalesFromDraft(draft),settings=readMonthlyIvaSettings(String(draft.monthly_iva_settings??''));
if(!/^2026-(0[1-9]|1[0-2])$/.test(settings.start)||Number(settings.start.slice(5))+source.amounts.length>13)throw new Error('Defina o período da projecção dentro de2026 antes de reutilizar vendas.');
if(book.currency!==draft.currency)throw new Error('Moeda da origem divergente; valores preservados, sem conversão.');
const rows=[...book.rows],periods=[...book.periods];
source.amounts.forEach((value,index)=>{const period=`2026-${String(Number(settings.start.slice(5))+index).padStart(2,'0')}`;
if(!periods.some(p=>p.period===period))periods.push({period,complete:false});
if(!rows.some(r=>r.sourcePeriod===period&&r.source!=='Introdução directa; projecção, não declaração submetida'))rows.push({...newSalesOperation(`sales-${period}`,period,book.currency),description:`Vendas do plano — ${period}`,amount:value??'',basis:settings.basis==='unknown'?'':settings.basis,sourceAmount:value,source:source.source,evidence:source.source});
});return {...book,rows,periods};
}
export function splitSales(book:SalesBook,id:string,newId:string):SalesBook {
const row=book.rows.find(r=>r.id===id);if(!row)throw new Error('Operação de origem não encontrada.');
if(row.sourceAmount===null&&!row.splitSource)throw new Error('Reparta uma venda reutilizada com valor de origem determinado; para entradas directas acrescente as operações em falta.');
const source=row.splitSource??{id:row.id,amount:row.sourceAmount??row.amount,period:row.period,currency:row.sourceCurrency,basis:row.basis};
if(!source.basis||source.amount===null||amount(source.amount)===null)throw new Error('Determine o valor e a representação do preço antes de repartir a origem.');
const first={...row,amount:'',sourceAmount:null,splitSource:source,source:`Repartição explícita de ${source.id}: ${source.amount} ${source.currency}; ${row.source}`};
return {...book,rows:[...book.rows.map(r=>r.id===id?first:r),{...first,id:newId,description:'Parcela adicional da mesma venda',treatment:'other',confirmed:[],evidence:''}],periods:book.periods.map(p=>p.period===row.period?{...p,complete:false}:p)};
}
export function recordSales(draft:Record<string,unknown>,book:SalesBook):SalesBook {return {...book,history:book.result?[...(book.history??[]),book.result]:book.history,result:calculateSales(draft,book)};}
function amount(raw:unknown):bigint|null {if(typeof raw!=='string'||!/^\d{1,15}(\.\d{1,6})?$/.test(raw.trim()))return null;const [n,d='']=raw.trim().split('.');return BigInt(n)*1000000n+BigInt(d.padEnd(6,'0'));}
function money(n:bigint):string {return `${n/1000000n}.${(n%1000000n).toString().padStart(6,'0').replace(/0+$/,'').padEnd(2,'0')}`;}
function sum(values:Array<string|null>):string|null {const parsed=values.map(amount);return parsed.some(v=>v===null)?null:money((parsed as bigint[]).reduce((a,b)=>a+b,0n));}
export function evaluateSalesOperation(row:SalesOperation,currency:string):SalesLineResult {
const rule=operationTreatments.find(r=>r.id===row.treatment),n=amount(row.amount);
const annex=row.treatment==='pharma_manufacturing_inputs'?pharmaAnnexEntry(row.pharmaAnnexItem):undefined;
const annexI=row.treatment==='annexI_goods'?annexIEntry(row.annexIItem):undefined;
const result:SalesLineResult={id:row.id,field:rule?.field??null,net:null,vat:null,gross:null,rate:rule?.rate??null,status:'indeterminate',reason:'',article:rule?.article??'Tratamento desconhecido',source:(rule?.source??'Fonte em falta')+(annex?`; ${pharmaAnnexReference(annex)}`:'')+(annexI?`; ${annexIReference(annexI)}`:'')};
const stop=(reason:string)=>({...result,reason});
if(currency!=='MZN'||row.sourceCurrency!==currency)return stop('Moeda fora de MZN ou divergente da origem; sem conversão silenciosa.');
if(!/^2026-(0[1-9]|1[0-2])$/.test(row.period))return stop('Período fora da cobertura de2026; sem cálculo histórico presumido.');
if(temporaryBenefit(row.treatment))return stop(temporaryBenefitNotice(row.treatment,row.period));
const regimeIssue=specialRegimeIssue(row.treatment,row.specialRegime);
if(regimeIssue)return {...stop(regimeIssue),field:null,rate:null};
const supplyIssue=onboardSupplyIssue(row.treatment,row.supplyCategory);
if(supplyIssue)return {...stop(supplyIssue),field:null,rate:null};
if(!rule||rule.rate===null||!rule.field)return stop('Operação não calculada: delimite incidência, territorialidade e fundamento desta linha. A remissão do campo06 não constitui uma regra de classificação de todas as operações no estrangeiro.');
if(n===null||!['net','included'].includes(row.basis))return stop('Montante ou indicação de IVA incluído/sem IVA em falta; vazio não significa zero.');
if(!row.description.trim()||!row.establishment.trim())return stop('Indique a operação e o estabelecimento a que pertence; não inferidos da localização do investimento.');
if(rule.conditions.some((_,i)=>!row.confirmed.includes(i))||!row.evidence.trim())return stop('Condições da operação ou fundamento/pressuposto em falta; o sector não prova o tratamento fiscal.');
if(row.sourceAmount!==null&&amount(row.sourceAmount)!==n)return stop('Divergência com o valor reutilizado: conserve a origem e prepare a repartição explicitamente; não substituir silenciosamente.');
if(row.treatment==='pharma_manufacturing_inputs'&&!annex)return stop('Escolha a linha aplicável do Anexo III/2022, com código e designação; um código livre, desconhecido ou de outro anexo não comprova a isenção.');
if(row.treatment==='annexI_goods'){
if(!annexI)return stop('Escolha a posição aplicável do Anexo I/2022, com código, designação e qualificadores; não presumir isenção por sector ou código livre.');
if(annexI.relatedRequired)return stop('Esta designação tem tratamento específico já disponível no artigo9(10), com direito à dedução nas condições do19(1)(b)(v). Escolha a continuidade indicada e confirme as suas condições; não atribuir07 apenas pela presença no Anexo I.');
if(annexI.relatedTreatments?.length&&row.annexIOnly!==true)return stop('A natureza ou o destino deste bem pode corresponder a outro tratamento já disponível. Escolha a continuidade aplicável ou fundamente expressamente por que a operação pertence apenas a9(12)(h); desconhecido não significa ausência desse enquadramento.');
}
if(row.treatment==='fundraising_public'||row.treatment==='fundraising_nonprofit'){const error=fundraisingError(row.fundraiser,row.treatment==='fundraising_nonprofit');if(error)return stop(error);}
const option=row.treatment.startsWith('production_')&&row.treatment.endsWith('_opted')?productionOptionCheck(row.taxOption,row.period):{};
if(option.error)return stop(option.error);
if(row.basis==='included'&&rule.rate===5){
const exact={net:fraction(n*20n,21000000n),vat:fraction(n,21000000n),gross:fraction(n,1000000n)};
return {...result,net:fractionPresentation(exact.net).decimal,vat:fractionPresentation(exact.vat).decimal,gross:money(n),exact,status:'calculated',reason:'Base e IVA conservados como fracções exactas (preço×20/21 e preço/21). Decimal a6casas é apresentação técnica, metade para cima; não é regra de arredondamento da declaração nem imposto final a pagar.'};
}
let net=n,vat=0n;
if(rule.rate===16&&row.basis==='included') {net=((n*100n+58000000n)/116000000n)*1000000n;vat=n-net;if(vat<0n)return stop('Arredondamento à unidade produz IVA negativo para este montante; reveja a linha e a documentação.');}
else vat=(n*BigInt(rule.rate)+50n)/100n;
return {...result,net:money(net),vat:money(vat),gross:money(row.basis==='included'?n:net+vat),status:rule.rate===0?'exempt':'calculated',reason:(rule.rate===0?(rule.field==='05'?'Isenção com direito à dedução nas condições legais; não é taxa zero nem dedução automática de compras.':'Isenção sem direito à dedução para esta operação; não é isenção geral da entidade.'):'IVA da operação projectada; não é imposto final a pagar nem declaração submetida.')+(option.summary?' '+option.summary:'')};
}
function key(draft:Record<string,unknown>,book:SalesBook,catalog=operationTreatments.filter(t=>book.rows.some(r=>r.treatment===t.id))):string {return JSON.stringify([operationVersion,catalog,acquisitionScope(draft),draft.currency,draft.province_id,draft.district_id,draft.business_plan_snapshot,draft.cashflow_snapshot,draft.monthly_iva_settings,book.currency,book.rows,book.periods]);}
export function salesCurrent(draft:Record<string,unknown>,book:SalesBook):boolean {return !!book.result&&book.result.version===operationVersion&&book.result.opportunity===acquisitionScope(draft)&&(book.result.key===key(draft,book)||book.result.key===key(draft,book,operationTreatments.filter(t=>legacyV2TreatmentIds.includes(t.id))));}
export function calculateSales(draft:Record<string,unknown>,book:SalesBook,now=new Date().toISOString()):SalesResult {
if(book.currency!=='MZN'||draft.currency!==book.currency)throw new Error('Confirme a moeda original MZN; sem conversão ou reinterpretação.');
if(new Set(book.rows.map(r=>r.id)).size!==book.rows.length||new Set(book.periods.map(p=>p.period)).size!==book.periods.length)throw new Error('Identificadores/períodos duplicados; corrija sem somar em duplicado.');
if(!book.periods.length||book.rows.some(r=>!book.periods.some(p=>p.period===r.period))||book.periods.some(p=>!/^2026-(0[1-9]|1[0-2])$/.test(p.period)))throw new Error('Cada operação deve pertencer a um período válido de2026 incluído na cobertura.');
let live:ReturnType<typeof monthlySalesFromDraft>|null=null;try {live=monthlySalesFromDraft(draft);}catch{ /* Explicitly block stale imported values below. */ }
const start=readMonthlyIvaSettings(String(draft.monthly_iva_settings??'')).start;
const rows=book.rows.map(r=>{
const result=evaluateSalesOperation(r,book.currency);
if(isExportService(r.treatment)&&r.relatedExport!==undefined){
const ref=r.relatedExport,target=ref&&typeof ref==='object'?book.rows.find(item=>item.id===ref.id&&item.id!==r.id):undefined;
if(!target||ref.description!==target.description||ref.treatment!==target.treatment)return {...result,net:null,vat:null,gross:null,status:'indeterminate' as const,reason:'A operação relacionada foi removida ou alterada. Actualize a referência e reveja as condições; preço do serviço e resultado anterior conservados.'};
}
const fundraiser=r.fundraiser;
if(r.treatment.startsWith('fundraising_')&&fundraiser&&book.rows.some(v=>v.id!==r.id&&v.treatment.startsWith('fundraising_')&&v.period.slice(0,4)===r.period.slice(0,4)&&String(v.fundraiser?.entityReference??'').trim()===String(fundraiser.entityReference??'').trim()&&v.fundraiser?.annualEvents!==fundraiser.annualEvents))return {...result,net:null,vat:null,gross:null,status:'indeterminate' as const,reason:'Totais anuais divergentes para a mesma entidade; resolva a divergência sem substituir dados de outra linha.'};
if(r.splitSource) {
const source=r.splitSource,group=book.rows.filter(v=>v.splitSource?.id===source.id),index=Number(source.period.slice(5))-Number(start.slice(5));
if(group.some(v=>v.period!==source.period||v.basis!==source.basis||v.sourceCurrency!==source.currency||JSON.stringify(v.splitSource)!==JSON.stringify(source))||sum(group.map(v=>v.amount))!==(amount(source.amount)===null?null:money(amount(source.amount)!))||!live||live.amounts[index]!==source.amount)return {...result,exact:undefined,net:null,vat:null,gross:null,status:'indeterminate' as const,reason:'Repartição não reconciliada com o total, período, moeda e representação do preço da origem; nenhuma parcela foi presumida.'};
}
if(r.sourceAmount!==null||r.source.startsWith('Vendas por produto')||r.source.startsWith('Receita mensal')) {
const index=Number(r.sourcePeriod.slice(5))-Number(start.slice(5));
if(!live||!/^2026-/.test(start)||r.sourcePeriod!==r.period||live.amounts[index]!==r.sourceAmount)return {...result,exact:undefined,net:null,vat:null,gross:null,status:'indeterminate' as const,reason:'A origem/período das vendas mudou. Reveja e confirme a nova origem; o resultado anterior foi conservado.'};
}
return result;
});
const periods=book.periods.map(p=>{
const matching=book.rows.map((r,i)=>({input:r,result:rows[i]})).filter(r=>r.input.period===p.period),fields:Record<string,string|null>={},exactFields:Record<string,FiscalFraction|null>={},reasons=matching.filter(r=>r.result.status==='indeterminate').map(r=>`${r.input.description||r.input.id}: ${r.result.reason}`);
const known=p.complete&&!matching.some(r=>r.result.status==='indeterminate');
for(const f of ['01','03','05','07'])fields[f]=known?sum(matching.filter(r=>r.result.field===f).map(r=>r.result.net)):null;
for(const [f,base] of [['02','01'],['04','03']])fields[f]=known?sum(matching.filter(r=>r.result.field===base).map(r=>r.result.vat)):null;
fields['06']=known?'0.00':null;
if(matching.some(r=>r.result.exact)) {
for(const [f,base,part] of [['01','01','net'],['02','01','vat'],['03','03','net'],['04','03','vat'],['05','05','net'],['06','06','net'],['07','07','net']] as const) {
exactFields[f]=known?addFractions(matching.filter(r=>r.result.field===base).map(r=>r.result.exact?.[part]??decimalFraction(r.result[part]!))):null;
fields[f]=exactFields[f]?fractionPresentation(exactFields[f]!).decimal:null;
}
}
if(!p.complete)reasons.push('Confirme que todas as operações do período foram incluídas; uma lista vazia só é zero após essa confirmação.');
return {period:p.period,fields,...(Object.keys(exactFields).length?{exactFields}:{}),reasons};
});
const labels=draft.selection_labels as Record<string,unknown>|undefined;
return {version:operationVersion,revision:(book.result?.revision??0)+1,calculatedAt:now,opportunity:acquisitionScope(draft),location:['province_id','district_id'].filter(k=>draft[k]).map(k=>String(labels?.[k]??draft[k])).join(' / '),currency:book.currency,key:key(draft,book),inputs:structuredClone(book.rows),rows,periods,rounding:'Base líquida: precisão técnica6decimais, metade para cima, sem arredondamento final da declaração. Preço geral com IVA: base=preço×100/116, arredondada à unidade mais próxima (metade para cima), IVA=preço−base, CIVA art.34 redacção Lei10/2025. Preço incluído5%: fracções exactas preço×20/21 e preço/21 conservadas; decimal a6casas/metade para cima apenas na apresentação. A regra declarativa não é presumida.'};
}
export function salesReportRows(draft:Record<string,unknown>):Array<[string,string,string,string]> {
try {const book=salesBook(draft),r=book.result;if(!r)return [];
const context=`${r.currency}; oportunidade ${r.opportunity}; ${r.location||'localização não indicada'}; ${r.version}; revisão ${r.revision}; ${r.calculatedAt}`;
const out:Array<[string,string,string,string]>=[['IVA mensal','Operações IVA L1',salesCurrent(draft,book)?'Resultado correspondente às entradas':'Histórico desactualizado; não aplicar à projecção actual',context],['IVA mensal','Método e limites L1',r.rounding,'Sem apuramento integral, dedução automática ou submissão AT']];
for(const row of r.inputs){const value=r.rows.find(v=>v.id===row.id)!;out.push(['IVA mensal',`${row.period} — ${row.description} — ${row.establishment}`,`Declarado ${row.amount||'em falta'} ${row.sourceCurrency}; ${row.basis==='included'?'IVA incluído':row.basis==='net'?'sem IVA':'base desconhecida'}; líquido ${value.net??'Indeterminado'}; IVA ${value.vat??'Indeterminado'}; bruto ${value.gross??'Indeterminado'}; campo ${value.field??'não determinado'}; ${value.reason}`,`${context}; ${value.article}; ${value.source}; origem: ${row.source}; pressuposto/documento: ${row.evidence||'em falta'}; condições confirmadas: ${row.confirmed.join(',')||'nenhuma'}`]);}
for(const row of r.inputs.filter(v=>v.fundraiser))out.push(['IVA mensal',`Manifestação ocasional — ${row.description}`,`Entidade ${row.fundraiser!.entityReference}; ano ${row.period.slice(0,4)}; total anual declarado ${row.fundraiser!.annualEvents}; manifestação ${row.fundraiser!.eventNumber}; actividade ${row.fundraiser!.activity}`,`${context}; dados declarados para a entidade, incluindo manifestações fora deste dossier; não é contagem automática das vendas.`]);
for(const row of r.inputs.filter(v=>isExportService(v.treatment)&&v.relatedExport))out.push(['IVA mensal',`Operação relacionada — ${row.description}`,`${row.relatedExport!.description}; ID ${row.relatedExport!.id}; tratamento ${row.relatedExport!.treatment}`,`${context}; referência escolhida expressamente nesta oportunidade,sem copiar valor para preço do serviço nem provar automaticamente o enquadramento subjacente`]);
for(const row of r.inputs.filter(v=>isOnboardSupply(v.treatment)))out.push(['IVA mensal',`Natureza do abastecimento — ${row.description}`,supplyCategories.find(([value])=>value===row.supplyCategory)?.[1]??'Por identificar',`${context}; CIVA13(2–3); natureza conservada no cálculo/relatório, sem aplicar dedução ou restituição automaticamente`]);
for(const row of r.inputs.filter(v=>isSpecialRegime(v.treatment)))out.push(['IVA mensal',`Regime especial — ${row.description}`,specialRegimeOptions.find(([value])=>value===row.specialRegime)?.[1]??'Por identificar',`${context}; CIVA14(1)(b/c/d),19(1)(b)(iv); regime declarado/documentado ou pressuposto expresso da projecção; não certifica admissão ou permanência, nem liquida importação ou saída do regime`]);
for(const value of r.rows.filter(v=>v.exact))out.push(['IVA mensal',`Precisão exacta — ${value.id}`,`Líquido ${fractionLabel(value.exact!.net)} MZN; IVA ${fractionLabel(value.exact!.vat)} MZN; bruto ${fractionLabel(value.exact!.gross)} MZN`,`${context}; apresentação decimal a6casas, aproximação quando a fracção não termina; não aplicar à declaração sem a sua regra própria.`]);
for(const p of r.periods){out.push(['IVA mensal',`Operações L1 — ${p.period}`,Object.entries(p.fields).map(([f,v])=>`${f}: ${v??'Indeterminado'}`).join('; '),`${context}; ${p.reasons.join(' ')}`]);
if(p.exactFields)out.push(['IVA mensal',`Precisão exacta do período — ${p.period}`,Object.entries(p.exactFields).map(([f,v])=>`${f}: ${v?fractionLabel(v):'Indeterminado'}`).join('; '),`${context}; totais em fracções MZN, calculados antes da apresentação decimal, sem regra declarativa presumida.`]);
}return out;
}catch{return [['IVA mensal','Operações IVA L1','Não foi possível recuperar as operações guardadas','Originais preservados; sem substituição por zero']];}
}