Files
Investidor-V2/resources/js/components/simulation-service-location.tsx
T

452 lines
22 KiB
TypeScript

import { inputText } from '../lib/input-text.ts';
import { useState } from 'react';
import {
newServiceLocation,
switchServiceTreatment,
serviceLocationBook,
serviceLocationConditions,
ownServiceConditions,
serviceLocationCurrent,
serviceLocationReportRows,
serviceLocationSource,
serviceLocationTreatments,
recordServiceLocations,
saveServiceLocationBook,
type ServiceLocationBook,
type ServiceLocationRow,
} from '@/lib/iva-service-location';
export function SimulationServiceLocation({
draft,
onChange,
}: {
draft: Record<string, unknown>;
onChange: (field: string, value: string) => void;
}) {
const [error, setError] = useState('');
let book: ServiceLocationBook;
try {
book = serviceLocationBook(draft);
} catch (cause) {
return <p role="alert">{String(cause)}</p>;
}
const save = (next: ServiceLocationBook) => {
try {
onChange('modelo_a_snapshot', saveServiceLocationBook(draft, next));
setError('');
} catch (cause) {
setError(String(cause));
}
};
const change = (id: string, patch: Partial<ServiceLocationRow>) =>
save({
...book,
rows: book.rows.map((row) =>
row.id === id ? { ...row, ...patch } : row,
),
});
return (
<details className="space-y-3 rounded border p-3">
<summary>
Localização — serviços, imóveis, trabalhos, actividades e
transporte
</summary>
<p>
Oportunidade:{' '}
{inputText(draft.context_opportunity || 'entrada geral')}. Regra
geral:ponto de estabelecimento do prestador a partir do qual o
serviço é prestado. Imóveis,execução total/essencial em bens
móveis e actividades materiais têm percursos
próprios,independentemente da sede do prestador.
</p>
<p>
Conferir primeiro a natureza e as regras especiais.
Endereço/nacionalidade do cliente não substituem os factos
relevantes. Digital e outros6(7)/(8)seguem os seus percursos.
Classificação territorial não concede isenção nem calcula IVA.
</p>
<p>{serviceLocationSource}</p>
{error && <p role="alert">{error}</p>}
<button
type="button"
className="underline"
onClick={() =>
save({
...book,
rows: [
...book.rows,
newServiceLocation(crypto.randomUUID()),
],
})
}
>
Acrescentar localização de serviço
</button>
{book.rows.map((row) => (
<details key={row.id} className="rounded border p-3">
<summary>
{row.description || 'Operação por identificar'} —{' '}
{row.period || 'mês por indicar'}
</summary>
<div className="grid gap-3 md:grid-cols-2">
<label>
Percurso de localização do serviço
<select
className="block rounded border p-2"
value={row.treatment}
onChange={(e) =>
change(
row.id,
switchServiceTreatment(
row,
e.target.value,
),
)
}
>
<option value="">Por indicar</option>
{serviceLocationTreatments.map((t) => (
<option key={t.id} value={t.id}>
{t.label}
</option>
))}
</select>
</label>
<label>
Natureza dos dados
<select
className="block rounded border p-2"
value={row.origin}
onChange={(e) =>
change(row.id, {
origin: e.target
.value as ServiceLocationRow['origin'],
})
}
>
<option value="projected">
Projectados / pressupostos
</option>
<option value="effective">
Efectivos declarados
</option>
</select>
</label>
{(
[
['description', 'Serviço identificado'],
[
'operationRef',
'Referência da operação / pressuposto',
],
['operationDate', 'Data do serviço / prevista'],
['period', 'Mês do serviço'],
[
'documentRef',
'Documento da operação / referência da previsão',
],
[
'documentDate',
'Data do documento / prevista',
],
[
'scope',
'Âmbito: serviço, operação, período e condições',
],
[
'evidence',
'Fundamento factual / pressupostos',
],
] as const
).map(([field, label]) => (
<label key={field}>
{label}
<input
className="block rounded border p-2"
type={
[
'operationDate',
'documentDate',
].includes(field)
? 'date'
: field === 'period'
? 'month'
: 'text'
}
value={row[field]}
onChange={(e) =>
change(row.id, {
[field]: e.target.value,
})
}
/>
</label>
))}
{row.treatment === 'transport_service' ? (
<>
<p>
Uma linha por trajecto;ida e volta
separadas. Use a mesma unidade nas duas
distâncias. Partida e chegada nacionais
incluem percurso fora do país6(6).
</p>
{(
[
[
'routeRef',
'Trajecto e referência / pressuposto',
],
['totalDistance', 'Distância total'],
[
'nationalDistance',
'Distância fisicamente nacional',
],
] as const
).map(([field, label]) => (
<label key={field}>
{label}
<input
className="block rounded border p-2"
value={row[field]}
onChange={(e) =>
change(row.id, {
[field]: e.target.value,
})
}
/>
</label>
))}
{(
[
[
'departure',
'País do ponto de partida',
],
['arrival', 'País do ponto de chegada'],
] as const
).map(([field, label]) => (
<label key={field}>
{label}
<select
className="block rounded border p-2"
value={row[field]}
onChange={(e) =>
change(row.id, {
[field]: e.target.value,
})
}
>
<option value="">
Por indicar
</option>
<option value="MZ">
Moçambique
</option>
<option value="foreign">
Estrangeiro
</option>
</select>
</label>
))}
</>
) : row.treatment === 'general_service' ? (
<>
<label>
Estabelecimento do prestador a partir do
qual o serviço é prestado
<input
className="block rounded border p-2"
value={row.providerPlace}
onChange={(e) =>
change(row.id, {
providerPlace: e.target.value,
})
}
/>
</label>
<label>
País desse estabelecimento
<select
className="block rounded border p-2"
value={row.providerCountry}
onChange={(e) =>
change(row.id, {
providerCountry: e.target.value,
})
}
>
<option value="">Por indicar</option>
<option value="MZ">Moçambique</option>
<option value="foreign">
Estrangeiro
</option>
</select>
</label>
<label>
Referência do estabelecimento prestador /
pressuposto
<input
className="block rounded border p-2"
value={row.providerRef}
onChange={(e) =>
change(row.id, {
providerRef: e.target.value,
})
}
/>
</label>
</>
) : (
row.treatment && (
<>
<label>
{row.treatment === 'immovable_service'
? 'Local do imóvel'
: row.treatment === 'movable_work'
? 'Local de execução total ou essencial'
: 'Local material da actividade ou serviço acessório'}
<input
className="block rounded border p-2"
value={row.servicePlace}
onChange={(e) =>
change(row.id, {
servicePlace:
e.target.value,
})
}
/>
</label>
<label>
Situação do local relevante
<select
className="block rounded border p-2"
value={row.placeCountry}
onChange={(e) =>
change(row.id, {
placeCountry:
e.target.value,
})
}
>
<option value="">
Por indicar
</option>
<option value="MZ">
Moçambique
</option>
<option value="foreign">
Estrangeiro
</option>
</select>
</label>
<label>
Referência da localização / pressuposto
<input
className="block rounded border p-2"
value={row.placeRef}
onChange={(e) =>
change(row.id, {
placeRef: e.target.value,
})
}
/>
</label>
<label>
Imóvel, bens ou actividade e relação do
serviço
<input
className="block rounded border p-2"
value={row.subjectRef}
onChange={(e) =>
change(row.id, {
subjectRef: e.target.value,
})
}
/>
</label>
</>
)
)}
</div>
<p>
Mudar percurso conserva os locais e referências,mas
exige rever os factos próprios. Campos sem aplicação
ficam ocultos e conservados.
</p>
<fieldset>
<legend>Factos próprios deste percurso</legend>
{[
...serviceLocationConditions,
...ownServiceConditions(row.treatment),
].map(([key, label]) => (
<label className="block" key={key}>
{label}
<select
className="block rounded border p-2"
value={row.conditions[key] ?? ''}
onChange={(e) =>
change(row.id, {
conditions: {
...row.conditions,
[key]: e.target.value as
| ''
| 'yes'
| 'no',
},
})
}
>
<option value="">Por indicar</option>
<option value="yes">Sim</option>
<option value="no">Não</option>
</select>
</label>
))}
</fieldset>
</details>
))}
{!!book.rows.length && (
<button
type="button"
className="rounded bg-emerald-800 p-2 text-white"
onClick={() => {
try {
save(recordServiceLocations(draft, book));
} catch (cause) {
setError(String(cause));
}
}}
>
Classificar localização e guardar versão
</button>
)}
{book.result && (
<>
<p role="status">
{serviceLocationCurrent(draft, book)
? 'Localizações correspondentes às entradas guardadas.'
: 'Entradas alteradas;localizações históricas conservadas. Reveja e classifique novamente.'}{' '}
{book.history?.length ?? 0} versões anteriores.
Classificação não determina isenção,IVA ou campo11.
</p>
<dl>
{serviceLocationReportRows(draft).map(
([, label, value, origin], index) => (
<div key={index}>
<dt className="font-semibold">{label}</dt>
<dd>
{value}
<small className="block">
{origin}
</small>
</dd>
</div>
),
)}
</dl>
</>
)}
</details>
);
}