From 95d25f838a784908667fc9dd22271da0b9ea3fcf Mon Sep 17 00:00:00 2001
From: "coderabbitai[bot]"
<136622811+coderabbitai[bot]@users.noreply.github.com>
Date: Thu, 16 Apr 2026 08:17:13 +0000
Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20CodeRabbit=20Chat:=20Implement?=
=?UTF-8?q?=20requested=20code=20changes?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docs/CHANGES.rst | 22 ++++++-
setup.py | 4 +-
src/Products/urban/config.py | 4 +-
src/Products/urban/docgen/helper_view.py | 3 +-
src/Products/urban/interfaces.py | 4 +-
src/Products/urban/migration/update_290.py | 11 ++++
.../urban/migration/upgrades_290.zcml | 10 ++-
src/Products/urban/notice/parcel.py | 5 +-
.../urban/profiles/default/metadata.xml | 4 +-
.../profiles/urban_types/factorytool.xml | 3 +-
src/Products/urban/setuphandlers.py | 39 ++++++++++-
src/Products/urban/workflows/configure.zcml | 9 ++-
.../urban/workflows/housing_workflow.py | 66 +++++++++++++++++++
13 files changed, 168 insertions(+), 16 deletions(-)
mode change 100755 => 100644 src/Products/urban/config.py
create mode 100644 src/Products/urban/workflows/housing_workflow.py
diff --git a/docs/CHANGES.rst b/docs/CHANGES.rst
index 56b37ae89..36e4f1d5d 100644
--- a/docs/CHANGES.rst
+++ b/docs/CHANGES.rst
@@ -8,6 +8,26 @@ Changelog
.. towncrier release notes start
+2.9.17 (2026-04-10)
+-------------------
+
+Bug fixes:
+
+
+- Fix missing import
+ [jchandelle] (SUP-52327)
+
+
+2.9.16 (2026-04-09)
+-------------------
+
+Bug fixes:
+
+
+- Fix housing security and local role
+ [jchandelle] (URB-3573)
+
+
2.9.15 (2026-04-02)
-------------------
@@ -2062,4 +2082,4 @@ bugfixes:
- corrected template "accuse de reception d'une reclamation" (#5168, #5198).
- corrected the display of the specificFeatures for notary letters.
- The "50m area" used in inquiries doesnt crash anymore when finding parcel owner without address (#5376).
-- Added warning on inquiry event when parcel owners without adress are found (#5289).
+- Added warning on inquiry event when parcel owners without adress are found (#5289).
\ No newline at end of file
diff --git a/setup.py b/setup.py
index e125a0114..c657b9360 100644
--- a/setup.py
+++ b/setup.py
@@ -4,7 +4,7 @@
import os
-version = "2.9.16.dev0"
+version = "2.9.18.dev0"
setup(
name="Products.urban",
@@ -113,4 +113,4 @@
"templates_per_site = Products.urban.templates:per_site",
],
},
-)
+)
\ No newline at end of file
diff --git a/src/Products/urban/config.py b/src/Products/urban/config.py
old mode 100755
new mode 100644
index 385292168..e77cd41c5
--- a/src/Products/urban/config.py
+++ b/src/Products/urban/config.py
@@ -123,6 +123,7 @@ def section(self, section_name):
"ExplosivesPossession": "urban: Add ExplosivesPossession",
"Inspection": "urban: Add Inspection",
"RoadDecree": "urban: Add RoadDecree",
+ "Housing": "urban: Add Housing",
}
setDefaultRoles("urban: Add Applicant", ("Manager", "Contributor"))
@@ -186,6 +187,7 @@ def section(self, section_name):
setDefaultRoles("urban: Add UrbanVocabularyTerm", ("Manager", "Contributor"))
setDefaultRoles("urban: Add ExplosivesPossession", ("Manager", "Contributor"))
setDefaultRoles("urban: Add RoadDecree", ("Manager", "Contributor"))
+setDefaultRoles("urban: Add Housing", ("Manager", "Contributor"))
product_globals = globals()
@@ -513,4 +515,4 @@ def registerClasses():
# Unregister the class
del Products.Archetypes.ATToolModule._types[key]
delattr(klass, "__ac_permissions__")
- registerType(klass, PROJECTNAME)
+ registerType(klass, PROJECTNAME)
\ No newline at end of file
diff --git a/src/Products/urban/docgen/helper_view.py b/src/Products/urban/docgen/helper_view.py
index 8520d6671..cdb0de94f 100644
--- a/src/Products/urban/docgen/helper_view.py
+++ b/src/Products/urban/docgen/helper_view.py
@@ -11,6 +11,7 @@
from Products.urban.interfaces import IUrbanEventInquiry
from Products.urban.services import cadastre
from Products.urban.utils import get_ws_meetingitem_infos
+from Products.urban.utils import get_ws_plonemeeting
from Products.urban.utils import getCurrentFolderManager
from collective.documentgenerator.helper.archetypes import ATDisplayProxyObject
from collective.documentgenerator.helper.archetypes import (
@@ -1473,4 +1474,4 @@ def format_date(self, folder, date=None, translatemonth=True, long_format=False)
class UrbanBaseProxyObject(ATDisplayProxyObject):
""" """
- helper_view = None
+ helper_view = None
\ No newline at end of file
diff --git a/src/Products/urban/interfaces.py b/src/Products/urban/interfaces.py
index d0e1edde8..1e9e119c5 100644
--- a/src/Products/urban/interfaces.py
+++ b/src/Products/urban/interfaces.py
@@ -341,7 +341,7 @@ class IInspection(IGenericLicence):
class IHousing(IGenericLicence):
"""
- Marker interface for inspection
+ Marker interface for housing
"""
@@ -760,4 +760,4 @@ class IIntentionToSubmitAmendedPlans(Interface):
class IMissingCapakey(Interface):
- """ """
+ """ """
\ No newline at end of file
diff --git a/src/Products/urban/migration/update_290.py b/src/Products/urban/migration/update_290.py
index ea2af7684..109133b2d 100644
--- a/src/Products/urban/migration/update_290.py
+++ b/src/Products/urban/migration/update_290.py
@@ -4,6 +4,7 @@
from Products.urban import UrbanMessage as _
from Products.urban.migration.utils import cook_javascript_resources
from Products.urban.utils import moveElementAfter
+from Products.urban.setuphandlers import set_licence_folder_security
from dm.historical import getHistory
from imio.helpers.catalog import reindexIndexes
from plone import api
@@ -325,3 +326,13 @@ def setup_index_referenceFT(context):
reindexIndexes(None, ["referenceFT"])
logger.info("upgrade step done!")
+
+
+def fix_housing_roaddecree(context):
+ logger = logging.getLogger("urban: Fix housing and roaddecree security")
+ setup_tool = api.portal.get_tool("portal_setup")
+ setup_tool.runImportStepFromProfile("profile-Products.urban:urbantypes", "factorytool")
+ portal_types = ["Housing", "RoadDecree"]
+ for portal_type in portal_types:
+ set_licence_folder_security(portal_type)
+ logger.info("upgrade step done!")
\ No newline at end of file
diff --git a/src/Products/urban/migration/upgrades_290.zcml b/src/Products/urban/migration/upgrades_290.zcml
index 55e881a42..3615102bc 100644
--- a/src/Products/urban/migration/upgrades_290.zcml
+++ b/src/Products/urban/migration/upgrades_290.zcml
@@ -76,4 +76,12 @@
handler=".update_290.setup_index_referenceFT"
profile="Products.urban:default" />
-
+
+
+
\ No newline at end of file
diff --git a/src/Products/urban/notice/parcel.py b/src/Products/urban/notice/parcel.py
index 5d907ca2b..3578dfce9 100644
--- a/src/Products/urban/notice/parcel.py
+++ b/src/Products/urban/notice/parcel.py
@@ -4,6 +4,7 @@
from Products.urban.notice.base import NoticeElement
from plone import api
+
class NoticeParcel(NoticeElement):
_excluded_keys = (
"parcel",
@@ -81,7 +82,7 @@ def resolved_division(self):
code = self._get_data("codeDivision")
if code:
return code
- #do mapping
+ # do mapping
division_name = self.division_text
if not division_name:
return None
@@ -94,4 +95,4 @@ def resolved_division(self):
for div in divisions
if div.get("alternative_name") and div.get("division")
}
- return mapping.get(division_name)
+ return mapping.get(division_name)
\ No newline at end of file
diff --git a/src/Products/urban/profiles/default/metadata.xml b/src/Products/urban/profiles/default/metadata.xml
index 69feb0553..0a6c6cc3e 100644
--- a/src/Products/urban/profiles/default/metadata.xml
+++ b/src/Products/urban/profiles/default/metadata.xml
@@ -1,7 +1,7 @@
- 2908
+ 2909
profile-Products.urban:preinstall
-
+
\ No newline at end of file
diff --git a/src/Products/urban/profiles/urban_types/factorytool.xml b/src/Products/urban/profiles/urban_types/factorytool.xml
index 9b7f6ec82..f3aef21d1 100644
--- a/src/Products/urban/profiles/urban_types/factorytool.xml
+++ b/src/Products/urban/profiles/urban_types/factorytool.xml
@@ -71,5 +71,6 @@
+
-
+
\ No newline at end of file
diff --git a/src/Products/urban/setuphandlers.py b/src/Products/urban/setuphandlers.py
index 6d602401e..64564dd3f 100644
--- a/src/Products/urban/setuphandlers.py
+++ b/src/Products/urban/setuphandlers.py
@@ -1862,7 +1862,8 @@ def check_if_type_already_install(urban_type):
def add_new_urban_licence_type(urban_type):
if check_if_type_already_install(urban_type):
return False
- add_aplication_folder(urban_type)
+ licence_folder = add_aplication_folder(urban_type)
+ set_licence_folder_security(urban_type, licence_folder)
add_imio_dashboard(urban_type)
config_folder = add_urban_config_folder(urban_type)
add_schedule(config_folder, urban_type)
@@ -1940,6 +1941,40 @@ def add_aplication_folder(urban_type, urban_folder=None):
acquire=0,
)
urban_folder.moveObjectsToBottom([licence_folder_id])
+ return licence_folder
+
+def set_licence_folder_security(urban_type, urban_folder=None):
+ if urban_folder is None:
+ site = api.portal.get()
+ urban_folder = getattr(site, "urban")
+ licencesfolder_names = getAllLicenceFolderIds()
+ urban_folder_names = getUrbanOnlyLicenceFolderIds()
+ uniquelicences_names = [
+ getLicenceFolderId("UniqueLicence"),
+ getLicenceFolderId("CODT_UniqueLicence"),
+ getLicenceFolderId("IntegratedLicence"),
+ getLicenceFolderId("CODT_IntegratedLicence"),
+ ]
+ environment_folder_names = getEnvironmentLicenceFolderIds() + uniquelicences_names
+ try:
+ # we try in case we apply the profile again...
+ urban_folder.manage_addProperty(
+ "urbanConfigId", urban_type, "string"
+ )
+ except BadRequest:
+ pass
+ urban_folder.manage_delLocalRoles(["urban_editors"])
+ urban_folder.manage_delLocalRoles(["environment_editors"])
+ if getLicenceFolderId(urban_type) in urban_folder_names:
+ urban_folder.manage_addLocalRoles("urban_readers", ("Reader",))
+ if urban_type != "CODT_IntegratedLicence":
+ urban_folder.manage_addLocalRoles("urban_editors", ("Contributor",))
+ if getLicenceFolderId(urban_type) in environment_folder_names:
+ urban_folder.manage_addLocalRoles("environment_readers", ("Reader",))
+ if urban_type != "CODT_IntegratedLicence":
+ urban_folder.manage_addLocalRoles("environment_editors", ("Contributor",))
+ if urban_type == "Inspection":
+ urban_folder.manage_addLocalRoles("inspection_editors", ("Contributor",))
def add_imio_dashboard(urban_type, urban_folder=None):
@@ -2089,4 +2124,4 @@ def add_vocabularies(config_folder, urban_type):
for voc_folder_id in config_folder.objectIds():
if voc_folder_id in vocabularies_with_HTML_description:
voc_folder = getattr(config_folder, voc_folder_id)
- setHTMLContentType(voc_folder, "description")
+ setHTMLContentType(voc_folder, "description")
\ No newline at end of file
diff --git a/src/Products/urban/workflows/configure.zcml b/src/Products/urban/workflows/configure.zcml
index b531ed8cd..5fe68b471 100644
--- a/src/Products/urban/workflows/configure.zcml
+++ b/src/Products/urban/workflows/configure.zcml
@@ -45,6 +45,13 @@
name="ticket_local_roles"
/>
+
+
-
+
\ No newline at end of file
diff --git a/src/Products/urban/workflows/housing_workflow.py b/src/Products/urban/workflows/housing_workflow.py
new file mode 100644
index 000000000..fe29c9d85
--- /dev/null
+++ b/src/Products/urban/workflows/housing_workflow.py
@@ -0,0 +1,66 @@
+# -*- coding: utf-8 -*-
+
+from Products.urban.workflows.licence_workflow import (
+ StateRolesMapping as BaseRoleMapping,
+)
+
+
+class StateRolesMapping(BaseRoleMapping):
+ """ """
+
+ mapping = {
+ "creation": {
+ BaseRoleMapping.get_readers: ("Reader",),
+ BaseRoleMapping.get_editors: (
+ "Editor",
+ "Reviewer",
+ "Contributor",
+ ),
+ BaseRoleMapping.get_opinion_editors: ("Reviewer", "Contributor"),
+ },
+ "analysis": {
+ BaseRoleMapping.get_readers: ("Reader",),
+ BaseRoleMapping.get_editors: (
+ "Editor",
+ "Reviewer",
+ "Contributor",
+ ),
+ BaseRoleMapping.get_opinion_editors: ("Reviewer", "Contributor"),
+ },
+ "1st_observation": {
+ BaseRoleMapping.get_readers: ("Reader",),
+ BaseRoleMapping.get_editors: (
+ "Editor",
+ "Reviewer",
+ "Contributor",
+ ),
+ BaseRoleMapping.get_opinion_editors: ("Reviewer", "Contributor"),
+ },
+ "2nd_observation": {
+ BaseRoleMapping.get_readers: ("Reader",),
+ BaseRoleMapping.get_editors: (
+ "Editor",
+ "Reviewer",
+ "Contributor",
+ ),
+ BaseRoleMapping.get_opinion_editors: ("Reviewer", "Contributor"),
+ },
+ "ended": {
+ BaseRoleMapping.get_readers: ("Reader",),
+ BaseRoleMapping.get_editors: (
+ "Editor",
+ "Reviewer",
+ "Contributor",
+ ),
+ BaseRoleMapping.get_opinion_editors: ("Reviewer", "Contributor"),
+ },
+ "annual_observation": {
+ BaseRoleMapping.get_readers: ("Reader",),
+ BaseRoleMapping.get_editors: (
+ "Editor",
+ "Reviewer",
+ "Contributor",
+ ),
+ BaseRoleMapping.get_opinion_editors: ("Reviewer", "Contributor"),
+ },
+ }
\ No newline at end of file