Skip to content

Reject in-progress current year in web digest generation - #3565

Merged
Freika merged 1 commit into
masterfrom
detail/bug-fix/reject-in-progress-current-year-in-web-digest-gene-9d64b8
Sep 9, 2026
Merged

Reject in-progress current year in web digest generation#3565
Freika merged 1 commit into
masterfrom
detail/bug-fix/reject-in-progress-current-year-in-web-digest-gene-9d64b8

Conversation

@detail-app

@detail-app detail-app Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Detail bug report: View on Detail

Bug

The web Users::DigestsController#create action gates year-end digest generation on a valid_year? helper whose upper-bound check used a strict > comparison, so year == Time.current.year was accepted and a Users::Digests::Yearly::CalculatingJob was enqueued for the still-in-progress year. The API controller (Api::V1::DigestsController#valid_year?) already used >= and rejected the current year, and the rest of the system — the yearly auto-scheduler (SchedulingJob targets 1.year.ago.year) and both controllers' dropdown builders (available_years_for_generation subtracts [Time.current.year]) — treats year-end digests as valid only for complete, past years. The web valid_year? was the lone outlier.

Impact: a signed-in user making an out-of-band POST /users/digests?year=<current_year> (the standard dropdown never offers the current year) could trigger generation of a partial-year digest. CalculatingJob persists a Users::Digest row and chains EmailSendingJob, which delivers a partial "Year in Review" email unless digest.distance.to_i.zero?. The persisted row also temporarily hides that year from the generation dropdown until repaired.

Fix

One-character change in app/controllers/users/digests_controller.rb: year > Time.current.yearyear >= Time.current.year, matching Api::V1::DigestsController#valid_year?. The web route now rejects the in-progress current year with the existing Invalid year selected alert and enqueues no job, aligning the web controller with the API, the dropdown builder, and the scheduling job. No new routes, migrations, i18n keys, or public API surface.

Testing

  • Added spec/regressions/digests_current_year_boundary_spec.rb — freezes time to mid-2026, creates a Stat for the current year (so scoped_stats.exists? is true and only the upper-bound operator can reject), and asserts both web and API reject the current year (no job enqueued; web alert / API 422) while still accepting a past year (job enqueued; web notice / API 202). The spec is load-bearing: reverting the operator back to > makes the web example fail with expected not to enqueue at least 1 jobs, but enqueued 1.
  • Existing digest request specs (web and API), the lite-window regression spec, the digest swagger spec, the yearly scheduling job spec, and the CalculateYear service spec pass with no regressions. RuboCop on the modified files and rails zeitwerk:check both pass.
  • End-to-end verification against a running dev server (Puma) and a Sidekiq worker with the seeded demo user: POST /digests?year=2026 returned 303 with the Invalid year selected flash, persisted no digest, and enqueued no job; POST /digests?year=2025 returned 303 with the "is being generated" notice, enqueued CalculatingJob, which chained EmailSendingJob and persisted a 2025 digest (distance 0 → email suppressed); the /digests dropdown omitted the current year; POST /api/v1/digests with the current year returned 422 {"error":"Invalid year"}; DELETE /digests/2025 destroyed the digest. The dev DB and Redis were cleaned afterward.

Automatic Fixes PRs can be configured here.

@detail-app
detail-app Bot requested a review from Freika September 7, 2026 10:01
@Freika
Freika merged commit 9bd0fcf into master Sep 9, 2026
19 checks passed
@Freika
Freika deleted the detail/bug-fix/reject-in-progress-current-year-in-web-digest-gene-9d64b8 branch September 9, 2026 18:50
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