Much better, Thanks!
Don't suppose there is a way to use wildcards in the postal code list. With most of my postal codes I only need the first 3 characters. There are a lot of variations.
Much better, Thanks!
Don't suppose there is a way to use wildcards in the postal code list. With most of my postal codes I only need the first 3 characters. There are a lot of variations.
Thanks lat9 but that's over my head, your guidance is appreciated
Given that you said you only care about first 3 characters, you could maybe even use this additional change which only matches on the customer's first 3 supplied postal code characters:
... and then only define 3-char patterns in the module's list of supported postal codes.Code:} else { $zipcode_zones = explode(',', strtoupper(str_replace(' ', '', $zipcode_table))); if (in_array(substr($this->dest_zipcode, 0, 3), $zipcode_zones)) { $this->dest_zone = $i; } }
.
Zen Cart - putting the dream of business ownership within reach of anyone!
Donate to: DrByte directly or to the Zen Cart team as a whole
Remember: Any code suggestions you see here are merely suggestions. You assume full responsibility for your use of any such suggestions, including any impact ANY alterations you make to your site may have on your PCI compliance.
Furthermore, any advice you see here about PCI matters is merely an opinion, and should not be relied upon as "official". Official PCI information should be obtained from the PCI Security Council directly or from one of their authorized Assessors.
Thanks DrByte,
This is the dilemma I'm facing. There are 124,000 area codes in the area we deliver. I recently discovered that if I only went with the first 3 characters of the postal codes I will lose the ability to charge extra for customers that are further away which are located by the last 3 characters of the postal codes (6 alpha/numeric characters in Canada). We are located in in Toronto, all the postal codes are prefixed with "M" and we deliver to all of them. The surrounding immediate surrounding are prefix with "L" and some are in our near vicinity, some we don't deliver to at all (too far) and some I want to if I can charge extra. This is why I was hoping to have the ability to use wild cards. M***** would cover all my postal codes in Toronto and say L4**** would cover all postal codes that have that prefix ... and so on.
One problem I anticipate is that there are postal codes with the same prefix that I don't want to deliver to at all. For example if I put L7E in my postal codes for Zone1 but I don't want to deliver to postal code L7E1H7, will it not give me the rate for Zone1 instead of telling the customer that we don't deliver to their area.
Unfortunately there is a limit of how many postal codes can be entered approximately 9,600. Is there a way to increase the limit so I can use zipship the hardway which I am more than happy with.
Don't know if there is an easy solution to my problem and would appreciate any suggestions.
Here's a radical experiment.
1. For pattern matching, I wonder if we can skip using the *'s idea and just assume a "prefix". That is, for M***** just list M, and for L4**** just use L4.
2. In any listed postal code, if you add a "!" at the beginning or end of the code, it will exclude that one. eg: M4B1Y! or !M4B1Y would exclude all M4B1Y* codes.
3. I also added stripping of hyphens ... so in theory this can also work for US zip codes where someone wants to add specificity in zip-plus-four format. (The original code trimmed all zips to the "minimum allowed length" in order to do matching, which kills the ability to do pattern-matching and negation.)
One caveat to note: if a postalcode pattern is present in more than one zone, the "last" non-excluded match will be used for calculating rates. (eg: if it matches in zones 1 and 3, then the rates from zone 3 will apply, ignoring its existence in zone 1).
Here's the updated code which does all this.
Code:$this->dest_zone = false; $this->default_zone = false; // $this->dest_zipcode = substr(strtoupper($order->delivery['postcode']), 0, (int)ENTRY_POSTCODE_MIN_LENGTH); $this->dest_zipcode = strtoupper(str_replace([' ', '-'], '', $order->delivery['postcode'])); for ($i = 1; $i <= $this->num_zones; $i++) { $current_table = "MODULE_SHIPPING_ZIPSHIP_CODES_$i"; if (defined($current_table)) { $zipcode_table = constant($current_table); if ($zipcode_table === '00000') { $this->default_zone = $i; } else { // Read codes from config $zipcodes = explode(',', str_replace([' ', '-'], '', strtoupper($zipcode_table))); // sort codes, first by alpha, then by reverse-length so we process longest-first usort($zipcodes, function($a, $b){ $a = trim($a, '!'); $b = trim($b, '!'); return strcmp($a, $b); }); usort($zipcodes, function($a, $b){ $a = trim($a, '!'); $b = trim($b, '!'); return (strlen($a) < strlen($b)) ? 1 : -1; }); // Check for exclusion patterns defined with a starting or ending ! symbol foreach($zipcodes as $check_against) { if ($check_against === '!' || strpos($check_against, '!') === false) continue; // if no ! skip checking this iteration if (strpos($this->dest_zipcode, trim($check_against, '!')) === 0) { // strip ! to do matching $this->dest_zone = false; // If exclusion detected, use "continue" to end this foreach and skip the next one as well continue 2; } } // Pass if the supplied code matches a defined prefix pattern foreach($zipcodes as $check_against) { if (strpos($check_against, '!') !== false) continue; if (strpos($this->dest_zipcode, $check_against) === 0) { $this->dest_zone = $i; // If a match is found, end this foreach break; } } } } } if ($this->dest_zone === false && $this->default_zone === false) { $this->enabled = false; } } } } public function quote($method = '')
Last edited by DrByte; 15 Dec 2020 at 10:21 PM. Reason: updated usort to be called twice; better PHP 8.0 compatibility
.
Zen Cart - putting the dream of business ownership within reach of anyone!
Donate to: DrByte directly or to the Zen Cart team as a whole
Remember: Any code suggestions you see here are merely suggestions. You assume full responsibility for your use of any such suggestions, including any impact ANY alterations you make to your site may have on your PCI compliance.
Furthermore, any advice you see here about PCI matters is merely an opinion, and should not be relied upon as "official". Official PCI information should be obtained from the PCI Security Council directly or from one of their authorized Assessors.
You are the "Sensei". I will give it a whirl tomorrow and let you know.
Cheers!!!