# storetown-media/module-tax-sync

> Automatic EU VAT rate synchronization for Magento 2 — imports and updates all European tax rates including automatic Tax Rule creation. Free open-source under MIT.

`composer require storetown-media/module-tax-sync`

Canonical URL: https://packagento.com/storetown-media/module-tax-sync

## At a glance

- **Vendor**: Storetown Media (https://packagento.com/storetown-media.md)
- **Latest version**: v1.5.1 — released 2026-08-23
- **Pricing**: Free
- **Package type**: Magento 2 module
- **Status**: active, accepting new buyers

## Installation

Packagento is licence-gated, so even free packages need a licence on a project before Composer can resolve them.

1. **Sign in or create an account** at https://packagento.com/customer/account/.

2. **Add the package to your account.** Open https://packagento.com/storetown-media/module-tax-sync and complete the free checkout. A licence is minted automatically.

3. **Create or pick a project, then activate the licence on it.**
   - Projects represent the Magento installs you deploy to. Manage them at https://packagento.com/projects/.
   - Activate the new licence on the project you'll deploy this package to. Activation is what generates the Composer credentials scoped to that project.

4. **Add the project credentials to your Magento codebase.**

   Grab the project's public + private key from https://packagento.com/projects/ (open the project, then its Credentials tab), and add them to `auth.json`:

   ```json
   {
     "http-basic": {
       "packagento.com": {
         "username": "ppk_live_...",
         "password": "psk_live_..."
       }
     }
   }
   ```

   Add the Packagento Composer repository to `composer.json`:

   ```json
   {
     "repositories": [
       { "type": "composer", "url": "https://packagento.com" }
     ]
   }
   ```

5. **Install and apply.**

   ```bash
   composer require storetown-media/module-tax-sync:*
   bin/magento setup:upgrade
   bin/magento setup:di:compile
   bin/magento cache:flush
   ```

## What it does

Automatic EU VAT rate synchronization for Magento 2 — imports and updates all European tax rates including automatic Tax Rule creation. Free open-source under MIT.

## README

![Storetown Media](view/adminhtml/web/images/storetown-logo.png)

**Automatische Synchronisierung aller EU-Mehrwertsteuersätze für Magento 2**

[![Magento 2](https://img.shields.io/badge/Magento-2.4.x-orange.svg)](https://magento.com)
[![PHP](https://img.shields.io/badge/PHP-8.1%2B-blue.svg)](https://php.net)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
[![Free Forever](https://img.shields.io/badge/Price-Free%20Forever-brightgreen.svg)](https://www.storetown-media.de/eu-tax-rate-sync-fuer-magento-2-community/)
[![Hyvä](https://img.shields.io/badge/Hyv%C3%A4-Compatible-FF6B35.svg)](https://www.hyva.io/)
[![Made in Germany](https://img.shields.io/badge/Made%20in-Germany-black.svg)](https://www.storetown-media.de/)

[📦 **Packagist**](https://packagist.org/packages/storetown/module-tax-sync) · [📚 **Produktseite**](https://www.storetown-media.de/eu-tax-rate-sync-fuer-magento-2-community/) · [💼 **Storetown-Media Org**](https://github.com/storetown-media)

---

### 🇪🇺 Überblick

Diese kostenlose Extension importiert und aktualisiert automatisch alle EU-Mehrwertsteuersätze in Ihrem Magento 2 Shop. Nie wieder manuelle Pflege von Steuersätzen bei Änderungen!

#### ✨ Features

- **27 EU-Länder** + Schweiz, Norwegen und Großbritannien
- **Standard- und ermäßigte Sätze** werden separat importiert
- **Automatische Tax Rules** werden erstellt und mit den Rates verknüpft
- **Cron-basierte Synchronisierung** (täglich, wöchentlich oder monatlich)
- **E-Mail-Benachrichtigungen** bei Änderungen
- **Admin-Benachrichtigungen** im Magento Backend
- **CLI-Befehle** für manuelle Synchronisierung
- **Fallback-Daten** falls die API nicht erreichbar ist

---

### 📦 Installation

#### Via Composer (empfohlen)

```bash
composer require storetown/module-tax-sync
bin/magento module:enable Storetown_TaxSync
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush
```

#### Manuelle Installation

1. Erstellen Sie den Ordner `app/code/Storetown/TaxSync`
2. Kopieren Sie alle Dateien in diesen Ordner
3. Führen Sie folgende Befehle aus:

```bash
bin/magento module:enable Storetown_TaxSync
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush
```

---

### ⚙️ Konfiguration

Navigieren Sie zu **Stores → Configuration → Storetown → EU Tax Rate Sync**

#### General Settings

| Option | Beschreibung |
|--------|--------------|
| Enable Auto Sync | Aktiviert die automatische Cron-Synchronisierung |
| Sync Frequency | Täglich, Wöchentlich oder Monatlich |
| Data Source | API-Quelle (vat-api.eu empfohlen) |
| Include Non-EU | CH, NO, GB mit einbeziehen |

#### Tax Rules

| Option | Beschreibung |
|--------|--------------|
| Auto-Create Tax Rules | Erstellt automatisch Tax Rules für jeden Steuersatz |
| Customer Tax Classes | Kundengruppen für die Rules |
| Product Tax Classes | Produktklassen für die Rules |

#### Notifications

| Option | Beschreibung |
|--------|--------------|
| Email Notifications | E-Mail bei Änderungen senden |
| Notification Email | Empfänger-Adresse |
| Admin Notification | Benachrichtigung im Admin-Panel |

---

### 🖥️ CLI-Befehle

#### Manuelle Synchronisierung

```bash
bin/magento tax:sync:run
```

Mit ausführlicher Ausgabe:

```bash
bin/magento tax:sync:run -vvv
```

#### Status anzeigen

```bash
bin/magento tax:sync:status
```

---

### 🌍 Unterstützte Länder

#### EU-Mitgliedstaaten (27)

| Land | Code | Standard | Ermäßigt |
|------|------|----------|----------|
| Österreich | AT | 20% | 10% |
| Belgien | BE | 21% | 6% |
| Bulgarien | BG | 20% | 9% |
| Kroatien | HR | 25% | 13% |
| Zypern | CY | 19% | 5% |
| Tschechien | CZ | 21% | 12% |
| Dänemark | DK | 25% | - |
| Estland | EE | 24% | 9% |
| Finnland | FI | 25,5% | 14% |
| Frankreich | FR | 20% | 5,5% |
| Deutschland | DE | 19% | 7% |
| Griechenland | GR | 24% | 13% |
| Ungarn | HU | 27% | 18% |
| Irland | IE | 23% | 13,5% |
| Italien | IT | 22% | 10% |
| Lettland | LV | 21% | 12% |
| Litauen | LT | 21% | 9% |
| Luxemburg | LU | 17% | 8% |
| Malta | MT | 18% | 7% |
| Niederlande | NL | 21% | 9% |
| Polen | PL | 23% | 8% |
| Portugal | PT | 23% | 13% |
| Rumänien | RO | 21% | 11% |
| Slowakei | SK | 23% | 5% |
| Slowenien | SI | 22% | 9,5% |
| Spanien | ES | 21% | 10% |
| Schweden | SE | 25% | 12% |

#### Nicht-EU (optional)

| Land | Code | Standard | Ermäßigt |
|------|------|----------|----------|
| Schweiz | CH | 8,1% | 2,6% |
| Großbritannien | GB | 20% | 5% |
| Norwegen | NO | 25% | 15% |

> **Datenquelle & ermäßigte Sätze:** Standardsätze werden live von [vat-api.eu](https://vat-api.eu/) bezogen (kostenlos, ohne API-Key); bei nicht erreichbarer API greifen die gepflegten Fallback-Daten. Da viele Länder **mehrere** ermäßigte Sätze haben (super-reduziert / ermäßigt / Park), importiert die Extension pro Land **einen** ermäßigten Hauptsatz (Bücher, Medikamente, Grundnahrungsmittel). Diesen können Sie pro Land jederzeit unter **Stores → Tax Zones and Rates** anpassen.

---

### 📋 Anforderungen

- Magento 2.4.x
- PHP 8.1 oder höher
- Cron muss konfiguriert sein (für Auto-Sync)

---

### 🔧 Fehlerbehebung

#### Logs prüfen

```bash
tail -f var/log/tax_sync.log
```

#### Cache leeren

```bash
bin/magento cache:flush
```

#### DI neu kompilieren

```bash
rm -rf generated/code/*
bin/magento setup:di:compile
```

---

### 🐛 Bug Reports & Feature Requests

- **Bug Report:** [Issue eröffnen mit Bug-Report-Template](../../issues/new?template=bug_report.md)
- **Feature Request:** [Issue eröffnen mit Feature-Request-Template](../../issues/new?template=feature_request.md)
- **Frage oder Diskussion:** [GitHub Discussions](../../discussions)
- **Sicherheitsproblem (kritisch):** Bitte **NICHT** als Issue, sondern direkt an **security@storetown-media.de** — siehe [SECURITY.md](SECURITY.md)

Pull Requests sind willkommen! Siehe [CONTRIBUTING.md](CONTRIBUTING.md).

---

_(README truncated for .md surface. Full README on https://packagento.com/storetown-media/module-tax-sync.)_

## Changelog

Alle wichtigen Änderungen an dieser Extension werden in dieser Datei dokumentiert.

Das Format basiert auf [Keep a Changelog](https://keepachangelog.com/de/1.0.0/),
und dieses Projekt folgt [Semantic Versioning](https://semver.org/lang/de/).


### [1.5.0] - 2026-08-23

#### Geändert

- **Composer-Paketname von `storetown/module-tax-sync` auf
  `storetown-media/module-tax-sync` geändert.** Damit tragen alle Storetown-Media-Module
  denselben Vendor-Namespace. Der alte Name ist über `replace` hinterlegt: Composer erkennt
  beide als dasselbe Paket, eine versehentliche Doppelinstallation ist ausgeschlossen.
- Das feste `version`-Feld wurde aus der `composer.json` entfernt; maßgeblich ist der Git-Tag.

#### Unverändert

- PHP-Namespace `Storetown\TaxSync\` und Magento-Modulname `Storetown_TaxSync` bleiben,
  damit bestehende Installationen nicht brechen. Es ändert sich ausschließlich der Name,
  unter dem Composer das Paket bezieht.

#### Umstieg

```bash
composer remove storetown/module-tax-sync
composer require storetown-media/module-tax-sync
```

### [1.4.2] - 2026-06-17

#### Behoben

- **PHP 8.4-Kompatibilität.** Die implizit-nullable Konstruktor-Parameter in `Model/Config/Backend/CronFrequency.php` (`$resource`, `$resourceCollection`) sind jetzt explizit als nullable typisiert (`?AbstractResource` bzw. `?AbstractDb`). Behebt die Meldung *„Deprecated: Implicitly marking parameter as nullable"*, die unter **PHP 8.4** `bin/magento setup:di:compile` (und damit den Produktiv-Deploy) abbrechen ließ.

### [1.4.1] - 2026-06-16

#### Behoben

- **Admin „Letzte Synchronisierung" zeigte ein falsches Datum** (z. B. 17.12.2021) und schien sich nach „Jetzt synchronisieren" nicht zu ändern. Ursache: Der Anzeige-Block reichte den gespeicherten `Y-m-d H:i:s`-UTC-Zeitstempel an `TimezoneInterface::date()` weiter — das parst Strings über das SHORT-Format der Locale und verwürfelt ISO-Datumswerte (falsches Datum, fehlende Sekunden). Der Zeitstempel wurde stets **korrekt gespeichert**, nur die Darstellung war defekt; der Sync (CLI wie Admin-Button) funktionierte. Fix: expliziter Parse als UTC + Umrechnung in die Shop-Zeitzone in `Block/Adminhtml/System/Config/LastSync.php`.

---

### [1.4.0] - 2026-06-16

#### Behoben

- **CRITICAL: Veraltete Datenquelle.** Die bisherige Primärquelle `euvatrates.com` wird seit 2016 nicht mehr gepflegt (`"last_updated":"2016-01-01"`) und liefert falsche Standardsätze (z. B. Rumänien 20 % statt aktuell 21 %). Da der Endpunkt weiterhin mit HTTP 200 und gültigem JSON antwortet, wurde er von der Verfügbarkeitsprüfung fälschlich als „erreichbar" eingestuft — der Fallback griff nie. `EuVatRates` ist jetzt dauerhaft als nicht verfügbar markiert und wird nicht mehr ausgewählt.

#### Hinzugefügt

- **`Model/Api/VatApiEu.php` — neue, gepflegte Primärquelle [vat-api.eu](https://vat-api.eu/)** (kostenlos, ohne API-Key). Liefert aktuelle Standardsätze für alle 27 EU-Mitgliedstaaten und ist neuer Standard (`tax_sync/general/api_source = vatapieu`).
- **`Model/Data/EuVatReducedRates.php`** — kuratierte Map der ermäßigten Sätze (Hauptsatz pro Land) als einzige Quelle der Wahrheit, gemeinsam genutzt von `VatApiEu` und `Fallback` (kein Drift mehr zwischen Live-Quelle und Fallback).
- **`Model/Data/NonEuVatRates.php`** — geteilte statische Sätze für CH/GB/NO. Da vat-api.eu nur die 27 EU-Staaten liefert, ergänzt die Live-Quelle diese Länder, sodass „Nicht-EU-Länder einbeziehen" jetzt auch mit der Live-Quelle funktioniert (zuvor wurden CH/NO über die Live-Quelle nie synchronisiert).
- Strukturprüfung in `VatApiEu`: Antworten mit weniger als 20 verwertbaren Ländern werden abgelehnt (Schutz gegen degradierte, aber HTTP-200-antwortende API).

#### Geändert

_(Changelog truncated for .md surface. Full history on https://packagento.com/storetown-media/module-tax-sync.)_

## Recent Versions

| Version | Released |
|---|---|
| v1.5.1 | 2026-08-23 |
| v1.5.0 | 2026-08-23 |
| 1.4.2 | 2026-06-17 |
| 1.4.1 | 2026-06-16 |
| 1.4.0 | 2026-06-16 |
| 1.3.1 | 2026-06-09 |
| 1.3.0 | 2026-05-14 |

## Dependencies

### Require

| Package | Constraint |
|---|---|
| magento/framework | ^103.0 |
| magento/module-admin-notification | ^100.4 |
| magento/module-backend | ^102.0 |
| magento/module-config | ^101.2 |
| magento/module-cron | ^100.4 |
| magento/module-email | ^101.1 |
| magento/module-store | ^101.1 |
| magento/module-tax | ^100.4 |
| php | ^8.1 |

### Replace

| Package | Constraint |
|---|---|
| storetown/module-tax-sync | self.version |

## Licence and pricing

Free. A licence is still minted on checkout and bound to your project for Composer access — no payment step.

Refundable within 14 days of first purchase via https://packagento.com/account/refunds/.

## Install via Claude Code or any MCP client

The Packagento MCP server can run the licence + project + Composer steps above in one tool call:

```
purchase_and_install_packages(
  composer_names=["storetown-media/module-tax-sync"],
  project_id="proj_xxx"
)
```

This handles cart, checkout, licence minting, project activation, and writes auth.json credentials. Connect a client with `claude mcp add packagento https://mcp.packagento.com`. Full setup at https://packagento.com/docs/mcp-setup.

## Vendor

Storetown Media is a Magento 2 vendor on Packagento. See https://packagento.com/storetown-media.md for their full catalogue.

