Jump to content

[solved] Carrier by postcode, the easy way


Recommended Posts

For PS1.4.7.

I have one carrier that delivers only for certain zip-codes. All of them in the same state.

Using default PS behaviour, a carrier is assigned for a zone... and the zone "is made" of states.

We cannot divide states into smaller parts.

 

So, just in case someone need this, I figured out a simply way to achieve this.

- I added a zone for my collection of postcodes

- I set up a carrier fot that zone

 

And in controllers/ParentOrderController.php, protected function _assignCarrier(), in line ~363 I made this change:

Before:

$id_zone = Address::getZoneById((int)($address->id));

After:

if(($address->id_state==348)&& in_array($address->postcode,array(31001,31014))){

$id_zone=13;

}else $id_zone = Address::getZoneById((int)($address->id));

 

This is an example. In my case, all of my postcodes belongs to the same state. If it is not your case, just delete the part "($address->id_state=xxx)

 

 

Luk.

Link to comment
Share on other sites

Updating Controllers or Classes directly is a really bad idea, as it will be lost if you do an upgrade of Prestashop.

The right way would be to create a new Override Controller and apply your changes there.

 

There is a module we created that lets you assign shipping cost by country, state, or zip code ranges which would make thing much easier http://www.prestashop.com/forums/index.php?/topic/148747-module-localized-shipping-set-shipping-rates-by-country-state-or-zipcode-range/

Link to comment
Share on other sites

The module was just a suggestion (it's more flexible and does not require changing any files).

 

The advice I gave (using override files instead of changing the controller directly) was the main reason for my reply, even if it is only 1 line change, in 6 months from now, you may forget about it, do an upgrade of PS and lose this change.

 

The is the good scenario where only 1 person works on the site, but if you use a developer, and change it, you will have no way of keeping track of those type of changes, which is why using the override folder is the best way to go.

Link to comment
Share on other sites

Thank you for your comments. I think you're right, so I decided to use "override" folder.

 

It's easy.

1) Just copy "classes/Address.php" to "override/classes/Address.php".

2) In line 28 change class name from AddressCore to Address

3) Before function getZoneById, paste this new function (maybe there's a way to access to this field inside the class)

 

/**

* Return postcode of address

*

* @param $id_address Address id

* @return integer postcode

*/

public static function getPostcodeByAddress($id_address){

$row = Db::getInstance()->getRow('

SELECT `postcode`

FROM '._DB_PREFIX_.'address a

WHERE a.`id_address` = '.(int)($id_address));

return $row['postcode'];

}

4) Add before first line of function getZoneById this:

$postcode=self::getPostcodeByAddress($id_address);

 

if(in_array($postcode,array(your list of postcodes)){

return id-of-your-zone;

}else

  • Like 1
Link to comment
Share on other sites

  • 5 months later...

Thank you for your comments. I think you're right, so I decided to use "override" folder.

 

It's easy.

1) Just copy "classes/Address.php" to "override/classes/Address.php".

2) In line 28 change class name from AddressCore to Address

3) Before function getZoneById, paste this new function (maybe there's a way to access to this field inside the class)

 

/**

* Return postcode of address

*

* @param $id_address Address id

* @return integer postcode

*/

public static function getPostcodeByAddress($id_address){

$row = Db::getInstance()->getRow('

SELECT `postcode`

FROM '._DB_PREFIX_.'address a

WHERE a.`id_address` = '.(int)($id_address));

return $row['postcode'];

}

4) Add before first line of function getZoneById this:

$postcode=self::getPostcodeByAddress($id_address);

 

if(in_array($postcode,array(your list of postcodes)){

return id-of-your-zone;

}else

 

What to do after that because nothing happens in BO

Link to comment
Share on other sites

  • 2 months later...
  • 3 weeks later...
  • 2 weeks later...
  • 4 weeks later...
  • 1 month later...
  • 3 weeks later...

Thanks for the solution. Anyway we can extend Address from AddressCore that is better:

 

Edit overrride/classes/Address.php(at least in Prestashop 1.5 exist by default):

 

 

class Address extends AddressCore

{

/**

* Return postcode of address

*

* @param $id_address Address id

* @return integer postcode

*/

public static function getPostcodeByAddress($id_address){

$row = Db::getInstance()->getRow('

SELECT `postcode`

FROM '._DB_PREFIX_.'address a

WHERE a.`id_address` = '.(int)($id_address));

 

return $row['postcode'];

}

 

/**

* Get zone id for a given address

*

* @param integer $id_address Address id for which we want to get zone id

* @return integer Zone id

*/

public static function getZoneById($id_address)

{

 

$postcode = self::getPostcodeByAddress($id_address);

 

if(in_array($postcode,array(list of postcode))){

return id-zone;

}else

if (isset(self::$_idZones[$id_address]))

return self::$_idZones[$id_address];

 

$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('

SELECT s.`id_zone` AS id_zone_state, c.`id_zone`

FROM `'._DB_PREFIX_.'address` a

LEFT JOIN `'._DB_PREFIX_.'country` c ON c.`id_country` = a.`id_country`

LEFT JOIN `'._DB_PREFIX_.'state` s ON s.`id_state` = a.`id_state`

WHERE a.`id_address` = '.(int)$id_address);

 

self::$_idZones[$id_address] = (int)((int)$result['id_zone_state'] ? $result['id_zone_state'] : $result['id_zone']);

return self::$_idZones[$id_address];

}

 

}

 

We can use else if(in_array($postcode,array(list of postcode))) return id-zone; for more postcodes in different zones.

Edited by jxrgxb (see edit history)
  • Like 2
Link to comment
Share on other sites

  • 1 month later...

i have written a module that applies rules to assign postal rates by post code using the idea from here. i will be writing some simpe instructions. see my signature for a link to the thread.

 

it is fully working buts needs to be released as an RC so it cdan be checked in the real world.

Link to comment
Share on other sites

  • 1 year later...
  • 10 months later...
  • 2 months later...
×
×
  • Create New...