Skip to content
Jerry Smidt edited this page Aug 5, 2024 · 8 revisions

How to exclude postcode ranges

Here's an example of additional validation that can be used to exclude certain postcode ranges. In this example we've excluded islands.

Edit the following files in your Magento module or create a new module and add them there. Make sure to change the validation to fit your needs (these are just examples).

Add dependency on Flekto_Postcode module:

etc/module.xml:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="PostcodeEu_PostcodeRangeValidation">
        <sequence>
            <module name="Flekto_Postcode"/>
        </sequence>
    </module>
</config>

Add configuration for mixins:

view/frontend/requirejs-config.js:

var config = {
    "config": {
        "mixins": {
            // NB: Change PostcodeEu_PostcodeRangeValidation to the name of your module.
            'Magento_Ui/js/lib/validation/validator': {
                'PostcodeEu_PostcodeRangeValidation/js/validation/validator-mixin-nl': true,
                'PostcodeEu_PostcodeRangeValidation/js/validation/validator-mixin-intl': true,
            },
            "Flekto_Postcode/js/form/element/postcode": {
                "PostcodeEu_PostcodeRangeValidation/js/form/element/postcode-mixin": true
            },
            "Flekto_Postcode/js/form/element/address-autofill-intl": {
                "PostcodeEu_PostcodeRangeValidation/js/form/element/address-autofill-intl-mixin": true
            },
        },
    },
};

Add mixin files:

view/frontend/web/js/form/element/postcode-mixin.js:

define([], function () {
    'use strict';

    return function (Component) {
        return Component.extend({
            defaults : {
                validation: {
                    'validate-wadden-nl': '${ $.parentScope }',
                },
            },
        });
    };
});

view/frontend/web/js/validation/validator-mixin-nl.js:

/*!
 * Validator mixin for Magento_Ui/js/lib/validation/validator
 */
define([
    'mage/translate',
], function ($t) {
    'use strict';

    return function (validator) {

        validator.addRule(
            'validate-wadden-nl',
            function (value, parentScope) {
                if (parentScope.split('.')[0] !== 'shippingAddress') {
                    return true
                }

                // Texel: 1790 - 1797
                // Vlieland: 8899
                // Terschelling: 8880 - 8885
                // Ameland: 9160 - 9164
                // Schiermonnikoog: 9166
                const regex = /^(179[0-7]|8899|888[0-5]|916[0-4]|9166)/;
                return value === '' || regex.test(value) === false;
            },
            $t('Sorry, wij bezorgen niet op dit Waddeneiland.')
        );

        return validator;
    };
});

view/frontend/web/js/form/element/address-autofill-intl-mixin.js:

define([], function () {
    'use strict';

    return function (Component) {
        return Component.extend({
            initialize: function () {
                this._super();
                this.validation['validate-excluded-shipping-locations'] = this;
                return this;
            },
        });
    }
})

view/frontend/web/js/validation/validator-mixin-intl.js:

/*!
 * Validator mixin for Magento_Ui/js/lib/validation/validator
 */
define([
    'mage/translate',
], function ($t) {
    'use strict';

    return function (validator) {

        // Regex patterns for postcode ranges to exclude from the shipping address.
        // Modify as needed.
        const excludedPostcodeRanges = {
            'NL':
                // Texel: 1790 - 1797
                // Vlieland: 8899
                // Terschelling: 8880 - 8885
                // Ameland: 9160 - 9164
                // Schiermonnikoog: 9166
                /^(179[0-7]|8899|888[0-5]|916[0-4]|9166)/,
            'DE':
                // Borkum: 26757
                // Juist: 26571
                // Norderney: 26548
                // Baltrum: 26579
                // Langeoog: 26465
                // Spiekeroog: 26474
                // Wangerooge: 26486
                // Sylt: 25980, 25992 - 25999
                // Föhr: 25938
                // Amrum: 25946
                /^(26757|26571|26548|26579|26465|26474|26486|25980|2599[2-9]|25938|25946)$/,
            'DK':
                // Bornholm: 37**
                // Ærø: 5970, 5985, 5960
                // Fanø: 6720
                // Samsø: 8305
                // Læsø: 9940
                /^(37\d\d|5970|5985|5960|6720|8305|9940)$/,
            'FR':
                // Corsica: 20***
                /^20/,
            'ES':
                // Balearic Islands: 07***
                // Province of Las Palmas: 35***
                // Province of Santa Cruz de Tenerife: 38***
                // Ceuta: 51001 - 51005
                // Melilla: 52001 - 52006
                /^(07|35|38|5100[1-5]|5200[1-6])/,
            'GB':
                // Isle of Man: IM1 - IM99
                // Jersey: JE1 - JE5
                // Guernsey: GY1 - GY8
                // Outer Hebrides / Western Isles: HS1 - HS9
                // Shetland: ZE1 - ZE3
                /^(IM\d|JE[1-5]|GY[1-8]|HS\d|ZE[1-3])/,
        };

        validator.addRule(
            'validate-excluded-shipping-locations',
            function (_, intlField) {
                if (
                    typeof excludedPostcodeRanges[intlField.countryCode] === 'undefined'
                    || intlField.parentScope !== 'shippingAddress'
                    || intlField.visible() === false
                    || intlField.address() === null
                ) {
                    return true;
                }

                const postcode = intlField.address().address.postcode;
                return false === excludedPostcodeRanges[intlField.countryCode].test(postcode);
            },
            $t('Sorry, we do not ship to this location.')
        );

        return validator;
    };
});

OneStepCheckout.com configuration instructions

Go to Stores -> Configuration -> Sales -> OneStepCheckout and make sure the following is configured for both the billing and shipping fields:

  1. The fields street.0, postcode, city, region are enabled.
  2. The option "Explode address rows" option is set to "no".

After that, you will probably want to apply some custom CSS to display the fields correctly. You may set the region field to hidden.

Tip: to label the individual street inputs, don't use the "Explode address rows" option. Instead, reveal the already existing labels using CSS.

Clone this wiki locally