Recently, I wrote a blog post about preventing PO box customer addresses being registered at checkout. Following on from that post, I was asked a rather sensible question: "is it possible to disallow PO boxes for shipping, but allow them for billing?" The answer is yes, but it does require a few more modifications to Magento.

As mentioned in the original post, the if statements with regular expressions required to block PO boxes and locked bags are as follows:

if (preg_match("/p\.* *o\.* *box/i", $this->getStreet(1))) {
 $errors[] = $helper->__('We cannot ship to PO boxes.');
}

and

if (preg_match("/locked *bag/i", $this->getStreet(1))) {
 $errors[] = $helper->__('We cannot ship to locked bags.');
}

Unlike in my original post, we need to add these in a new validation function, which we will only use for validating shipping addresses. In the file:

magento/app/code/core/Mage/Customer/Model/Address/Abstract.php

simply make a copy of the validate() function, name it something like validate_pobox() and insert the above code as before. The result should look something like this:

public function validate_pobox()
{
 $errors = array();
 $helper = Mage::helper('customer');
 $this->implodeStreetAddress();
 if (!Zend_Validate::is($this->getFirstname(), 'NotEmpty')) {
 $errors[] = $helper->__('Please enter first name.');
 }

 if (!Zend_Validate::is($this->getLastname(), 'NotEmpty')) {
 $errors[] = $helper->__('Please enter last name.');
 }

 if (!Zend_Validate::is($this->getStreet(1), 'NotEmpty')) {
 $errors[] = $helper->__('Please enter street.');
 }
 
 if (preg_match("/p\.* *o\.* *box/i", $this->getStreet(1))) { 
 $errors[] = $helper->__('We cannot ship to PO boxes.');
 }

 if (preg_match("/locked *bag/i", $this->getStreet(1))) {
 $errors[] = $helper->__('We cannot ship to locked bags.');
 }

 if (!Zend_Validate::is($this->getCity(), 'NotEmpty')) {
 $errors[] = $helper->__('Please enter city.');
 }

 if (!Zend_Validate::is($this->getTelephone(), 'NotEmpty')) {
 $errors[] = $helper->__('Please enter telephone.');
 }

 if (!Zend_Validate::is($this->getPostcode(), 'NotEmpty')) {
 $errors[] = $helper->__('Please enter zip/postal code.');
 }

 if (!Zend_Validate::is($this->getCountryId(), 'NotEmpty')) {
 $errors[] = $helper->__('Please enter country.');
 }

 if ($this->getCountryModel()->getRegionCollection()->getSize()
 && !Zend_Validate::is($this->getRegionId(), 'NotEmpty')) {
 $errors[] = $helper->__('Please enter state/province.');
 }

 if (empty($errors)) {
 return true;
 }
 return $errors;
}

Now that we have the necessary validation function, we need to ensure that it is used instead of the default function in the checkout module. The file to be modified is this one:

/magento/app/code/core/Mage/Checkout/Model/Type/Onepage.php

In the Onepage.php file we need to modify three functions:

  • saveBilling
  • saveShipping
  • validateOrder

The first function requires a small block of code to be added, while the last two just need the instance of validate() changed to validate_pobox(). To avoid ambiguities, I have attached the modified Onepage.php file. Simply download the file and search for 'TODO', as I have wrapped all three of the required changes in comments that start with the word 'TODO'.

Finally, the standard warning about modifying core files applies here as well. Rather than directly modifying core files make copies of the affected files before modifying them and place them in the local directory.


Magento Compatibility

Post originally written for Magento version:1.3.2.3
Tested with Magento version(s):1.3.2.3