gewebe / sylius-vat-plugin
VAT number address field with validation, EU VAT rates plugin for Sylius
Installs: 16 949
Dependents: 0
Suggesters: 0
Security: 0
Stars: 5
Watchers: 2
Forks: 1
Open Issues: 1
Type:sylius-plugin
Requires
- php: ^8.0
- ibericode/vat: ^2.0
- sylius/mailer-bundle: ^1.8 || ^2.0@beta
- sylius/sylius: ^1.12
- symfony/webpack-encore-bundle: ^1.15
Requires (Dev)
- behat/behat: ^3.6.1
- behat/mink-selenium2-driver: ^1.4
- dmore/behat-chrome-extension: ^1.3
- dmore/chrome-mink-driver: ^2.7
- friends-of-behat/mink: ^1.8
- friends-of-behat/mink-browserkit-driver: ^1.4
- friends-of-behat/mink-debug-extension: ^2.0.0
- friends-of-behat/mink-extension: ^2.4
- friends-of-behat/page-object-extension: ^0.3
- friends-of-behat/suite-settings-extension: ^1.0
- friends-of-behat/symfony-extension: ^2.1
- friends-of-behat/variadic-extension: ^1.3
- phpspec/phpspec: ^7.2
- phpstan/extension-installer: ^1.0
- phpstan/phpstan: ^1.8.1
- phpstan/phpstan-doctrine: 1.3.40
- phpstan/phpstan-strict-rules: ^1.3.0
- phpstan/phpstan-webmozart-assert: ^1.2.0
- phpunit/phpunit: ^9.5
- polishsymfonycommunity/symfony-mocker-container: ^1.0
- sylius-labs/coding-standard: ^4.2
- symfony/browser-kit: ^5.4 || ^6.0
- symfony/debug-bundle: ^5.4 || ^6.0
- symfony/dotenv: ^5.4 || ^6.0
- symfony/flex: ^2.2.2
- symfony/intl: ^5.4 || ^6.0
- symfony/web-profiler-bundle: ^5.4 || ^6.0
- vimeo/psalm: 5.12.0
Conflicts
- behat/mink-selenium2-driver: >=1.7.0
- symfony/framework-bundle: 6.2.8
README
Features
- Installer for EU VAT rates with countries and zones
- New fields for VAT number at
Address
andShopBillingData
entity - Configure VAT number field requirement:
- Optional / Required
- Required if customer filled “Company” field
- Required in selected countries
- Validate VAT number:
- Format for selected country
- Country is same as selected country
- Validity using VIES API for EU VAT number
- Revalidate customers VAT numbers after a given time
- Placing an order without VAT in the EU, if
- VAT number validation was successful
- Customers taxation country is different from shop billing country
Installation
Download the plugin via composer
composer require gewebe/sylius-vat-plugin
Enable the plugin in bundles.php
# config/bundles.php return [ # ... Gewebe\SyliusVATPlugin\GewebeSyliusVATPlugin::class => ['all' => true], ];
Import the plugin configurations
# config/packages/_sylius.yaml imports: # ... - { resource: '@GewebeSyliusVATPlugin/config/app/config.yml'}
Configure taxation address
For EU VAT, the address for taxation should be set to the shipping address in the Sylius configuration.
# config/packages/_sylius.yaml sylius_core: shipping_address_based_taxation: true
Copy templates
Copy customized templates to your templates directory (e.g templates/bundles/
):
mkdir -p templates/bundles/SyliusAdminBundle/ cp -R vendor/gewebe/sylius-vat-plugin/templates/SyliusAdminBundle/* templates/bundles/SyliusAdminBundle/ mkdir -p templates/bundles/SyliusShopBundle/ cp -R vendor/gewebe/sylius-vat-plugin/templates/SyliusShopBundle/* templates/bundles/SyliusShopBundle/
Extend Address
entity
# src/Entity/Addressing/Address.php namespace App\Entity\Addressing; use Doctrine\ORM\Mapping as ORM; use Gewebe\SyliusVATPlugin\Entity\VatNumberAddressInterface; use Gewebe\SyliusVATPlugin\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 VatNumberAddressInterface { use VatNumberAwareTrait;
If you use yaml
mapping add also:
# config/doctrine/Address.orm.yaml App\Entity\Addressing\Address: type: entity table: sylius_address fields: vatNumber: type: string column: vat_number nullable: true vatValid: type: boolean column: vat_valid vatValidatedAt: type: datetime column: vat_validated_at nullable: true
Add or Extend ShopBillingData
entity
# src/Entity/Channel/ShopBillingData.php namespace App\Entity\Channel; use Doctrine\ORM\Mapping as ORM; use Gewebe\SyliusVATPlugin\Entity\ShopBillingDataVatNumberAwareTrait; use Gewebe\SyliusVATPlugin\Entity\ShopBillingDataVatNumberInterface; use Sylius\Component\Core\Model\ShopBillingData as BaseShopBillingData; /** * @ORM\Entity * @ORM\Table(name="sylius_shop_billing_data") */ #[ORM\Entity] #[ORM\Table(name: 'sylius_shop_billing_data')] class ShopBillingData extends BaseShopBillingData implements ShopBillingDataVatNumberInterface { use ShopBillingDataVatNumberAwareTrait;
If you use yaml
mapping add also:
# config/doctrine/ShopBillingData.orm.yaml App\Entity\Channel\ShopBillingData: type: entity table: sylius_shop_billing_data fields: vatNumber: type: string column: vat_number nullable: true
Override the resource for shop_billing_data
in your sylius config:
# config/packages/_sylius.yaml sylius_core: resources: shop_billing_data: classes: model: App\Entity\Channel\ShopBillingData
Update your database schema
bin/console doctrine:migrations:diff bin/console doctrine:migrations:migrate
Usage
Install EU countries and VAT rates
# EU VAT on digital services (MOSS scheme) bin/console vat:install:eu # EU with French VAT (cross-border) bin/console vat:install:eu FR # EU with French VAT and passed threshold in Spain and Portugal (cross-border) bin/console vat:install:eu FR -t ES,PT # EU with French VAT included in price bin/console vat:install:eu FR -i # EU with German standard and reduced VAT categories bin/console vat:install:eu DE -c standard,reduced
Validate customers VAT number
1. Create new order with VAT number at shipping address
2. Show VAT number and validation status at admin orders
Testing
Setup Traditional
$ composer install $ cd tests/Application $ yarn install $ yarn build $ bin/console assets:install public -e test $ bin/console doctrine:schema:create -e test $ export APP_ENV=test $ symfony server:start --port=8080 --dir=public
Setup Docker
$ docker compose up -d
$ docker compose exec app make init
Run Tests
$ vendor/bin/behat $ vendor/bin/phpspec run $ vendor/bin/phpstan analyse -c phpstan.neon -l max src/ $ vendor/bin/psalm
Coding Standard
$ vendor/bin/ecs check