Invalid VAT number for individuals, what can I do?

  • Posts: 79
  • Thank you received: 3
9 years 8 months ago #192813

-- HikaShop version -- : Business: 2.3.5
-- Joomla version -- : 3.2.3
-- PHP version -- : 5.3.3

Hello, I have select "online Vat number check" in Configuration->Taxes->VAT number check, and when I edit a "Company" Address with a Valid Company vat number works correctly, but when I edit a "Individual" address with a valid document number, I obtain an "Invalid VAT number" error.

I need this information for booth, individuals and Companies

Should I configure VAT number field in a special manner?

Regards

Please Log in or Create an account to join the conversation.

  • Posts: 82906
  • Thank you received: 13378
  • MODERATOR
9 years 8 months ago #192857

Hi,

The VAT number field is only to be used for VAT numbers, not any other number.
If you need to collect a document number for individuals, them you should create a new custom field of the table "address" via the menu Display>Custom fields so that individuals could use that field instead of the VAT number field.

Please Log in or Create an account to join the conversation.

  • Posts: 79
  • Thank you received: 3
9 years 8 months ago #192900

Ok, then, can I use vat number format check function with a custom field for individuals?

If answer is yes, where is it located? and how I can use it?

Or maybe:
Can I do this field required only for a group of users? because if I can do that, my problem wil be solved. Because I can change my users policy in order to assign a user type at the registration phase.

Regards

Last edit: 9 years 8 months ago by pljuarez.

Please Log in or Create an account to join the conversation.

  • Posts: 13201
  • Thank you received: 2322
9 years 8 months ago #192915

Hi,

To check the VAT format on another custom field, you can create a plugin based on the function "onBeforeAddressCreate()" and "onBeforeAddressUpdate()". Then use the same functions as in the VAT helper in order to do the checks.

Something like:

	function onBeforeAddressCreate($addressData, $do){
		if(!$this->isValid($addressData)){
			$do = false;
			return false;
		}
		return true;
	}

	function onBeforeAddressUpdate($addressData, $do){
		if(!$this->isValid($addressData)){
			$do = false;
			return false;
		}
		return true;
	}

	function isValid(&$vat){

		$class = hikashop_get('class.zone');
		$zone = $class->get(@$vat->address_country);
		if(empty($zone->zone_code_2) || !in_array($zone->zone_code_2,array('AT','BE','BG','CY','CZ','DK','EE','EL','DE','PT','GR','ES','FI','HR','HU','LU','MT','SI',
		'FR','GB','IE','IT','LV','LT','NL','PL','SK','RO','SE'))){
			//skip check for countries outside europe
			return true;
		}

		//skip VAT number check for las palmas as las palmas is not in the european VAT zone
		if($zone->zone_code_2=='ES' && !empty($vat->address_state)){
			$statezone = $class->get(@$vat->address_state);
			if($statezone->zone_code_3=='GC'){
				return true;
			}
		}

		static $vat_check = null;
		if(!isset($vat_check)){
			$config = hikashop_config();
			$vat_check = (int)$config->get('vat_check',2);
		}
		//Country code GR is in fact VAT EL!
		if($zone->zone_code_2 == 'GR') $zone->zone_code_2 = 'EL';

		switch($vat_check){
			case 1:
			case 2:

				if(is_object($vat)){
					$vat_number =& $vat->address_vat;
				}else{
					$vat_number =& $vat;
				}
				$regex = $this->getRegex($vat_number);

				if($regex===false){
					if(is_object($vat) && !empty($vat->address_country)){
						//try to get the VAT country prefix from the country in the address
						if(!empty($zone->zone_code_2)){
							$vat_number = $zone->zone_code_2.$vat_number;
							$regex = $this->getRegex($vat_number);
						}
					}
					if($regex===false){
						$app = JFactory::getApplication();
						$this->message = JText::_('VAT_NOT_FOR_YOUR_COUNTRY');
						if(@$_REQUEST['tmpl']=='component'){
							hikashop_display($this->message,'error');
						}else{
							$app->enqueueMessage($this->message);
						}
						return false;
					}
				}

				if(!$this->regexCheck($vat_number,$regex)){
					return false;
				}
				$vat_number = strtoupper(str_replace(array(' ','.','-'),array('','',''),$vat_number));
				$code = substr($vat_number,0, 2);
				if($code == 'GR'){
					$code = 'EL';
					$vat_number = $code.substr($vat_number,2);
				}
				if($zone->zone_code_2 != $code){
					//Error, the VAT does not match with the specified country...
					$app = JFactory::getApplication();
					$this->message = 'Your VAT number can not be used with the country you selected. Please select the right country ( CODE: '.$code.') or make sure your VAT starts with '.$zone->zone_code_2;
					if(@$_REQUEST['tmpl']=='component'){
						hikashop_display($this->message,'error');
					}else{
						$app->enqueueMessage($this->message);
					}
					return false;
				}

				if($vat_check==2){
					return $this->onlineCheck($vat_number);
				}
			case 0:
			default:
		}
		return true;
	}

	function getRegex($vat){
		$regex = false;
		switch(strtoupper(substr(str_replace(array(' ','.','-'),array('','',''),$vat),0, 2))) {
					case 'AT':
							$regex = '/^(AT){0,1}U[0-9]{8}$/i';
							break;
					case 'BE':
							$regex = '/^(BE){0,1}[0]{0,1}[0-9]{9}[0-9]{0,2}$/i';
							break;
					case 'BG':
							$regex = '/^(BG){0,1}[0-9]{9,10}$/i';
							break;
					case 'CY':
							$regex = '/^(CY){0,1}[0-9]{8}[A-Z]$/i';
							break;
					case 'CZ':
							$regex = '/^(CZ){0,1}[0-9]{8,10}$/i';
							break;
					case 'DK':
							$regex = '/^(DK){0,1}([0-9]{2}[\ ]{0,1}){3}[0-9]{2}$/i';
							break;
					case 'EE':
					case 'DE':
					case 'PT':
					case 'EL':
					case 'GR':
							$regex = '/^(EE|EL|DE|GR|PT){0,1}[0-9]{9}$/i';
							break;
					case 'ES':
							$regex = '/^(ES){0,1}([0-9A-Z][0-9]{7}[A-Z])|([A-Z][0-9]{7}[0-9A-Z])$/i';
							break;
					case 'FI':
					case 'HU':
					case 'LU':
					case 'MT':
					case 'SI':
							$regex = '/^(FI|HU|LU|MT|SI){0,1}[0-9]{8}$/i';
							break;
					case 'FR':
							$regex = '/^(FR){0,1}[0-9A-Z]{2}[\ ]{0,1}[0-9]{9}$/i';
							break;
					case 'GB':
							$regex = '/^(GB){0,1}([1-9][0-9]{2}[\ ]{0,1}[0-9]{4}[\ ]{0,1}[0-9]{2})|([1-9][0-9]{2}[\ ]{0,1}[0-9]{4}[\ ]{0,1}[0-9]{2}[\ ]{0,1}[0-9]{3})|((GD|HA)[0-9]{3})$/i';
							break;
					case 'HR':
							$regex = '/^(HR){0,1}[0-9]{11}$/i';
							break;
					case 'IE':
							$regex = '/^(IE){0,1}[0-9][0-9A-Z\+\*][0-9]{5}[A-Z]$/i';
							break;
					case 'IT':
					case 'LV':
							$regex = '/^(IT|LV){0,1}[0-9]{11}$/i';
							break;
					case 'LT':
							$regex = '/^(LT){0,1}([0-9]{9}|[0-9]{12})$/i';
							break;
					case 'NL':
							$regex = '/^(NL){0,1}[0-9]{9}B[0-9]{2}$/i';
							break;
					case 'PL':
					case 'SK':
							$regex = '/^(PL|SK){0,1}[0-9]{10}$/i';
							break;
					case 'RO':
							$regex = '/^(RO){0,1}[1-9][0-9]{1,9}$/i';
							break;
					case 'SE':
							$regex = '/^(SE){0,1}[0-9]{12}$/i';
							break;
					default:
							break;
			}
			return $regex;
	}

	function regexCheck(  $vat , $regex) {
		if(!preg_match($regex, str_replace(array(' ','.','-'),array('','',''),$vat))){
			$app = JFactory::getApplication();
			$this->message = JText::_('VAT_NUMBER_NOT_VALID');
			if(@$_REQUEST['tmpl']=='component'){
				hikashop_display($this->message,'error');
			}else{
				$app->enqueueMessage($this->message);
			}

			return false;
		}
		return true;
	}

	function onlineCheck($vat){
		JPluginHelper::importPlugin('hikashop');
		$dispatcher = JDispatcher::getInstance();
		$processed = false;
		$rc = $dispatcher->trigger( 'onBeforeVATOnlineCheck', array( &$this, &$processed, &$vat) );
		if( $processed) {
			return $rc;
		}

		//no online check for php4
		if (extension_loaded('soap')) {
			try{
				$client = new SoapClient("http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl");
				$countryCode = substr($vat, 0, 2);
				$result = $client->checkVat(array('countryCode' => $countryCode, 'vatNumber' => substr($vat, 2)));
				if(empty($result) || !$result->valid) {
					$this->message = JText::_('VAT_NUMBER_NOT_VALID');
				}
			}catch(SoapFault $e) {
				$this->message = $e->__toString();
				return true;
				//$result = false;
			}catch (Exception $e) {
				$this->message = $e->__toString();
				return true;
				//$result = false;
			}
			if ($result === false || empty($result) || !$result->valid ) {
				$app = JFactory::getApplication();
				if($_REQUEST['tmpl']=='component'){
					hikashop_display($this->message,'error');
				}else{
					$app->enqueueMessage($this->message);
				}
				return false;
			}
		}else{
			$app = JFactory::getApplication();
			$this->message = JText::_('SOAP_EXTENSION_NOT_FOUND');
			if($_REQUEST['tmpl']=='component'){
				hikashop_display($this->message,'error');
			}else{
				$app->enqueueMessage($this->message);
			}
			return false;
		}
		return true;
	}

Please Log in or Create an account to join the conversation.

  • Posts: 79
  • Thank you received: 3
9 years 8 months ago #193235

Thanks for your information. I was looking for a reason to use some time to program a plugin and this is the perfect occasion.

Any way, I'm spanish, and while I am revising your code, I FOUND A BUG. I saw a VAT exception for Las Palmas (you use comment line "//skip VAT number check for las palmas as las palmas is not in the european VAT zone" before the code I saw). If you do this exception, you must also do it for Santa Cruz de Tenerife because the VAT exception is for all the autonomous community of the Canary Islands consists of two provinces Las Palmas and Santa Cruz de Tenerife (zone_code_3=='TF')

Regards

Please Log in or Create an account to join the conversation.

  • Posts: 79
  • Thank you received: 3
9 years 8 months ago #193294

Hello again.

I have created and instaled my plugin named verifica_vat. (No installation errors). I think next step is use it.
I located address class at /administrator/components/com_hikashop/classes folder and I found save function on it that call _checkVat function and this one use vat helper.

I have 2 questions:
1.- May I change this class code in order to force it to use my plugin instead of helper? How can I do it?
2.- If first awnser is No, What should I do to use my plugin in order to verify VAT number?.

Thanks in advance.

Regards

Last edit: 9 years 8 months ago by pljuarez.

Please Log in or Create an account to join the conversation.

  • Posts: 13201
  • Thank you received: 2322
9 years 8 months ago #193484

Hi,

Thanks for your report about the Santa Cruz de Tenerife exception.

Regarding the question about how to use the functions in the plugin instead of the one in the Helper, you have to use $this.
For example:

$this->regexCheck($vat_number,$regex)
This will call the function in your plugin, $this allow to make local calls.
So if in the code you see something like:
$theClass = hikashop_get('class.the');
$theVar = $theClass->theFunction();
This call a class, so to use the function of your plugin replace that by:
$theVar = $this->theFunction();

Please Log in or Create an account to join the conversation.

  • Posts: 79
  • Thank you received: 3
9 years 8 months ago #193520

Thanks for your reply. Note it´s my first plugin. One more question.
should I do these changes at /administrator/components/com_hikashop/classes/address.php?

Regards

Please Log in or Create an account to join the conversation.

  • Posts: 82906
  • Thank you received: 13378
  • MODERATOR
9 years 8 months ago #193576

Hi,

No, Xavier was talking about creating a new joomla plugin implementing specific code to handle that.
It's definitely not an easy task. You might need to hire a Joomla developer to help you with that if you're not familiar with such development. We have partners you can contact for such project here: www.hikashop.com/home/our-partners.html
But if you're a skilled PHP developer it shouldn't be a problem.

Please Log in or Create an account to join the conversation.

  • Posts: 79
  • Thank you received: 3
9 years 8 months ago #193828

Hi Nicholas.
I had create my own plugin, I instaled it without errors, and I published it.
When I select HikaShop -> System ->Plugins->New. I can see it in the list (plugin-list.jpg). When I click on it, Joomla opens it in Joomla Plugin Manager (plugin_Manager.jpg). I saved it, and it appears enabled at Joomla Plugin Manager list (plugin_Man_list.jpg) but not at HickaShop System->plugin list.

The only thing I need to know is how can I invoke it? (I also attached php code and plugin xml.), because, I understood, when you install and publish a pluging, this plugin overrides every helper function you use into plugin.

Please, correct me if I'm wrong.

Regards

Last edit: 9 years 8 months ago by pljuarez.

Please Log in or Create an account to join the conversation.

  • Posts: 82906
  • Thank you received: 13378
  • MODERATOR
9 years 8 months ago #193984

Hi,

You need to deactivate the option "VAT number check" of the HikaShop configuration so that the VAT check is not done anymore by HikaShop.
Then, your plugin will be called automatically just before the address is saved and you'll be able to do the checks you want etc in your plugin.

I checked its code and it looks good. You should definitely get it called in the onBeforeAddressCreate function if you activated the plugin via the Joomla plugins manager.

Please Log in or Create an account to join the conversation.

  • Posts: 79
  • Thank you received: 3
9 years 8 months ago #194052

Thank you very much for your reply Nicolas. Yesterday I spent all day looking for information about Joomla plugins, but I don't found anything that suits with my problem.

I did some minors changes in my plugin php code replacing this code lines because hikashop vat_chek config is set to 0 :

if(!isset($vat_check)){
	$config = hikashop_config();
	$vat_check = (int)$config->get('vat_check',2);
}

by this other:
$usuario = JFactory::getUser();
foreach ($usuario->groups as $grupo){
	$grupo = (int)$grupo;
	if ($grupo == 21){ //My User group 21 = Company with VAT number => Online check
		$vat_check = 2;
	}
	if ($grupo == 23){ //My User group 23 = Company without VAT number => No check
		$vat_check = 0;
	}
	if ($grupo == 24){ //My User group 24 = Individuals	=> Format check
		$vat_check = 1;
	}
}

I have tried some scenarios putting some flags in the code, AND IT WORKS!!!

Regards

Last edit: 9 years 8 months ago by pljuarez.

Please Log in or Create an account to join the conversation.

  • Posts: 79
  • Thank you received: 3
8 years 9 months ago #231281

Hello, I have One question:

¿Have you modified vat_check behaviour?

Because, my plugin STOP WORK SUDENLY!!!. Some weeks ago it works but today I'm doing VAT tests and when I edit one of my Billing addresses at checkout it don't work.
No error messages, symply don't check VAT number anymore if i type "123456a" and clic "Ok button" Hikashop store this value without checking it

I insert in my plugin code one flag in order to see one value and don't work.
This is the flag;:

		$app = JFactory::getApplication();
		$this->message = 'valor de Vat_check: '.$vat_check;
		hikashop_display($this->message,'error');

I look for my plugin in Joomla plugin manager and it is active, but in Hikashop Configuration->Plugins there are no plugins include if I create a new one, edit it and save it like Hikashop message said.

What can I do?

Please Log in or Create an account to join the conversation.

  • Posts: 82906
  • Thank you received: 13378
  • MODERATOR
8 years 9 months ago #231311

Hi,

The onBeforeAddressCreate($addressData, $do) and onBeforeAddressUpdate($addressData, $do) triggers still work like before.
We didn't touch them in a long time.
So it must be something else.
Try on the backend of the website. The saving of the address in the backend should also trigger your plugin. If it doesn't, it means that the plugin is either not enabled, its files have been removed, or its access is restricted in some way.
If it works in the backend and not the frontend, then is a problem with the way your checkout is configured I suppose.
For example, maybe you changed the way the addresses are edited on the checkout with the settings of the Checkout tab of the HikaShop configuration.

Please Log in or Create an account to join the conversation.

  • Posts: 79
  • Thank you received: 3
8 years 8 months ago #232030

Hi Nicholas. Sorry for delay, I'm out of office for some days.

My plugin does not work either in the backend. Maybe this can be influenced by the selections in System-> Configuration-> ACL? (I attach my "Plugins" ACL configuration)

Anyway, my plugin should be displayed in System->Plugins list?. Because there is no plugins also if I add new one via "New" button.

Thanks

Attachments:
Last edit: 8 years 8 months ago by pljuarez.

Please Log in or Create an account to join the conversation.

  • Posts: 82906
  • Thank you received: 13378
  • MODERATOR
8 years 8 months ago #232035

Hi,

No, you don't need to see it in System>Plugins.
But you need to enable it in the Joomla plugins manager.
Could you provide a copy of the plugin ? It would be easier to tell you what's wrong with it.

Please Log in or Create an account to join the conversation.

  • Posts: 79
  • Thank you received: 3
8 years 8 months ago #232101

The plugin is enable, as you can see in attached file "hika_plug.jpg" and "joomla_plug.jpg", when I click in "New" button at System->Plugins it appear enabled. In addition I have reinstalled and enabled it in joomla plugin manager and refresh joomla cache in joomla extension manager and still don't work in fronten, neither the backend.

Attached are plugin files, which are the same as I attached a few posts above.
www.hikashop.com/forum/checkout/875355-i...can-i-do.html#193828
Files "verifica_vat.php" and "verifica_vat_xml.txt"

Anyway what's about ACL? , does ACL can affect?

Regards

Attachments:
Last edit: 8 years 8 months ago by pljuarez. Reason: Original xml file filtered and don't attached, resaved as txt file

Please Log in or Create an account to join the conversation.

  • Posts: 82906
  • Thank you received: 13378
  • MODERATOR
8 years 8 months ago #232260

Hi,

The problem is indeed in your plugin.
The goal of the plugin is to change the $do variable passed to the onBeforeAddressCreate and onBeforeAddressUpdate functions to false when the vat number is invalid.
But to do that, you need to have the $do variable passed as a reference. And for that, you need to prefix the $do variable with the & symbol, like in our developer documentation:
www.hikashop.com/support/documentation/6...ntation.html#address
But you didn't put the & symbol in your plugin and thus, instead of having a reference to the $do variable, you get a copy of it. And thus, even if you change your copy to false, the original variable is still true and thus, even though your plugin is executed properly, it just doesn't do anything.

Add the & symbols and you'll see that it will work.

Please Log in or Create an account to join the conversation.

  • Posts: 79
  • Thank you received: 3
8 years 7 months ago #234604

Hello Nicholas, sorry for delay, but I was out of office last 3 weeks.

Like you said, the problem is in the plugin, because I have inserted a sleep(10) function behind a var_dump function in order to see the values of the user object, I tried with both objects in var_dump function ($usr_joomla and $usr_hika) and process waits 10 seconds (this means that the plugin is running) but I didn't obtain any output.

To obtain hikashop user id I used this code:

$usr_joomla = JFactory::getUser(); //obtain joomla user 
$class = hikashop_get('class.user');
$usr_hika = $class->get($usr_joomla->id,'cms');  //obtain hikashop user

var_dump(get_object_vars($usr_joomla));
sleep (10);

switch ($usr_hika->user_tipo){
	case...

"user_tipo" is a custom field I created in user table.

Like you can see, I use JFactory::getUser() function in order to obtain a Joomla userid to obtain a valid hikashop userid and then I access to hikashop user custom fields values. Before last update this code ran correctly.

Did you modified hikashop user behaviour?
What can I do to access hikashop user custom fields values?

Thanks in advance

Last edit: 8 years 7 months ago by pljuarez.

Please Log in or Create an account to join the conversation.

  • Posts: 82906
  • Thank you received: 13378
  • MODERATOR
8 years 7 months ago #234608

Hi,

We didn't change anything. The custom user fields values are still in $usr_hika.
Please note however that this code won't work if you're not logged in.
For example, if you do a guest checkout: you still have a user address, but Joomla doesn't have a user account and thus $usr_joomla->id will be empty.

Also, doing a sleep won't help you debug your code.
A sleep will stop the processing of the request before resuming it. But what you echo in your code won't be sent to the browser until you do a flush or the process exit.
The simplest is to do it like that:
var_dump($usr_joomla);
exit;
That way, the process immediately stops and you get the var_dump data displayed.

Please Log in or Create an account to join the conversation.

Time to create page: 0.095 seconds
Powered by Kunena Forum