Skip to content

feat(phase10): ship Wave 4 admin Reports backend (Wave 4.1) - #262

Merged
chelebyy merged 39 commits into
mainfrom
feat/phase10-public-page-coverage
Jun 3, 2026
Merged

feat(phase10): ship Wave 4 admin Reports backend (Wave 4.1)#262
chelebyy merged 39 commits into
mainfrom
feat/phase10-public-page-coverage

Conversation

@chelebyy

@chelebyy chelebyy commented Jun 2, 2026

Copy link
Copy Markdown
Owner

Summary

Closes the backend Reports gap that was blocking the /admin/v1/reports admin endpoints since the Phase 10 frontend coverage expansion. Frontend hooks useRevenueReport / useOccupancyReport / usePopularVehicles were already wired to USE_MOCK=false and 404'd against the backend.

Wave 4 status (per docs/12_Phase10_PreLaunch_Gates.md §10.0.1.3)

Wave 4 is partially closed by this PR:

  • Reports backend (Wave 4.1) — shipped in this PR.
  • ⏸️ Settings/system persistence — formally DEFERRED (post-launch technical debt; requires a SystemSettings entity + config migration).
  • ⏸️ Fleet/maintenance complete action — formally DEFERRED (post-launch technical debt; requires a Maintenance entity + state-machine migration).

Both deferrals are launch-non-critical and documented in the new handoff at docs/handoffs/2026-06-03-phase10-wave4-closure-handoff.md.

Changes

New files

  • backend/src/RentACar.API/Contracts/Reports/ReportDtos.cs — DTOs matching the frontend RevenueReport / OccupancyReport / PopularVehicleReportItem shapes.
  • backend/src/RentACar.API/Services/IReportsService.cs — 3-method interface.
  • backend/src/RentACar.API/Services/ReportsService.cs — period-aware aggregation from Reservations / PaymentIntents / Vehicles.
  • backend/src/RentACar.API/Controllers/AdminReportsController.cs[Route("api/admin/v1/reports")], [Authorize(Policy = AdminOnly)], [EnableRateLimiting(Standard)].
  • backend/tests/RentACar.Tests/Unit/Controllers/AdminReportsControllerTests.cs — 7 tests (mocked IReportsService).
  • backend/tests/RentACar.Tests/Unit/Services/ReportsServiceTests.cs — 14 tests (InMemory DB).

Modified

  • backend/src/RentACar.API/Configuration/ServiceCollectionExtensions.cs — registered IReportsService.
  • docs/12_Phase10_PreLaunch_Gates.md — Wave 4 status updated, 10.0.8 Wave 4 Completion Evidence section added.
  • docs/10_Execution_Tracking.md — Wave 4 bullet updated, new 03.06.2026 delivery row added.
  • docs/handoffs/2026-06-03-phase10-wave4-closure-handoff.md — comprehensive session handoff.

Verification

Command Result
dotnet build backend/tests/RentACar.Tests/RentACar.Tests.csproj --no-restore 0 warning / 0 error
dotnet test backend/tests/RentACar.Tests/RentACar.Tests.csproj --no-build --filter "FullyQualifiedName~Reports" 21/21 PASS (7 controller + 14 service)
Full unit suite 615/615 PASS, 0 failed

Out of scope

  • Dokploy deployment, canlıya alma, 9 DEFERRED Phase 10 launch gates (Lighthouse, API health, Dokploy service health, SSL Labs, monitoring, UAT, rollback plan, incident response).
  • 1 transitive brace-expansion moderate npm audit finding (deliberate separate-PR decision per PR fix(security): bump vitest to 4.1.x to address CVE-2026-47429 #260 handoff).

Test evidence

dotnet test ... --filter "FullyQualifiedName~Reports" -> Başarılı! 0 Başarısız, 21 Başarılı, 21 Toplam

🤖 Generated with Claude Code

Sisyphus and others added 30 commits May 17, 2026 00:17
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…in dashboard coverage

- Add 8 tests to PaymentServiceTests (Hold→PendingPayment, invalid state, missing 3DS, deposit capture failure, GetPaymentStatus)
- Add 9 tests to ReservationServiceTests (distributed lock, no-vehicle, overlap, blank/missing/non-succeeded intent, extend-hold negative paths)
- Create DashboardPage.test.tsx for admin dashboard (3 tests: loading, loaded, empty state)
- Update docs/12_Phase10_PreLaunch_Gates.md: payment row 4 → GO (91.71%), reservation row 5 → GO (82.47%), summary 10/22 GO
- Update docs/10_Execution_Tracking.md: backend section, KPI row, footer
- Add session handoff for 17 May state
…wPicker teardown

- ReservationServiceTests: pass reservationId as exclude param in overlap mock (matches actual CreateHoldAsync call)
- SearchForm.test.tsx: use Reflect.deleteProperty instead of undefined assignment for absent showPicker case
…age-coverage

# Conflicts:
#	docs/10_Execution_Tracking.md
#	docs/12_Phase10_PreLaunch_Gates.md
…age-coverage

# Conflicts:
#	backend/tests/k6/README.md
#	backend/tests/k6/admin-dashboard.js
#	backend/tests/k6/availability-query.js
#	backend/tests/k6/concurrent-booking.js
#	backend/tests/k6/concurrent-search.js
#	backend/tests/k6/mixed-traffic.js
#	backend/tests/k6/payment-intent.js
#	docs/02_ADR_ENTERPRISE_FULL.md
#	docs/04_IDD_ENTERPRISE_FULL.md
#	docs/09_Implementation_Plan.md
#	docs/10_Execution_Tracking.md
#	docs/12_Phase10_PreLaunch_Gates.md
#	docs/handoffs/2026-05-17-220746-phase10-local-docker-load-validation-handoff.md
- Infrastructure.csproj: keep Microsoft.Extensions.Configuration.Binder (PR #259),
  adopt main's deps versions (10.0.8 / 2.13.17 / etc.)
- phase10 load-baseline handoff: keep PR #259's version (the post-#234 closure)
…merge

- docs/handoffs/2026-05-18-PR-235-load-baseline-closure-body.md: tracked archival of the PR body used to open PR #235 / merge PR #259.
- docs/12_Phase10_PreLaunch_Gates.md: gate #9 (Concurrent booking simulation) now records PR #259 MERGED 2026-06-02 with merge SHA 544613c, on top of the 18 May 2026 local Docker baseline verification.
- docs/10_Execution_Tracking.md: 02.06.2026 follow-up delivery entry added, recording the merge confirmation, branch sync state (0 ahead / 0 behind), and the gh pr view evidence.
- docs/handoffs/2026-05-18-022152-phase10-load-baseline-complete-and-docs-sync.md: new 'Follow-up — PR #259 MERGED 2026-06-02' section preserves the authoritative post-merge state and the working-tree preservation rules (no .sisyphus/, no k6/results/, no restore of the 5 historical handoff deletions).
- Project overview and design-context sections removed from CLAUDE.md; the canonical architecture/conventions/design/security rules already live in AGENTS.md.
- CLAUDE.md kept lean and focused on session-tooling rules + day-to-day commands (backend/frontend/single-test invocations), per the existing 'This file covers session-tooling rules' intent.
- Header pointer added at the top directing readers to AGENTS.md for full guidelines.
- This is a tooling-only change; no code, no contracts, no test surface affected.
Sisyphus and others added 7 commits June 2, 2026 23:06
…ession

- docs/handoffs/2026-06-02-225758-phase10-pr259-merge-paperwork-and-claudemd-restructure.md: new handoff record for this session's work.
- Captures the post-merge state after PR #259 landed: 2-commit split (46735ea phase10 docs + 5f4c406 CLAUDE.md restructure), branch sync verified 0 ahead / 0 behind, working-tree preservation rules, and the surfaced-but-deferred Dependabot 2-critical follow-up.
- Chained to docs/handoffs/2026-05-18-022152-phase10-load-baseline-complete-and-docs-sync.md (predecessor), does not supersede it. Predecessor gained a '## Follow-up' section in commit 46735ea.
- Manual validation: 0 TODO placeholders, all required sections present, no secrets, all referenced files exist. Skill scripts/validate_handoff.py was unavailable at validation time (sandbox/ephemeral); manual checks replicate the script's criteria.
- First-action item for the next session: triage the 2 critical Dependabot alerts on main.
PR #260 (fix/security-vitest-2026-06-02, OPEN) bumps vitest and
@vitest/coverage-v8 from ^3.2.4 to ^4.1.0 to address two Dependabot
critical alerts on main (CVE-2026-47429 / GHSA-5xrq-8626-4rwp):
- #37: frontend/package.json vitest < 4.1.0
- #38: frontend/pnpm-lock.yaml vitest < 4.1.0

Resolves the 'Pending Work' item #1 surfaced in the predecessor handoff
(2026-06-02-225758-...).

Verification recorded in PR #260 body (also archived):
- pnpm audit: 0 critical, 0 high
- pnpm test: 190/190 PASS
- pnpm build: 0 error
- pnpm lint: 0 error

Out of scope (deliberately deferred):
- 1 transitive moderate brace-expansion (eslint chain) — separate fix
  path; future PR with override rationale
- 9 DEFERRED Phase 10 launch gates (Dokploy-dependent, user-deferred)

The PR #260 branch is fix/security-vitest-2026-06-02; CI is in progress.
It will land on main independently of feat/phase10-public-page-coverage
when merged; Dependabot auto-closes alerts #37 and #38 on merge.

Working-tree state preserved per predecessor handoff rules:
- 5 deleted historical handoffs (D) remain uncommitted
- .sisyphus/ and backend/tests/k6/results/ remain untracked

Refs: PR #260, CVE-2026-47429, GHSA-5xrq-8626-4rwp, Dependabot #37 + #38
…l tooling/results

Working-tree preservation rule (set by docs/handoffs/2026-05-18-022152-...
and preserved through 2026-06-02-225758-... + 2026-06-02-232800-...) held
5 historical handoff deletions in D status pending explicit user
direction. The user's 'dokploy,canlıya alma hariç kalan işlemleri bitir'
instruction this session is that direction.

- git rm 5 historical handoffs (May 2026) — content fully superseded by
  the surviving 2026-05-17-... and 2026-06-02-... handoff chains
  (verified by cross-reference)
- .gitignore: add .sisyphus/ (Sisyphus agent runtime dir, local only)
- .gitignore: add backend/tests/k6/results/ (6 local k6 result JSONs
  from 17-18 May 2026 smoke runs, regenerable)

No code, no test, no contract surface changed. Per project 'no mixed
concerns' rule, this commit is logically separate from the docs
paperwork sync that follows in the next commit.
…aunch gate #11

PR #260 (fix/security-vitest-2026-06-02, MERGED 2026-06-02T20:36Z,
SHA 220d602) closed the 2 Dependabot critical vitest alerts on main
(CVE-2026-47429 / GHSA-5xrq-8626-4rwp). All CI checks SUCCESS on
PR #260 (Backend Unit/Integration, Frontend Lint/Test/Build, Docker
Build, CodeQL csharp+js). The 1 transitive moderate 'brace-expansion'
(eslint chain) remains; deliberate follow-up — separate PR with
override rationale.

- docs/12_Phase10_PreLaunch_Gates.md gate #11: appended PR #260 closure
  evidence (vitest ^3.2.4 → ^4.1.0, 190/190 tests PASS, 0 build/lint
  error) and the 1 transitive moderate note. Gate remains GO.
- docs/10_Execution_Tracking.md: new 02.06.2026 | Follow-up row for
  PR #260 merge confirmation, mirroring the existing PR #259 row
  pattern (date, label, MERGED + SHA, handoff link, PR body archive
  link).
- docs/handoffs/2026-06-02-235900-...: new comprehensive session
  handoff for this branch cleanup + PR #260 paperwork sync. Chained to
  the immediate predecessor (2026-06-02-232800-...).

Phase 10 launch-gate source of truth and milestone ledger are now
in sync with the current main HEAD (cef9964...). 9 DEFERRED Phase
10 gates (Dokploy-dependent) remain untouched per user direction.
Working tree is now 'structurally clean' after the chore commit in
this session.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Address Codex P1 review feedback (chatgpt-codex-connector, review
4413547177, commit c01f766): the dependency-vuln gate #11 row text
updated in the previous commit mentioned PR #260's vitest bump, but a
reviewer reading PR #261's diff in isolation might think the bump is in
this PR. It is not — PR #260 was a separate branch already merged to
main. This commit adds one inline note to gate #11 making it
unambiguous that the row tracks main HEAD state, not PR branch state,
and that the vitest bump lives in PR #260 (already on main).

PR #261 body also added via 'gh pr edit' for full context (docs-only
PR, no code/test/contract surface changed).

Refs: PR #261, PR #260, Codex review 4413547177
Closes the backend Reports gap that has been blocking the admin /admin/v1/reports
endpoints since the Phase 10 frontend coverage expansion (PR #261). The frontend
hook layer (useRevenueReport / useOccupancyReport / usePopularVehicles) was already
wired to USE_MOCK=false and was 404ing against the backend.

Scope
- backend Reports surface: IReportsService + ReportsService (period-aware aggregation
  from Reservations / PaymentIntents / Vehicles via IApplicationDbContext).
- New controller: AdminReportsController (api/admin/v1/reports, AdminOnly policy,
  standard rate limit) exposing revenue / occupancy / popular-vehicles endpoints.
- DTOs: RevenueReportResponse, OccupancyReportResponse, PopularVehicleReportItemResponse
  matching the frontend types in lib/api/admin/types.ts.
- DI registration in ServiceCollectionExtensions.
- Tests: 7 controller tests (mocked service) + 14 service tests (InMemory DB) = 21 new
  tests. dotnet build clean (0 warning / 0 error). Full unit suite 615/615 PASS.

Out of scope (deferred to post-launch)
- settings/system persistence (no backend SystemSettings entity; config migration).
- fleet/maintenance complete action (no Maintenance entity; fleet workflow needs
  state-machine + migration).
Both are documented in the session handoff as launch-non-critical and remain in the
post-launch technical-debt registry per Wave 4 completion criteria.
Updates Wave 4 status in the launch-gate source of truth and the execution
tracker, and archives the session handoff for the next agent.

- docs/12_Phase10_PreLaunch_Gates.md: header 'Wave 4 DEFERRED' replaced with
  'Wave 4 PARTIALLY COMPLETED — Reports backend shipped; settings/system +
  maintenance stub formally DEFERRED'. Wave 4 row in 10.0.1.3 scoped-review
  table marked closed. New 10.0.8 Wave 4 Completion Evidence section added,
  mirroring the Wave 1/2/3 closure blocks (kapanış tarihi, kapsam, verify
  results, file list, formal deferral note).
- docs/10_Execution_Tracking.md: Wave 4 bullet moved from 'Bekliyor' to
  'PARTIALLY COMPLETED'. New 03.06.2026 | Delivery row in the milestone
  ledger recording the Reports backend delivery + the formal defer.
- docs/handoffs/2026-06-03-phase10-wave4-closure-handoff.md: comprehensive
  session handoff with session metadata, handoff chain, current state summary,
  codebase understanding, files modified, decisions made, pending work, risk
  register, verification evidence, reproducible commands, related artifacts.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9f9258489d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

r.PickupDateTime < dayEnd && r.ReturnDateTime > dayStart);

var rate = totalVehicles > 0
? Math.Round((decimal)occupied / totalVehicles, 4)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Return occupancy rates as percentages

When real reports are used, this computes rates as fractions (e.g. 2 occupied out of 4 vehicles returns 0.5), but the admin reports frontend consumes occupancyRate on a 0–100 scale: the existing mocks use values like 70.97, and the occupancy chart is rendered with domain={[0, 100]} while prefixing %. This makes live dashboard values display as %0.5 and plot near zero for a 50% occupancy day; either multiply the backend rate by 100 or change the frontend contract consistently.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in 82510bd: occupancy rates now return 0-100 percentage values, with service/controller tests updated for the frontend contract.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 46d57b1d14

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +95 to +99
var reservations = await dbContext.Reservations
.AsNoTracking()
.Where(r => RevenueEligibleStatuses.Contains(r.Status))
.Select(r => new { r.PickupDateTime, r.ReturnDateTime })
.ToListAsync(cancellationToken);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Filter occupancy reservations to the requested period

For weekly/monthly/yearly occupancy reports after the database has historical completed rentals, this query materializes every paid/active/completed reservation because it never applies the resolved startUtc/endUtc overlap window. The later per-day loop only needs reservations where PickupDateTime < endUtc && ReturnDateTime > startUtc; without that predicate the endpoint does days * allHistoricalReservations in memory and can become slow or memory-heavy as booking history grows.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in 82510bd: occupancy reservations are now filtered by the requested report-window overlap before per-day aggregation. Added service coverage for out-of-period reservations.

Comment on lines +172 to +176
.Where(p => p.Status == PaymentStatus.Succeeded
&& p.CreatedAt >= startUtc
&& p.CreatedAt < endUtc
&& p.Reservation != null
&& vehicleIds.Contains(p.Reservation.VehicleId))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Match popular-vehicle revenue to counted rentals

When a counted rental was paid outside the selected period (for example a May booking/payment for a June pickup), reservationsQuery includes it in RentalCount by pickup date but this revenue query excludes its succeeded payment by PaymentIntent.CreatedAt, so the popular-vehicles report shows understated or zero revenue for rentals it is counting. Use the reservation ids/date scope from reservationsQuery when summing payment amounts, or make both metrics use the same period basis.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in 82510bd: popular-vehicle revenue now sums succeeded payments by the scoped reservation IDs, matching the counted rental basis. I also aligned the revenue report to the same eligible-reservation scope.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@chelebyy
chelebyy merged commit 7daeb93 into main Jun 3, 2026
9 checks passed
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.

2 participants