fix(server): default missing entry_timestamp for non-daily custom measurements - #2091
Conversation
…surements Fixes #2074 where logging custom measurement categories with non-Daily frequencies (e.g. Hourly, All, Unlimited) failed with a Postgres NOT NULL constraint error on custom_measurements.entry_timestamp when omitted by callers like log_custom_metric in AI chat. - Added defaultEntryTimestamp helper using @workspace/shared isDayString and Date.UTC date construction to prevent timezone jump issues. - When entry_timestamp is omitted and entry_date is today, defaults to new Date().toISOString() to preserve the exact hour, minute, and second of entry. - Updated upsertCustomMeasurement and bulkUpsertCustomMeasurements in measurementRepository.ts. - Added unit tests in measurementRepository.customMetricTimestamp.test.ts and chatbotToolsCheckin.test.ts.
PR Validation ResultsChange Detection
✅ All checks passed. Thank you! |
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughCustom measurement upserts now apply UTC-aware timestamp defaults for daily, non-daily, single, and bulk entries. The service passes timezone data to the repository. Tests cover repository defaults and successful ChangesCustom measurement timestamp handling
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant CheckinTools
participant MeasurementService
participant MeasurementRepository
participant Database
CheckinTools->>MeasurementService: log_custom_metric payload
MeasurementService->>MeasurementService: resolve payload or account timezone
MeasurementService->>MeasurementRepository: upsert custom measurement with source and timezone
MeasurementRepository->>MeasurementRepository: default entry timestamp
MeasurementRepository->>Database: insert or update custom measurement
Database-->>MeasurementRepository: persisted row
MeasurementRepository-->>MeasurementService: upsert result
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
SparkyFitnessServer/tests/measurementRepository.customMetricTimestamp.test.ts (1)
25-61: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMake the current-day fallback test deterministic.
Line 40 uses the wall clock. Lines 59-61 only verify that the value is parseable. A UTC-midnight fallback would pass this test even though the PR requires the current timestamp for today.
Set a fixed clock. Use a fixed
entryDate. Assert the exact value passed as parameter$6.As per coding guidelines, avoid
toISOString().split('T')[0]for business-logic dates and keep calendar days asYYYY-MM-DDstrings.🤖 Prompt for 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. In `@SparkyFitnessServer/tests/measurementRepository.customMetricTimestamp.test.ts` around lines 25 - 61, Update the test case around upsertCustomMeasurement to use a fixed system clock and a fixed YYYY-MM-DD entryDate string instead of deriving today from toISOString().split('T')[0]. Assert that values[5] equals the exact expected current timestamp produced by the fixed clock, replacing the parseability-only checks while preserving the existing query assertions.Source: Coding guidelines
🤖 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 `@SparkyFitnessServer/models/measurementRepository.ts`:
- Around line 35-38: The current-time fallback incorrectly compares entryDate
against the UTC day; update the shared measurement upsert logic used by both
single-row and bulk operations to compare it with todayInZone(userTimezone),
while preserving the existing now timestamp return. Add coverage for matching
and non-matching dates across positive and negative timezone offsets around UTC
midnight.
In
`@SparkyFitnessServer/tests/measurementRepository.customMetricTimestamp.test.ts`:
- Around line 10-11: Replace the any-typed mockClient in the measurement
repository tests with the existing MockDbClient helper, and type query-call
values as unknown[] or an explicit query-call tuple. Remove the associated
`@typescript-eslint/no-explicit-any` suppressions while preserving the existing
test behavior.
---
Nitpick comments:
In
`@SparkyFitnessServer/tests/measurementRepository.customMetricTimestamp.test.ts`:
- Around line 25-61: Update the test case around upsertCustomMeasurement to use
a fixed system clock and a fixed YYYY-MM-DD entryDate string instead of deriving
today from toISOString().split('T')[0]. Assert that values[5] equals the exact
expected current timestamp produced by the fixed clock, replacing the
parseability-only checks while preserving the existing query assertions.
🪄 Autofix
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 Plus
Run ID: 77ffcb17-ffbe-452a-9894-572b5dab13e5
📒 Files selected for processing (3)
SparkyFitnessServer/models/measurementRepository.tsSparkyFitnessServer/tests/chatbotToolsCheckin.test.tsSparkyFitnessServer/tests/measurementRepository.customMetricTimestamp.test.ts
|
@CodeRabbit can you review again. |
|
|
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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 `@SparkyFitnessServer/models/measurementRepository.ts`:
- Around line 1151-1154: The custom-measurement paths still use explicit any
types and ESLint suppressions. In
SparkyFitnessServer/models/measurementRepository.ts around lines 1151-1154, type
database rows, existingByKey, writtenByInput, and update results; in
SparkyFitnessServer/services/measurementService.ts around lines 1651-1652,
define a payload type, type user identifiers, and replace the category-lookup
callback’s any parameter. Remove the related suppressions while preserving
existing behavior.
In `@SparkyFitnessServer/services/measurementService.ts`:
- Around line 1651-1652: Update the timezone selection near the current-day
timestamp fallback to accept payload.timezone only when
isValidTimeZone(payload.timezone) returns true; otherwise call
loadUserTimezone(authenticatedUserId). Preserve the existing authenticated-user
fallback and ensure invalid or absent payload values never reach the timestamp
logic.
In
`@SparkyFitnessServer/tests/measurementRepository.customMetricTimestamp.test.ts`:
- Around line 73-127: Make the timezone-boundary tests deterministic by using
fake timers and freezing Tokyo to 2026-08-08T23:30:00.000Z and Los Angeles to
2026-08-08T00:30:00.000Z. In both upsertCustomMeasurement tests, assert the
captured entry_timestamp parameter equals the corresponding frozen ISO timestamp
instead of only checking date validity, and restore real timers after each test.
🪄 Autofix
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 Plus
Run ID: dede3100-2ced-43c9-978a-394c4ff2d97e
📒 Files selected for processing (3)
SparkyFitnessServer/models/measurementRepository.tsSparkyFitnessServer/services/measurementService.tsSparkyFitnessServer/tests/measurementRepository.customMetricTimestamp.test.ts
Fixes #2074 where logging custom measurement categories with non-Daily frequencies (e.g. Hourly, All, Unlimited) failed with a Postgres NOT NULL constraint error on custom_measurements.entry_timestamp when omitted by callers like log_custom_metric in AI chat.
Tip
Help us review and merge your PR faster!
Please ensure you have completed the Checklist below.
For Frontend changes, please run
pnpm run validateto check for any errors.PRs that include tests and clear screenshots are highly preferred!
Note: AI-generated descriptions must be manually edited for conciseness. Do not paste raw AI summaries.
Description
What problem does this PR solve?
(Keep it concise. 1–2 sentences.)
How did you implement the solution?
(Brief technical approach.)
Linked Issue: Closes #2074
How to Test
...PR Type
Checklist
All PRs:
New features only:
Frontend changes (
SparkyFitnessFrontend/):pnpm run validateand it passes.en) translation file.Backend changes (
SparkyFitnessServer/):rls_policies.sqlfor any new user-specific tables.UI changes (components, screens, pages):
Mobile changes (
SparkyFitnessMobile/):Screenshots
Click to expand
Before
After
Notes for Reviewers
Summary by CodeRabbit
Bug Fixes
Tests