- Notifications
You must be signed in to change notification settings - Fork474
Payment transactions#990
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
base:dev
Are you sure you want to change the base?
Conversation
vercelbot commentedOct 30, 2025 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
The latest updates on your projects. Learn more aboutVercel for GitHub.
|
coderabbitaibot commentedOct 30, 2025 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughRefactors the payments surface from a flat AdminTransaction shape to a typed Transaction schema with entry arrays; adds transaction-builder functions for subscriptions, one-time purchases, and item-quantity changes; updates backend route, shared interfaces/SDK, dashboard UI, and tests to consume the new model. Changes
Sequence Diagram(s)sequenceDiagram participant Client participant Route as GET /internal/payments/transactions participant DB as Database participant Builder as Transaction Builder participant Schema as transactionSchema Client->>Route: GET /transactions?type=...&cursor=... Route->>DB: fetch subs, otps, item-qty-changes (parallel) DB-->>Route: raw rows Route->>Route: merge & sort rows -> TransactionRow[] alt when building Route->>Builder: buildXTransaction({ row }) Builder-->>Route: Transaction end Route->>Schema: validate Transaction[] Schema-->>Route: valid Route-->>Client: { transactions: Transaction[], next_cursor }Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for usingCodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Greptile Overview
Greptile Summary
This PR refactors the payment transaction API to use dedicated builder functions, improving code organization and maintainability.
Key Changes
- Refactored transaction construction: Extracted transaction building logic from the route handler into dedicated builder functions (
buildSubscriptionTransaction,buildOneTimePurchaseTransaction,buildItemQuantityChangeTransaction) - Added comprehensive tests: New test file covers edge cases including missing product snapshots, test mode handling, and money amount multiplication
- Improved type safety: Better separation between internal
TransactionSourcetypes and externalTransactiontypes - Frontend integration: Added transaction table component with filtering by type and customer type
- Money arithmetic: Implemented proper decimal handling for multi-currency amounts using BigInt for precision
Architecture Improvements
The refactoring follows good separation of concerns:
- Route handler manages pagination and API concerns
- Builder functions handle transaction object construction
- Money arithmetic is isolated and well-tested
- Type definitions are centralized in shared package
Confidence Score: 4/5
- This PR is safe to merge with minimal risk - the refactoring improves code quality and has comprehensive test coverage
- Score reflects solid refactoring with good test coverage. Minor concern about pagination efficiency when filtering after merge-sort, but unlikely to cause issues in practice
- Pay attention to
apps/backend/src/app/api/latest/internal/payments/transactions/route.tsx- the pagination logic filters transactions after fetching and merging, which may need optimization for large datasets
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| apps/backend/src/app/api/latest/internal/payments/transactions/route.tsx | 4/5 | Refactored to use builder functions for transaction construction; improved maintainability and separation of concerns |
| apps/backend/src/app/api/latest/internal/payments/transactions/transaction-builder.ts | 5/5 | New file with comprehensive test coverage; implements transaction building logic with proper money arithmetic |
| apps/dashboard/src/components/data-table/transaction-table.tsx | 4/5 | Frontend component for displaying transactions with filtering and pagination; uses Map for customer data lookup |
Sequence Diagram
sequenceDiagram participant Client as Dashboard Client participant API as Transaction API Route participant Builder as Transaction Builder participant DB as Prisma Database participant Interface as Admin Interface Client->>Interface: listTransactions(params) Interface->>API: GET /internal/payments/transactions Note over API: Parse cursor (sub|iqc|otp) Note over API: Validate limit (1-200) API->>DB: Find subscription cursor API->>DB: Find item change cursor API->>DB: Find purchase cursor par Fetch all transaction sources API->>DB: findMany(subscriptions) API->>DB: findMany(itemQuantityChanges) API->>DB: findMany(oneTimePurchases) end DB-->>API: Return records loop For each source type API->>Builder: buildSubscriptionTransaction Builder-->>API: Transaction object API->>Builder: buildItemQuantityChangeTransaction Builder-->>API: Transaction object API->>Builder: buildOneTimePurchaseTransaction Builder-->>API: Transaction object end Note over API: Sort by createdAt DESC, id DESC Note over API: Filter by transaction type Note over API: Slice to page limit Note over API: Build next cursor API-->>Interface: {transactions, next_cursor} Interface-->>Client: {transactions, nextCursor} Client->>Client: Display in TransactionTable9 files reviewed, 1 comment
Uh oh!
There was an error while loading.Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Actionable comments posted: 3
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
apps/backend/src/app/api/latest/internal/payments/transactions/route.tsx(4 hunks)apps/backend/src/app/api/latest/internal/payments/transactions/transaction-builder.test.ts(1 hunks)apps/backend/src/app/api/latest/internal/payments/transactions/transaction-builder.ts(1 hunks)apps/backend/src/lib/email-rendering.tsx(2 hunks)apps/dashboard/src/components/data-table/transaction-table.tsx(2 hunks)packages/stack-shared/src/interface/admin-interface.ts(3 hunks)packages/stack-shared/src/interface/crud/transactions.ts(1 hunks)packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts(3 hunks)packages/template/src/lib/stack-app/apps/interfaces/admin-app.ts(3 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use ES6 Maps instead of Records wherever possible in TypeScript code
Files:
apps/backend/src/app/api/latest/internal/payments/transactions/transaction-builder.test.tsapps/backend/src/app/api/latest/internal/payments/transactions/transaction-builder.tsapps/backend/src/lib/email-rendering.tsxapps/dashboard/src/components/data-table/transaction-table.tsxpackages/template/src/lib/stack-app/apps/implementations/admin-app-impl.tspackages/stack-shared/src/interface/admin-interface.tsapps/backend/src/app/api/latest/internal/payments/transactions/route.tsxpackages/template/src/lib/stack-app/apps/interfaces/admin-app.tspackages/stack-shared/src/interface/crud/transactions.ts
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
When writing tests, prefer .toMatchInlineSnapshot over other selectors where possible
Files:
apps/backend/src/app/api/latest/internal/payments/transactions/transaction-builder.test.ts
apps/{dashboard,dev-launchpad}/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
For blocking alerts and errors in the UI, never use toast; use alerts instead
Files:
apps/dashboard/src/components/data-table/transaction-table.tsx
apps/{dashboard,dev-launchpad}/**/*.{css,tsx,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Animations: keep hover/click transitions snappy; do not delay actions with pre-hover transitions; apply transitions after the action (e.g., fade-out on hover end)
Files:
apps/dashboard/src/components/data-table/transaction-table.tsx
packages/template/**
📄 CodeRabbit inference engine (AGENTS.md)
When changes are needed for stack or js packages, make them in packages/template instead
Files:
packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.tspackages/template/src/lib/stack-app/apps/interfaces/admin-app.ts
🧠 Learnings (1)
📚 Learning: 2025-10-20T22:25:40.427Z
Learnt from: CRPR: stack-auth/stack-auth#0File: AGENTS.md:0-0Timestamp: 2025-10-20T22:25:40.427ZLearning: Applies to apps/backend/src/app/api/latest/**/route.ts : In backend API routes, use the custom route handler system to ensure consistent API responsesApplied to files:
apps/backend/src/app/api/latest/internal/payments/transactions/route.tsx
🧬 Code graph analysis (8)
apps/backend/src/app/api/latest/internal/payments/transactions/transaction-builder.test.ts (2)
apps/backend/src/lib/tenancies.tsx (1)
Tenancy(47-47)apps/backend/src/app/api/latest/internal/payments/transactions/transaction-builder.ts (3)
buildSubscriptionTransaction(173-216)buildOneTimePurchaseTransaction(218-261)buildItemQuantityChangeTransaction(263-291)
apps/backend/src/app/api/latest/internal/payments/transactions/transaction-builder.ts (3)
packages/stack-shared/src/utils/currency-constants.tsx (2)
Currency(3-7)SUPPORTED_CURRENCIES(9-45)packages/stack-shared/src/utils/strings.tsx (1)
typedToLowercase(15-18)apps/backend/src/lib/tenancies.tsx (1)
Tenancy(47-47)
apps/dashboard/src/components/data-table/transaction-table.tsx (4)
packages/stack-shared/src/interface/crud/transactions.ts (4)
TransactionEntry(176-176)Transaction(206-206)TransactionType(189-189)TRANSACTION_TYPES(178-187)apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/use-admin-app.tsx (1)
useAdminApp(29-44)packages/stack-ui/src/components/data-table/cells.tsx (2)
AvatarCell(45-52)TextCell(7-43)packages/stack-ui/src/components/data-table/data-table.tsx (1)
DataTableManualPagination(174-238)
packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts (2)
packages/template/src/lib/stack-app/apps/implementations/common.ts (1)
createCache(29-34)packages/stack-shared/src/interface/crud/transactions.ts (2)
TransactionType(189-189)Transaction(206-206)
packages/stack-shared/src/interface/admin-interface.ts (1)
packages/stack-shared/src/interface/crud/transactions.ts (2)
TransactionType(189-189)Transaction(206-206)
apps/backend/src/app/api/latest/internal/payments/transactions/route.tsx (2)
packages/stack-shared/src/interface/crud/transactions.ts (3)
TRANSACTION_TYPES(178-187)transactionSchema(191-204)Transaction(206-206)apps/backend/src/app/api/latest/internal/payments/transactions/transaction-builder.ts (3)
buildSubscriptionTransaction(173-216)buildItemQuantityChangeTransaction(263-291)buildOneTimePurchaseTransaction(218-261)
packages/template/src/lib/stack-app/apps/interfaces/admin-app.ts (1)
packages/stack-shared/src/interface/crud/transactions.ts (2)
TransactionType(189-189)Transaction(206-206)
packages/stack-shared/src/interface/crud/transactions.ts (4)
packages/stack-shared/src/utils/currency-constants.tsx (3)
SUPPORTED_CURRENCIES(9-45)Currency(3-7)MoneyAmount(1-1)packages/stack-shared/src/utils/errors.tsx (1)
throwErr(10-19)packages/stack-shared/src/schema-fields.ts (8)
yupString(187-190)yupObject(247-251)yupNumber(191-194)customerTypeSchema(547-547)productSchema(569-592)yupUnion(257-281)yupArray(213-216)yupBoolean(195-198)packages/stack-shared/src/utils/objects.tsx (1)
typedFromEntries(281-283)
⏰ 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). (12)
- GitHub Check: all-good
- GitHub Check: Vercel Agent Review
- GitHub Check: lint_and_build (latest)
- GitHub Check: check_prisma_migrations (22.x)
- GitHub Check: docker
- GitHub Check: setup-tests
- GitHub Check: build (22.x)
- GitHub Check: build (22.x)
- GitHub Check: build (22.x)
- GitHub Check: restart-dev-and-test
- GitHub Check: restart-dev-and-test-with-custom-base-port
- GitHub Check: Security Check
apps/backend/src/app/api/latest/internal/payments/transactions/transaction-builder.test.ts OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
apps/backend/src/app/api/latest/internal/payments/transactions/transaction-builder.tsShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
There was a problem hiding this 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
♻️ Duplicate comments (1)
apps/dashboard/src/components/data-table/transaction-table.tsx (1)
131-139:USD-only handling remains unresolved.This issue was already flagged in a previous review. The function still only displays USD amounts and shows '—' for all other currencies, which blanks the amount column for non-USD tenants. Please refer to the previous review comment for the proposed solution.
🧹 Nitpick comments (2)
apps/dashboard/src/components/data-table/transaction-table.tsx (2)
51-58:Consider simplifying the redundant check.The condition at line 56 returns
'other'when aproductGrantexists without subscription or purchase IDs, but line 57 also returns'other'as the default. Since both paths lead to the same result, line 56 can be removed.Apply this diff:
function deriveSourceType(transaction: Transaction): SourceType { if (transaction.entries.some(isItemQuantityChangeEntry)) return 'item_quantity_change'; const productGrant = transaction.entries.find(isProductGrantEntry); if (productGrant?.subscription_id) return 'subscription'; if (productGrant?.one_time_purchase_id) return 'one_time';- if (productGrant) return 'other'; return 'other'; }
86-89:Improve type safety in the default fallback.The
as anycast suppresses type checking. SincetransactionTypeis typed asTransactionType | null, the default case should only handlenull. Consider using a type-safe fallback.Apply this diff:
default: {- return { label: (transactionType as any) ?? '—', Icon: CircleHelp };+ return { label: transactionType ?? 'Unknown', Icon: CircleHelp }; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/dashboard/src/components/data-table/transaction-table.tsx(2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use ES6 Maps instead of Records wherever possible in TypeScript code
Files:
apps/dashboard/src/components/data-table/transaction-table.tsx
apps/{dashboard,dev-launchpad}/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
For blocking alerts and errors in the UI, never use toast; use alerts instead
Files:
apps/dashboard/src/components/data-table/transaction-table.tsx
apps/{dashboard,dev-launchpad}/**/*.{css,tsx,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Animations: keep hover/click transitions snappy; do not delay actions with pre-hover transitions; apply transitions after the action (e.g., fade-out on hover end)
Files:
apps/dashboard/src/components/data-table/transaction-table.tsx
🧬 Code graph analysis (1)
apps/dashboard/src/components/data-table/transaction-table.tsx (4)
packages/stack-shared/src/interface/crud/transactions.ts (4)
TransactionEntry(176-176)Transaction(206-206)TransactionType(189-189)TRANSACTION_TYPES(178-187)apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/use-admin-app.tsx (1)
useAdminApp(29-44)packages/stack-ui/src/components/data-table/cells.tsx (2)
AvatarCell(45-52)TextCell(7-43)packages/stack-ui/src/components/data-table/data-table.tsx (1)
DataTableManualPagination(174-238)
⏰ 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). (12)
- GitHub Check: build (22.x)
- GitHub Check: build (22.x)
- GitHub Check: build (22.x)
- GitHub Check: setup-tests
- GitHub Check: lint_and_build (latest)
- GitHub Check: restart-dev-and-test-with-custom-base-port
- GitHub Check: restart-dev-and-test
- GitHub Check: check_prisma_migrations (22.x)
- GitHub Check: all-good
- GitHub Check: Vercel Agent Review
- GitHub Check: docker
- GitHub Check: Security Check
🔇 Additional comments (1)
apps/dashboard/src/components/data-table/transaction-table.tsx (1)
172-172:Verify the test mode amount display behavior.Test mode transactions display
'Test mode'instead of the actual amount. Please confirm whether this is the intended UX or if both the test mode indicator and the amount should be shown (e.g.,'$10.00 (Test mode)').
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
There was a problem hiding this 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
♻️ Duplicate comments (3)
apps/dashboard/src/components/data-table/transaction-table.tsx (2)
131-139:Fix amount display for non-USD charges.This issue was flagged in a previous review and remains unresolved.
pickChargedAmountDisplayonly returns USD amounts; all other currencies render as'—', which blanks the amount column for non-USD tenants.
192-218:Fix critical type mismatch in transaction filtering logic.This issue was flagged in a previous review and remains unresolved. The column returns
SourceTypevalues but the toolbar populates the filter dropdown withTransactionTypevalues fromTRANSACTION_TYPES. These value sets don't overlap, so filtering will never match and always return empty results.apps/backend/src/app/api/latest/internal/payments/transactions/transaction-builder.ts (1)
125-146:Net amount is forced to USD "0" for non‑USD charges.This issue was flagged in a previous review and remains unresolved. If a purchase is denominated solely in a non-USD currency (e.g., EUR), this code emits
net_amount: { USD: "0" }, causing downstream reporting to falsely record zero revenue.This is compounded by the schema constraint in
packages/stack-shared/src/interface/crud/transactions.ts(lines 90-92) that only allows USD innet_amount.
🧹 Nitpick comments (1)
apps/backend/src/app/api/latest/internal/payments/transactions/transaction-builder.ts (1)
263-291:Unused parameter in buildItemQuantityChangeTransaction.The
tenancyparameter is accepted but never used in the function body. Consider removing it if it's not needed, or add a comment explaining why it's reserved for future use.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
apps/backend/src/app/api/latest/internal/payments/transactions/transaction-builder.test.ts(1 hunks)apps/backend/src/app/api/latest/internal/payments/transactions/transaction-builder.ts(1 hunks)apps/dashboard/src/components/data-table/transaction-table.tsx(2 hunks)apps/e2e/tests/backend/endpoints/api/v1/internal/transactions.test.ts(3 hunks)packages/stack-shared/src/interface/crud/transactions.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/backend/src/app/api/latest/internal/payments/transactions/transaction-builder.test.ts
🧰 Additional context used
🧬 Code graph analysis (3)
apps/backend/src/app/api/latest/internal/payments/transactions/transaction-builder.ts (5)
packages/stack-shared/src/schema-fields.ts (1)
productSchema(569-592)apps/backend/src/lib/payments.tsx (1)
productToInlineProduct(427-443)packages/stack-shared/src/utils/currency-constants.tsx (2)
Currency(3-7)SUPPORTED_CURRENCIES(9-45)packages/stack-shared/src/utils/strings.tsx (1)
typedToLowercase(15-18)apps/backend/src/lib/tenancies.tsx (1)
Tenancy(47-47)
apps/dashboard/src/components/data-table/transaction-table.tsx (6)
packages/stack-shared/src/interface/crud/transactions.ts (4)
TransactionEntry(176-176)Transaction(206-206)TransactionType(189-189)TRANSACTION_TYPES(178-187)apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/use-admin-app.tsx (1)
useAdminApp(29-44)packages/stack-ui/src/components/data-table/cells.tsx (2)
AvatarCell(45-52)TextCell(7-43)packages/stack-ui/src/components/ui/tooltip.tsx (3)
Tooltip(40-40)TooltipTrigger(40-40)TooltipContent(40-40)packages/stack-ui/src/components/data-table/data-table.tsx (1)
DataTableManualPagination(174-238)packages/stack-ui/src/components/ui/select.tsx (5)
Select(160-160)SelectTrigger(160-160)SelectValue(160-160)SelectContent(160-160)SelectItem(160-160)
packages/stack-shared/src/interface/crud/transactions.ts (4)
packages/stack-shared/src/utils/currency-constants.tsx (3)
SUPPORTED_CURRENCIES(9-45)Currency(3-7)MoneyAmount(1-1)packages/stack-shared/src/utils/errors.tsx (1)
throwErr(10-19)packages/stack-shared/src/schema-fields.ts (8)
yupString(187-190)yupObject(247-251)yupNumber(191-194)customerTypeSchema(547-547)inlineProductSchema(606-631)yupUnion(257-281)yupArray(213-216)yupBoolean(195-198)packages/stack-shared/src/utils/objects.tsx (1)
typedFromEntries(281-283)
⏰ 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). (12)
- GitHub Check: build (22.x)
- GitHub Check: build (22.x)
- GitHub Check: build (22.x)
- GitHub Check: check_prisma_migrations (22.x)
- GitHub Check: restart-dev-and-test-with-custom-base-port
- GitHub Check: docker
- GitHub Check: restart-dev-and-test
- GitHub Check: lint_and_build (latest)
- GitHub Check: all-good
- GitHub Check: setup-tests
- GitHub Check: Vercel Agent Review
- GitHub Check: Security Check
Uh oh!
There was an error while loading.Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (1)
apps/backend/src/app/api/latest/internal/payments/transactions/transaction-builder.ts (1)
124-145:Net amount is forced to USD "0" for non‑USD charges.This issue was already identified in a previous review. When a purchase is denominated solely in EUR or another non-USD currency, this code still emits
net_amount: { USD: "0" }, falsely recording zero revenue. Thenet_amountshould reflect the actual charged currencies instead of fabricating zero USD values.
🧹 Nitpick comments (2)
apps/backend/src/app/api/latest/internal/payments/transactions/transaction-builder.ts (2)
30-52:Consider validating the fallback structure.The
as ProductSnapshotcast on line 41 bypasses type checking. While the structure appears complete, ifProductSnapshotevolves, this could lead to runtime type mismatches.Consider using a schema validator or ensuring all fields match the expected type explicitly:
return { display_name: options.displayName, customer_type: options.customerType, prices: {}, stackable: false, server_only: false, included_items: {},+ client_metadata: null,+ client_read_only_metadata: null,+ server_metadata: null,- } as ProductSnapshot;+ };
172-260:Consider extracting shared logic from subscription and one-time purchase builders.
buildSubscriptionTransactionandbuildOneTimePurchaseTransactionshare nearly identical logic (~45 lines of duplication), differing only in which ID field they pass tocreateProductGrantEntry. Extracting common logic would improve maintainability.Consider creating a shared helper:
functionbuildPurchaseTransaction(options:{entity:Subscription|OneTimePurchase,idField:{subscriptionId?:string}|{oneTimePurchaseId?:string},}):Transaction{const{ entity, idField}=options;constcustomerType=typedToLowercase(entity.customerType);constproduct=entity.productasInferType<typeofproductSchema>|null;constproductSnapshot=ensureProductSnapshot(product,customerType);constselectedPrice=product ?resolveSelectedPriceFromProduct(product,entity.priceId??null) :null;constquantity=entity.quantity;constchargedAmount=buildChargedAmount(selectedPrice,quantity);consttestMode=entity.creationSource==="TEST_MODE";constentries:TransactionEntry[]=[createProductGrantEntry({ customerType,customerId:entity.customerId,productId:entity.productId??null,product:productSnapshot,priceId:entity.priceId??null, quantity, ...idField,}),];constmoneyTransfer=createMoneyTransferEntry({ customerType,customerId:entity.customerId, chargedAmount,skip:testMode,});if(moneyTransfer){entries.push(moneyTransfer);}return{id:entity.id,created_at_millis:entity.createdAt.getTime(),effective_at_millis:entity.createdAt.getTime(),type:"purchase", entries,adjusted_by:[],test_mode:testMode,};}exportfunctionbuildSubscriptionTransaction(options:{subscription:Subscription}):Transaction{returnbuildPurchaseTransaction({entity:options.subscription,idField:{subscriptionId:options.subscription.id},});}exportfunctionbuildOneTimePurchaseTransaction(options:{purchase:OneTimePurchase}):Transaction{returnbuildPurchaseTransaction({entity:options.purchase,idField:{oneTimePurchaseId:options.purchase.id},});}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/backend/src/app/api/latest/internal/payments/transactions/transaction-builder.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
apps/backend/src/app/api/latest/internal/payments/transactions/transaction-builder.ts (6)
packages/stack-shared/src/interface/crud/transactions.ts (2)
TransactionEntry(176-176)Transaction(206-206)packages/stack-shared/src/schema-fields.ts (1)
productSchema(569-592)apps/backend/src/lib/payments.tsx (1)
productToInlineProduct(427-443)packages/stack-shared/src/utils/currency-constants.tsx (2)
Currency(3-7)SUPPORTED_CURRENCIES(9-45)packages/stack-shared/src/utils/strings.tsx (1)
typedToLowercase(15-18)apps/backend/src/lib/tenancies.tsx (1)
Tenancy(47-47)
⏰ 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). (5)
- GitHub Check: check_prisma_migrations (22.x)
- GitHub Check: lint_and_build (latest)
- GitHub Check: all-good
- GitHub Check: Vercel Agent Review
- GitHub Check: Security Check
🔇 Additional comments (6)
apps/backend/src/app/api/latest/internal/payments/transactions/transaction-builder.ts (6)
1-8:LGTM!Imports are well-organized and appropriate for the transaction builder functionality.
10-28:LGTM!Type definitions provide appropriate flexibility for handling various product and price configurations.
54-63:LGTM!The function correctly handles edge cases and null guards. The
as anycast on line 61 is acceptable for field stripping in this context.
65-122:LGTM!The money multiplication logic correctly handles decimal arithmetic using BigInt for precision, and properly manages signs and currency decimals. The charged amount builder appropriately iterates through supported currencies.
147-170:LGTM!The product grant entry structure is correct and includes all necessary fields for tracking product grants in transactions.
262-290:LGTM!The item quantity change transaction builder is straightforward and correctly constructs a transaction with a single
item_quantity_changeentry.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
packages/stack-shared/src/interface/admin-interface.ts (1)
598-611:Method signature correctly updated to new Transaction model.The method signature, query construction, and return type are all correctly updated to use
TransactionandTransactionType. The implementation properly handles optional parameters and builds the query string as needed.Consider extracting
customerTypeto a type definition similar toTransactionTypefor consistency:In
packages/stack-shared/src/interface/crud/transactions.ts, add:exportconstCUSTOMER_TYPES=['user','team','custom']asconst;exporttypeCustomerType=(typeofCUSTOMER_TYPES)[number];Then update this method signature:
-async listTransactions(params?: { cursor?: string, limit?: number, type?: TransactionType, customerType?: 'user' | 'team' | 'custom' }): Promise<{ transactions: Transaction[], nextCursor: string | null }>+async listTransactions(params?: { cursor?: string, limit?: number, type?: TransactionType, customerType?: CustomerType }): Promise<{ transactions: Transaction[], nextCursor: string | null }>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
packages/stack-shared/src/interface/admin-interface.ts(3 hunks)packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts(3 hunks)packages/template/src/lib/stack-app/apps/interfaces/admin-app.ts(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/template/src/lib/stack-app/apps/interfaces/admin-app.ts
🧰 Additional context used
🧬 Code graph analysis (2)
packages/stack-shared/src/interface/admin-interface.ts (1)
packages/stack-shared/src/interface/crud/transactions.ts (2)
TransactionType(111-111)Transaction(128-128)
packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts (2)
packages/template/src/lib/stack-app/apps/implementations/common.ts (1)
createCache(29-34)packages/stack-shared/src/interface/crud/transactions.ts (2)
TransactionType(111-111)Transaction(128-128)
⏰ 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). (11)
- GitHub Check: Vercel Agent Review
- GitHub Check: build (22.x)
- GitHub Check: build (22.x)
- GitHub Check: restart-dev-and-test
- GitHub Check: restart-dev-and-test-with-custom-base-port
- GitHub Check: docker
- GitHub Check: check_prisma_migrations (22.x)
- GitHub Check: build (22.x)
- GitHub Check: all-good
- GitHub Check: setup-tests
- GitHub Check: lint_and_build (latest)
🔇 Additional comments (4)
packages/stack-shared/src/interface/admin-interface.ts (1)
11-11:LGTM! Import updated to use new Transaction model.The import correctly switches from
AdminTransactiontoTransactionandTransactionType, aligning with the PR's refactor to a typed transaction schema.packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts (3)
7-7:LGTM! Import correctly references new Transaction types.The import properly brings in
TransactionandTransactionTypefrom the shared package, aligning with the refactor to a unified transaction model.
77-79:Cache key correctly updated with new TransactionType.The cache tuple properly includes
TransactionType | undefinedand maintains parameter order alignment with thelistTransactionsmethod signature, ensuring correct cache behavior for different query combinations.
594-604:LGTM! Transaction methods consistently updated.Both
listTransactionsanduseTransactionsare correctly updated to use the newTransactionandTransactionTypetypes. Cache access patterns properly align with the cache definition, and return types are consistent across both the async method and React hook.
Uh oh!
There was an error while loading.Please reload this page.
Summary by CodeRabbit
New Features
Bug Fixes