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

27 lines
3.9 KiB
TypeScript

export const fxTempoSource='Orientação operacional expressa da Tempo,25/10/2026:compra de moeda→taxa de compra;venda→taxa de venda;operações comerciais→taxa média de referência do Banco de Moçambique na data de submissão indicada. Interpretar compra/venda pela perspectiva do boletim. Excepções fiscais específicas conservam disposição,data,taxa e âmbito;sem recálculo automático dos históricos.';
export type FxSelection={issuer?:string;nature:''|'purchase'|'sale'|'commercial';submissionDate:string;bulletinDate:string;bulletinRef:string;source:string;sourceCurrency:string;direction:''|'mzn_per_unit'|'units_per_mzn';bulletinPerspective:string;relation:''|'same'|'opposite';buy:string;sell:string;mean:string;mode:'general'|'exception';exceptionRef:string;exceptionScope:string;exceptionDate:string;exceptionRate:string;applied?:{column:string;rate:string;date:string;source:string;selectedAt:string;selectionKey:string}};
export function emptyFxSelection():FxSelection{return{nature:'',submissionDate:'',bulletinDate:'',bulletinRef:'',source:'',sourceCurrency:'',direction:'',bulletinPerspective:'',relation:'',buy:'',sell:'',mean:'',mode:'general',exceptionRef:'',exceptionScope:'',exceptionDate:'',exceptionRate:''};}
function date(s:string){const d=new Date(s+'T00:00:00Z');return /^\d{4}-\d{2}-\d{2}$/.test(s)&&Number.isFinite(d.getTime())&&d.toISOString().slice(0,10)===s;}
function positive(s:string){return /^\d{1,15}(\.\d{1,8})?$/.test(s)&&Number(s)>0;}
export function fxSelectionKey(s:FxSelection):string{const {applied,...inputs}=s;void applied;return JSON.stringify(inputs);}
export function selectFx(s:FxSelection):NonNullable<FxSelection['applied']>{
if(!['purchase','sale','commercial'].includes(s.nature)||!date(s.submissionDate)||!s.bulletinRef.trim()||!s.source.trim()||!s.sourceCurrency.trim()||!['mzn_per_unit','units_per_mzn'].includes(s.direction))throw Error('Indique natureza,data de submissão,moeda,direcção e boletim/fonte;sem usar taxa actual ouzero por defeito.');
let column='',rate='',day='';
if(s.mode==='exception'){
if(!s.exceptionRef.trim()||!s.exceptionScope.trim()||!date(s.exceptionDate)||!positive(s.exceptionRate))throw Error('Excepção exige disposição fiscal,âmbito,data e taxa identificados;os restantes percursos continuam disponíveis.');
column='exception';rate=s.exceptionRate;day=s.exceptionDate;
}else{
if(s.mode!=='general'||s.bulletinDate!==s.submissionDate||!date(s.bulletinDate))throw Error('Use boletim da data de submissão indicada;ausência de boletim não autoriza usar a taxa mais recente.');
if(s.nature==='commercial'){
let officialUrl=false;try{officialUrl=['bancomoc.mz','www.bancomoc.mz'].includes(new URL(s.source).hostname);}catch{/* An identified official local exemplar does not require another validation. */}if(!officialUrl&&s.issuer?.trim()!=='Banco de Moçambique')throw Error('Operação comercial usa taxa média de referência do Banco de Moçambique;identifique a origemBM do boletim arquivado ou a suaURL,sem exigir nova validação da fonte aceite.');
column='mean';rate=s.mean;
}else{
if(!s.bulletinPerspective.trim()||!['same','opposite'].includes(s.relation))throw Error('Identifique a perspectiva indicada no boletim e a relação com a natureza declarada;sem inverter a operação do cliente por presunção.');
column=(s.nature==='purchase')===(s.relation==='same')?'buy':'sell';rate=column==='buy'?s.buy:s.sell;
}
day=s.submissionDate;
}
if(!positive(rate))throw Error('Taxa da coluna aplicável ausente ou inválida;não calcular média a partir de compra/venda.');
return{column,rate,date:day,source:`${s.bulletinRef};${s.source};perspectiva:${s.bulletinPerspective||'média de referênciaBM'};natureza:${s.nature};relação:${s.relation||'não aplicável à média'};${s.mode==='exception'?s.exceptionRef+';'+s.exceptionScope:fxTempoSource}`,selectedAt:new Date().toISOString(),selectionKey:fxSelectionKey(s)};
}