Functional Weave
Code in Python

logistics.duty-estimate@1.0.1

README.md

4,007 bytes · view raw

# logistics.duty-estimate

An estimate of what an import costs in tax: customs duty on the customs
value, then import VAT on the customs value plus the duty. **Review:** this is
money-critical and the vectors want sign-off from a customs broker before the
version is relied on.

```
customsValue = goods + freight + insurance
duty         = customsValue x dutyBasisPoints / 10000
vatValue     = customsValue + duty + vatAdditions
importVat    = vatValue x the VAT rate in force on importDate
totalPayable = duty + importVat
```

## Why it is shaped this way

- **CIF basis.** The UK and the EU value imports for duty on what it cost to
  get them to the border: the price of the goods plus transport, insurance,
  loading and handling up to the place the goods enter (HMRC, "Delivery costs
  to include in the customs value"; EU Union Customs Code, Article 71).
  Charging duty on the invoice price alone is the common mistake. For a
  country that values on an FOB basis (the United States, for one), pass
  freight and insurance as zero.
- **VAT goes on top of duty.** The value for import VAT is the customs value
  plus the duty plus incidental costs to the first destination in the country
  (HMRC IMPS04150; VAT Directive 2006/112/EC, Article 86). Those later costs,
  and any excise duty, are `vatAdditions`: VAT is charged on them, duty is
  not.
- **The duty rate is an argument.** It depends on the commodity code, the
  country of origin, preferences under a trade agreement, quotas and
  suspensions; that lookup belongs to a tariff service, not a table here. Only
  ad valorem duty is modelled: specific duties (per kilogram, per litre),
  anti-dumping duty and excise must be worked out separately (excise then
  goes into `vatAdditions`).
- **The VAT rate is data.** It comes from `finance.tax.vat-rate` for the
  jurisdiction, category and import date, so historic imports use the rate
  then in force.
- **Rounding is the caller's choice**, applied to duty and to VAT separately,
  because the published guidance does not settle it and brokers' systems
  differ. `down` (truncate to the penny) and `half-up` are the usual choices.

## Not modelled

Low-value consignment rules (in Great Britain, VAT on goods of £135 or less
is charged at the point of sale, not at import), customs duty reliefs,
postponed VAT accounting (which changes when the VAT is paid, not how much),
and currency conversion: every amount must be in the currency of the import
declaration, and a mix is an error.

## Sources

- HMRC, "Delivery costs to include in the customs value",
  https://www.gov.uk/guidance/delivery-costs-to-include-in-the-customs-value
- HMRC internal manual IMPS04150, "Value for import VAT: normal rules:
  incidental expenses",
  https://www.gov.uk/hmrc-internal-manuals/imports/imps04150
- Regulation (EU) No 952/2013 (Union Customs Code), Article 71; Council
  Directive 2006/112/EC, Article 86.

## Before you rely on this

**Not professional advice.** This capability calculates customs duty figures from published rules. It is a software component for developers, not tax advice. Rules change and every rate here has an effective date. Check that the dates cover your case. Verify results against the official sources listed above, and have a customs specialist review how you use it, before anyone relies on the output. Provided "as is" under its licence, without warranty.

**Unreviewed.** This capability's implementations agree in every language and pass its published test vectors, which were worked out from the official sources cited. But no qualified customs specialist has yet checked those vectors, or confirmed that the capability covers the cases it claims. Treat it as a draft. Do not use it for real people, money or decisions without your own expert review. Once a qualified reviewer signs off, this notice is replaced with their name, qualification and the date. Each new version needs fresh sign-off.

1.0.1 marks it unreviewed. The code and the tests are unchanged.