diff --git a/CHANGES.rst b/CHANGES.rst
index 75150f9b..47d0662a 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -4,7 +4,11 @@ Changelog
6.3.16 (unreleased)
-------------------
-- Nothing changed yet.
+- Modulo: ``mime_type`` is now indexed as the mime type of ``file_principale``
+ (the main attached file). The ``to_7321`` upgrade step re-aligns the catalog
+ index and refreshes stale ``portal_enhancedlinks`` cache entries for existing
+ Modulo objects.
+ [TheSaintSimon]
6.3.15 (2026-01-29)
diff --git a/src/design/plone/contenttypes/indexers/configure.zcml b/src/design/plone/contenttypes/indexers/configure.zcml
index 7a660671..75018257 100644
--- a/src/design/plone/contenttypes/indexers/configure.zcml
+++ b/src/design/plone/contenttypes/indexers/configure.zcml
@@ -81,6 +81,10 @@
factory=".punto_di_contatto.PuntoDiContattoMoreTextToIndex"
name="IPuntoDiContatto"
/>
+
- 7320
+ 7321
profile-redturtle.bandi:default
profile-collective.venue:default
diff --git a/src/design/plone/contenttypes/tests/test_modulo_mime_type.py b/src/design/plone/contenttypes/tests/test_modulo_mime_type.py
new file mode 100644
index 00000000..ba0239a5
--- /dev/null
+++ b/src/design/plone/contenttypes/tests/test_modulo_mime_type.py
@@ -0,0 +1,90 @@
+# -*- coding: utf-8 -*-
+from design.plone.contenttypes.testing import (
+ DESIGN_PLONE_CONTENTTYPES_INTEGRATION_TESTING,
+)
+from design.plone.contenttypes.upgrades.to_730x import to_7321
+from plone import api
+from plone.app.testing import setRoles
+from plone.app.testing import TEST_USER_ID
+from plone.namedfile.file import NamedBlobFile
+
+import os
+import unittest
+
+
+class TestModuloMimeType(unittest.TestCase):
+ layer = DESIGN_PLONE_CONTENTTYPES_INTEGRATION_TESTING
+
+ def setUp(self):
+ self.portal = self.layer["portal"]
+ setRoles(self.portal, TEST_USER_ID, ["Manager"])
+
+ filename = os.path.join(os.path.dirname(__file__), "example.pdf")
+ with open(filename, "rb") as pdf_file:
+ pdf_data = pdf_file.read()
+
+ # Build a real Modulo with a PDF as main file.
+ self.documento = api.content.create(
+ container=self.portal,
+ type="Documento",
+ title="Documento",
+ )
+ self.modulo = api.content.create(
+ container=self.documento,
+ type="Modulo",
+ title="Modulo",
+ file_principale=NamedBlobFile(
+ data=pdf_data,
+ filename="example.pdf",
+ contentType="application/pdf",
+ ),
+ )
+ self.modulo_2 = api.content.create(
+ container=self.documento,
+ type="Modulo",
+ title="Modulo_2",
+ file_principale=NamedBlobFile(
+ data=pdf_data,
+ filename="example.pdf",
+ contentType="application/pdf",
+ ),
+ )
+
+ def test_to_7321_refreshes_modulo_mime_type_cache(self):
+ enhancedlinks_tool = api.portal.get_tool("portal_enhancedlinks")
+ # Simulate the stale cache entry that the upgrade has to refresh.
+ enhancedlinks_tool._enhanced_links[self.modulo.UID()] = {
+ "getObjSize": "1 KB",
+ "mime_type": "text/plain",
+ }
+
+ # Start from the broken cached mime type.
+ self.assertEqual(
+ enhancedlinks_tool.get_enhanced_link(self.modulo.UID())["mime_type"],
+ "text/plain",
+ )
+
+ # The upgrade reindexes Modulo mime_type and refreshes enhanced links.
+ to_7321(self.portal)
+
+ # After the refresh the cache must reflect the PDF mime type.
+ self.assertEqual(
+ enhancedlinks_tool.get_enhanced_link(self.modulo.UID())["mime_type"],
+ "application/pdf",
+ )
+
+ def test_modulo_base_tool_mime_type(self):
+ # Without any stale cache, the tool should already have the correct
+ # mime type for the Modulo (taken from file_principale).
+ enhancedlinks_tool = api.portal.get_tool("portal_enhancedlinks")
+ result = enhancedlinks_tool.get_enhanced_link(self.modulo.UID())
+ self.assertEqual(result["mime_type"], "application/pdf")
+
+ def test_modulo_mime_type_indexer(self):
+ # The indexer should return the correct mime type for the Modulo.
+
+ catalog = api.portal.get_tool("portal_catalog")
+ results = catalog(UID=self.modulo_2.UID())
+ brain = results[0]
+
+ self.assertEqual(brain.mime_type, "application/pdf")
diff --git a/src/design/plone/contenttypes/upgrades/configure.zcml b/src/design/plone/contenttypes/upgrades/configure.zcml
index 5e9842d7..81108469 100644
--- a/src/design/plone/contenttypes/upgrades/configure.zcml
+++ b/src/design/plone/contenttypes/upgrades/configure.zcml
@@ -969,4 +969,11 @@
destination="7320"
handler=".to_730x.to_7320"
/>
+
diff --git a/src/design/plone/contenttypes/upgrades/to_730x.py b/src/design/plone/contenttypes/upgrades/to_730x.py
index af406683..e87f750d 100644
--- a/src/design/plone/contenttypes/upgrades/to_730x.py
+++ b/src/design/plone/contenttypes/upgrades/to_730x.py
@@ -301,3 +301,23 @@ def to_7320(context):
links = retriever.retrieveLinks()
refs = getObjectsFromLinks(servizio, links)
updateReferences(servizio, refs)
+
+
+def to_7321(context):
+
+ logger.info("### RE-ALIGN MODULES MIME-TYPES ###")
+
+ brains = api.content.find(portal_type="Modulo")
+ logger.info("Reindexing mime_type for {} Modulo objects".format(len(brains)))
+ portal_enhancedlinks = api.portal.get_tool("portal_enhancedlinks")
+ cached_uids = portal_enhancedlinks._enhanced_links
+ tot = len(brains)
+ for i, brain in enumerate(brains, start=1):
+ if i % 1000 == 0:
+ logger.info("Progress: {}/{}".format(i, tot))
+ brain.getObject().reindexObject(idxs=["mime_type"])
+ uid = brain.UID
+ if uid not in cached_uids:
+ continue
+ portal_enhancedlinks.get_enhanced_link(uid, force_reload=True)
+ logger.info("- {}".format(uid))