concretecms-community-store / community_store

An open, free and community developed eCommerce system for Concrete CMS
https://concretecms-community-store.github.io/community_store/
MIT License
106 stars 66 forks source link

Feature: VAT number validation #108

Open katalysis opened 7 years ago

katalysis commented 7 years ago

Business to business sales in within the EU are not subject to VAT sales tax where a valid VAT number is provided.

http://europa.eu/youreurope/business/vat-customs/cross-border/index_en.htm

I would like to add the capability to validate a VAT number and only charge VAT where the number is not present or validated.

Validation could be achieved using this library: https://www.npmjs.com/package/validate-vat

I would see this being rendered as a further option under ‘When to Charge Tax’ in the Add a Tax Rate form:

If the customer’s VAT number is missing or invalid [x]

The display of this option could be triggered by the creation of a VAT Number store order attribute.

This could probably be achieved as an add on package but I imagine it would need to override a few core files to work.

Would it be acceptable to add this feature to the Community Store core?

Remo commented 7 years ago

I'd support this, done this in the past too.

It's super old and I'm not suggesting to use it over the JS library, just as a reference..

<?php

defined('C5_EXECUTE') or die('Access Denied.');

define('VAT_VALIDATION_WSDL_URL', 'http://ec.europa.eu/taxation_customs/vies/services/checkVatService?wsdl');

$client = new SoapClient(VAT_VALIDATION_WSDL_URL);
$th = Loader::helper('text');
$uid = $th->sanitize($_REQUEST['uid']);

unset($_SESSION['shop-vat-uid']);

if ($uid != '') {
    $countrycode = substr($uid, 0, 2);
    $vatNumber = substr($uid, 2);
    if ($client) {
        $params = array(
            'countryCode' => $countrycode,
            'vatNumber' => $vatNumber,
            'requesterCountryCode' => '',
            'requesterVatNumber' => ''
        );
        try {
            $result = $client->checkVatApprox($params);
            if ($result->valid) {
                $_SESSION['shop-vat-uid'] = $uid;
                echo 1;
            } else {
                echo 0;
            }
        } catch (SoapFault $e) {
            echo 0;
        }
    } else {
        echo 0;
    }
} else {
    echo 1;
}
Jozzeh commented 7 years ago

I'd really like to see this as well. The European VAT rules can be quite a mess to implement...

For example:

The initial implementation can be fairly simple but the questions above are a small portion of other questions that can rise to make something that works for every store.

krebbi commented 7 years ago

making online-business in germany and selling throughout the world VAT is a pain is the a**.. we have local laws which are only partially useable as EU-law overrides them. there are cases where you have to pay the taxes based on the buyers location in his country. while b2b is always handled with reverse-charge. e.g. i sell digital downloads like a theme or ebook from my german online shop to an Italian customer I have to charge the Italian VAT and pay it to the Italian tax office. but this customer also buys a nice printed calendar as well I have to add german VAT.

Without a international tax consultant, this problem can not be solved.

Mesuva commented 7 years ago

I'd certainly welcome anything that helps set up stores to be more flexible for tax purposes.

What I can't really help with is experience or advice, I've really only got my Australian experience to go on, and we've got it pretty simple - one tax and it's 10%, applied to Australian sales only.

katalysis commented 7 years ago

Thanks to all for the comments above. I now have a go ahead on this project and need to build something.

It feels to me that this should probably be its own 'EU Business2Business VAT' package to avoid exposing users who don't need it to the added complexity.

Jozzeh commented 7 years ago

I have been looking into this feature. Here is a small inventory of Community-Store "Core" files which would require overriding:

Even though a package would be excellent to avoid users to the added complexity, I'm worried that every file which references CartTotal.php and Order.php should be overriden as well. This would lead to a huge amount of files being overridden.

My first thought is also to create a seperate package, however after looking at the code changes required, I would rather choose for a 'core change'. If there is a better way in which we could use a seperate package, I would be happy to hear it and work towards creating a package instead of a 'core change'.

Anyway, let's say we change the community_store and do not work with a seperate package. Below is how I would go to work. I'm eagered to hear other opinions.

To avoid exposing users to the EU VAT complexity, we might extend the general settings in the tax-tab and add a checkbox 'This store uses EU VAT rules'. If that checkbox is checked, then the magic happens.

The other EU VAT settings could be a subpage below taxes (top button next to "Add Tax Rate"). EU VAT settings could be:

By creating a EU vat type (such as shippingmethodtypes), other developers could create a new EU vat types, specific for their country/region if the 'normal' EU-VAT rules do not apply and share it with others.

vvinci00 commented 1 year ago

Hello,

just a tip or maybe I'm wrong in configuring somethings... the "EU VAT" should be applied only when the product/service are bought or should be shipped in EU and outside the source Country. example:

  1. User buy an item from Italy and the store is in Italy -> VAT should be applied
  2. User buy an item from Germany and the store is in Italy -> VAT should not be applied
  3. User buy an item from Italy but shipped in Germany and the store is in Italy -> VAT should not be applied
  4. User buy an item from Germany but shipped in Italy and the store is in Italy -> VAT should be applied

I don't have understood if I have to configure somethings to do so, but it seems to be a "simply" check on destination: if destination is different from source and VAT ID is a valid EU VAT so VAT should not be applied. in all other case, VAT must be applied.