Skip to content

fix(requests): refresh modified timestamps#2729

Open
saudademjj wants to merge 6 commits intoseerr-team:developfrom
saudademjj:saudademjj/fix-request-modified-date
Open

fix(requests): refresh modified timestamps#2729
saudademjj wants to merge 6 commits intoseerr-team:developfrom
saudademjj:saudademjj/fix-request-modified-date

Conversation

@saudademjj
Copy link
Copy Markdown

@saudademjj saudademjj commented Mar 19, 2026

Description

  • Fixes Date Modified on Requests Not Accurate #2728
  • Refresh MediaRequest.updatedAt whenever a request entity is updated so the request list's Modified time stays aligned with approval and decline status changes.
  • Add regression coverage for both the approve and decline request status flows.
  • AI assistance disclosure: I used Codex as an AI coding assistant under my review and verified the final changes and PR updates myself.

How Has This Been Tested?

  • Ran the full validation suite successfully on 100.92.89.12 using Node v22.18.0 and pnpm v10.24.0.
  • pnpm exec prettier --check server/entity/MediaRequest.ts server/routes/request.test.ts
  • pnpm exec eslint server/entity/MediaRequest.ts server/routes/request.test.ts
  • pnpm test server/routes/auth.test.ts server/routes/request.test.ts
  • pnpm typecheck:server
  • pnpm build
  • pnpm i18n:extract
  • pnpm i18n:extract completed without introducing any tracked file changes in the validation checkout.

Screenshots / Logs (if applicable)

  • Not applicable.

Checklist:

  • I have read and followed the contribution guidelines.
  • Disclosed any use of AI (see our policy)
  • I have updated the documentation accordingly.
  • All new and existing tests passed.
  • Successful build pnpm build
  • Translation keys pnpm i18n:extract
  • Database migration (if required)

Summary by CodeRabbit

  • Tests

    • Added integration tests covering request approve, decline, and retry flows to improve reliability.
  • Bug Fixes

    • Ensure request status changes now correctly record the acting user and update timestamps so UI and history reflect the latest state.

@saudademjj saudademjj requested a review from a team as a code owner March 19, 2026 10:24
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 19, 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

Adds an integration test suite for request routes and ensures modified requests explicitly set modifiedBy and updatedAt before being persisted when approving, declining, or retrying requests.

Changes

Cohort / File(s) Summary
Request Route Logic
server/routes/request.ts
Set request.modifiedBy = req.user and request.updatedAt = new Date() before persisting status changes in the /:requestId/retry and /:requestId/:status POST handlers.
Request Route Integration Tests
server/routes/request.test.ts
New Node node:test integration tests for POST /request/:requestId/approve, POST /request/:requestId/decline, and POST /request/:requestId/retry; assert status transitions, modifiedBy identity, and that updatedAt advances and is persisted.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • gauthier-th
  • fallenbagel
  • 0xSysR3ll

Poem

🐰 A little hop, a little fix,

Timestamps now renew their tricks.
Approve, decline, or try once more,
Modified marks the moment's lore.
Hop-hop—records true forevermore.

🚥 Pre-merge checks | ✅ 4
✅ 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 clearly and specifically describes the main change: refreshing modified timestamps for request entities during approval/decline operations.
Linked Issues check ✅ Passed Code changes directly address issue #2728 by updating MediaRequest.updatedAt timestamps in approve, decline, and retry flows, with comprehensive test coverage added.
Out of Scope Changes check ✅ Passed All changes are scoped to fixing the modified timestamp issue in request routes and adding regression tests; no unrelated modifications detected.

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


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
Copy Markdown

@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)
server/routes/request.test.ts (1)

81-114: Consider adding a test for the decline flow as well.

The current test covers approval but the @BeforeUpdate() hook should also refresh updatedAt when a request is declined. Adding a similar test case would provide more comprehensive coverage.

📝 Example test case for decline
it('refreshes updatedAt when a request is declined', async () => {
  const requestRepository = getRepository(MediaRequest);
  const pendingRequest = await createPendingRequest();
  const previousUpdatedAt = pendingRequest.updatedAt.toISOString();
  const agent = await authenticatedAgent('admin@seerr.dev', 'test1234');

  const res = await agent.post(`/request/${pendingRequest.id}/decline`);

  assert.strictEqual(res.status, 200);
  assert.ok(
    new Date(res.body.updatedAt).getTime() >
      new Date(previousUpdatedAt).getTime()
  );
  assert.strictEqual(savedRequest.status, MediaRequestStatus.DECLINED);
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/routes/request.test.ts` around lines 81 - 114, Add a parallel test for
the decline flow that mirrors the approve test: use createPendingRequest() to
seed a pending MediaRequest, capture previousUpdatedAt from
pendingRequest.updatedAt, authenticate as admin via
authenticatedAgent('admin@seerr.dev','test1234'), POST to /request/{id}/decline,
assert response status is 200, assert the returned updatedAt is greater than
previousUpdatedAt, and assert the request's status is
MediaRequestStatus.DECLINED (use the same repository/getRepository(MediaRequest)
or the response body to validate status); this ensures the `@BeforeUpdate`() hook
refreshes updatedAt on decline.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@server/routes/request.test.ts`:
- Around line 81-114: Add a parallel test for the decline flow that mirrors the
approve test: use createPendingRequest() to seed a pending MediaRequest, capture
previousUpdatedAt from pendingRequest.updatedAt, authenticate as admin via
authenticatedAgent('admin@seerr.dev','test1234'), POST to /request/{id}/decline,
assert response status is 200, assert the returned updatedAt is greater than
previousUpdatedAt, and assert the request's status is
MediaRequestStatus.DECLINED (use the same repository/getRepository(MediaRequest)
or the response body to validate status); this ensures the `@BeforeUpdate`() hook
refreshes updatedAt on decline.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 659a9f27-f88b-4f0c-9bf4-d2cdfc3a77bb

📥 Commits

Reviewing files that changed from the base of the PR and between c7185d4 and fe6eb51.

📒 Files selected for processing (2)
  • server/entity/MediaRequest.ts
  • server/routes/request.test.ts

Copy link
Copy Markdown
Collaborator

@fallenbagel fallenbagel left a comment

Choose a reason for hiding this comment

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

Please update the PR description to follow the PR template.

@saudademjj
Copy link
Copy Markdown
Author

Updated the PR description to match the repository template and pushed f222e83b to add the decline regression test CodeRabbit suggested. The current validation status and environment blockers are documented in the PR body.

Copy link
Copy Markdown

@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)
server/routes/request.test.ts (1)

117-171: Coverage is solid; consider extracting shared transition assertions.

Approve/decline tests duplicate setup and verification steps. A small helper would reduce drift and make future status-flow extensions easier.

♻️ Optional refactor sketch
+async function assertRequestTransition(
+  action: 'approve' | 'decline',
+  expectedStatus: MediaRequestStatus
+) {
+  const requestRepository = getRepository(MediaRequest);
+  const pendingRequest = await createPendingRequest();
+  const previousUpdatedAt = pendingRequest.updatedAt.toISOString();
+  const agent = await authenticatedAgent('admin@seerr.dev', 'test1234');
+
+  const res = await agent.post(`/request/${pendingRequest.id}/${action}`);
+
+  assert.strictEqual(res.status, 200);
+  assert.notStrictEqual(res.body.updatedAt, previousUpdatedAt);
+  assert.ok(new Date(res.body.updatedAt).getTime() > new Date(previousUpdatedAt).getTime());
+  assert.strictEqual(res.body.modifiedBy.email, 'admin@seerr.dev');
+
+  const savedRequest = await requestRepository.findOneOrFail({
+    where: { id: pendingRequest.id },
+    relations: { modifiedBy: true },
+  });
+
+  assert.strictEqual(savedRequest.status, expectedStatus);
+  assert.strictEqual(savedRequest.modifiedBy?.email, 'admin@seerr.dev');
+  assert.ok(savedRequest.updatedAt.getTime() > pendingRequest.updatedAt.getTime());
+}
+
 describe('POST /request/:requestId/:status', () => {
   it('refreshes updatedAt when a request is approved', async () => {
-    // duplicated body...
+    await assertRequestTransition('approve', MediaRequestStatus.APPROVED);
   });

   it('refreshes updatedAt when a request is declined', async () => {
-    // duplicated body...
+    await assertRequestTransition('decline', MediaRequestStatus.DECLINED);
   });
 });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/routes/request.test.ts` around lines 117 - 171, The two tests in
request.test.ts ('refreshes updatedAt when a request is approved' and 'refreshes
updatedAt when a request is declined') duplicate setup and verification; extract
a helper (e.g., assertRequestTransition or runRequestTransition) that accepts
the action ('approve' | 'decline') and expected MediaRequestStatus to perform:
createPendingRequest, capture previousUpdatedAt, call authenticatedAgent, post
to `/request/${id}/${action}`, assert status 200, assert res.body.updatedAt
changed and is newer, assert res.body.modifiedBy.email is 'admin@seerr.dev',
load savedRequest via getRepository(MediaRequest).findOneOrFail with relations,
assert savedRequest.status equals expected MediaRequestStatus and
modifiedBy.email and that savedRequest.updatedAt is newer than
pendingRequest.updatedAt; then replace the two tests with calls to that helper
for approve and decline.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@server/routes/request.test.ts`:
- Around line 117-171: The two tests in request.test.ts ('refreshes updatedAt
when a request is approved' and 'refreshes updatedAt when a request is
declined') duplicate setup and verification; extract a helper (e.g.,
assertRequestTransition or runRequestTransition) that accepts the action
('approve' | 'decline') and expected MediaRequestStatus to perform:
createPendingRequest, capture previousUpdatedAt, call authenticatedAgent, post
to `/request/${id}/${action}`, assert status 200, assert res.body.updatedAt
changed and is newer, assert res.body.modifiedBy.email is 'admin@seerr.dev',
load savedRequest via getRepository(MediaRequest).findOneOrFail with relations,
assert savedRequest.status equals expected MediaRequestStatus and
modifiedBy.email and that savedRequest.updatedAt is newer than
pendingRequest.updatedAt; then replace the two tests with calls to that helper
for approve and decline.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4dbb025b-5588-4422-8084-ce2d5306a9f7

📥 Commits

Reviewing files that changed from the base of the PR and between fe6eb51 and f222e83.

📒 Files selected for processing (1)
  • server/routes/request.test.ts

@saudademjj
Copy link
Copy Markdown
Author

Updated the PR template again after finishing the full validation run on 100.92.89.12. Prettier, ESLint, tests, server typecheck, build, and i18n extraction all passed on Node 22.18.0 / pnpm 10.24.0.

@saudademjj saudademjj force-pushed the saudademjj/fix-request-modified-date branch from f222e83 to 3bb9f9e Compare March 20, 2026 13:17
Copy link
Copy Markdown

@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 (2)
server/routes/request.ts (1)

647-650: Consider setting modifiedBy in retry flow for audit consistency.

POST /:requestId/:status records the actor (modifiedBy), but retry currently does not. Keeping both paths aligned will make audit metadata consistent.

Suggested patch
       // this also triggers updating the parent media's status & sending to *arr
       request.status = MediaRequestStatus.APPROVED;
+      request.modifiedBy = req.user;
       request.updatedAt = new Date();
       await requestRepository.save(request);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/routes/request.ts` around lines 647 - 650, The retry flow updates
request.status and request.updatedAt and saves via
requestRepository.save(request) but does not set request.modifiedBy, causing
inconsistent audit metadata; update the retry code path to assign the current
actor to request.modifiedBy (same source used in POST /:requestId/:status), then
set request.updatedAt and save with requestRepository.save(request) so both
approval and retry flows record the modifier consistently.
server/routes/request.test.ts (1)

122-176: Optional: parameterize approve/decline test bodies to reduce duplication.

The two status tests are nearly identical aside from endpoint and expected status, so a small table-driven helper would simplify future maintenance.

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

In `@server/routes/request.test.ts` around lines 122 - 176, The two tests in
request.test.ts ("refreshes updatedAt when a request is approved" and "refreshes
updatedAt when a request is declined") are duplicated; refactor into a single
table-driven helper that accepts the endpoint suffix ('approve'/'decline') and
the expected status (MediaRequestStatus.APPROVED / MediaRequestStatus.DECLINED).
Extract the common setup (createRequest(), previousUpdatedAt,
authenticatedAgent('admin@seerr.dev', 'test1234'), requestRepository) and common
assertions (res.status === 200, res.body.updatedAt changed and newer,
res.body.modifiedBy.email, fetching savedRequest and checking
savedRequest.updatedAt) into a helper function (e.g.,
runStatusChangeTest(endpointSuffix, expectedStatus)) and call it for both
'approve' and 'decline' to remove duplication while keeping the existing
assertions and relations lookups.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@server/routes/request.test.ts`:
- Around line 122-176: The two tests in request.test.ts ("refreshes updatedAt
when a request is approved" and "refreshes updatedAt when a request is
declined") are duplicated; refactor into a single table-driven helper that
accepts the endpoint suffix ('approve'/'decline') and the expected status
(MediaRequestStatus.APPROVED / MediaRequestStatus.DECLINED). Extract the common
setup (createRequest(), previousUpdatedAt, authenticatedAgent('admin@seerr.dev',
'test1234'), requestRepository) and common assertions (res.status === 200,
res.body.updatedAt changed and newer, res.body.modifiedBy.email, fetching
savedRequest and checking savedRequest.updatedAt) into a helper function (e.g.,
runStatusChangeTest(endpointSuffix, expectedStatus)) and call it for both
'approve' and 'decline' to remove duplication while keeping the existing
assertions and relations lookups.

In `@server/routes/request.ts`:
- Around line 647-650: The retry flow updates request.status and
request.updatedAt and saves via requestRepository.save(request) but does not set
request.modifiedBy, causing inconsistent audit metadata; update the retry code
path to assign the current actor to request.modifiedBy (same source used in POST
/:requestId/:status), then set request.updatedAt and save with
requestRepository.save(request) so both approval and retry flows record the
modifier consistently.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2029c61a-3fc4-4e27-8067-6b94a8a09a3a

📥 Commits

Reviewing files that changed from the base of the PR and between 3bb9f9e and efa8344.

📒 Files selected for processing (2)
  • server/routes/request.test.ts
  • server/routes/request.ts

@fallenbagel fallenbagel added this to the v3.2.0 milestone Mar 28, 2026
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.

Date Modified on Requests Not Accurate

2 participants