diff --git a/addons/base_geolocalize/models/base_geocoder.py b/addons/base_geolocalize/models/base_geocoder.py
index 1c012b86f1d160bcd08e5f189051c2eb7abe371b..2b2431fa8de6542d89b9f944af046d1c709d42f2 100644
--- a/addons/base_geolocalize/models/base_geocoder.py
+++ b/addons/base_geolocalize/models/base_geocoder.py
@@ -87,7 +87,8 @@ class GeoCoder(models.AbstractModel):
             return None
         url = 'https://nominatim.openstreetmap.org/search'
         try:
-            headers = {'User-Agent': 'Odoo (http://www.odoo.com/contactus)'}
+            headers = {'User-Agent': self.env['ir.config_parameter'].get_param('base_geolocalize.user_agent',
+                                                                               'Odoo (http://www.odoo.com/contactus)')}
             response = requests.get(url, headers=headers, params={'format': 'json', 'q': addr})
             _logger.info('openstreetmap nominatim service called')
             if response.status_code != 200:
diff --git a/addons/portal/static/src/scss/portal.scss b/addons/portal/static/src/scss/portal.scss
index a3d82a8ef57ee84ed96e535e89e63fecf249e080..6d19d944e56bdcacfc3d098f3581c0f4e8e6cbd6 100644
--- a/addons/portal/static/src/scss/portal.scss
+++ b/addons/portal/static/src/scss/portal.scss
@@ -342,6 +342,10 @@ img, .media_iframe_video, .o_image {
             white-space: nowrap;
             overflow: hidden;
             text-overflow: ellipsis;
+
+            &:has(a) {
+                color: $primary;
+            }
         }
     }
 
diff --git a/addons/sale_timesheet/models/project.py b/addons/sale_timesheet/models/project.py
index e407f30bc18605740bac06adaa1016bf2d35967a..391d8c9443678ff2be23856d2c2c1239580111ec 100644
--- a/addons/sale_timesheet/models/project.py
+++ b/addons/sale_timesheet/models/project.py
@@ -84,7 +84,7 @@ class Project(models.Model):
     def _compute_warning_employee_rate(self):
         projects = self.filtered(lambda p: p.allow_billable and p.allow_timesheets and p.bill_type == 'customer_project' and p.pricing_type == 'employee_rate')
         tasks = projects.task_ids.filtered(lambda t: not t.non_allow_billable)
-        employees = self.env['account.analytic.line'].read_group([('task_id', 'in', tasks.ids), ('non_allow_billable', '=', False)], ['employee_id', 'project_id'], ['employee_id', 'project_id'], ['employee_id', 'project_id'], lazy=False)
+        employees = self.env['account.analytic.line'].read_group([('task_id', 'in', tasks.ids), ('non_allow_billable', '=', False)], ['employee_id', 'project_id'], ['employee_id', 'project_id'], lazy=False)
         dict_project_employee = defaultdict(list)
         for line in employees:
             dict_project_employee[line['project_id'][0]] += [line['employee_id'][0]] if line['employee_id'] else []
diff --git a/addons/test_xlsx_export/tests/test_export.py b/addons/test_xlsx_export/tests/test_export.py
index 2c336028372865b8a90172212460d263e1327d98..86574093adda1a57a90d3c890a857e68b5e9cdef 100644
--- a/addons/test_xlsx_export/tests/test_export.py
+++ b/addons/test_xlsx_export/tests/test_export.py
@@ -7,6 +7,7 @@ from unittest.mock import patch
 
 from odoo import http
 from odoo.tests import common, tagged
+from odoo.tools import mute_logger
 from odoo.tools.misc import get_lang
 from odoo.addons.web.controllers.main import ExportXlsxWriter
 from odoo.addons.mail.tests.common import mail_new_test_user
@@ -412,3 +413,38 @@ class TestComputedBinaryExport(XlsxCreatorCase):
             ['OdooBot (1)'],
             ["['computed value']"],
         ])
+
+    @mute_logger('odoo.addons.web.controllers.main')
+    def test_export_with_deleted_field(self):
+        model = self.env['ir.model']._get('res.partner')
+        url = '/web/export/namelist'
+        header = {"Content-Type": "application/json"}
+
+        custom_field = self.env['ir.model.fields'].create([{
+            'name': 'x_test',
+            'ttype': 'char',
+            'field_description': 'test field',
+            'model_id': model.id,
+        }])
+
+        export_template = self.env['ir.exports'].create({
+            'name': custom_field.name,
+            'export_fields': [(0, 0, {'name': custom_field.name})],
+        })
+
+        data = json.dumps({
+                'params': {
+                    'model': model.model,
+                    'export_id': export_template.id,
+                    },
+                })
+
+        export_line_field = self.env['ir.exports.line'].search([('name', '=', export_template.name)])
+
+        self.url_open(url, data, headers=header).json()
+        self.assertTrue(export_line_field.exists())
+
+        custom_field.unlink()
+
+        self.url_open(url, data, headers=header).json()
+        self.assertFalse(export_line_field.exists())
diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py
index 972f1589e42760f52a3df6da3ac48237f327c7c9..f8ae022e698e4d4ad1beec79cd65bef97b84d929 100644
--- a/addons/web/controllers/main.py
+++ b/addons/web/controllers/main.py
@@ -1807,7 +1807,15 @@ class Export(http.Controller):
     def namelist(self, model, export_id):
         # TODO: namelist really has no reason to be in Python (although itertools.groupby helps)
         export = request.env['ir.exports'].browse([export_id]).read()[0]
-        export_fields_list = request.env['ir.exports.line'].browse(export['export_fields']).read()
+        exported_fields = request.env['ir.exports.line'].browse(export['export_fields'])
+        fields = self.fields_get(model)
+
+        for invalid_fields in exported_fields.filtered(lambda f: f.name not in fields):
+            # ir.exports.line lack a ondelete=cascade foreign key on ir.model.fields
+            _logger.warning("Field %r not found for saved ir.exports of model %s, deleting", invalid_fields.name, model)
+            invalid_fields.unlink()
+
+        export_fields_list = exported_fields.read()
 
         fields_data = self.fields_info(
             model, [f['name'] for f in export_fields_list])
diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py
index 0e6f8c1911b9c96619addd7d230212316729864c..df8f490307e0aec20c911b33c9451557f026fe00 100644
--- a/addons/website_sale/controllers/main.py
+++ b/addons/website_sale/controllers/main.py
@@ -581,11 +581,11 @@ class WebsiteSale(http.Controller):
             name_change = partner_su and 'name' in data and data['name'] != partner_su.name
             email_change = partner_su and 'email' in data and data['email'] != partner_su.email
 
-            # Prevent changing the partner name if invoices have been issued.
-            if name_change and not partner_su.can_edit_vat():
+            # Prevent changing the billing partner name if invoices have been issued.
+            if mode[1] == 'billing' and name_change and not partner_su.can_edit_vat():
                 error['name'] = 'error'
                 error_message.append(_(
-                    "Changing your name is not allowed once invoices have been issued for your"
+                    "Changing your name is not allowed once documents have been issued for your"
                     " account. Please contact us directly for this operation."
                 ))
 
diff --git a/addons/website_sale/i18n/website_sale.pot b/addons/website_sale/i18n/website_sale.pot
index 73e88c89054a3865408b7eb3aa4d0277b227e2a0..6ec2a4f5ede2d74f692fe97f33da2c933cc2619c 100644
--- a/addons/website_sale/i18n/website_sale.pot
+++ b/addons/website_sale/i18n/website_sale.pot
@@ -782,6 +782,14 @@ msgid ""
 "account. Please contact us directly for this operation."
 msgstr ""
 
+#. module: website_sale
+#: code:addons/website_sale/controllers/main.py:0
+#, python-format
+msgid ""
+"Changing your name is not allowed once documents have been issued for your "
+"account. Please contact us directly for this operation."
+msgstr ""
+
 #. module: website_sale
 #: model:ir.model.fields,field_description:website_sale.field_product_public_category__child_id
 msgid "Children Categories"