All Projects → driesvints → Vat Calculator

driesvints / Vat Calculator

Licence: mit
Handle all the hard stuff related to EU MOSS tax/vat regulations, the way it should be. Integrates with Laravel and Cashier — or in a standalone PHP application.

Labels

Projects that are alternatives of or similar to Vat Calculator

Laravelshoppingcart
Shopping Cart Implementation for Laravel Framework
Stars: ✭ 853 (-2.63%)
Mutual labels:  laravel
Laravel Mention
a laravel user mentioned package
Stars: ✭ 12 (-98.63%)
Mutual labels:  laravel
Mysql Workbench Export Laravel 5 Migrations
A MySQL Workbench plugin which exports a Model to Laravel 5 Migrations
Stars: ✭ 876 (+0%)
Mutual labels:  laravel
Laravel Pay
可能是我用过的最优雅的 Alipay 和 WeChat 的 laravel 支付扩展包了
Stars: ✭ 856 (-2.28%)
Mutual labels:  laravel
Binding Of Isaac Api
A RESTful API for the Binding of Isaac game series
Stars: ✭ 11 (-98.74%)
Mutual labels:  laravel
Improved Polymorphic Eloquent Builder
🔨 Improved Polymorphic Eloquent Builder
Stars: ✭ 12 (-98.63%)
Mutual labels:  laravel
Laravel Mail Preview
A mail driver to quickly preview mail
Stars: ✭ 851 (-2.85%)
Mutual labels:  laravel
Backend
Nodes backend package
Stars: ✭ 13 (-98.52%)
Mutual labels:  laravel
Laravel Blog 5.6.5
Learning Laravel by making simple Blog
Stars: ✭ 12 (-98.63%)
Mutual labels:  laravel
Laravel Image Optimizer
Optimize images in your Laravel app
Stars: ✭ 873 (-0.34%)
Mutual labels:  laravel
Lumen Api Demo
Lumen rest api demo with Dingo/Api, JWT, CORS, PHPUNIT
Stars: ✭ 856 (-2.28%)
Mutual labels:  laravel
Blender
The Laravel template used for our CMS like projects
Stars: ✭ 862 (-1.6%)
Mutual labels:  laravel
Laravel Test Factory Helper
Generate Laravel test factories from your existing models
Stars: ✭ 873 (-0.34%)
Mutual labels:  laravel
Deployer
Deployer is a free and open source deployment tool.
Stars: ✭ 854 (-2.51%)
Mutual labels:  laravel
Laravel Smsgateway Notification Channel
SMS Gateway notification channel for Laravel
Stars: ✭ 13 (-98.52%)
Mutual labels:  laravel
Dockerized lara
Build your Laravel App with Redis - Mongodb - MariaDB - Nginx - php7 - zsh
Stars: ✭ 9 (-98.97%)
Mutual labels:  laravel
Easy Cache
a cache trait for Laravel to do cache eaily
Stars: ✭ 12 (-98.63%)
Mutual labels:  laravel
Vue Model
Model component for Vue.js
Stars: ✭ 877 (+0.11%)
Mutual labels:  laravel
Laravel Doctrine Tenancy
A multi-tenancy implementation for Laravel that uses Doctrine.
Stars: ✭ 13 (-98.52%)
Mutual labels:  laravel
Laravel Mailguneu
Allow customising the Mailgun server URL to use EU servers.
Stars: ✭ 13 (-98.52%)
Mutual labels:  laravel

VatCalculator

Tests Code Style Latest Stable Version Total Downloads

Handle all the hard stuff related to EU MOSS tax/vat regulations, the way it should be. Integrates with Laravel and Cashier — or in a standalone PHP application.

// Easy to use!
$countryCode = VatCalculator::getIPBasedCountry();
VatCalculator::calculate(24.00, $countryCode);
VatCalculator::calculate(24.00, $countryCode, $postalCode);
VatCalculator::calculate(71.00, 'DE', '41352', $isCompany = true);
VatCalculator::getTaxRateForLocation('NL');

// Check validity of a VAT number
VatCalculator::isValidVATNumber('NL123456789B01');

Contents

Requirements

  • PHP 5.5 or higher
  • (optional) Laravel 5.0 or higher

Installation

Install the package with composer:

composer require mpociot/vat-calculator

Standalone

You can also use this package without Laravel. Simply create a new instance of the VatCalculator and use it. All documentation examples use the Laravel Facade code, so make sure not to call the methods as if they were static methods.

use Mpociot\VatCalculator\VatCalculator;

$vatCalculator = new VatCalculator();
$vatCalculator->setBusinessCountryCode('DE');
$countryCode = $vatCalculator->getIPBasedCountry();
$grossPrice = $vatCalculator->calculate( 49.99, 'LU' );

Usage

Calculate the gross price

To calculate the gross price use the calculate method with a net price and a country code as parameters.

$grossPrice = VatCalculator::calculate( 24.00, 'DE' );

The third parameter is the postal code of the customer.

As a fourth parameter, you can pass in a boolean indicating whether the customer is a company or a private person. If the customer is a company, which you should check by validating the VAT number, the net price gets returned.

$grossPrice = VatCalculator::calculate( 24.00, 'DE', '12345', $isCompany = true );

Receive more information

After calculating the gross price you can extract more information from the VatCalculator.

$grossPrice = VatCalculator::calculate( 24.00, 'DE' ); // 28.56
$taxRate    = VatCalculator::getTaxRate(); // 0.19
$netPrice   = VatCalculator::getNetPrice(); // 24.00
$taxValue   = VatCalculator::getTaxValue(); // 4.56

Validate EU VAT numbers

Prior to validating your customers VAT numbers, you can use the shouldCollectVAT method to check if the country code requires you to collect VAT in the first place.

if (VatCalculator::shouldCollectVAT('DE')) {

}

To validate your customers VAT numbers, you can use the isValidVATNumber method. The VAT number should be in a format specified by the VIES. The given VAT numbers will be truncated and non relevant characters / whitespace will automatically be removed.

This service relies on a third party SOAP API provided by the EU. If, for whatever reason, this API is unavailable a VATCheckUnavailableException will be thrown.

try {
    $validVAT = VatCalculator::isValidVATNumber('NL 123456789 B01');
} catch( VATCheckUnavailableException $e ){
    // Please handle me
}

Get EU VAT number details

To get the details of a VAT number, you can use the getVATDetails method. The VAT number should be in a format specified by the VIES. The given VAT numbers will be truncated and non relevant characters / whitespace will automatically be removed.

This service relies on a third party SOAP API provided by the EU. If, for whatever reason, this API is unavailable a VATCheckUnavailableException will be thrown.

try {
    $vat_details = VatCalculator::getVATDetails('NL 123456789 B01');
    print_r($vat_details);
    /* Outputs
    stdClass Object
    (
        [countryCode] => NL
        [vatNumber] => 123456789B01
        [requestDate] => 2017-04-06+02:00
        [valid] => false
        [name] => Name of the company
        [address] => Address of the company
    )
    */
} catch( VATCheckUnavailableException $e ){
    // Please handle me
}

Laravel Validator Extension

If you want to include the VAT number validation directly in your existing Form Requests / Validations, use the vat_number validation rule.

Example:

$rules = array(
    'first_name'  => 'required',
    'last_name'   => 'required',
    'company_vat' => 'vat_number'
);

$validator = Validator::make(Input::all(), $rules);

Important: The validator extension returns false when the VAT ID Check SOAP API is unavailable.

Cashier integration

If you want to use this package in combination with Laravel Cashier you can let your billable model use the BillableWithinTheEU trait. Because this trait overrides the getTaxPercent method of the Billable trait, we have to explicitly tell our model to do so.

use Laravel\Cashier\Billable;
use Mpociot\VatCalculator\Traits\BillableWithinTheEU;
use Laravel\Cashier\Contracts\Billable as BillableContract;

class User extends Model implements BillableContract
{
    use Billable, BillableWithinTheEU {
        BillableWithinTheEU::taxPercentage insteadof Billable;
    }

    protected $dates = ['trial_ends_at', 'subscription_ends_at'];
}

By using the BillableWithinTheEU trait, your billable model has new methods to set the tax rate for the billable model.

Set everything in one command:

  • setTaxForCountry($countryCode, $company = false)

Or use the more readable, chainable approach:

  • useTaxFrom($countryCode) — Use the given countries tax rate
  • asIndividual() — The billable model is not a company (default)
  • asBusiness() — The billable model is a valid company

So in order to set the correct tax percentage prior to subscribing your customer, consider the following workflow:

$user = User::find(1);

// For individuals use:
$user->useTaxFrom('NL');

// For business customers with a valid VAT ID, use:
$user->useTaxFrom('NL')->asBusiness();

$user->subscription('monthly')->create($creditCardToken);

Get the IP based Country of your user

Right now you'll need to show your users a way to select their country - probably a drop down - to use this country for the VAT calculation.

This package has a small helper function, that tries to lookup the Country of the user, based on the IP they have.

$countryCode = VatCalculator::getIPBasedCountry();

The $countryCode will either be false, if the service is unavailable, or the country couldn't be looked up. Otherwise the variable contains the two-letter country code, which can be used to prefill the user selection.

Frontend Integration

vat_calculator.js

Phew - so you know how to use this class, built your fancy payment form and now...? Well - you want to display the correct prices to your users and want it to update dynamically. So go ahead, add some routes, write some Javascript and in no time you'll be up and running, right?

Or you use the built in routes and vat_calculator.js library.

The VatCalculator JS library will automatically:

  • Calculate taxes whenever the selected country value changes
  • Automatically validate VAT-IDs / VAT numbers and use it for the calculation
  • Prefill the user's country with the IP based country

The Javascript library has no dependencies on third party frameworks.

In order to use the Javascript helper you need to publish the package files first. Go ahead and type:

php artisan vendor:publish --provider="Mpociot\VatCalculator\VatCalculatorServiceProvider"

Now you have a file called vat_calculator.js in your public/js folder.

Integrating it in your payment form

Add the published javascript file to your payment form.

<head>
    ...
    <script type="text/javascript" src="/js/vat_calculator.js"></script>
</head>

By default, the VatCalculator JS script is looking for a form with the ID payment-form. This form needs a data-amount attribute specifying the amount to use for the tax calculation in cents (just like Stripe uses it).

So your form should look like this, when you would calculate the taxes for 24.99 €

<form method="post" id="payment-form" data-amount="2499">

Next up, you need a dropdown to let your users select their billing country. This select field needs the data-vat="country" attribute, so that the VatCalculator JS knows, where to look for country codes.

Since there are also quite a few VAT rate exceptions for specific regions or cities, it is highly recommended to add an input field to collect postal codes. This field needs a data-vat="postal-code" attribute.

And last but not least, to automatically validate VAT Numbers / VAT IDs you can have an input field with the data-vat="vat_number" attribute specified.

So your form will look like this:

<form method="POST" id="payment-form" data-amount="2499">
    <div class="form-row">
        <label>
            <span>Country</span>
            <select data-vat="country">
                <option value="US">United States</option>
                <option value="GB">United Kingdom</option>
                <option value="DE">Germany</option>
                <option value="FR">France</option>
                <option value="IT">Italy</option>
                <option value="ES">Spain</option>
                <option value="CA">Canada</option>
                <option value="AU">Australia</option>
            </select>
        </label>
    </div>
    
    <div class="form-row">
        <label>
            <span>Postal Code</span>
            <input data-vat="postal-code"/>
        </label>
    </div>
    
    <div class="form-row">
        <label>
            <span>VAT Number</span>
            <input data-vat="vat-number"/>
        </label>
    </div>
</form>

Extra fields

To display the live tax calculation, you can use the classes vat-subtotal, vat-taxrate, vat-taxes and vat-total on any DOM element and VatCalculator JS will automatically set the inner HTML content for you.

Example:

<strong>Subtotal</strong>: € <span class="vat-subtotal"></span>
<strong>Tax rate</strong>: <span class="vat-taxrate"></span>%
<strong>Taxes</strong>: € <span class="vat-taxes"></span>
<strong>Total</strong>: € <span class="vat-total"></span>

Form attributes

Attribute Description Required
data-amount Use this attribute on the form you want to use for live calculation. It's the price in cent used for the calculation. Yes

Form fields

In order to calculate the right taxes, you need to add some extra inputs to your payment form. All these fields need to have a data-vat attribute. You need to include at least the country.

Attribute Description Required
country Customer’s country (2-letter ISO code). Yes
postal-code Customer's postal code No Highly recommended
vat-number Billing VAT number No

Advanced usage

Use a different form selector

Use VATCalculator.init('#my-selector') to initialize the live calculation on a different form.

Use a custom formatter function to modify calculation result HTML

Use VATCalculator.setCurrencyFormatter to use a different method to format the calculated values for the HTML output. This function will receive the calculation result as a parameter.

Example:

VATCalculator.setCurrencyFormatter(function(value){
    return value.toFixed(2) + ' €';
});

Trigger calculation manually

Call VATCalculator.calculate() to trigger the calculation manually. For example when you change the data-amount attribute on your form.

Preconfigured routes

In order for VatCalculator JS to work properly, these routes will be added to your application. If you don't want to use the Javascript library, you can of course disable the routes in the configuration file.

Method Route Usage
GET vatcalculator/tax-rate-for-location/{country}/{postal-code} Returns the VAT / tax rate for the given country (2-letter ISO code).
GET vatcalculator/country-code Returns the 2-letter ISO code based from the IP address.
GET vatcalculator/validate-vat-id/{vat_id} Validates the given VAT ID
GET vatcalculator/calculate Calculates the gross price based on the parameters: netPrice, country and vat_number

Configuration

By default, the VatCalculator has all EU VAT rules predefined, so that it can easily be updated, if it changes for a specific country.

If you need to define other VAT rates, you can do so by publishing the configuration and add more rules.

The configuration file also determines whether you want to use the VatCalculator JS routes or not.

Important: Be sure to set your business country code in the configuration file, to get correct VAT calculation when selling to business customers in your own country.

To publish the configuration files, run the vendor:publish command

php artisan vendor:publish --provider="Mpociot\VatCalculator\VatCalculatorServiceProvider"

This will create a vat_calculator.php in your config directory.

Changelog

Check out the CHANGELOG in this repository for all the recent changes.

Maintainers

VatCalculator is maintained by Dries Vints. Originally created by Marcel Pociot.

License

VatCalculator is open-sourced software licensed under the MIT license.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].