Skip to content

Conversation

@lissavxo
Copy link
Collaborator

@lissavxo lissavxo commented Dec 29, 2025

Related to #1021

Description

Added fields param to client payment table
Changed generate payment id endpoint to add the new fields param
Added functions to update and get fields

Test plan

Test api/payments/paymentId endpoint sending an array of objects in string format called fields

Summary by CodeRabbit

  • New Features

    • Add custom field support for payments with storage, retrieval, and update of payment fields.
    • Persist payment fields as structured metadata on payment records.
  • Chores

    • Add specific validation and error responses for malformed fields, invalid field structure, and invalid amounts.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 29, 2025

📝 Walkthrough

Walkthrough

Adds support for custom client payment fields: validators to parse/validate fields and amount, response messages for new validation errors, DB schema migration to store JSON fields, service API changes to persist/retrieve/update fields, and API handler updates to accept and forward fields.

Changes

Cohort / File(s) Summary
Error Messages
constants/index.ts
Added three validation error entries: INVALID_FIELDS_FORMAT_400, INVALID_FIELD_STRUCTURE_400, INVALID_AMOUNT_400.
Database Schema & Migration
prisma-local/schema.prisma, prisma-local/migrations/.../migration.sql
Added non-null fields column (LongText) with default '[]' to ClientPayment; migration SQL adds the column.
Service Layer
services/clientPaymentService.ts
Added ClientPaymentField interface; extended generatePaymentId(address, amount, fields?) to persist fields as JSON; added getClientPaymentFields and updateClientPaymentFields.
Validation Utilities
utils/validators.ts
Added parseClientPaymentFields and parseAmount; introduced ClientPaymentFieldInput; updated CreatePaymentIdPOSTParameters and CreatePaymentIdInput to include fields and parsed amount; updated parseCreatePaymentIdPOSTRequest.
API Handler
pages/api/payments/paymentId/index.ts
Now unpacks amount and fields from parser, passes fields to generatePaymentId, and handles new validation error cases; removed unused Decimal import.

Sequence Diagram

sequenceDiagram
    participant Client
    participant APIHandler as API Handler
    participant Validators
    participant Service as Payment Service
    participant DB as Database

    Client->>APIHandler: POST /api/payments/paymentId {address, amount, fields}
    APIHandler->>Validators: parseCreatePaymentIdPOSTRequest(body)
    Validators->>Validators: parseAmount(amountInput)
    alt Invalid Amount
        Validators-->>APIHandler: INVALID_AMOUNT_400
        APIHandler-->>Client: 400 Response
    end
    Validators->>Validators: parseClientPaymentFields(fieldsInput)
    alt Invalid Fields Format
        Validators-->>APIHandler: INVALID_FIELDS_FORMAT_400
        APIHandler-->>Client: 400 Response
    end
    alt Invalid Field Structure
        Validators-->>APIHandler: INVALID_FIELD_STRUCTURE_400
        APIHandler-->>Client: 400 Response
    end
    Validators-->>APIHandler: {amount, fields, address}
    APIHandler->>Service: generatePaymentId(address, amount, fields)
    Service->>DB: Create ClientPayment (address, amount, fields JSON)
    DB-->>Service: Created record
    Service-->>APIHandler: payment object
    APIHandler-->>Client: 200 OK {paymentId, ...}
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Suggested labels

enhancement (UI/UX/feature)

Suggested reviewers

  • chedieck

Poem

🐰 A tiny field hops into place,
Validated, stored, a neat little space,
From client to DB, a JSON parade,
Payments now hold the custom parade — hooray! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: client payment fields' directly describes the main change—adding a fields feature to client payments—and is concise and clear.
Description check ✅ Passed The description covers the key changes and includes a test plan, but lacks detail about the purpose and context of the feature.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a843e2f and bfb52e0.

📒 Files selected for processing (1)
  • utils/validators.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • utils/validators.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Run Tests

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
Contributor

@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.

Actionable comments posted: 1

🧹 Nitpick comments (3)
pages/api/payments/paymentId/index.ts (1)

16-19: Redundant parseAddress call.

parseAddress(address) is called here on line 17, but generatePaymentId in services/clientPaymentService.ts (line 21) also calls parseAddress(address) internally. This results in double validation/parsing.

Consider either:

  1. Removing the call here since the service handles it, or
  2. Removing it from the service and relying on the caller to provide a parsed address
Option 1: Remove redundant call here
-      const { amount, fields, address } = parseCreatePaymentIdPOSTRequest(req.body)
-      const parsedAddress = parseAddress(address)
-
-      const paymentId = await generatePaymentId(parsedAddress, amount, fields)
+      const { amount, fields, address } = parseCreatePaymentIdPOSTRequest(req.body)
+      const paymentId = await generatePaymentId(address, amount, fields)
services/clientPaymentService.ts (1)

68-81: Silent failure for non-existent payment.

getClientPaymentFields returns an empty array both when the payment doesn't exist and when fields are genuinely empty. If distinguishing these cases matters for callers, consider returning null for non-existent payments or throwing an error.

Alternative: Return null for non-existent payment
-export const getClientPaymentFields = async (paymentId: string): Promise<ClientPaymentField[]> => {
+export const getClientPaymentFields = async (paymentId: string): Promise<ClientPaymentField[] | null> => {
   const clientPayment = await prisma.clientPayment.findUnique({
     where: { paymentId },
     select: { fields: true }
   })
   if (clientPayment === null) {
-    return []
+    return null
   }
   try {
     return JSON.parse(clientPayment.fields) as ClientPaymentField[]
   } catch {
     return []
   }
 }
utils/validators.ts (1)

580-585: Remove unused ClientPaymentFieldInput interface.

This interface is defined at lines 580-585 but has no usages anywhere in the codebase.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1025cd2 and a843e2f.

📒 Files selected for processing (6)
  • constants/index.ts
  • pages/api/payments/paymentId/index.ts
  • prisma-local/migrations/20251228021700_client_payment_fields/migration.sql
  • prisma-local/schema.prisma
  • services/clientPaymentService.ts
  • utils/validators.ts
🧰 Additional context used
🧬 Code graph analysis (2)
utils/validators.ts (2)
services/clientPaymentService.ts (1)
  • ClientPaymentField (10-15)
constants/index.ts (1)
  • RESPONSE_MESSAGES (8-111)
pages/api/payments/paymentId/index.ts (3)
utils/validators.ts (2)
  • parseCreatePaymentIdPOSTRequest (644-660)
  • parseAddress (32-49)
services/clientPaymentService.ts (1)
  • generatePaymentId (17-52)
constants/index.ts (1)
  • RESPONSE_MESSAGES (8-111)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Run Tests
🔇 Additional comments (9)
prisma-local/schema.prisma (1)

289-289: LGTM!

The new fields column is well-designed: LongText provides sufficient capacity for storing JSON arrays, and the default "[]" ensures backward compatibility with existing records.

prisma-local/migrations/20251228021700_client_payment_fields/migration.sql (1)

1-2: LGTM!

The migration correctly adds the fields column with NOT NULL and a default value of '[]', ensuring existing rows are properly handled without requiring data backfill.

constants/index.ts (1)

107-110: LGTM!

The new error constants follow the existing patterns in the codebase with appropriate status codes and clear, descriptive messages.

utils/validators.ts (2)

629-642: LGTM!

The amount parsing correctly handles edge cases: undefined/empty returns undefined, and the validation ensures positive numbers only. Using Prisma.Decimal from the trimmed string preserves precision for monetary values.


644-659: LGTM!

The updated parser correctly integrates the new amount and fields parsing while maintaining backward compatibility (both are optional).

pages/api/payments/paymentId/index.ts (1)

30-38: LGTM!

The new error cases properly handle the validation errors introduced for fields and amount, following the established pattern in this handler.

services/clientPaymentService.ts (3)

10-15: LGTM!

The ClientPaymentField interface is well-structured with a required name property and sensible optional fields. The value type of string | boolean provides appropriate flexibility for different field types.


83-88: LGTM!

The update function is straightforward. If the paymentId doesn't exist, Prisma will throw an appropriate error which is consistent with other update patterns in this service.


39-40: LGTM!

The fields are correctly serialized to JSON with a sensible default of '[]' when undefined.

@Klakurka Klakurka requested a review from chedieck January 1, 2026 05:25
@Klakurka Klakurka added enhancement (UI/UX/feature) New feature or request enhancement (behind the scenes) Stuff that users won't see and removed enhancement (UI/UX/feature) New feature or request labels Jan 1, 2026
@Klakurka Klakurka added this to the Phase 3 milestone Jan 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement (behind the scenes) Stuff that users won't see

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants