feat: Gebiete mit Zollpflicht vom Versand ausgenommen
Docker Image bauen und veroeffentlichen / build-and-push (push) Successful in 2m7s
Docker Image bauen und veroeffentlichen / build-and-push (push) Successful in 2m7s
Vorgabe war: nur dorthin liefern, wo keine Zollabwicklung noetig ist. Die
EU-Einstellung erfuellt das auf Laenderebene — die Union ist eine
Zollunion, eine Sendung von Deutschland nach Frankreich braucht keine
Zollanmeldung. Der Laendercode allein genuegt aber nicht.
Einige Gebiete gehoeren zu einem EU-Mitgliedstaat, liegen aber ausserhalb
des Zoll- und/oder Steuergebiets der Union. Dorthin ist jede Sendung eine
Ausfuhr mit Zollinhaltserklaerung, Handelsrechnung und moeglichen
Einfuhrabgaben beim Empfaenger. Zwei davon liegen in DEUTSCHLAND:
Helgoland (27498) und Büsingen am Hochrhein (78266)
Sie waren also selbst bei der Einstellung "Nur Deutschland" betroffen.
Dazu kommen Kanarische Inseln, Ceuta, Melilla, die franzoesischen
Ueberseegebiete, Livigno, Campione d'Italia, Åland und der Berg Athos.
Erkennbar sind sie nur an der Postleitzahl. findCustomsExcludedArea
prueft sie je Land, denn dieselbe Ziffernfolge bedeutet anderswo etwas
anderes: "22" ist in Finnland Åland, in Italien die Provinz Como. Die
Checkout-Route weist solche Anschriften mit einer Meldung ab, die das
Gebiet benennt und auf die Abholung verweist.
Azoren und Madeira sind bewusst NICHT ausgenommen: sie gehoeren voll zum
Zoll- und Steuergebiet, dorthin gilt der normale Binnenversand. Ein Test
haelt das fest, damit sie nicht versehentlich mitgesperrt werden.
Die Hinweistexte auf "Versand und Zahlung" nennen die Ausnahmen jetzt
ausdruecklich — in beiden Einstellungen und beiden Sprachen.
8 neue Tests in shipping-region.test.ts, 1 in der Checkout-Route
("weist Helgoland ab, obwohl es in Deutschland liegt").
tsc: 0 Fehler. vitest: 359/359 gruen (zuvor 350). eslint: 0 Warnungen.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
1 parent
6d7a77c8dd
commit
1bdf4df04a
6 files changed
+165
-5
No files matched your search
@@ -11,6 +11,7 @@ import {
|
||||
DEFAULT_SHIPPING_REGION,
|
||||
EU_COUNTRY_CODES,
|
||||
allowedCountryCodes,
|
||||
findCustomsExcludedArea,
|
||||
isCountryAllowed,
|
||||
parseShippingRegion,
|
||||
} from "./shipping-region";
|
||||
@@ -89,3 +90,54 @@ describe("isCountryAllowed", () => {
|
||||
expect(isCountryAllowed("EU", " ")).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("findCustomsExcludedArea", () => {
|
||||
test("erkennt die beiden deutschen Gebiete ausserhalb des Zollgebiets", () => {
|
||||
// Der ueberraschende Teil: selbst bei "Nur Deutschland" gibt es
|
||||
// Anschriften, die eine Zollanmeldung braeuchten.
|
||||
expect(findCustomsExcludedArea("DE", "27498")).toBe("Helgoland");
|
||||
expect(findCustomsExcludedArea("DE", "78266")).toBe("Büsingen am Hochrhein");
|
||||
});
|
||||
|
||||
test("laesst normale deutsche Anschriften durch", () => {
|
||||
expect(findCustomsExcludedArea("DE", "86450")).toBeNull();
|
||||
expect(findCustomsExcludedArea("DE", "10115")).toBeNull();
|
||||
});
|
||||
|
||||
test("erkennt spanische Sondergebiete", () => {
|
||||
expect(findCustomsExcludedArea("ES", "51001")).toBe("Ceuta");
|
||||
expect(findCustomsExcludedArea("ES", "52001")).toBe("Melilla");
|
||||
expect(findCustomsExcludedArea("ES", "38001")).toBe("Kanarische Inseln");
|
||||
// Festland Spanien bleibt normaler Binnenversand.
|
||||
expect(findCustomsExcludedArea("ES", "28001")).toBeNull();
|
||||
});
|
||||
|
||||
test("unterscheidet gleiche Ziffern in verschiedenen Laendern", () => {
|
||||
// "22" ist in Finnland Åland, in Italien die Provinz Como. Deshalb ist
|
||||
// die Zuordnung je Land und nicht global.
|
||||
expect(findCustomsExcludedArea("FI", "22100")).toBe("Åland");
|
||||
expect(findCustomsExcludedArea("IT", "22100")).toBeNull();
|
||||
expect(findCustomsExcludedArea("IT", "22061")).toBe("Campione d'Italia");
|
||||
});
|
||||
|
||||
test("erkennt franzoesische Ueberseegebiete", () => {
|
||||
expect(findCustomsExcludedArea("FR", "97100")).toBe("Französische Überseegebiete");
|
||||
expect(findCustomsExcludedArea("FR", "75001")).toBeNull();
|
||||
});
|
||||
|
||||
test("Azoren und Madeira sind KEIN Sondergebiet", () => {
|
||||
// Sie gehoeren voll zum Zoll- und Steuergebiet — normaler Binnenversand.
|
||||
expect(findCustomsExcludedArea("PT", "9500-001")).toBeNull();
|
||||
expect(findCustomsExcludedArea("PT", "9000-001")).toBeNull();
|
||||
});
|
||||
|
||||
test("ist unempfindlich gegen Leerzeichen und Kleinschreibung", () => {
|
||||
expect(findCustomsExcludedArea("de", " 27498 ")).toBe("Helgoland");
|
||||
expect(findCustomsExcludedArea("NL", "1234 ab")).toBeNull();
|
||||
});
|
||||
|
||||
test("ohne Land oder Postleitzahl gibt es nichts zu melden", () => {
|
||||
expect(findCustomsExcludedArea(null, "27498")).toBeNull();
|
||||
expect(findCustomsExcludedArea("DE", null)).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -50,6 +50,85 @@ export function allowedCountryCodes(region: ShippingRegion): string[] {
|
||||
return region === "EU" ? [...EU_COUNTRY_CODES].sort() : ["DE"];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gebiete, die zu einem EU-Mitgliedstaat gehoeren, aber ausserhalb des
|
||||
* Zoll- und/oder Steuergebiets der Union liegen.
|
||||
*
|
||||
* Die EU ist eine Zollunion — deshalb braucht eine Sendung von Deutschland
|
||||
* nach Frankreich keine Zollanmeldung. Fuer diese Gebiete gilt das NICHT:
|
||||
* dorthin ist jede Sendung eine Ausfuhr mit Zollinhaltserklaerung,
|
||||
* Handelsrechnung und moeglichen Einfuhrabgaben beim Empfaenger. Ein
|
||||
* Versandetikett allein reicht nicht.
|
||||
*
|
||||
* Erkennbar sind sie nur an der Postleitzahl, nicht am Laendercode — und zwei
|
||||
* davon liegen in DEUTSCHLAND. Ohne diese Liste braeuchte also selbst die
|
||||
* Einstellung "Nur Deutschland" gelegentlich eine Zollabwicklung.
|
||||
*
|
||||
* Die Zuordnung ist bewusst je Land, weil dieselbe Ziffernfolge anderswo ein
|
||||
* ganz normales Gebiet bezeichnet: "22" ist in Finnland Åland, in Italien
|
||||
* aber die Provinz Como.
|
||||
*
|
||||
* NICHT enthalten, weil sie voll zum Zoll- UND Steuergebiet gehoeren: die
|
||||
* Azoren und Madeira (Portugal). Dorthin gilt der normale EU-Binnenversand.
|
||||
*/
|
||||
export const CUSTOMS_EXCLUDED_AREAS: {
|
||||
country: string;
|
||||
name: string;
|
||||
/** Vollstaendige Postleitzahlen. */
|
||||
exact?: string[];
|
||||
/** Anfaenge von Postleitzahlen. */
|
||||
prefixes?: string[];
|
||||
}[] = [
|
||||
// Beide liegen ausserhalb des EU-Zollgebiets: Buesingen gehoert zum
|
||||
// Schweizer Zollgebiet, Helgoland zu gar keinem.
|
||||
{ country: "DE", name: "Helgoland", exact: ["27498"] },
|
||||
{ country: "DE", name: "Büsingen am Hochrhein", exact: ["78266"] },
|
||||
// Ceuta und Melilla liegen ausserhalb von Zoll- UND Steuergebiet, die
|
||||
// Kanaren innerhalb des Zoll-, aber ausserhalb des Steuergebiets — beides
|
||||
// bedeutet in der Praxis eine Zollanmeldung.
|
||||
{ country: "ES", name: "Ceuta", prefixes: ["51"] },
|
||||
{ country: "ES", name: "Melilla", prefixes: ["52"] },
|
||||
{ country: "ES", name: "Kanarische Inseln", prefixes: ["35", "38"] },
|
||||
// Livigno liegt ausserhalb des Zollgebiets; Campione d'Italia gehoert seit
|
||||
// 2020 dazu, bleibt aber ausserhalb des Steuergebiets (es gilt Schweizer
|
||||
// Mehrwertsteuer). Exakte Postleitzahlen, weil "23" und "22" in Italien
|
||||
// sonst ganze Provinzen treffen wuerden.
|
||||
{ country: "IT", name: "Livigno", exact: ["23041"] },
|
||||
{ country: "IT", name: "Campione d'Italia", exact: ["22061"] },
|
||||
// Die Übersee-Départements gehoeren zum Zoll-, nicht zum Steuergebiet; die
|
||||
// Übersee-Gebiete (98) gehoeren zu keinem von beiden.
|
||||
{ country: "FR", name: "Französische Überseegebiete", prefixes: ["97", "98"] },
|
||||
// Innerhalb der Zollunion, ausserhalb des Steuergebiets — es gibt eine
|
||||
// Steuergrenze mit Anmeldepflicht.
|
||||
{ country: "FI", name: "Åland", prefixes: ["22"] },
|
||||
{ country: "GR", name: "Berg Athos", exact: ["63086"] },
|
||||
];
|
||||
|
||||
/**
|
||||
* Liegt diese Anschrift in einem Gebiet, das trotz EU-Zugehoerigkeit eine
|
||||
* Zollabwicklung erfordert? Gibt den Namen des Gebiets zurueck, sonst null.
|
||||
*
|
||||
* Leerzeichen und Kleinschreibung werden abgefangen: Postleitzahlen werden in
|
||||
* mehreren EU-Laendern mit Leerzeichen geschrieben (Niederlande "1234 AB"),
|
||||
* und eine Bestellung an einer Schreibweise scheitern zu lassen waere kein
|
||||
* Schutz, sondern ein Fehler.
|
||||
*/
|
||||
export function findCustomsExcludedArea(
|
||||
country: string | null | undefined,
|
||||
zip: string | null | undefined
|
||||
): string | null {
|
||||
const countryCode = country?.trim().toUpperCase();
|
||||
const postalCode = zip?.replace(/\s+/g, "").toUpperCase();
|
||||
if (!countryCode || !postalCode) return null;
|
||||
|
||||
for (const area of CUSTOMS_EXCLUDED_AREAS) {
|
||||
if (area.country !== countryCode) continue;
|
||||
if (area.exact?.includes(postalCode)) return area.name;
|
||||
if (area.prefixes?.some((prefix) => postalCode.startsWith(prefix))) return area.name;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Darf in dieses Land geliefert werden?
|
||||
*
|
||||
|
||||
Reference in new issue
Block a user