Skip to content

Wire in disputes, fiat payments, GraphQL, and cache admin routers (#816, #817, #818, #819) - #903

Merged
github-actions[bot] merged 7 commits into
Smartdevs17:mainfrom
DannyBongos:fix/issues-816-819-dispute-fiat-graphql-cache
Sep 25, 2026
Merged

github-actions[bot] merged 7 commits into
Smartdevs17:mainfrom
DannyBongos:fix/issues-816-819-dispute-fiat-graphql-cache

Conversation

@DannyBongos

Copy link
Copy Markdown
Contributor

Summary

All four issues turned out to share the same root cause: substantial, often well-tested backend modules already existed but were never mounted into the running Express app (backend/src/index.ts), so their endpoints were unreachable.

#816 — Payment dispute management
The dispute module (backend/disputes/) had a complete type model (disputeModel.ts) but the service stored everything in an in-memory Map (lost on restart, no tenant isolation) and the controller was untyped with inconsistent error handling. Fixed by:

  • Adding a Dispute Prisma model + migration (tenantId-scoped, matching this schema's existing conventions)
  • Rewriting disputeService.ts to persist via Prisma, scope every query to the caller's tenantId, and derive amount/currency from the referenced Payment record instead of trusting client input
  • Typing disputeController.ts with asyncHandler/requireUser, matching refunds.ts's conventions
  • Fixing a missing .js extension on an ESM import in disputeRoutes.ts that would have broken at runtime
  • Implementing getAnalytics() against the DisputeAnalytics interface that already existed but had no implementation
  • Registering hourly auto-escalation (72h response deadline) in scheduled-tasks.ts
  • Mounting the router at /api/v1/disputes

#817 — Wire transfer payments
Wire transfer support was already fully implemented in fiat-payments.ts / providers/fiat.ts — SWIFT validation for international wires, differentiated fee calculation, compliance holds on high-value international wires, wire instructions generation, and per-method analytics. The router (routes/fiat-payments.ts) exposing all of this (bank verification, payment initiation, /wire-instructions, webhooks, reconciliation) was never mounted. Fixed by mounting it at /api/v1/fiat-payments.

#818 — Cache admin endpoints
routes/cache.ts (stats/clear/evict) existed but was never mounted. Fixed by mounting it at /api/v1/cache.

#819 — GraphQL gateway
graphql/gateway.ts (graphQLRouter/graphQLWsRouter) existed but was never mounted. Fixed by mounting it at /graphql and /graphql/ws.

All four new mounts are behind authMiddleware since none of these routers guard themselves internally.

Notes

  • Per repo convention, no test run was performed as part of this change (token-conscious workflow); all logic changes preserve existing business rules and reuse already-existing type contracts verbatim.
  • docs/RESPONSE_CACHING.md references invalidateCache()/clearMemoryCache()/CacheTTL.LONG exports that don't currently exist in middleware/cache.ts — flagging this doc/code drift here since it was noticed during investigation, but left out of scope for this PR.

Resolves #816
Resolves #817
Resolves #818
Resolves #819

Adds Dispute model plus DisputeStatus/DisputeReason/DisputeResolutionOutcome
enums, matching the tenantId/deletedAt/snake_case conventions used
throughout schema.prisma. Part of Smartdevs17#816.
Replaces the in-memory Map with real persistence. Every operation is
now scoped to the caller's tenantId, amount/currency are derived from
the referenced Payment instead of trusted from the client, and
getAnalytics() implements the DisputeAnalytics shape already declared
in disputeModel.ts but never implemented. Part of Smartdevs17#816.
Matches the auth/error-handling convention used by refunds.ts, adds a
requireUser() guard, and adds the GET /analytics handler. Part of Smartdevs17#816.
disputeController was imported without the required .js extension,
which fails under this project's ESM resolution. Also wires up the new
/analytics route. Part of Smartdevs17#816.
Wires disputeService.processEscalations() into the scheduled-tasks
registry so disputes past their 72h response deadline actually get
escalated, following the same ScheduledTaskMeta pattern as every
other job in this file. Closes Smartdevs17#816.
…ters

Four fully-implemented modules were never wired into the running app:

- disputes/disputeRoutes.ts (Smartdevs17#816) — /api/v1/disputes
- routes/fiat-payments.ts (Smartdevs17#817) — /api/v1/fiat-payments. ACH/wire bank
  verification, payment initiation, wire instructions, webhooks and
  reconciliation were all already implemented in fiat-payments.ts and
  providers/fiat.ts (including SWIFT validation and compliance holds for
  international wires); only the router mount was missing.
- graphql/gateway.ts (Smartdevs17#819) — /graphql and /graphql/ws
- routes/cache.ts (Smartdevs17#818) — /api/v1/cache admin stats/clear/evict

All four are mounted behind authMiddleware since none of them guard
themselves internally. Resolves Smartdevs17#817, Smartdevs17#818, Smartdevs17#819 and completes Smartdevs17#816.
@drips-wave

drips-wave Bot commented Sep 25, 2026

Copy link
Copy Markdown

@Toluwalase-Daniel Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@vercel

vercel Bot commented Sep 25, 2026

Copy link
Copy Markdown

@Toluwalase-Daniel is attempting to deploy a commit to the smartdevs17's projects Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions
github-actions Bot merged commit 68e1b3c into Smartdevs17:main Sep 25, 2026
2 of 3 checks passed
github-actions Bot pushed a commit that referenced this pull request Sep 26, 2026
–#811) (#910)

## Summary

These four Stellar Wave billing features were largely implemented but three of the routers were never mounted on the API (same class of gap as #816–#819 in PR #903). This PR wires them in.

| Issue | Change |
|-------|--------|
| **#808** Stripe subscription billing | Mount `subscriptionsRouter` at `/api/v1/subscriptions` |
| **#809** Invoice generation + PDF export | Already mounted at `/api/v1/invoice` (`GET /:id/pdf`); called out next to the related mounts so the batch closes together |
| **#810** Payment retry + exponential backoff | Mount `retryRouter` at `/api/v1/payment-retry` |
| **#811** Multiple payment methods per account | Mount `paymentMethodsRouter` at `/api/v1/payment-methods` |

## Test plan

- [ ] Confirm routes appear under `/api/v1` after boot
- [ ] `GET/POST /api/v1/subscriptions` (with `x-tenant-id`)
- [ ] `GET /api/v1/invoice/:id/pdf` returns `application/pdf`
- [ ] `GET /api/v1/payment-retry/analytics`
- [ ] `POST/GET /api/v1/payment-methods`

Resolves #808
Resolves #809
Resolves #810
Resolves #811
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant