Files
Investidor-V2/resources/js/components/simulation-fx-selection.tsx
T

256 lines
9.8 KiB
TypeScript

import { useState } from 'react';
import type { CurrencyEventRow } from '@/lib/iva-currency-events';
import {
emptyFxSelection,
selectFx,
fxTempoSource,
type FxSelection,
} from '@/lib/iva-fx-selection';
const columnLabels: Record<string, string> = {
buy: 'Compra',
sell: 'Venda',
mean: 'Média de referência BM',
exception: 'Excepção fiscal identificada',
};
const directionLabels: Record<string, string> = {
mzn_per_unit: 'MZN por unidade da moeda original',
units_per_mzn: 'unidades da moeda original por MZN',
};
export function SimulationFxSelection({
row,
onChange,
}: {
row: CurrencyEventRow;
onChange: (patch: Partial<CurrencyEventRow>) => void;
}) {
const [error, setError] = useState(''),
[preview, setPreview] = useState<ReturnType<typeof selectFx> | null>(
null,
);
const s = row.fxSelection ?? {
...emptyFxSelection(),
sourceCurrency: row.sourceCurrency,
direction: row.fxDirection,
};
const edit = (patch: Partial<FxSelection>) => {
setPreview(null);
onChange({ fxSelection: { ...s, ...patch } });
};
const text = (
key:
| 'submissionDate'
| 'bulletinDate'
| 'bulletinRef'
| 'source'
| 'sourceCurrency'
| 'bulletinPerspective'
| 'buy'
| 'sell'
| 'mean'
| 'exceptionRef'
| 'exceptionScope'
| 'exceptionDate'
| 'exceptionRate',
label: string,
) => (
<label className="block" key={key}>
{label}
<input
value={s[key]}
type={key.endsWith('Date') ? 'date' : 'text'}
onChange={(e) => edit({ [key]: e.target.value })}
/>
</label>
);
return (
<fieldset className="rounded border p-3">
<legend>P104 — selecção da taxa segundo orientação da Tempo</legend>
<p>{fxTempoSource}</p>
<label>
Natureza da operação declarada
<select
value={s.nature}
onChange={(e) =>
edit({
nature: e.target.value as FxSelection['nature'],
})
}
>
<option value="">Por indicar</option>
<option value="purchase">Compra de moeda</option>
<option value="sale">Venda de moeda</option>
<option value="commercial">Operação comercial</option>
</select>
</label>
{text('submissionDate', 'Data de submissão indicada')}
{text('sourceCurrency', 'Moeda original já declarada')}
{text('bulletinRef', 'Boletim,edição e série de referência')}
{text(
'source',
'Fonte do boletim;URL do Banco de Moçambique para operações comerciais',
)}
{text('bulletinDate', 'Data do boletim')}
<label>
Emitente identificado do boletim,quando a fonte é um exemplar
arquivado
<input
value={s.issuer ?? ''}
onChange={(e) => edit({ issuer: e.target.value })}
/>
</label>
<label>
Sentido da cotação
<select
value={s.direction}
onChange={(e) =>
edit({
direction: e.target
.value as FxSelection['direction'],
})
}
>
<option value="">Por indicar</option>
<option value="mzn_per_unit">
MZN por unidade da moeda original
</option>
<option value="units_per_mzn">
Unidades da moeda original porMZN
</option>
</select>
</label>
<button
type="button"
onClick={() =>
edit({
sourceCurrency: s.sourceCurrency || row.sourceCurrency,
direction: s.direction || row.fxDirection,
submissionDate: s.submissionDate || row.fxDate,
bulletinDate: s.bulletinDate || row.fxDate,
source: s.source || row.fxSource,
})
}
>
Reutilizar moeda,sentido e data já indicados nos campos
vazios;conferir a data de submissão
</button>
<label>
Regra aplicável
<select
value={s.mode}
onChange={(e) =>
edit({ mode: e.target.value as FxSelection['mode'] })
}
>
<option value="general">Procedimento geral da Tempo</option>
<option value="exception">
Excepção fiscal específica identificada
</option>
</select>
</label>
{s.mode === 'exception' ? (
<>
{text(
'exceptionRef',
'Disposição fiscal que impõe outra data/taxa',
)}
{text('exceptionScope', 'Âmbito da excepção')}
{text('exceptionDate', 'Data imposta pela disposição')}
{text(
'exceptionRate',
'Taxa da excepção,com fonte no boletim indicado',
)}
</>
) : s.nature === 'commercial' ? (
text(
'mean',
'Coluna Média da série de referênciaBM;sem calcular média própria',
)
) : (
<>
{text(
'bulletinPerspective',
'Perspectiva de compra/venda indicada no boletim',
)}
<label>
Relação da natureza declarada com a perspectiva do
boletim
<select
value={s.relation}
onChange={(e) =>
edit({
relation: e.target
.value as FxSelection['relation'],
})
}
>
<option value="">Por conferir</option>
<option value="same">Mesma perspectiva</option>
<option value="opposite">
Perspectiva contrária:compra do cliente
corresponde a venda do emitente,ou inversamente
</option>
</select>
</label>
{text('buy', 'Taxa da coluna Compra do boletim')}
{text('sell', 'Taxa da coluna Venda do boletim')}
</>
)}
{error && <p role="alert">{error}</p>}
<button
type="button"
onClick={() => {
try {
setPreview(selectFx(s));
setError('');
} catch (e) {
setError(String(e));
}
}}
>
Conferir selecção e impacto
</button>
{preview && (
<div>
<p>
Coluna:{columnLabels[preview.column]};taxa:
{preview.rate};data:{preview.date};sentido:
{directionLabels[s.direction]}. Confirmação substitui os
campos cambiais desta linha:{row.fxRate || 'taxa vazia'}{' '}
→ {preview.rate};{row.fxDate || 'data vazia'} →{' '}
{preview.date};{row.sourceCurrency || 'moeda vazia'} →{' '}
{s.sourceCurrency}. O resultado e os históricos
permanecem até usar «Conferir moeda/eventos e guardar
versão».
</p>
<button
type="button"
onClick={() => {
onChange({
fxSelection: { ...s, applied: preview },
sourceCurrency: s.sourceCurrency,
fxDirection: s.direction,
fxRate: preview.rate,
fxDate: preview.date,
fxSource: preview.source,
fxRuleRef:
s.mode === 'exception'
? s.exceptionRef
: fxTempoSource,
});
setPreview(null);
}}
>
Confirmar selecção nesta linha
</button>
</div>
)}
<p>
Não usar taxa de apresentação nem a mais recente como substituto
de boletim ausente. Compra/venda são interpretadas pela
perspectiva indicada;relação desconhecida fica por esclarecer.
Alterações não recalculam versões anteriores.
</p>
</fieldset>
);
}