Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the ✨ Finishing touches🧪 Generate unit tests✅ Unit Test PR creation complete.
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. Comment |
| -- AlterTable | ||
| ALTER TABLE "ItemQuantityChange" ADD COLUMN "customerType" "CustomerType" NOT NULL; |
There was a problem hiding this comment.
todo: migration here with existing customerId
There was a problem hiding this comment.
Greptile Summary
This PR introduces a comprehensive transactions feature that consolidates payment-related activities from multiple sources into a unified view. The implementation spans database schema changes, API endpoints, frontend components, and comprehensive testing.
Database Changes: The core change adds a customerType field to the ItemQuantityChange table, enabling consistent categorization across all payment transaction types (subscriptions, one-time purchases, and item quantity changes). This allows the system to distinguish between USER, TEAM, and CUSTOM customer types uniformly.
API Implementation: A new internal transactions endpoint (/api/latest/internal/payments/transactions) aggregates data from three separate database tables using complex cursor-based pagination. The endpoint supports filtering by transaction type and customer type, with parallel database queries and in-memory sorting to provide a chronological view of all payment activities.
Frontend Integration: The dashboard gains a new transactions page with filtering capabilities, accessible through the payments sidebar. The implementation follows the established patterns in the codebase, using the same data table architecture and admin interface patterns found throughout the application.
Supporting Infrastructure: The changes include schema validation updates, admin interface methods, template implementations, and comprehensive end-to-end tests covering various transaction scenarios and pagination edge cases.
The implementation maintains consistency with existing patterns - database migrations follow Prisma conventions, the API uses the established SmartRouteHandler pattern, and the frontend components follow the same architecture as other admin features like the user table.
Confidence score: 2/5
- This PR contains a critical database migration issue that will break production deployments with existing data
- Score lowered due to the dangerous database migration that adds a NOT NULL column without handling existing records
- Pay close attention to the migration file and consider adding a default value or data backfill strategy
15 files reviewed, 3 comments
| - Added the required column `customerType` to the `ItemQuantityChange` table without a default value. This is not possible if the table is not empty. | ||
|
|
||
| */ | ||
| -- AlterTable | ||
| ALTER TABLE "ItemQuantityChange" ADD COLUMN "customerType" "CustomerType" NOT NULL; |
There was a problem hiding this comment.
logic: This migration will fail if the ItemQuantityChange table has existing data. Adding a NOT NULL column without a default value to a populated table is not possible. Need to either add a default value, make the column nullable initially, or provide a data migration strategy.
Context Used: Rule - When modifying database schema with NOT NULL constraints or enum changes, ensure migrations handle existing data properly to avoid failures on populated tables. (link)
|
|
||
| export function TransactionTable() { | ||
| const app = useAdminApp(); | ||
| const [filters, setFilters] = React.useState<{ cursor?: string, limit?: number, type?: 'subscription' | 'one_time' | 'item_quantity_change', customerType?: 'user' | 'team' | 'custom' }>({ |
There was a problem hiding this comment.
style: Consider extracting the filter type definition to avoid duplication between the state type and the onUpdate function parameters.
| cursor: options.cursor, | ||
| limit: options.limit, | ||
| type: options.columnFilters.find(f => f.id === 'type')?.value as any, | ||
| customerType: options.columnFilters.find(f => f.id === 'customer_type')?.value as any, |
There was a problem hiding this comment.
style: The mapping from 'customer_type' column ID to 'customerType' filter property creates inconsistent naming. Consider using consistent naming throughout.
apps/backend/prisma/migrations/20250918005821_item_quantity_change_customer_type/migration.sql
Outdated
Show resolved
Hide resolved
apps/backend/src/app/api/latest/internal/payments/transactions/route.tsx
Show resolved
Hide resolved
There was a problem hiding this comment.
for tomorrow this is good to merge once you finish the migration code in the SQL. eventualyl, we'll want the following layout tho:
/**
* A transaction is an event where one of the following happens:
*
* - An item quantity changes
* - An offer quantity changes
* - Money is transferred between the customer and the platform
* - A combination of the above
*
* The type of the transaction is determined by what triggered it (eg. a checkout flow, automatic renewal, etc.)
*/
type Transaction = {
id: string,
createdAtMillis: number,
effectiveAtMillis: number, // may differ sometimes, especially for subscription cancellations or renewals
settledAtMillis: number, // if a purchase,
/**
* The item quantity changes for this transaction. Note that it does not include any quantity changes that were caused by offer quantity changes, as those are in the separate offerQuantityChanges array.
*/
itemQuantityChanges: {
itemId: string,
quantity: number,
}[],
offerQuantityChanges: {
offerId?: string,
offer: Offer,
priceId: string,
quantity: number,
// subscriptionId or oneTimePurchaseId can be set, or neither, but never both (the priceId's recurrence must match whichever of the two is set)
subscriptionId?: string,
oneTimePurchaseId?: string,
}[],
/**
* Before fees, in the currency of the transaction. May be negative for refunds.
*/
chargedAmount: null | {
[currencyCode: Uppercase<CurrencyCode>]: MoneyAmount,
},
/**
* After fees, in the currency of the recipient (currently always USD, although this might change when we expand to other currencies). May be negative for refunds.
*/
receivedAmount: null | {
USD: MoneyAmount,
},
customerType: "user" | "team" | "custom",
customerId: string,
testMode: boolean,
} & (
| {
type: "purchase", // a purchase, usually happens at the end of a checkout flow
itemQuantityChanges: [],
}
| {
type: "refund",
originalTransactionId: string, // not always
}
| {
type: "refund_reversal", // very rare, see stripe docs
originalRefundTransactionId: string,
}
| {
type: "automatic_subscription_renewal",
subscriptionId: string,
itemQuantityChanges: [],
offerQuantityChanges: [],
}
| {
type: "subscription_cancellation",
subscriptionId: string,
itemQuantityChanges: [],
}
| {
type: "manual_item_quantity_change",
offerQuantityChanges: [],
chargedAmount: null,
receivedAmount: null,
testMode: false,
}
)|
Caution CodeRabbit plans did not produce any file changes. |
!--
Make sure you've read the CONTRIBUTING.md guidelines: https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md
-->
High-level PR Summary
This PR introduces a transactions feature to the payment system, allowing users to view and manage payment history across different transaction types. The implementation includes a database schema update to add
customerTypeto theItemQuantityChangetable, a new API endpoint for retrieving transaction data, and a UI interface in the dashboard to display transactions in a filterable table format. The PR consolidates subscription purchases, one-time purchases, and item quantity changes into a unified transaction view with appropriate filtering options for customer type and transaction type. The implementation also includes end-to-end tests to verify the functionality of the new transactions API.⏱️ Estimated Review Time: 15-30 minutes
💡 Review Order Suggestion
apps/backend/prisma/schema.prismaapps/backend/prisma/migrations/20250918005821_item_quantity_change_customer_type/migration.sqlapps/backend/src/app/api/latest/payments/items/[customer_type]/[customer_id]/[item_id]/update-quantity/route.tspackages/stack-shared/src/interface/crud/transactions.tsapps/backend/src/app/api/latest/internal/payments/transactions/route.tsxpackages/stack-shared/src/interface/admin-interface.tspackages/template/src/lib/stack-app/apps/interfaces/admin-app.tspackages/template/src/lib/stack-app/apps/implementations/admin-app-impl.tsapps/dashboard/src/components/data-table/transaction-table.tsxapps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/transactions/page.tsxapps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/transactions/page-client.tsxapps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sidebar-layout.tsxapps/e2e/tests/backend/endpoints/api/v1/internal/transactions.test.tspackages/stack-shared/src/schema-fields.tspackages/stack-ui/src/components/data-table/toolbar.tsxReview by RecurseML
🔍 Review performed on 4950494..e4e07d2
✅ Files analyzed, no issues (2)
•
apps/backend/src/app/api/latest/internal/payments/transactions/route.tsx•
apps/dashboard/src/components/data-table/transaction-table.tsx⏭️ Files skipped (trigger manually) (10)
apps/backend/prisma/migrations/20250918005821_item_quantity_change_customer_type/migration.sqlapps/backend/prisma/schema.prismaapps/backend/src/app/api/latest/payments/items/[customer_type]/[customer_id]/[item_id]/update-quantity/route.tsapps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/transactions/page-client.tsxapps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/transactions/page.tsxapps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sidebar-layout.tsxpackages/stack-shared/src/schema-fields.tspackages/stack-ui/src/components/data-table/toolbar.tsxpackages/template/src/lib/stack-app/apps/implementations/admin-app-impl.tspackages/template/src/lib/stack-app/apps/interfaces/admin-app.tsImportant
Add transactions feature with database, API, UI, and test updates for managing payment history.
customerTypecolumn toItemQuantityChangetable inschema.prismaandmigration.sql.route.tsxfor retrieving transactions with filters fortypeandcustomer_type.update-quantity/route.tsto includecustomerTypein item quantity changes.TransactionTablecomponent intransaction-table.tsxfor displaying transactions with filtering options.page.tsxandpage-client.tsx.sidebar-layout.tsxto include transactions in navigation.transactions.test.tsfor transaction retrieval and pagination.AdminTransactiontype intransactions.ts.listTransactionsmethod toadmin-interface.tsandadmin-app-impl.ts.This description was created by
for 8d7f42d. You can customize this summary. It will automatically update as commits are pushed.