Skip to content

Split the payment-processing file into smaller, focused files - #1692

Merged
stefan-burke merged 2 commits into
mainfrom
claude/payment-processing-refactor-fqrnpg
Jul 10, 2026
Merged

Split the payment-processing file into smaller, focused files#1692
stefan-burke merged 2 commits into
mainfrom
claude/payment-processing-refactor-fqrnpg

Conversation

@stefan-burke

@stefan-burke stefan-burke commented Jul 10, 2026

Copy link
Copy Markdown
Member

What changed

The payment-processing code was one very large file (nearly 2,000 lines) that was allowed to skip our "keep files small" rule as a special exception. This splits it into a folder of smaller files that each do one job, and removes that exception so the rule now applies normally.

The behaviour is exactly the same — this is purely a reorganisation. All the same functions run in the same order; they just live in tidier, easier-to-find files now.

The new files

Everything moved into a payment-processing/ folder:

  • metadata — reads the details a customer's payment carries into a booking.
  • classify — checks with the payment provider that a payment really happened, and proves the payment is ours (not another site sharing the same provider).
  • cancel — the "payment cancelled / card declined" page and its "try again" link.
  • refunds — the actual refunding, plus the set list of reasons a payment might need refunding.
  • package-pricing — re-checks that a bundle's contents and prices haven't changed since the customer started paying.
  • items — re-checks every line of an order against the current listings.
  • pricing — works out the expected price and decides whether a price changed mid-payment.
  • create — turns a good payment into a real booking.
  • store-refund — when a booking can't be completed, keeps the customer's details as a placeholder and refunds them, so nobody who paid is ever lost.
  • index — ties it all together: reserve the payment, process it, and record the outcome so repeats are safe.

Duplication cleanup

Splitting a file this large reveals repeated snippets that our duplication checker couldn't see while they were buried in one giant file. These were removed by sharing small helpers rather than silencing the checker — for example one helper that builds a booking's listing-and-bundle identity, one that builds the placeholder rows for a deleted listing, and one that totals up allocated items.

Checks

Type-checking, linting, and the duplication check all pass, and the payment and webhook test suites (230+ tests) pass.

🤖 Generated with Claude Code

https://claude.ai/code/session_01J251sRHStWRgsijyynWunC


Generated by Claude Code

Summary by CodeRabbit

  • New Features

    • Added more reliable payment-session verification and processing with replay-safe idempotency.
    • Added protections against outdated prices, package/bundle structure changes, and edge drift, including fail-closed pricing validation.
    • Added keep-and-refund handling when bookings can’t be completed, with clear, user-facing refund outcomes.
    • Improved cancelled-payment pages with context-aware “Try again” routing.
  • Bug Fixes

    • Better handling for deleted, unavailable, or closed listings during checkout.
    • Preserved customer answers and prevented duplicate booking/cancellation results on repeated provider events.
  • Documentation

    • Added internal payment-processing follow-up items for review.

…xemption

The 1,985-line payment-processing module was grandfathered out of the
noExcessiveLinesPerFile rule. Split it into a payment-processing/ folder of
single-purpose files, each well under the limit, and drop its biome.json entry:

- metadata.ts   — read signed session metadata into a BookingIntent
- classify.ts   — validate the paid session and prove it is ours (price proof)
- cancel.ts     — the payment-cancelled/declined page and its retry link
- refunds.ts    — refund mechanics plus the typed refund reasons (RefundSpec)
- package-pricing.ts — re-validate package structure and per-line price drift
- items.ts      — validate every signed line against the current database
- pricing.ts    — build the checkout intent, re-price, and gate on price drift
- create.ts     — turn a validated session into a real attendee
- store-refund.ts — keep-and-refund placeholder + balance settle paths
- index.ts      — the two-phase locked orchestration

Splitting surfaced duplication jscpd could not see inside the monolith; fixed
with shared helpers rather than ignores: bookingSlot (listing id + package
path), datelessGhostBookings, allocatedUnitsByChild, a SessionProcessor type
for the two processors, and merging currentOrderTree into orderEdgeDrifted.

Importers (webhooks.ts, the two test files) now import from the specific files.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J251sRHStWRgsijyynWunC
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2cea1bf2-3b61-4c86-ae2e-ff85989acbd7

📥 Commits

Reviewing files that changed from the base of the PR and between 7637154 and 516d9b4.

📒 Files selected for processing (1)
  • TODO.md

📝 Walkthrough

Walkthrough

The payment-processing implementation was split from one module into focused modules for session metadata, validation, pricing revalidation, cancellation, refunds, booking creation, placeholder storage, and orchestration. Imports and tests now reference the new module paths.

Changes

Payment processing flow

Layer / File(s) Summary
Session metadata and validation
src/features/api/payment-processing/metadata.ts, src/features/api/payment-processing/classify.ts, src/features/api/payment-processing/cancel.ts, src/features/api/webhooks.ts
Metadata parsing, price-proof classification, paid-session validation, cancellation retry routing, and webhook imports are separated into dedicated modules.
Current listing and pricing revalidation
src/features/api/payment-processing/items.ts, src/features/api/payment-processing/package-pricing.ts, src/features/api/payment-processing/pricing.ts, test/features/api/payment-processing/packages.test.ts
Current listings, package structure, child allocations, signed prices, and charged totals are revalidated before booking.
Booking creation and refund persistence
src/features/api/payment-processing/create.ts, src/features/api/payment-processing/refunds.ts, src/features/api/payment-processing/store-refund.ts, test/features/api/payment-processing/pair-entries-by-listing.test.ts
Attendee creation, answer persistence, refund handling, placeholder bookings, balance settlement, and failure result storage are implemented in separate modules.
Reservation and payment orchestration
src/features/api/payment-processing/index.ts, biome.json, TODO.md
Reservation conflicts, ledger replay, session processing, terminalization, error formatting, formatter configuration, and payment-processing follow-up notes are updated for the split.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Webhooks
  participant processPaymentSession
  participant validatePaidSession
  participant createAttendeeForSession
  participant storeRefundedBooking
  Webhooks->>processPaymentSession: payment session id
  processPaymentSession->>validatePaidSession: validate provider session
  validatePaidSession-->>processPaymentSession: validated session
  processPaymentSession->>createAttendeeForSession: create attendee and bookings
  createAttendeeForSession-->>processPaymentSession: success or honour failure
  processPaymentSession->>storeRefundedBooking: persist failed payment when required
  storeRefundedBooking-->>processPaymentSession: terminal payment result
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: splitting the payment-processing module into smaller focused files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/payment-processing-refactor-fqrnpg

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@src/features/api/payment-processing/index.ts`:
- Around line 298-316: Prevent post-commit failures from triggering
storeRefundedBooking: narrow the try/catch around createAttendeeForSession to
only pre-commit operations, or ensure its post-write cleanup path (including
ensureAllBookings) is non-throwing. Preserve refund handling for genuine
pre-commit failures while allowing persisted bookings to complete without
refunding.

In `@src/features/api/payment-processing/items.ts`:
- Around line 135-154: Batch listing and package-pricing database reads in
validateAllItems and loadPackagePricingByGroup instead of awaiting
getListingWithCount and group pricing queries sequentially per item/group; add
or use getListingsWithCount for all required listing IDs and fetch pricing data
in grouped queries while preserving validation and fail-closed behavior.
🪄 Autofix (Beta)

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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 7f8852d9-2252-419c-85a1-2639ee3dbede

📥 Commits

Reviewing files that changed from the base of the PR and between 828e5ba and 7637154.

📒 Files selected for processing (15)
  • biome.json
  • src/features/api/payment-processing.ts
  • src/features/api/payment-processing/cancel.ts
  • src/features/api/payment-processing/classify.ts
  • src/features/api/payment-processing/create.ts
  • src/features/api/payment-processing/index.ts
  • src/features/api/payment-processing/items.ts
  • src/features/api/payment-processing/metadata.ts
  • src/features/api/payment-processing/package-pricing.ts
  • src/features/api/payment-processing/pricing.ts
  • src/features/api/payment-processing/refunds.ts
  • src/features/api/payment-processing/store-refund.ts
  • src/features/api/webhooks.ts
  • test/features/api/payment-processing/packages.test.ts
  • test/features/api/payment-processing/pair-entries-by-listing.test.ts
💤 Files with no reviewable changes (2)
  • biome.json
  • src/features/api/payment-processing.ts

Comment thread src/features/api/payment-processing/index.ts
Comment thread src/features/api/payment-processing/items.ts
Two pre-existing behaviours CodeRabbit flagged on PR #1692 (post-commit refund
window in processReservedSession; unbatched per-item DB reads in
validateAllItems/loadPackagePricingByGroup). Both predate the split — the code
was moved verbatim — so they're out of scope for the reorganisation PR and are
captured here for a future change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J251sRHStWRgsijyynWunC
@stefan-burke
stefan-burke enabled auto-merge July 10, 2026 09:46
@stefan-burke
stefan-burke added this pull request to the merge queue Jul 10, 2026
Merged via the queue into main with commit 04796f8 Jul 10, 2026
1 check passed
@stefan-burke
stefan-burke deleted the claude/payment-processing-refactor-fqrnpg branch July 10, 2026 09:54
stefan-burke pushed a commit that referenced this pull request Jul 10, 2026
The merge of main placed PR #1692's follow-up heading directly after this
branch's TODO entry, tripping markdownlint MD022. Add the blank line.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LpihwVNefhvq7XLVwq1wX4
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