Skip to content

Commit

Permalink
Merge branch 'jonathanmaron-gb-nir'
Browse files Browse the repository at this point in the history
A huge thanks to @jonathanmaron for providing a solution for Northern Ireland to validate their VAT ID's after Brexit.
  • Loading branch information
DragonBe committed Jan 5, 2021
2 parents 439dfd1 + bd77864 commit fa87787
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 2 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ vendor/
build/
composer.lock
.scannerwork/
.idea/

1 change: 0 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
"description": "EU VAT numbers validation using the VIES Service of the European Commission",
"keywords": ["VIES","VAT","EU","EC"],
"homepage": "https://github.com/DragonBe/vies",
"minimum-stability": "stable",
"license": "MIT",
"authors": [
{
Expand Down
111 changes: 111 additions & 0 deletions src/Vies/Validator/ValidatorXI.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?php

declare (strict_types=1);

/**
* \DragonBe\Vies
*
* @author Paweł Krzaczkowski <[email protected]>
* @license MIT
*/

namespace DragonBe\Vies\Validator;

/**
* This validator was derived from the "ValidatorGB" validator to validate the "XI" VAT numbers of
* "United Kingdom (Northern Ireland)" following the end of the Brexit transition period on December, 31 2020.
*
* It is based on the information at:
* https://www.avalara.com/vatlive/en/vat-news/brexit-northern-ireland-vat-and-eoro--xi--number.html
*
* As more information is published, this validator may be made more precise:
*
* - Remove the logic to validate Isle of Man numbers?
* - Remove the logic to validate 'GD' and 'HA' prefixes?
*
*/

/**
* Class ValidatorXI
* @package DragonBe\Vies\Validator
*
* VAT format: [C1 C2 C3 C4 C5]
* [C1 C2 C3 C4 C5 C6 C7 C8 C9]
* [C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 C11 C12]
*
* Range:
* C1 .. C2 Alphanumeric from A to Z or 0 to 9
* C2 .. C11 Numeric from 0 to 9
*
* Rules:
* Case 1:
* [C1 C2] Alpha: “GD” or “HA”
* C3 ... C5 Numeric from 0 to 9
*
* if [C1 C2] = “GD”
* [C3 C4 C5] from 000 to 499
*
* If [C1 C2] = “HA”
* [C3 C4 C5] from 500 to 999
*
* Case 2
* [C1 C2 C3] from 000 to 009 are numbers for Isle of Man
* [C10 C11 C12] > 000
* [C1 C2 C3 C4 C5 C6 C7 C8 C9] >000000000
*
* [C8 C9]
* R1 = (8*C1 + 7*C2 + 6*C3 + 5*C4 + 4*C5 + 3*C6 + 2*C7 + C8C9) modulo 97
* R2 = ((8*C1 + 7*C2 + 6*C3 + 5*C4 + 4*C5 + 3*C6 + 2*C7 + C8C9) + 55) modulo 97
* Either R1 or R2 must equal to zero.
*
*/
class ValidatorXI extends ValidatorAbstract
{
/**
* {@inheritdoc}
*/
public function validate(string $vatNumber): bool
{
if (strlen($vatNumber) == 5) {
return $this->validateGovernment($vatNumber);
}

if (strlen($vatNumber) != 9 && strlen($vatNumber) != 12) {
return false;
}

$weights = [8, 7, 6, 5, 4, 3, 2];
$checkVal = $this->sumWeights($weights, $vatNumber);
$checkVal += (int)substr($vatNumber, 7, 2);

$Result1 = $checkVal % 97;
$Result2 = ($Result1 + 55) % 97;

return ! ($Result1 * $Result2);
}

/**
* Validate Government VAT
*
* @param string $vatNumber
*
* @return bool
*/
private function validateGovernment(string $vatNumber): bool
{
$prefix = strtoupper(substr($vatNumber, 0, 2));
$number = (int) substr($vatNumber, 2, 3);

// Government departments
if ($prefix == 'GD') {
return $number < 500;
}

// Health authorities
if ($prefix == 'HA') {
return $number > 499;
}

return false;
}
}
3 changes: 2 additions & 1 deletion src/Vies/Vies.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class Vies
const VIES_PORT = 80;
const VIES_WSDL = '/taxation_customs/vies/checkVatService.wsdl';
const VIES_TEST_WSDL = '/taxation_customs/vies/checkVatTestService.wsdl';
const VIES_EU_COUNTRY_TOTAL = 28;
const VIES_EU_COUNTRY_TOTAL = 29;
const VIES_TEST_VAT_NRS = [100, 200, 201, 202, 300, 301, 302, 400, 401, 500, 501, 600, 601];

protected const VIES_EU_COUNTRY_LIST = [
Expand Down Expand Up @@ -83,6 +83,7 @@ class Vies
'SI' => ['name' => 'Slovenia', 'validator' => Validator\ValidatorSI::class],
'SK' => ['name' => 'Slovakia', 'validator' => Validator\ValidatorSK::class],
'GB' => ['name' => 'United Kingdom', 'validator' => Validator\ValidatorGB::class],
'XI' => ['name' => 'United Kingdom (Northern Ireland)', 'validator' => Validator\ValidatorXI::class],
'EU' => ['name' => 'MOSS Number', 'validator' => Validator\ValidatorEU::class],
];

Expand Down
31 changes: 31 additions & 0 deletions tests/Vies/Validator/ValidatorXITest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare (strict_types=1);

namespace DragonBe\Test\Vies\Validator;

class ValidatorXITest extends AbstractValidatorTest
{
/**
* @covers \DragonBe\Vies\Validator\ValidatorXI
* @dataProvider vatNumberProvider
*/
public function testValidator(string $vatNumber, bool $state)
{
$this->validateVatNumber('XI', $vatNumber, $state);
}

public function vatNumberProvider()
{
return [
['925901618', true],
['GD001', true],
['HA500', true],
['434031493', false],
['12345', false],
['GD500', false],
['HA100', false],
['12345678', false],
];
}
}

0 comments on commit fa87787

Please sign in to comment.