Skip to content

URB-3650: Error handling (+ mailing content rule) for Notice forms#584

Open
daggelpop wants to merge 4 commits into
2.9.xfrom
URB-3650_notice_form_error_handling
Open

URB-3650: Error handling (+ mailing content rule) for Notice forms#584
daggelpop wants to merge 4 commits into
2.9.xfrom
URB-3650_notice_form_error_handling

Conversation

@daggelpop

@daggelpop daggelpop commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Added failure notifications for NOTICE form response errors, including automatic event-triggered alerts.
    • Introduced an automatic mailing content rule to notify support when NOTICE response handling fails.
  • Improvements

    • Strengthened error handling for NOTICE response processing, with clearer user messages and more precise failure classification.
    • Improved robustness when sending NOTICE-related files by safely handling per-file failures.
    • Updated French translations for NOTICE request-processing and response-failure messages.

@daggelpop daggelpop requested a review from mpeeters June 18, 2026 09:44
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@daggelpop, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 39 minutes and 27 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0f3ac985-f29b-43b6-9bd3-2a843dc4350e

📥 Commits

Reviewing files that changed from the base of the PR and between 7ff4f0f and bb05258.

📒 Files selected for processing (1)
  • src/Products/urban/browser/notice_forms.py
📝 Walkthrough

Walkthrough

This PR adds structured exception handling for NOTICE webservice failures by introducing a NoticeResponseException hierarchy, refactoring WebserviceNotice._handle_error to raise typed exceptions instead of returning error dicts, and updating NoticeResponseActionForm to emit NoticeResponseFailedEvent on failures. A migration upgrade step (2915→2916) provisions a Plone mailing content rule triggered by that event.

Changes

NOTICE Form Error Handling & Mailing Content Rule

Layer / File(s) Summary
NOTICE response exception hierarchy
src/Products/urban/notice/exceptions.py
Adds NoticeResponseException base with i18n get_user_message() and five typed subclasses (UnprocessableEntityException, WrongStatusException, MissingNotificationException, MalformedFieldException, MissingFieldException) covering all webservice error categories.
Webservice error handling refactor
src/Products/urban/services/notice.py
Rewrites _handle_error to raise typed exceptions from HTTP status codes and SOAP error code/category pairs. Updates post_notification_response and post_notification_document to raise instead of returning error dicts.
Content rule event type and ZCML registration
src/Products/urban/contentrules/notice.py, src/Products/urban/contentrules/configure.zcml
Adds INoticeResponseFailedEvent interface and NoticeResponseFailedEvent ObjectEvent. Registers the interface as an IRuleEventType in ZCML.
Form error handling and event emission
src/Products/urban/browser/notice_forms.py
Adds _notify_response_error helper that emits NoticeResponseFailedEvent. Wraps transfer_response and each transfer_notice_file call in try/except blocks that set status messages and invoke the helper.
Migration upgrade step and localization
src/Products/urban/migration/update_290.py, src/Products/urban/migration/upgrades_290.zcml, src/Products/urban/profiles/default/metadata.xml, src/Products/urban/locales/..., news/URB-3650.feature
Adds setup_notice_form_error_mailing_content_rule provisioning a notification_form_failed Plone content rule with a mail action. Registers as upgrade step 2915→2916, bumps profile version, and syncs .pot/.po translation catalogs.

Sequence Diagram(s)

sequenceDiagram
  rect rgba(173, 216, 230, 0.5)
    Note over NoticeResponseActionForm,NoticeResponseFailedEvent: Response Transfer Flow
    NoticeResponseActionForm->>WebserviceNotice: transfer_response(data)
    alt NoticeResponseException raised
      WebserviceNotice-->>NoticeResponseActionForm: NoticeResponseException
      NoticeResponseActionForm->>NoticeResponseActionForm: set error status (get_user_message)
      NoticeResponseActionForm->>NoticeResponseFailedEvent: _notify_response_error(notice_id, error_report)
      NoticeResponseFailedEvent->>ContentRule: trigger INoticeResponseFailedEvent
      ContentRule->>MailAction: send failure email to support
    else Generic exception raised
      WebserviceNotice-->>NoticeResponseActionForm: Exception
      NoticeResponseActionForm->>NoticeResponseActionForm: set generic error status + log
      NoticeResponseActionForm->>NoticeResponseFailedEvent: _notify_response_error(notice_id, str(exc))
    end
  end
  rect rgba(144, 238, 144, 0.5)
    Note over NoticeResponseActionForm,WebserviceNotice: Per-File Transfer Flow
    loop each file
      NoticeResponseActionForm->>WebserviceNotice: transfer_notice_file(file)
      alt success
        WebserviceNotice-->>NoticeResponseActionForm: file metadata
        NoticeResponseActionForm->>NoticeResponseActionForm: append to sent_documents
      else Exception
        WebserviceNotice-->>NoticeResponseActionForm: Exception
        NoticeResponseActionForm->>NoticeResponseFailedEvent: _notify_response_error(notice_id, str(exc))
      end
    end
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • mpeeters

Poem

🐇 A NOTICE once failed with a frown,
No dict could be passed up or down.
Exceptions now soar,
Events knock the door,
And the mailbox sends alerts to town! 📬

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: adding error handling for Notice forms and setting up a mailing content rule for failures.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch URB-3650_notice_form_error_handling

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Products/urban/browser/notice_forms.py`:
- Around line 218-220: The NoticeResponseFailedEvent is being emitted with an
event_wrapper built from the Urban folder context instead of the current form
context, which breaks context-driven mail template substitutions like
${parent_url}. Replace the use of api.portal.get().urban in the IContextWrapper
initialization with the appropriate current form context (such as self or the
relevant dossier/event object) so that NoticeResponseFailedEvent receives the
correct contextual information for the mail template to resolve its
substitutions properly.
- Around line 269-277: The exception handling in the `transfer_notice_file`
method call is too broad and drops typed exception handling. Instead of catching
only generic Exception, add a specific catch for NoticeResponseException before
the generic Exception handler to preserve its localized user message and
structured error reporting path. The NoticeResponseException should be handled
to properly utilize its built-in error messaging, while the generic Exception
handler can serve as a fallback for unexpected errors. This ensures that typed
exceptions from the NOTICE webservice layer are not lost in translation.

In `@src/Products/urban/locales/fr/LC_MESSAGES/urban.po`:
- Around line 314-317: The French translation in the msgstr line for the
notification error message contains the incorrect word "status" instead of the
proper French translation "statut". In the error message string in the urban.po
file, change "status inapproprié" to "statut inapproprié" to ensure proper
French language usage in the UI.

In `@src/Products/urban/services/notice.py`:
- Around line 219-271: The code directly accesses nested dictionary keys
error["code"]["code"] and error["category"] without validation, which will raise
KeyError if the SOAP WS response contains a partial error payload. Before
branching on these conditions throughout the entire error handling block,
validate that these keys exist using safe dictionary access methods like .get()
with appropriate defaults, or add explicit existence checks. Apply this
validation to all the conditional branches that check error["code"]["code"] and
error["category"] to ensure malformed responses are caught and handled
gracefully by falling through to the default NoticeResponseException case
instead of raising uncaught exceptions.
- Around line 286-293: Wrap the response.json() call and the status check (lines
286-287) in a try-except block that catches ValueError and KeyError exceptions.
When either of these exceptions occur (indicating malformed JSON body or missing
status field), instantiate and raise a NoticeResponseException to maintain the
exception hierarchy contract. This ensures that JSON parsing failures and
missing status keys are treated as NoticeResponseException rather than raw
exceptions, keeping all NOTICE WS response errors consistent within your
exception hierarchy.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fc3799ed-bb21-4bd3-9ee4-b61fade077f1

📥 Commits

Reviewing files that changed from the base of the PR and between 28e1a7b and c34ac96.

📒 Files selected for processing (11)
  • news/URB-3650.feature
  • src/Products/urban/browser/notice_forms.py
  • src/Products/urban/contentrules/configure.zcml
  • src/Products/urban/contentrules/notice.py
  • src/Products/urban/locales/fr/LC_MESSAGES/urban.po
  • src/Products/urban/locales/urban.pot
  • src/Products/urban/migration/update_290.py
  • src/Products/urban/migration/upgrades_290.zcml
  • src/Products/urban/notice/exceptions.py
  • src/Products/urban/profiles/default/metadata.xml
  • src/Products/urban/services/notice.py

Comment thread src/Products/urban/browser/notice_forms.py Outdated
Comment thread src/Products/urban/browser/notice_forms.py
Comment thread src/Products/urban/locales/fr/LC_MESSAGES/urban.po
Comment thread src/Products/urban/services/notice.py
Comment thread src/Products/urban/services/notice.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant