import {ispcEligibilityBook,ispcEligibilityCurrent} from './ispc-eligibility.ts'; import {acquisitionScope} from './iva-acquisitions.ts'; import {addFractions,decimalFraction,fraction,fractionPresentation,type FiscalFraction} from './fiscal-rational.ts'; export type IspcWithholdingInput={applicable:''|'no'|'yes';quarter:string;base:string;priorAnnualPurchases:string;naturalOccasional:''|'yes'|'no';unregistered:''|'yes'|'no';related:''|'yes'|'no';activity:''|'forestry'|'fishery'|'livestock'|'agriculture'|'poultry'|'beekeeping'|'other';reference:string;}; export type IspcWithholdingResult={input:IspcWithholdingInput;key:string;status:'calculated'|'indeterminate'|'not_applicable';reason:string;withheld:FiscalFraction|null;calculatedAt:string;source:string}; export type IspcWithholdingBook={version:1;input:IspcWithholdingInput;result?:IspcWithholdingResult;history?:IspcWithholdingResult[]}; export const ispcWithholdingSource='Lei9/2025,republicaçãoISPC,arts3(3–4),12(3–4);PDF10–11/p2180(10–11). Retenção liberatória5% sobre aquisição a pessoa singular ocasional não inscrita, ligada à actividade, até limite global anual2.500.000MZN; factura por conta do fornecedor e entrega trimestral em modelo próprio. Não é crédito contra o imposto próprio nem se aplica o mínimo500 desta prestação à retenção.'; const blank=():IspcWithholdingInput=>({applicable:'',quarter:'1',base:'',priorAnnualPurchases:'',naturalOccasional:'',unregistered:'',related:'',activity:'',reference:''}); function snapshot(d:Record){const s=JSON.parse(String(d.modelo_a_snapshot||'{"version":1,"books":{}}'));if(s.version!==1||!s.books||typeof s.books!=='object'||Array.isArray(s.books))throw Error('Livros não recuperáveis; originais preservados.');return s;} function validate(b:IspcWithholdingBook){if(!b||b.version!==1||!b.input||Object.keys(blank()).some(k=>typeof b.input[k as keyof IspcWithholdingInput]!=='string')||['applicable','naturalOccasional','unregistered','related'].some(k=>!['','yes','no'].includes(b.input[k as keyof IspcWithholdingInput]))||!['','forestry','fishery','livestock','agriculture','poultry','beekeeping','other'].includes(b.input.activity)||b.history!==undefined&&!Array.isArray(b.history))throw Error('RetençõesISPC não recuperáveis; originais preservados.');} function map(d:Record):Record{const v=snapshot(d).ispcWithholdings;if(v===undefined)return{};if(!v||typeof v!=='object'||Array.isArray(v))throw Error('Mapa de retençõesISPC inválido.');return v;} export function ispcWithholdingBook(d:Record):IspcWithholdingBook{const b=map(d)[acquisitionScope(d)]??{version:1,input:blank()};validate(b);return b;} export function saveIspcWithholdingBook(d:Record,b:IspcWithholdingBook):string{validate(b);return JSON.stringify({...snapshot(d),ispcWithholdings:{...map(d),[acquisitionScope(d)]:b}});} export function recordIspcWithholding(d:Record,b:IspcWithholdingBook,now=new Date().toISOString()):IspcWithholdingBook{validate(b);const i=b.input,e=ispcEligibilityBook(d),r:IspcWithholdingResult={input:structuredClone(i),key:JSON.stringify([acquisitionScope(d),i]),status:'indeterminate',reason:'Identifique se existem aquisições abrangidas; não presumir retenção zero.',withheld:null,calculatedAt:now,source:ispcWithholdingSource}; if(i.applicable==='no'){r.status='not_applicable';r.reason='Sem aquisições abrangidas, segundo declaração expressa; entradas anteriores preservadas.';} else if(i.applicable==='yes'&&(!ispcEligibilityCurrent(d,e)||e.result?.status!=='compatible'||e.result.optionStatus==='not_opted'||e.result.optionStatus==='indeterminate'||e.input.origin==='effective'&&e.result.optionStatus!=='recorded')){r.reason='Guarde o enquadramento e a opção aplicáveis do adquirenteISPC antes de calcular retenção efectiva; sem inferir adesão.';} else if(i.applicable==='yes'){ if(i.naturalOccasional==='no'||i.unregistered==='no'||i.related==='no'||i.activity==='other'){r.status='not_applicable';r.reason='Aquisição fora do recorte12(3–4) declarado; outros regimes de retenção mantêm análise própria,sem presumir isenção.';} else if(i.naturalOccasional==='yes'&&i.unregistered==='yes'&&i.related==='yes'&&i.activity&&i.reference.trim()&&['1','2','3','4'].includes(i.quarter)){ try{const base=decimalFraction(i.base),prior=decimalFraction(i.priorAnnualPurchases),total=addFractions([base,prior]);if(BigInt(total.numerator)>2500000n*BigInt(total.denominator))r.reason='Total global anual superior2.500.000MZN: tratamento da aquisição acima do limite por corresponder; não reter automaticamente5% nem truncar a base.';else{r.status='calculated';r.withheld=fraction(BigInt(base.numerator)*5n,BigInt(base.denominator)*100n);r.reason='Retenção5% calculada separadamente do imposto próprio; emitir factura por conta do fornecedor e preparar entrega trimestral em modelo próprio. Sem deduzir esta retenção da prestaçãoISPC.';}}catch{r.reason='Base e aquisições globais anteriores do ano necessários,incluindo zero expresso; não presumir montantes.';} }else r.reason='Identifique pessoa singular ocasional3(3–4),actividade abrangida,não inscrição,ligação à actividade,trimestre e suporte; dados desconhecidos não viram não aplicáveis.'; } return{...b,...(b.result?{history:[...(b.history??[]),structuredClone(b.result)]}:{}),result:r};} export function ispcWithholdingReportRows(d:Record):Array<[string,string,string,string]>{try{const b=ispcWithholdingBook(d),r=b.result;if(!r)return[];return[['ISPC','Retenção em aquisições ocasionais',`${r.status}; ${r.withheld?fractionPresentation(r.withheld).decimal+' MZN':'Indeterminado/não aplicado'}; ${r.reason}`,`2026/T${r.input.quarter}; base:${r.input.base}; anteriores globais:${r.input.priorAnnualPurchases}; suporte:${r.input.reference}; ${r.key===JSON.stringify([acquisitionScope(d),b.input])?'Entradas correspondentes':'Histórico preservado;rever entradas'}; ${r.calculatedAt}; ${r.source}`]];}catch(e){return[['ISPC','Retenção não recuperável',String(e),'Originais preservados.']];}}