Skip to content

Feature: more specific mailing#1231

Merged
lodewiges merged 8 commits intostagingfrom
feature/spefic-mails
Feb 18, 2026
Merged

Feature: more specific mailing#1231
lodewiges merged 8 commits intostagingfrom
feature/spefic-mails

Conversation

@lodewiges
Copy link
Contributor

@lodewiges lodewiges commented Feb 10, 2026

Summary
Refactors credit delivery report emails to send to a single configured email address (TREASURER_EMAIL) instead of every user with the treasurer role.

Motivation
Previously, all users with the treasurer role received credit notification emails. This caused:

Administrative accounts to receive unnecessary emails

Which annoyed me a lot, so it needed to change :)

Changes

  • Modified CreditInsufficientNotificationJob to send one email to [Rails.application.config.x.treasurer_email]
  • Updated UserCreditMailer#credit_delivery_report_mail to use the configured email directly
  • Updated associated tests and mailer previews

This fixes #442 (kinda)

Summary by CodeRabbit

  • Refactor

    • Credit delivery reports are consolidated into a single report sent to the central treasurer contact configured in the app, replacing individual per‑treasurer emails. User-facing insufficient-credit emails continue to be sent as before.
  • Tests

    • Tests updated to expect the consolidated report delivery to the configured treasurer contact.
  • Documentation / Previews

    • Mailer previews updated to reflect the consolidated report signature and recipient.

Copilot AI review requested due to automatic review settings February 10, 2026 22:33
@coderabbitai
Copy link

coderabbitai bot commented Feb 10, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Replaces per-treasurer iteration with a single consolidated credit delivery report sent to the configured treasurer email (Rails.application.config.x.treasurer_email). The mailer signature is simplified to credit_delivery_report_mail(success_count, unnotifyable_users) and callers, tests, and previews are updated accordingly.

Changes

Cohort / File(s) Summary
Job
app/jobs/credit_insufficient_notification_job.rb
Removed loop over User.treasurer; now calls UserCreditMailer.credit_delivery_report_mail(success_count, unnotifyable_users).deliver_later once.
Mailer
app/mailers/user_credit_mailer.rb
Changed credit_delivery_report_mail signature to (success_count, unnotifyable_users); @user is now a Struct using Rails.application.config.x.treasurer_name; recipient changed to Rails.application.config.x.treasurer_email; added RuboCop disables around method body.
Tests & Previews
spec/jobs/credit_insufficient_notification_job_spec.rb, spec/mailers/previews/user_credit_mailer_preview.rb
Removed treasurer user setup and references; updated expectations and preview call to the new mailer signature and to use Rails.application.config.x.treasurer_email.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I hopped through lines of midnight code,
One tidy change along the road,
A single note now takes to air,
No scattered sends — a lighter care,
🥕✨ — From your rabbit, neatly stowed.

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (1 warning, 2 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Feature: more specific mailing' is vague and generic, failing to convey meaningful details about the changeset. Use a more specific title such as 'Refactor treasurer email delivery to use configured address' to clearly describe the main change.
Linked Issues check ❓ Inconclusive The PR partially addresses issue #442 by reducing email surface but does not implement the main objective of periodic role synchronization. Clarify whether this PR is intended as a temporary mitigation or if role synchronization implementation is planned separately.
✅ Passed checks (2 passed)
Check name Status Explanation
Description check ✅ Passed The PR description provides summary, motivation, and changes but does not follow the template structure with checklist sections for database migrations and other standard sections.
Out of Scope Changes check ✅ Passed All changes are directly related to the PR objective of refactoring treasurer email delivery to use a configured address instead of per-user sending.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/spefic-mails

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.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors the credit delivery report email system to send notifications to a single configured email address (TREASURER_EMAIL) instead of iterating through all users with the treasurer role. This change reduces email duplication, prevents administrative accounts from receiving unnecessary notifications, and decouples notification recipients from user roles.

Changes:

  • Removed the loop over User.treasurer in favor of a single email to the configured treasurer address
  • Updated the credit_delivery_report_mail method signature to remove the treasurer parameter
  • Updated tests and mailer previews to reflect the new method signature

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
app/jobs/credit_insufficient_notification_job.rb Simplified notification sending by removing the loop over treasurer users and sending a single email to the configured address
app/mailers/user_credit_mailer.rb Removed the treasurer parameter and updated the email recipient to use Rails.application.config.x.treasurer_email
spec/jobs/credit_insufficient_notification_job_spec.rb Removed the treasurer user fixture and updated the test to verify email is sent to the configured address
spec/mailers/previews/user_credit_mailer_preview.rb Updated the preview to match the new method signature without the treasurer parameter

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@codecov
Copy link

codecov bot commented Feb 10, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 77.59%. Comparing base (b6a0b0e) to head (2f133d2).
⚠️ Report is 1 commits behind head on staging.

Additional details and impacted files
@@             Coverage Diff             @@
##           staging    #1231      +/-   ##
===========================================
- Coverage    77.61%   77.59%   -0.02%     
===========================================
  Files           54       54              
  Lines         1407     1406       -1     
===========================================
- Hits          1092     1091       -1     
  Misses         315      315              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 11 to 19
@unnotifyable_users = unnotifyable_users
@success_count = success_count
@title = 'Notificatie over de saldomail'

subject = "Er is #{@success_count.positive? ? 'een' : 'geen'} saldomail verstuurd"

mail to: treasurer.email, subject:
mail to: Rails.application.config.x.treasurer_email, subject:
end

Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

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

credit_delivery_report_mail no longer sets @user, but the shared mailer layout renders Beste <%= @user.name %>, (see app/views/layouts/mailer.html.erb:364). This will raise a NoMethodError when generating the report email. Set @user to a suitable object (e.g., a lightweight struct using config.x.treasurer_name/treasurer_title) or update the mailer layout to handle the report mail without requiring @user.

Copilot uses AI. Check for mistakes.
subject = "Er is #{@success_count.positive? ? 'een' : 'geen'} saldomail verstuurd"

mail to: treasurer.email, subject:
mail to: Rails.application.config.x.treasurer_email, subject:
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

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

The report email template currently won’t display the success count because it uses a non-output ERB tag (<% @success_count %>) instead of <%= @success_count %> in app/views/user_credit_mailer/credit_delivery_report_mail.html.erb:4. Since this PR changes how the report is delivered, it’s worth fixing so the email contains the intended information.

Suggested change
mail to: Rails.application.config.x.treasurer_email, subject:
mail to: Rails.application.config.x.treasurer_email, subject: subject

Copilot uses AI. Check for mistakes.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
app/mailers/user_credit_mailer.rb (1)

18-18: TREASURER_EMAIL unconfigured silently falls back to treasurer@example.com.

With this change the configured address is now the sole recipient. If TREASURER_EMAIL is not set in a production or staging environment, credit delivery reports will route to treasurer@example.com (the default in config/application.rb Line 63) with no error or warning. Consider adding a startup check or at minimum a log warning when the value matches the default placeholder, so misconfiguration is detected early.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/mailers/user_credit_mailer.rb` at line 18, The mailer call in
UserCreditMailer (the mail line using
Rails.application.config.x.treasurer_email) will silently send to the default
treasurer@example.com when TREASURER_EMAIL is not configured; add a detection +
warning so misconfiguration is visible: implement a small check (either in an
application initializer or in UserCreditMailer.before_action/initialize) that
compares Rails.application.config.x.treasurer_email against the known
placeholder "treasurer@example.com" and logs a WARN/error message (including the
current environment) when they match, and optionally raise or notify depending
on env (e.g., raise in production/staging or fail fast at startup). Ensure the
check references the exact config key
(Rails.application.config.x.treasurer_email) and the mailer class name
(UserCreditMailer) so it triggers before sending.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@app/mailers/user_credit_mailer.rb`:
- Line 18: The mailer call in UserCreditMailer (the mail line using
Rails.application.config.x.treasurer_email) will silently send to the default
treasurer@example.com when TREASURER_EMAIL is not configured; add a detection +
warning so misconfiguration is visible: implement a small check (either in an
application initializer or in UserCreditMailer.before_action/initialize) that
compares Rails.application.config.x.treasurer_email against the known
placeholder "treasurer@example.com" and logs a WARN/error message (including the
current environment) when they match, and optionally raise or notify depending
on env (e.g., raise in production/staging or fail fast at startup). Ensure the
check references the exact config key
(Rails.application.config.x.treasurer_email) and the mailer class name
(UserCreditMailer) so it triggers before sending.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
app/mailers/user_credit_mailer.rb (1)

17-17: Placeholder fallback treasurer@example.com will silently swallow emails if TREASURER_EMAIL is unset.

From config/application.rb:

config.x.treasurer_email = ENV.fetch('TREASURER_EMAIL', 'treasurer@example.com')

If TREASURER_EMAIL is not configured in a deployment environment, every credit delivery report will be silently delivered to a non-existent placeholder address rather than failing loudly. This PR concentrates all treasurer notifications to this single address, which makes the misconfiguration risk higher than before — previously, at least some real users would still receive the email.

Consider replacing the soft default with a hard KeyError at startup, or adding an initializer check:

🔧 Suggested change in config/application.rb
- config.x.treasurer_email = ENV.fetch('TREASURER_EMAIL', 'treasurer@example.com')
+ config.x.treasurer_email = ENV.fetch('TREASURER_EMAIL')

Or, if a fallback is required for non-production environments, guard it explicitly:

- config.x.treasurer_email = ENV.fetch('TREASURER_EMAIL', 'treasurer@example.com')
+ config.x.treasurer_email = ENV.fetch('TREASURER_EMAIL') do
+   raise "TREASURER_EMAIL must be configured" if Rails.env.production?
+   'treasurer@example.com'
+ end
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/mailers/user_credit_mailer.rb` at line 17, The mailer currently uses a
soft default treasurer@example.com via config.x.treasurer_email which will
silently swallow real reports; remove the fallback and make TREASURER_EMAIL
required by changing the config to use ENV.fetch('TREASURER_EMAIL') with no
default (or add an application initializer that raises if ENV['TREASURER_EMAIL']
is blank in non-development/test), and keep app/mailers/user_credit_mailer.rb
referencing Rails.application.config.x.treasurer_email unchanged so any missing
config surfaces as a startup error rather than routing emails to the
placeholder.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@app/mailers/user_credit_mailer.rb`:
- Line 17: The mailer currently uses a soft default treasurer@example.com via
config.x.treasurer_email which will silently swallow real reports; remove the
fallback and make TREASURER_EMAIL required by changing the config to use
ENV.fetch('TREASURER_EMAIL') with no default (or add an application initializer
that raises if ENV['TREASURER_EMAIL'] is blank in non-development/test), and
keep app/mailers/user_credit_mailer.rb referencing
Rails.application.config.x.treasurer_email unchanged so any missing config
surfaces as a startup error rather than routing emails to the placeholder.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
app/mailers/user_credit_mailer.rb (2)

10-10: rubocop:disable Metrics/AbcSize is likely only needed because of the Struct.new chain.

The chained .new(:name).new(...) call adds extra branches that inflate the ABC score. If the Struct is extracted to a constant (as suggested above), this disable directive can probably be removed, keeping the metrics cop active as a natural quality gate.

Also applies to: 23-23

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/mailers/user_credit_mailer.rb` at line 10, The Metrics/AbcSize disable in
user_credit_mailer.rb was added to suppress the inflated ABC score caused by the
chained Struct.new(...).new(...) pattern; extract the temporary Struct into a
named constant (e.g., define a USER_CREDIT_STRUCT = Struct.new(:name) or similar
at top-level or inside the class) and replace the chained .new(...) usage with
calls to that constant, which eliminates the extra branches and lets you remove
the `# rubocop:disable Metrics/AbcSize` directive (also update the similar
occurrence around line 23) so RuboCop can enforce the ABC metric normally.

21-21: Ensure TREASURER_EMAIL is set in all environments to avoid silent misdelivery.

Rails.application.config.x.treasurer_email falls back to 'treasurer@example.com' when the env var is absent. Since this mailer now sends all credit delivery reports to this single address, a missing or misconfigured env var in staging/production will silently route all reports to a placeholder address with no error raised.

Consider adding a startup check (e.g., in an initializer) to assert that TREASURER_EMAIL is present and non-default before the application boots in production.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/mailers/user_credit_mailer.rb` at line 21, Add a startup assertion that
the TREASURER_EMAIL env var is set and not the default placeholder to prevent
silent misdelivery; create an initializer that reads
Rails.application.config.x.treasurer_email (the same config used in
user_credit_mailer.rb) and, in production (or any non-development env), raise or
abort boot if the value is blank or equals 'treasurer@example.com' so the app
fails fast when the treasurer address is misconfigured.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/mailers/user_credit_mailer.rb`:
- Around line 12-14: Extract the anonymous Struct into a class-level constant
(e.g., TREASURER = Struct.new(:name)) and stop creating a new Struct on each
call; then fetch the configured treasurer name into a local (e.g.,
treasurer_name = Rails.application.config.x.treasurer_name.presence ||
'Treasurer') and instantiate `@user` via `@user` = TREASURER.new(treasurer_name) so
`@user.name` is never nil and the Struct allocation is constant across
invocations.

---

Nitpick comments:
In `@app/mailers/user_credit_mailer.rb`:
- Line 10: The Metrics/AbcSize disable in user_credit_mailer.rb was added to
suppress the inflated ABC score caused by the chained Struct.new(...).new(...)
pattern; extract the temporary Struct into a named constant (e.g., define a
USER_CREDIT_STRUCT = Struct.new(:name) or similar at top-level or inside the
class) and replace the chained .new(...) usage with calls to that constant,
which eliminates the extra branches and lets you remove the `# rubocop:disable
Metrics/AbcSize` directive (also update the similar occurrence around line 23)
so RuboCop can enforce the ABC metric normally.
- Line 21: Add a startup assertion that the TREASURER_EMAIL env var is set and
not the default placeholder to prevent silent misdelivery; create an initializer
that reads Rails.application.config.x.treasurer_email (the same config used in
user_credit_mailer.rb) and, in production (or any non-development env), raise or
abort boot if the value is blank or equals 'treasurer@example.com' so the app
fails fast when the treasurer address is misconfigured.

Comment on lines +12 to +14
@user = Struct.new(:name).new(
Rails.application.config.x.treasurer_name
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Extract the Struct to a constant and guard against a nil treasurer name.

Two concerns here:

  1. Struct.new(:name) anti-patternStruct.new(...) inside an instance method creates an unnecessary new anonymous class on every invocation, which also creates new independent entries in the method cache. Since treasurer_name is a single static field, define the Struct as a class-level constant instead.

  2. Silent blank nameconfig/application.rb sets treasurer_name to ENV.fetch('TREASURER_NAME', nil), so @user.name will be nil when the env var is absent. If the template uses @user.name in a greeting, it renders blank with no warning.

♻️ Proposed fix
+  TreasurerRecipient = Struct.new(:name)
+
   # rubocop:disable Metrics/AbcSize
   def credit_delivery_report_mail(success_count, unnotifyable_users)
-    `@user` = Struct.new(:name).new(
-      Rails.application.config.x.treasurer_name
-    )
+    `@user` = TreasurerRecipient.new(
+      Rails.application.config.x.treasurer_name || 'Treasurer'
+    )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@user = Struct.new(:name).new(
Rails.application.config.x.treasurer_name
)
TreasurerRecipient = Struct.new(:name)
# rubocop:disable Metrics/AbcSize
def credit_delivery_report_mail(success_count, unnotifyable_users)
`@user` = TreasurerRecipient.new(
Rails.application.config.x.treasurer_name || 'Treasurer'
)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/mailers/user_credit_mailer.rb` around lines 12 - 14, Extract the
anonymous Struct into a class-level constant (e.g., TREASURER =
Struct.new(:name)) and stop creating a new Struct on each call; then fetch the
configured treasurer name into a local (e.g., treasurer_name =
Rails.application.config.x.treasurer_name.presence || 'Treasurer') and
instantiate `@user` via `@user` = TREASURER.new(treasurer_name) so `@user.name` is
never nil and the Struct allocation is constant across invocations.

@lodewiges lodewiges enabled auto-merge February 18, 2026 10:36
Copy link

@PvanBelle PvanBelle left a comment

Choose a reason for hiding this comment

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

prima met engels accent

@lodewiges lodewiges added this pull request to the merge queue Feb 18, 2026
Merged via the queue into staging with commit 68ff0a4 Feb 18, 2026
6 checks passed
@lodewiges lodewiges deleted the feature/spefic-mails branch February 18, 2026 10:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rollen van gebruiker worden alleen gesynchroniseerd na login

2 participants

Comments