flux-se / sylius-eu-vat-plugin
Add EU VAT field and validation for Sylius using VIES API Webservice.
Installs: 14 364
Dependents: 0
Suggesters: 0
Security: 0
Stars: 16
Watchers: 4
Forks: 8
Open Issues: 1
Type:sylius-plugin
Requires
- php: ^8.1
- prometee/vies-client-bundle: ^2.0
- sylius/core-bundle: ^1.12
Requires (Dev)
- ext-json: *
- behat/behat: ^3.7
- behat/mink: ^1.9
- dbrekelmans/bdi: ^1.0
- friends-of-behat/mink: ^1.9
- friends-of-behat/mink-browserkit-driver: ^1.4
- friends-of-behat/mink-debug-extension: ^2.0
- friends-of-behat/mink-extension: ^2.4
- friends-of-behat/page-object-extension: ^0.3
- friends-of-behat/symfony-extension: ^2.1
- friends-of-behat/variadic-extension: ^1.3
- matthiasnoback/symfony-config-test: ^5.1
- phpspec/phpspec: ^7.0
- phpstan/extension-installer: ^1.2
- phpstan/phpstan-doctrine: ^1
- phpstan/phpstan-strict-rules: ^1
- phpstan/phpstan-webmozart-assert: ^1
- phpunit/phpunit: ^10.5
- polishsymfonycommunity/symfony-mocker-container: ^1.0
- rector/rector: ^1.0
- robertfausk/behat-panther-extension: ^1.1
- sylius-labs/coding-standard: ^4.0
- sylius/sylius: ^1.12
- symfony/browser-kit: ^5.4|^6.4
- symfony/debug-bundle: ^5.4|^6.4
- symfony/dotenv: ^5.4|^6.4
- symfony/intl: ^5.4|^6.4
- symfony/runtime: ^5.4|^6.4
- symfony/web-profiler-bundle: ^5.4|^6.4
- symfony/webpack-encore-bundle: ^1.16
- vimeo/psalm: ^4|^5
Suggests
- sylius/admin-bundle: Use the Sylius default admin
- sylius/api-bundle: Use the Sylius default API
- sylius/shop-bundle: Use the Sylius default front shop
README
EU VAT field and validation for Sylius using VIES API Webservice
This plugin is adding :
- two new attributes to the
Channel
entity allowing to know from which country your shop is from and what's the European zone to target - VAT Number field to the
Address
entity - validation over VIES API on this field
- validation of the address country (vat number country should equal to the address country)
- the basic European rule allowing the seller not to charge
VAT to foreign European customers who have provided a valid VAT number :
- (Shop country === customer country vat number) then do nothing
- (Shop country !== customer country vat number) then remove taxes
Screenshots
Shop checkout
Shop account
Installation
composer require flux-se/sylius-eu-vat-plugin
Configuration
Enable this plugin :
<?php # config/bundles.php return [ // ... FluxSE\SyliusEUVatPlugin\FluxSESyliusEUVatPlugin::class => ['all' => true], // ... ];
Add default config if you want to get access to the default fixtures this plugin need.
# config/packages/flux_se_sylius_eu_vat.yaml imports: - { resource: "@FluxSESyliusEUVatPlugin/config/config.yaml" } # If you are using SyliusAdminBundle - { resource: "@FluxSESyliusEUVatPlugin/config/admin.yaml" }
Copy Sylius overridden templates to your templates directory (e.g templates/bundles/
):
# If you are using SyliusAdminBundle mkdir -p templates/bundles/SyliusAdminBundle/ cp -R vendor/flux-se/sylius-eu-vat-plugin/templates/SyliusAdminBundle/* templates/bundles/SyliusAdminBundle/ # If you are using SyliusShopBundle mkdir -p templates/bundles/SyliusShopBundle/ cp -R vendor/flux-se/sylius-eu-vat-plugin/templates/SyliusShopBundle/* templates/bundles/SyliusShopBundle/
Update Channel
entity : src/Entity/Channel/Channel.php
<?php declare(strict_types=1); namespace App\Entity\Channel; use Doctrine\ORM\Mapping as ORM; use FluxSE\SyliusEUVatPlugin\Entity\EuropeanChannelAwareTrait; use Sylius\Component\Core\Model\Channel as BaseChannel; /** * @ORM\Entity() * @ORM\Table(name="sylius_channel") */ #[ORM\Entity] #[ORM\Table(name: 'sylius_channel')] class Channel extends BaseChannel implements ChannelInterface { use EuropeanChannelAwareTrait; }
And the corresponding interface : src/Entity/Channel/ChannelInterface.php
<?php declare(strict_types=1); namespace App\Entity\Channel; use FluxSE\SyliusEUVatPlugin\Entity\EuropeanChannelAwareInterface; use Sylius\Component\Core\Model\ChannelInterface as BaseChannelInterface; interface ChannelInterface extends BaseChannelInterface, EuropeanChannelAwareInterface { }
Click me : if you are using YAML ORM definitions
# config/doctrine/Address.orm.yml App\Entity\Adressing\Address : type: entity table: sylius_address fields: vatNumber: name: vat_number type: string nullable: true
Then change the default Sylius model class :
# config/packages/sylius_channel.yaml sylius_channel: resources: channel: classes: model: App\Entity\Channel\Channel
Update Address
entity : src/Entity/Addressing/Address.php
<?php declare(strict_types=1); namespace App\Entity\Addressing; use Doctrine\ORM\Mapping as ORM; use FluxSE\SyliusEUVatPlugin\Entity\VATNumberAwareTrait; use Sylius\Component\Core\Model\Address as BaseAddress; /** * @ORM\Entity() * @ORM\Table(name="sylius_address") */ #[ORM\Entity] #[ORM\Table(name: 'sylius_address')] class Address extends BaseAddress implements AddressInterface { use VATNumberAwareTrait; }
And the corresponding interface : src/Entity/Addressing/AddressInterface.php
<?php declare(strict_types=1); namespace App\Entity\Addressing; use FluxSE\SyliusEUVatPlugin\Entity\VATNumberAwareInterface; use Sylius\Component\Core\Model\AddressInterface as BaseAddressInterface; interface AddressInterface extends BaseAddressInterface, VATNumberAwareInterface { }
Click me : if you are using YAML ORM definitions
# config/doctrine/Channel.orm.yml App\Entity\Channel\Channel: type: entity table: sylius_channel manyToOne: baseCountry: targetEntity: Sylius\Component\Addressing\Model\CountryInterface fetch: EAGER joinColumn: name: base_country_id onDelete: "SET NULL" europeanZone: targetEntity: Sylius\Component\Addressing\Model\ZoneInterface fetch: EAGER joinColumn: name: european_zone_id onDelete: "SET NULL"
Then change the default Sylius model class :
# config/packages/sylius_addressing.yaml sylius_addressing: resources: address: classes: model: App\Entity\Addressing\Address
Update your database :
# This bundle use doctrine migrations ^3 (see `src/Migrations` folder for more details)
php ./bin/console doctrine:migrations:migrate
Load some required fixtures :
./bin/console sylius:fixture:load european_vat_zones
Go to your admin panel and edit your Channel
to set the two fields to indicate to this plugin :
- What is your base country to compare to your customer country.
- What is the European zone to know if the customer is part of the Europe or not.
Fixtures
You can add some fixtures to auto-configure your channel, for example add this into a yaml file :
# config/packages/my_fixtures.yaml sylius_fixtures: suites: french_european_channel: listeners: logger: ~ fixtures: address_with_vat_number: options: custom: my_customer: first_name: "John" last_name: "Doe" phone_number: "+33912345678" company: "My Company Inc." street: "1234 Street Avenue" city: "London" postcode: "1234" country_code: "GB" customer: "john.doe@mycompany.com" vat_number: ~ # could also be "GB123456789" eu_vat_plugin_european_channel: options: custom: default: channel: "default_channel_code" # Put an existing Channel code base_country: "FR" # Existing Country code european_zone: "EU" # Existing Zone code