diff --git a/addons/account/__init__.py b/addons/account/__init__.py
index 8f86bd5681f78f0a8cc962fbad730cf0f071221f..2ad6a224d7dac1fdf7002e6492b1483e05d7c78c 100644
--- a/addons/account/__init__.py
+++ b/addons/account/__init__.py
@@ -48,11 +48,11 @@ def _auto_install_l10n(cr, registry):
         if country_code == 'MX':
             module_list.append('l10n_mx_edi')
 
-        # European countries will be using SEPA
-        europe = env.ref('base.europe', raise_if_not_found=False)
-        if europe:
-            europe_country_codes = [x.code for x in europe.country_ids]
-            if country_code in europe_country_codes:
+        # SEPA zone countries will be using SEPA
+        sepa_zone = env.ref('base.sepa_zone', raise_if_not_found=False)
+        if sepa_zone:
+            sepa_zone_country_codes = sepa_zone.mapped('country_ids.code')
+            if country_code in sepa_zone_country_codes:
                 module_list.append('account_sepa')
                 module_list.append('account_bank_statement_import_camt')
         module_ids = env['ir.module.module'].search([('name', 'in', module_list), ('state', '=', 'uninstalled')])
diff --git a/odoo/addons/base/data/res_country_data.xml b/odoo/addons/base/data/res_country_data.xml
index 70820a3953b3f12cc1a67ac69a2972cd4cdf7d72..79076a097e7907b7b061807e9a89ae49105839cc 100644
--- a/odoo/addons/base/data/res_country_data.xml
+++ b/odoo/addons/base/data/res_country_data.xml
@@ -1033,7 +1033,7 @@
             <field eval="692" name="phone_code" />
         </record>
         <record id="mk" model="res.country">
-            <field name="name">Macedonia, the former Yugoslav Republic of</field>
+            <field name="name">North Macedonia</field>
             <field name="code">mk</field>
             <field file="base/static/img/country_flags/mk.png" name="image" type="base64" />
             <field name="currency_id" ref="MKD" />
@@ -1820,5 +1820,20 @@
                 ref('ec'),ref('fk'),ref('gs'),ref('gf'),ref('gy'),
                 ref('py'),ref('pe'),ref('sr'),ref('uy'),ref('ve')])]"/>
         </record>
+
+        <record id="sepa_zone" model="res.country.group">
+            <field name="name">SEPA Countries</field>
+            <field name="country_ids" eval="[(6,0,[
+                ref('ad'),ref('at'),ref('ax'),ref('be'),ref('bg'),
+                ref('bl'),ref('ch'),ref('cy'),ref('cz'),ref('de'),
+                ref('dk'),ref('ee'),ref('es'),ref('fi'),ref('fr'),
+                ref('uk'),ref('gf'),ref('gg'),ref('gi'),ref('gp'),
+                ref('gr'),ref('hr'),ref('hu'),ref('ie'),ref('im'),
+                ref('is'),ref('it'),ref('je'),ref('li'),ref('lt'),
+                ref('lu'),ref('lv'),ref('mc'),ref('mf'),ref('mq'),
+                ref('mt'),ref('nl'),ref('no'),ref('pl'),ref('pm'),
+                ref('pt'),ref('re'),ref('ro'),ref('se'),ref('si'),
+                ref('sk'),ref('sm'),ref('va'),ref('yt')])]"/>
+        </record>
     </data>
 </odoo>
diff --git a/odoo/addons/base/models/res_bank.py b/odoo/addons/base/models/res_bank.py
index 6910385f43789655b452e7b555471a3db65bb528..4b212f5bb08b5a67ec7c1d641ba043365821b7cf 100644
--- a/odoo/addons/base/models/res_bank.py
+++ b/odoo/addons/base/models/res_bank.py
@@ -131,12 +131,17 @@ class ResPartnerBank(models.Model):
         communication = ""
         if comment:
             communication = (comment[:137] + '...') if len(comment) > 140 else comment
-        qr_code_string = 'BCD\n001\n1\nSCT\n%s\n%s\n%s\nEUR%s\n\n\n%s' % (self.bank_bic, self.company_id.name, self.acc_number, amount, communication)
+        qr_code_string = 'BCD\n001\n1\nSCT\n%s\n%s\n%s\nEUR%s\n\n\n%s' % (self.bank_bic or "", self.company_id.name, self.acc_number, amount, communication)
         qr_code_url = '/report/barcode/?type=%s&value=%s&width=%s&height=%s&humanreadable=1' % ('QR', werkzeug.url_quote_plus(qr_code_string), 128, 128)
         return qr_code_url
 
     def _validate_qr_code_arguments(self):
+        sepa_zones_codes = [c.code for c in self.env.ref('base.sepa_zone').country_ids]
+        # Some country instances share the same IBAN country code (e.g. Ã…land Islands and Finland IBANs are "FI", but Ã…land Islands code is "AX").
+        # Therefore sepa_zones_codes is too permissive, "AX" is not a valid IBAN country code.
+        not_iban_codes = ("AX", "NC", "YT", "TF", "BL", "RE", "MF", "GP", "PM", "PF", "GF", "MQ", "JE", "GG", "IM")
+        sepa_zones_codes = [code for code in sepa_zones_codes if code not in not_iban_codes]
         for bank in self:
-            bank.qr_code_valid = (bank.bank_bic
-                                            and bank.company_id.name
-                                            and bank.acc_number)
+            bank.qr_code_valid = (bank.company_id.name and
+                                  bank.acc_number and
+                                  bank.sanitized_acc_number[:2] in sepa_zones_codes)