656 lines
25 KiB
TypeScript
656 lines
25 KiB
TypeScript
import type { Acquisition, AcquisitionResult } from './iva-acquisitions.ts';
|
||
import type { AcquisitionEligibility } from './iva-acquisition-right.ts';
|
||
import { acquisitionScope, readAcquisitionStore } from './iva-acquisitions.ts';
|
||
import {
|
||
linkedOperationRight,
|
||
linkedBeverageDeductionRight,
|
||
} from './iva-acquisition-right.ts';
|
||
import { acquisitionTreatmentIssue } from './iva-acquisition-continuity.ts';
|
||
import {
|
||
decimalFraction,
|
||
fraction,
|
||
fractionPresentation,
|
||
subtractFractions,
|
||
} from './fiscal-rational.ts';
|
||
export const acquisitionBCVersion = 'acquisition-imports-exclusions/1';
|
||
export const acquisitionBCSource =
|
||
'L2-B/C: CIVA18(1)(a/b),18(2),19,20(1)(a–f)/20(2)/20(3)(a/b),21. Lei13/2016 PDF14–15,p1426(272–273);Lei22/2022 PDF3,p2252(27),art20(2–3);Lei10/2025 PDF13,p2180(13),18(2)/19(2). Bebidas13(2):Lei13/2016 PDF12,p1426(270). MZN/2026,mesmo mês documental;sem pro rata18(6),regularizações ou restituiçãoL3.';
|
||
type Choice = '' | 'yes' | 'no';
|
||
export const expenseOptions = [
|
||
['ordinary', 'Despesa sem exclusão especial'],
|
||
[
|
||
'vehicle',
|
||
'Viatura de turismo,barco de recreio,helicóptero,avião,moto ou outro veículo',
|
||
],
|
||
['fuel', 'Combustível normalmente utilizável em viaturas automóveis'],
|
||
['travel', 'Transportes e viagens do sujeito passivo/pessoal'],
|
||
['lodging_food', 'Alojamento e alimentação'],
|
||
['beverages', 'Bebidas,tabaco e recepção'],
|
||
['telephone', 'Comunicações telefónicas'],
|
||
['luxury', 'Divertimento e luxo'],
|
||
['other', 'Outro caso — por enquadrar'],
|
||
] as const;
|
||
export type AcquisitionBC = {
|
||
version: 1;
|
||
expense: string;
|
||
reducedSupply: Choice;
|
||
evidence: string;
|
||
facts: Record<string, Choice>;
|
||
fuelKind: '' | 'diesel' | 'other';
|
||
dieselUse:
|
||
| ''
|
||
| 'heavy_passengers'
|
||
| 'public_passengers'
|
||
| 'machine'
|
||
| 'agriculture'
|
||
| 'other';
|
||
beveragePath: '' | 'deduction' | 'refund';
|
||
importer: string;
|
||
belongs: Choice;
|
||
ownImportVat: Choice;
|
||
vatBasis: '' | 'due' | 'exempt' | 'zero' | 'unknown';
|
||
vatRef: string;
|
||
goodsRef: string;
|
||
source?: { map: string; id: string; fingerprint: string };
|
||
};
|
||
export function newAcquisitionBC(): AcquisitionBC {
|
||
return {
|
||
version: 1,
|
||
expense: '',
|
||
reducedSupply: '',
|
||
evidence: '',
|
||
facts: {},
|
||
fuelKind: '',
|
||
dieselUse: '',
|
||
beveragePath: '',
|
||
importer: '',
|
||
belongs: '',
|
||
ownImportVat: '',
|
||
vatBasis: '',
|
||
vatRef: '',
|
||
goodsRef: '',
|
||
};
|
||
}
|
||
export function acquisitionBCDetails(b: AcquisitionBC): string {
|
||
const labels: Record<string, string> = {
|
||
exigibleInPeriod:
|
||
'IVA aduaneiro exigível no período de exercício confirmado pelo documento',
|
||
tourism: 'Bem abrangido20(1)(a)',
|
||
saleOrExploit: 'Venda/exploração como objecto da actividade',
|
||
resale: 'Combustível para revenda',
|
||
dieselScope: 'Âmbito específico do uso de gasóleo confirmado',
|
||
commercialTraveller: 'Viajante comercial por conta própria',
|
||
ownLandline: 'Telefone fixo em nome do sujeito passivo',
|
||
beverageSpecial: 'Bebidas no âmbito13(2)',
|
||
onlyDeduction: 'Parcela exclusivamente para dedução',
|
||
notCoastalFishing: 'Sem provisões de pesca costeira',
|
||
};
|
||
const keys: Record<string, string[]> = {
|
||
vehicle: [
|
||
'tourism',
|
||
...(b.facts.tourism === 'yes' ? ['saleOrExploit'] : []),
|
||
],
|
||
fuel: [
|
||
'resale',
|
||
...(b.fuelKind === 'diesel' && b.dieselUse !== 'other'
|
||
? ['dieselScope']
|
||
: []),
|
||
],
|
||
lodging_food: ['commercialTraveller'],
|
||
telephone: ['ownLandline'],
|
||
beverages: [
|
||
'beverageSpecial',
|
||
...(b.facts.beverageSpecial === 'yes'
|
||
? [
|
||
...(b.beveragePath === 'deduction'
|
||
? ['onlyDeduction']
|
||
: []),
|
||
'notCoastalFishing',
|
||
]
|
||
: []),
|
||
],
|
||
};
|
||
return [
|
||
...(b.facts.exigibleInPeriod !== undefined ? ['exigibleInPeriod'] : []),
|
||
...(keys[b.expense] ?? []),
|
||
]
|
||
.map(
|
||
(k) =>
|
||
`${labels[k]}:${b.facts[k] === 'yes' ? 'Sim' : b.facts[k] === 'no' ? 'Não' : 'Por indicar'}`,
|
||
)
|
||
.concat(
|
||
b.expense === 'fuel'
|
||
? [
|
||
`Combustível:${b.fuelKind === 'diesel' ? 'Gasóleo' : b.fuelKind === 'other' ? 'Outro' : 'Por indicar'}`,
|
||
`Utilização:${{ heavy_passengers: 'Pesado de passageiros', public_passengers: 'Transporte público licenciado,excepto rent a car', machine: 'Máquina,não veículo matriculado', agriculture: 'Tractor agrícola,emprego exclusivo/predominante', other: 'Outro uso50%', '': 'Por indicar' }[b.dieselUse]}`,
|
||
]
|
||
: [],
|
||
b.expense === 'beverages' && b.facts.beverageSpecial === 'yes'
|
||
? [
|
||
`Via:${b.beveragePath === 'deduction' ? 'DeduçãoL2' : b.beveragePath === 'refund' ? 'RestituiçãoL3' : 'Por indicar'}`,
|
||
]
|
||
: [],
|
||
)
|
||
.join('; ');
|
||
}
|
||
export function validAcquisitionBC(v: unknown): v is AcquisitionBC {
|
||
if (!v || typeof v !== 'object' || Array.isArray(v)) return false;
|
||
const b = v as AcquisitionBC;
|
||
return (
|
||
b.version === 1 &&
|
||
[
|
||
'expense',
|
||
'evidence',
|
||
'vatRef',
|
||
'goodsRef',
|
||
'importer',
|
||
'fuelKind',
|
||
'dieselUse',
|
||
'beveragePath',
|
||
'vatBasis',
|
||
].every((k) => typeof b[k as keyof AcquisitionBC] === 'string') &&
|
||
[b.reducedSupply, b.belongs, b.ownImportVat].every((v) =>
|
||
['', 'yes', 'no'].includes(v),
|
||
) &&
|
||
!!b.facts &&
|
||
typeof b.facts === 'object' &&
|
||
!Array.isArray(b.facts) &&
|
||
Object.values(b.facts).every((v) => ['', 'yes', 'no'].includes(v)) &&
|
||
(!b.source ||
|
||
['map', 'id', 'fingerprint'].every(
|
||
(k) =>
|
||
typeof b.source?.[k as keyof typeof b.source] === 'string',
|
||
))
|
||
);
|
||
}
|
||
type ImportSource = {
|
||
id: string;
|
||
treatment?: string;
|
||
description?: string;
|
||
documentRef?: string;
|
||
documentDate?: string;
|
||
period?: string;
|
||
importDate?: string;
|
||
importer?: string;
|
||
};
|
||
const importMaps = ['importExemptions', 'objectiveImports', 'remissionImports'];
|
||
export function acquisitionImportSources(draft: Record<string, unknown>) {
|
||
const store = readAcquisitionStore(
|
||
draft.modelo_a_snapshot,
|
||
) as unknown as Record<string, Record<string, { rows: ImportSource[] }>>;
|
||
return importMaps.flatMap((map) =>
|
||
(store[map]?.[acquisitionScope(draft)]?.rows ?? []).map((row) => ({
|
||
map,
|
||
row,
|
||
label: `${row.description || row.id} — ${row.period ?? ''} — ${row.documentRef || 'documento por indicar'}`,
|
||
})),
|
||
);
|
||
}
|
||
export function reuseAcquisitionImport(
|
||
draft: Record<string, unknown>,
|
||
row: Acquisition,
|
||
map: string,
|
||
id: string,
|
||
): Acquisition {
|
||
const src = acquisitionImportSources(draft).find(
|
||
(v) => v.map === map && v.row.id === id,
|
||
);
|
||
if (!src)
|
||
throw Error('Origem da importação indisponível;dados conservados.');
|
||
const bc = row.bc ?? newAcquisitionBC();
|
||
return {
|
||
...row,
|
||
description: row.description || src.row.description || '',
|
||
documentRef: row.documentRef || src.row.documentRef || '',
|
||
documentDate:
|
||
row.documentDate ||
|
||
src.row.documentDate ||
|
||
src.row.importDate ||
|
||
'',
|
||
period: row.period || src.row.period || '',
|
||
bc: {
|
||
...bc,
|
||
importer: bc.importer || src.row.importer || '',
|
||
source: { map, id, fingerprint: JSON.stringify(src.row) },
|
||
},
|
||
};
|
||
}
|
||
export function acquisitionBCSourceKey(
|
||
draft: Record<string, unknown>,
|
||
rows: Acquisition[],
|
||
): string {
|
||
return rows.some((r) => r.bc)
|
||
? JSON.stringify({
|
||
version: acquisitionBCVersion,
|
||
sources: rows
|
||
.filter((r) => r.bc?.source)
|
||
.map(
|
||
(r) =>
|
||
acquisitionImportSources(draft).find(
|
||
(s) =>
|
||
s.map === r.bc!.source!.map &&
|
||
s.row.id === r.bc!.source!.id,
|
||
)?.row ?? null,
|
||
),
|
||
})
|
||
: '';
|
||
}
|
||
function validDate(value: string) {
|
||
const d = new Date(value + 'T00:00:00Z');
|
||
return (
|
||
/^\d{4}-\d{2}-\d{2}$/.test(value) &&
|
||
Number.isFinite(d.getTime()) &&
|
||
d.toISOString().slice(0, 10) === value
|
||
);
|
||
}
|
||
export function evaluateAcquisitionBC(
|
||
row: Acquisition,
|
||
currency: string,
|
||
registered: Choice,
|
||
draft: Record<string, unknown> | undefined,
|
||
raw: AcquisitionResult,
|
||
partial?: { right: AcquisitionEligibility; noExcludedPayments: Choice },
|
||
): AcquisitionResult {
|
||
const bc = row.bc!;
|
||
let right =
|
||
partial?.right ??
|
||
(row.deductionLink && draft
|
||
? linkedOperationRight(draft, row.deductionLink)
|
||
: {
|
||
status: 'indeterminate' as const,
|
||
reason: 'Vínculo à operação de destino em falta.',
|
||
source: acquisitionBCSource,
|
||
});
|
||
const stop = (
|
||
reason: string,
|
||
status: 'eligible' | 'no_right' | 'indeterminate' = 'indeterminate',
|
||
percent?: number,
|
||
): AcquisitionResult => {
|
||
const exact =
|
||
percent !== undefined && raw.vat !== null
|
||
? decimalFraction(raw.vat)
|
||
: null;
|
||
const deductibleExact = exact
|
||
? fraction(
|
||
BigInt(exact.numerator) * BigInt(percent!),
|
||
BigInt(exact.denominator) * 100n,
|
||
)
|
||
: undefined;
|
||
return {
|
||
...raw,
|
||
reason,
|
||
deductible: deductibleExact
|
||
? fractionPresentation(deductibleExact).decimal
|
||
: null,
|
||
...(deductibleExact
|
||
? {
|
||
deductibleExact,
|
||
nonDeductibleExact: subtractFractions(
|
||
exact!,
|
||
deductibleExact,
|
||
),
|
||
}
|
||
: {}),
|
||
eligibility: {
|
||
...right,
|
||
status,
|
||
reason,
|
||
source: acquisitionBCSource + '; ' + right.source,
|
||
},
|
||
};
|
||
};
|
||
if (!validAcquisitionBC(bc))
|
||
return stop('CondiçõesB/C não recuperáveis;sem regra por defeito.');
|
||
if (
|
||
currency !== 'MZN' ||
|
||
row.sourceCurrency !== currency ||
|
||
!/^2026-(0[1-9]|1[0-2])$/.test(row.period) ||
|
||
raw.vat === null
|
||
)
|
||
return stop(raw.reason || 'IVA/moeda/período em falta.');
|
||
if (row.domestic === 'no') {
|
||
if (!/^\d{1,15}(\.\d{1,6})?$/.test(row.vat.trim()))
|
||
return stop(
|
||
'Indique expressamente o IVA do bilhete;diferença entre custo líquido/bruto não constitui montante aduaneiro identificado.',
|
||
);
|
||
if (
|
||
(row.net.trim() && raw.net === null) ||
|
||
(row.gross.trim() && raw.gross === null)
|
||
)
|
||
return stop(
|
||
'Valores de custo preenchidos inválidos;conservar e resolver a divergência.',
|
||
);
|
||
} else if (raw.net === null || raw.gross === null) return stop(raw.reason);
|
||
if (
|
||
raw.net !== null &&
|
||
raw.gross !== null &&
|
||
fractionPresentation(
|
||
subtractFractions(
|
||
decimalFraction(raw.gross),
|
||
decimalFraction(raw.net),
|
||
),
|
||
).decimal !== raw.vat
|
||
)
|
||
return stop(
|
||
'Líquido + IVA diverge do bruto declarado;sem substituir valores.',
|
||
);
|
||
const treatmentIssue = acquisitionTreatmentIssue(row.acquisitionTreatment);
|
||
if (treatmentIssue) return stop(treatmentIssue);
|
||
if (!['projected', 'effective'].includes(row.origin))
|
||
return stop('Indique dados efectivos ou pressupostos de projecção.');
|
||
if (
|
||
row.sourceMonth !== null &&
|
||
(!row.sourceBasis ||
|
||
row.sourceAmount === null ||
|
||
(row.sourceBasis === 'net' ? raw.net : raw.gross) === null ||
|
||
JSON.stringify(decimalFraction(row.sourceAmount)) !==
|
||
JSON.stringify(
|
||
decimalFraction(
|
||
(row.sourceBasis === 'net' ? raw.net : raw.gross)!,
|
||
),
|
||
))
|
||
)
|
||
return stop(
|
||
'Valor de origem divergente ou por classificar;sem sobrescrita.',
|
||
);
|
||
if (
|
||
(row.domestic === 'no' && row.field !== '11') ||
|
||
(row.domestic === 'yes' && row.field === '11') ||
|
||
!['yes', 'no'].includes(row.domestic)
|
||
)
|
||
return stop('Separe aquisição interna08–10 da importação de bens11.');
|
||
if (bc.source) {
|
||
const src = draft
|
||
? acquisitionImportSources(draft).find(
|
||
(s) => s.map === bc.source!.map && s.row.id === bc.source!.id,
|
||
)
|
||
: undefined;
|
||
if (!src || JSON.stringify(src.row) !== bc.source.fingerprint)
|
||
return stop(
|
||
'OrigemL1 da importação alterada:adopte explicitamente os dados actuais,conservando edições e histórico.',
|
||
);
|
||
if (
|
||
[
|
||
'service_in_customs_value',
|
||
'accessory_service_first_destination',
|
||
].includes(src.row.treatment ?? '')
|
||
)
|
||
return stop(
|
||
'Origem é serviço incluído na base aduaneira12(1)(e),não IVA próprio da importação de bens;identifique o bilhete dos bens,sem somar novamente IVA do serviço.',
|
||
);
|
||
}
|
||
if (registered !== 'yes')
|
||
return stop(
|
||
'Enquadramento do adquirente no regime normal por confirmar.',
|
||
);
|
||
if (
|
||
row.allocation === 'no_right' ||
|
||
row.integrity === 'no' ||
|
||
row.exclusion === 'excluded'
|
||
)
|
||
return stop(
|
||
'Sem direito pela afectação,exclusão expressa ou impedimento18(3–5) declarado.',
|
||
'no_right',
|
||
0,
|
||
);
|
||
if (row.allocation === 'mixed' && !partial)
|
||
return stop(
|
||
'Afectação parcial/pro rata depende deD;sem dedução integral presumida.',
|
||
);
|
||
if (
|
||
!partial &&
|
||
(!row.deductionLink ||
|
||
row.deductionLink.scopeConfirmed !== 'yes' ||
|
||
!row.deductionLink.allocationRef.trim() ||
|
||
row.allocation !== 'taxable_only')
|
||
)
|
||
return stop(
|
||
'Confirme afectação exclusiva e referência à operação ligada.',
|
||
);
|
||
if (
|
||
bc.expense === 'beverages' &&
|
||
bc.facts.beverageSpecial === 'yes' &&
|
||
['deduction', 'refund'].includes(bc.beveragePath) &&
|
||
draft &&
|
||
row.deductionLink
|
||
)
|
||
right = linkedBeverageDeductionRight(
|
||
draft,
|
||
row.deductionLink,
|
||
bc.facts.notCoastalFishing === 'yes',
|
||
);
|
||
if (right.status === 'no_right') return stop(right.reason, 'no_right', 0);
|
||
if (right.status !== 'eligible') return stop(right.reason);
|
||
const noExcludedPayments =
|
||
partial?.noExcludedPayments ?? row.deductionLink?.noExcludedPayments;
|
||
if (noExcludedPayments === 'no')
|
||
return stop('Pagamentos15(6)(c)/19(2) excluídos.', 'no_right', 0);
|
||
if (noExcludedPayments !== 'yes')
|
||
return stop('Exclusão19(2) por esclarecer.');
|
||
if (
|
||
!validDate(row.documentDate) ||
|
||
row.documentDate.slice(0, 7) !== row.period
|
||
)
|
||
return stop(
|
||
'Documento e exercício no mesmo mês neste incremento;dedução posterior não presumida.',
|
||
);
|
||
if (
|
||
!row.documentRef.trim() ||
|
||
row.legalDocument !== 'yes' ||
|
||
row.held !== 'yes' ||
|
||
row.integrity !== 'yes'
|
||
)
|
||
return stop(
|
||
'Referência,forma legal,posse e integridade do documento por completar.',
|
||
);
|
||
if (row.domestic === 'no') {
|
||
if (
|
||
row.documentType !== 'customs' ||
|
||
!bc.importer.trim() ||
|
||
!bc.goodsRef.trim() ||
|
||
!bc.vatRef.trim() ||
|
||
bc.belongs !== 'yes' ||
|
||
bc.ownImportVat !== 'yes'
|
||
)
|
||
return stop(
|
||
'Bilhete de despacho,importador/titularidade,bens/linha e IVA próprio devido na importação por completar;fornecedor inscrito no IVA interno não é exigido.',
|
||
);
|
||
if (bc.facts.exigibleInPeriod !== 'yes')
|
||
return stop(
|
||
'Exigibilidade do IVA aduaneiro no período de exercício por confirmar pelo documento21(1);não inferida só da emissão do bilhete.Dedução posterior conserva percurso próprio.',
|
||
);
|
||
if (!['due', 'exempt', 'zero'].includes(bc.vatBasis))
|
||
return stop(
|
||
'IVA da importação desconhecido;não inferir montante da classificaçãoL1 ou calcular direitosL13.',
|
||
);
|
||
if (
|
||
['exempt', 'zero'].includes(bc.vatBasis) &&
|
||
decimalFraction(raw.vat).numerator !== '0'
|
||
)
|
||
return stop(
|
||
'IVA positivo incompatível com isenção/zero declarado;resolver divergência sem substituir montante.',
|
||
);
|
||
} else if (
|
||
!['invoice', 'equivalent'].includes(row.documentType) ||
|
||
!row.supplier.trim() ||
|
||
row.supplierRegistered !== 'yes'
|
||
)
|
||
return stop(
|
||
'Factura/documento equivalente e fornecedor interno inscrito por completar.',
|
||
);
|
||
if (row.domestic === 'yes' && bc.reducedSupply === 'yes')
|
||
return stop(
|
||
'IVA suportado em fornecimento17-A:exclusão20(2),Lei22/2022;distinta do destino19(2).',
|
||
'no_right',
|
||
0,
|
||
);
|
||
if (row.domestic === 'yes' && bc.reducedSupply !== 'no')
|
||
return stop(
|
||
'Indique se o IVA suportado respeita a fornecimento17-A;sem inferir pela taxa ou valor.',
|
||
);
|
||
if (
|
||
!expenseOptions.some(([id]) => id === bc.expense) ||
|
||
bc.expense === 'other' ||
|
||
!bc.evidence.trim()
|
||
)
|
||
return stop(
|
||
'Natureza da despesa e fundamento factual/documental por identificar.',
|
||
);
|
||
const f = bc.facts;
|
||
switch (bc.expense) {
|
||
case 'ordinary':
|
||
return stop(
|
||
'Elegível pelas condições declaradas18/19;sem exclusão especial20 identificada.',
|
||
'eligible',
|
||
100,
|
||
);
|
||
case 'vehicle':
|
||
if (f.tourism === '')
|
||
return stop(
|
||
'Classificação do veículo na definição20(1)(a) em falta.',
|
||
);
|
||
if (f.tourism === 'no')
|
||
return stop(
|
||
'Veículo fora da definição20(1)(a),segundo características/utilização documentadas.',
|
||
'eligible',
|
||
100,
|
||
);
|
||
if (f.tourism !== 'yes')
|
||
return stop('Indique se o bem está abrangido por20(1)(a).');
|
||
if (f.saleOrExploit === 'yes')
|
||
return stop(
|
||
'Excepção20(3)(a):venda/exploração do bem constitui objecto da actividade;combustível conserva20(1)(b).',
|
||
'eligible',
|
||
100,
|
||
);
|
||
return f.saleOrExploit === 'no'
|
||
? stop(
|
||
'Bem abrangido20(1)(a),sem excepção20(3)(a).',
|
||
'no_right',
|
||
0,
|
||
)
|
||
: stop(
|
||
'Venda/exploração como objecto da actividade por esclarecer.',
|
||
);
|
||
case 'fuel':
|
||
if (f.resale === 'yes')
|
||
return stop(
|
||
'Combustível adquirido para revenda,conforme ressalva20(3)(a);fundamento específico documentado.',
|
||
'eligible',
|
||
100,
|
||
);
|
||
if (f.resale !== 'no')
|
||
return stop(
|
||
'Destino de revenda do combustível por esclarecer.',
|
||
);
|
||
if (bc.fuelKind === 'other')
|
||
return stop(
|
||
'Combustível normalmente utilizável em viaturas,fora da excepção gasóleo20(1)(b).',
|
||
'no_right',
|
||
0,
|
||
);
|
||
if (bc.fuelKind !== 'diesel')
|
||
return stop('Natureza do combustível por indicar.');
|
||
if (bc.dieselUse === 'other')
|
||
return stop(
|
||
'Gasóleo20(1)(b):dedução50%,não taxa de IVA nem pro rata geral.',
|
||
'eligible',
|
||
50,
|
||
);
|
||
if (
|
||
[
|
||
'heavy_passengers',
|
||
'public_passengers',
|
||
'machine',
|
||
'agriculture',
|
||
].includes(bc.dieselUse)
|
||
) {
|
||
if (f.dieselScope !== 'yes')
|
||
return stop(
|
||
'Confirme o âmbito específico20(1)(b)(i–iv);não basta escolher a categoria.',
|
||
);
|
||
return stop(
|
||
'Gasóleo20(1)(b)(i–iv):dedução integral no uso específico confirmado;transporte público exclui rent a car,máquina não é veículo matriculado,tractor agrícola tem emprego exclusivo/predominante.',
|
||
'eligible',
|
||
100,
|
||
);
|
||
}
|
||
return stop('Utilização do gasóleo por indicar.');
|
||
case 'travel':
|
||
return stop(
|
||
'Transportes/viagens do sujeito passivo e pessoal excluídos20(1)(c).',
|
||
'no_right',
|
||
0,
|
||
);
|
||
case 'lodging_food':
|
||
return f.commercialTraveller === 'yes'
|
||
? stop(
|
||
'Excepção20(3)(b):viajante comercial por conta própria,no quadro da actividade profissional.',
|
||
'eligible',
|
||
100,
|
||
)
|
||
: f.commercialTraveller === 'no'
|
||
? stop(
|
||
'Alojamento/alimentação excluídos20(1)(d),sem excepção20(3)(b).',
|
||
'no_right',
|
||
0,
|
||
)
|
||
: stop(
|
||
'Âmbito de viajante comercial por conta própria por esclarecer.',
|
||
);
|
||
case 'telephone':
|
||
return f.ownLandline === 'yes'
|
||
? stop(
|
||
'Telefone fixo em nome do sujeito passivo:excepção expressa20(1)(e).',
|
||
'eligible',
|
||
100,
|
||
)
|
||
: f.ownLandline === 'no'
|
||
? stop(
|
||
'Comunicações telefónicas fora da excepção20(1)(e).',
|
||
'no_right',
|
||
0,
|
||
)
|
||
: stop('Telefone fixo e titularidade por esclarecer.');
|
||
case 'luxury':
|
||
return stop(
|
||
'Despesa de divertimento/luxo20(1)(f),segundo natureza/montante e exploração normal declarados.',
|
||
'no_right',
|
||
0,
|
||
);
|
||
case 'beverages':
|
||
if (bc.facts.beverageSpecial === 'no')
|
||
return stop(
|
||
'Bebidas/tabaco/recepção excluídos20(1)(d),fora do fundamento especial13(2).',
|
||
'no_right',
|
||
0,
|
||
);
|
||
if (
|
||
bc.facts.beverageSpecial === 'yes' &&
|
||
bc.beveragePath === 'refund' &&
|
||
right.reason.startsWith('Via de dedução13(2)')
|
||
)
|
||
return stop(
|
||
'Via restituição13(2):linha documental integral escolhida para acompanhamentoL3-E,sem dedução desta parcela. Não representa pedido apresentado,concessão ou recebimento.',
|
||
'no_right',
|
||
0,
|
||
);
|
||
if (
|
||
bc.facts.beverageSpecial === 'yes' &&
|
||
bc.beveragePath === 'deduction' &&
|
||
bc.facts.onlyDeduction === 'yes' &&
|
||
right.reason.startsWith('Via de dedução13(2)')
|
||
)
|
||
return stop(
|
||
right.reason +
|
||
' IVA suportado identificado neste documento;mesma parcela não segue restituiçãoL3.',
|
||
'eligible',
|
||
100,
|
||
);
|
||
return stop(
|
||
'Via especial13(2) por delimitar:dedução ou restituiçãoL3,sem dupla contagem;tabaco/recepção não herdam a excepção de bebidas.',
|
||
);
|
||
}
|
||
return stop('Tratamento não implementado;rascunho preservado.');
|
||
}
|