-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Ensure amounts are accurately converted to USD #2701
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 our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The latest updates on your projects. Learn more about Vercel for Git βοΈ
|
|
Warning Rate limit exceeded@steven-tey has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 16 minutes and 44 seconds before requesting another review. β How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. π¦ How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. π Files selected for processing (1)
WalkthroughThis change introduces a comprehensive import error logging system for external partner data imports. It adds structured error log schemas, ingestion endpoints, and retrieval pipes, enabling error logs to be recorded and downloaded as CSVs. Currency normalization to USD is implemented for imported commissions, and import IDs are now generated and propagated throughout import actions, schemas, and email notifications. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant API (GET /download)
participant withWorkspace
participant getImportErrorLogs
participant CSV Formatter
User->>API (GET /download): Requests error logs for workspace/importId
API (GET /download)->>withWorkspace: Validates workspace context
withWorkspace->>getImportErrorLogs: Fetches error logs by workspaceId/importId
getImportErrorLogs-->>withWorkspace: Returns error log data
withWorkspace->>CSV Formatter: Maps logs to CSV format
CSV Formatter-->>API (GET /download): Returns CSV data
API (GET /download)-->>User: Sends CSV file as response
sequenceDiagram
participant ImportAction
participant createId
participant ImporterQueue
participant ImportWorker
participant logImportError
ImportAction->>createId: Generate importId (prefix "import_")
ImportAction->>ImporterQueue: Queue import job with importId
ImporterQueue->>ImportWorker: Processes import job
ImportWorker->>logImportError: Logs structured errors with importId
Estimated code review effortπ― 4 (Complex) | β±οΈ ~40 minutes Possibly related PRs
Poem
β¨ Finishing Touches
π§ͺ Generate unit 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. πͺ§ TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
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
π Outside diff range comments (1)
apps/web/lib/partnerstack/import-commissions.ts (1)
180-188: Potential inconsistency in duplicate commission detection.The duplicate commission check on Line 186 still uses the original
commission.transaction.amountinstead of the convertedamount. This could cause issues when comparing commissions that have been currency-converted versus those that haven't.amount: commission.transaction.amount, + amount: amount,
π§Ή Nitpick comments (5)
apps/web/lib/zod/schemas/import-logs.ts (1)
3-20: Well-structured import log schema with comprehensive validation.The schema provides good type safety with appropriate enum constraints for source platforms, entity types, and error codes. The field structure supports effective import tracking and debugging.
Consider adding success codes to the
codeenum (e.g., "SUCCESS", "CREATED", "UPDATED") to provide complete import status tracking alongside error cases.apps/web/lib/tinybird/record-import-logs.ts (1)
10-20: Consider removing or conditionalizing the console log.The implementation is solid with proper validation and early return for empty arrays. However, the console log on line 17 might be noisy in production environments.
Consider using a conditional log or removing it:
- console.log("importLogs", logs.length); + if (process.env.NODE_ENV === "development") { + console.log("importLogs", logs.length); + }packages/email/src/templates/campaign-imported.tsx (1)
62-76: Consider using a configurable API base URL.The conditional rendering and security attributes are implemented correctly. However, the hardcoded API URL could cause issues in different environments.
Consider using an environment variable or constant for the API base URL:
- href={`https://api.dub.co/${workspace.slug}/import/${importId}/download`} + href={`${process.env.NEXT_PUBLIC_API_URL || 'https://api.dub.co'}/${workspace.slug}/import/${importId}/download`}apps/web/app/api/workspaces/[idOrSlug]/import/[importId]/download/route.ts (1)
6-29: Consider adding error handling and input validation.The implementation correctly fetches and converts import logs to CSV format with appropriate headers. However, consider adding explicit error handling for the async operations and input validation for the importId parameter.
export const GET = withWorkspace(async ({ workspace, params }) => { const { importId } = params; + + if (!importId || typeof importId !== 'string') { + return new Response('Invalid import ID', { status: 400 }); + } - const importLogs = await getImportLogs({ - workspaceId: workspace.id, - importId, - }); + try { + const importLogs = await getImportLogs({ + workspaceId: workspace.id, + importId, + }); + } catch (error) { + console.error('Failed to fetch import logs:', error); + return new Response('Failed to fetch import logs', { status: 500 }); + }apps/web/lib/tolt/import-commissions.ts (1)
185-206: Consider consistent currency case handling.The currency conversion logic is correct, but there's a minor inconsistency: the
currencyparameter is passed as lowercase fromimportCommissions(line 69) but is then converted to uppercase for comparison. Consider standardizing to either uppercase or lowercase throughout for consistency.- if (currency.toUpperCase() !== "USD" && fxRates) { + if (currency !== "usd" && fxRates) {and
- if (currency.toUpperCase() !== "USD" && fxRates) { + if (currency !== "usd" && fxRates) {
π Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
π Files selected for processing (24)
apps/web/app/api/workspaces/[idOrSlug]/import/[importId]/download/route.ts(1 hunks)apps/web/lib/actions/partners/create-program.ts(1 hunks)apps/web/lib/actions/partners/start-partnerstack-import.ts(2 hunks)apps/web/lib/actions/partners/start-rewardful-import.ts(2 hunks)apps/web/lib/actions/partners/start-tolt-import.ts(2 hunks)apps/web/lib/analytics/convert-currency.ts(1 hunks)apps/web/lib/api/create-id.ts(1 hunks)apps/web/lib/partnerstack/import-commissions.ts(9 hunks)apps/web/lib/partnerstack/schemas.ts(2 hunks)apps/web/lib/rewardful/api.ts(0 hunks)apps/web/lib/rewardful/import-commissions.ts(13 hunks)apps/web/lib/rewardful/import-customers.ts(7 hunks)apps/web/lib/rewardful/import-partners.ts(4 hunks)apps/web/lib/rewardful/schemas.ts(1 hunks)apps/web/lib/tinybird/get-import-logs.ts(1 hunks)apps/web/lib/tinybird/record-import-logs.ts(1 hunks)apps/web/lib/tolt/api.ts(1 hunks)apps/web/lib/tolt/import-commissions.ts(10 hunks)apps/web/lib/tolt/schemas.ts(2 hunks)apps/web/lib/types.ts(2 hunks)apps/web/lib/zod/schemas/import-logs.ts(1 hunks)packages/email/src/templates/campaign-imported.tsx(3 hunks)packages/tinybird/datasources/dub_import_logs.datasource(1 hunks)packages/tinybird/pipes/get_import_logs.pipe(1 hunks)
π€ Files with no reviewable changes (1)
- apps/web/lib/rewardful/api.ts
π§° Additional context used
π§ Learnings (6)
π Learning: in apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx, the form schema uses partial condition ob...
Learnt from: TWilson023
PR: dubinc/dub#2673
File: apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx:56-66
Timestamp: 2025-07-30T15:25:13.936Z
Learning: In apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx, the form schema uses partial condition objects to allow users to add empty/unconfigured condition fields without type errors, while submission validation uses strict schemas to ensure data integrity. This two-stage validation pattern improves UX by allowing progressive completion of complex forms.
Applied to files:
apps/web/lib/rewardful/schemas.tsapps/web/lib/types.tsapps/web/lib/tolt/schemas.tsapps/web/lib/partnerstack/schemas.tsapps/web/lib/zod/schemas/import-logs.ts
π Learning: in apps/web/ui/partners/rewards/rewards-logic.tsx, when setting the entity field in a reward conditi...
Learnt from: TWilson023
PR: dubinc/dub#2673
File: apps/web/ui/partners/rewards/rewards-logic.tsx:268-275
Timestamp: 2025-07-30T15:29:54.131Z
Learning: In apps/web/ui/partners/rewards/rewards-logic.tsx, when setting the entity field in a reward condition, dependent fields (attribute, operator, value) should be reset rather than preserved because different entities (customer vs sale) have different available attributes. Maintaining existing fields when the entity changes would create invalid state combinations and confusing UX.
Applied to files:
apps/web/lib/rewardful/schemas.tsapps/web/lib/actions/partners/start-rewardful-import.tsapps/web/lib/partnerstack/schemas.tsapps/web/lib/rewardful/import-partners.tsapps/web/lib/rewardful/import-customers.tsapps/web/lib/actions/partners/create-program.ts
π Learning: in the partnerprogramsummary email template (packages/email/src/templates/partner-program-summary.ts...
Learnt from: devkiran
PR: dubinc/dub#2448
File: packages/email/src/templates/partner-program-summary.tsx:0-0
Timestamp: 2025-05-29T04:45:18.504Z
Learning: In the PartnerProgramSummary email template (packages/email/src/templates/partner-program-summary.tsx), the stat titles are hardcoded constants ("Clicks", "Leads", "Sales", "Earnings") that will always match the ICONS object keys after toLowerCase() conversion, so icon lookup failures are not possible.
Applied to files:
apps/web/lib/partnerstack/import-commissions.tsapps/web/lib/tolt/import-commissions.ts
π Learning: in the singular integration (apps/web/app/(ee)/api/singular/webhook/route.ts), the event names in th...
Learnt from: devkiran
PR: dubinc/dub#2637
File: apps/web/app/(ee)/api/singular/webhook/route.ts:0-0
Timestamp: 2025-07-17T06:41:45.620Z
Learning: In the Singular integration (apps/web/app/(ee)/api/singular/webhook/route.ts), the event names in the singularToDubEvent object have intentionally different casing: "Copy GAID" and "copy IDFA". This casing difference is valid and should not be changed, as these are the correct event names expected from Singular.
Applied to files:
apps/web/lib/partnerstack/schemas.ts
π Learning: when zod enum validation is used (e.g., `z.enum(payment_method_types)`), it ensures the validated va...
Learnt from: devkiran
PR: dubinc/dub#2433
File: apps/web/app/api/workspaces/[idOrSlug]/billing/payment-methods/route.ts:74-76
Timestamp: 2025-05-29T09:47:33.583Z
Learning: When Zod enum validation is used (e.g., `z.enum(PAYMENT_METHOD_TYPES)`), it ensures the validated value is one of the valid enum values, making subsequent type casts to the corresponding TypeScript types safe without additional validation.
Applied to files:
apps/web/lib/zod/schemas/import-logs.ts
π Learning: in apps/web/lib/api/links/bulk-create-links.ts, the team accepts the risk of potential undefined res...
Learnt from: devkiran
PR: dubinc/dub#2177
File: apps/web/lib/api/links/bulk-create-links.ts:66-84
Timestamp: 2025-06-06T07:59:03.120Z
Learning: In apps/web/lib/api/links/bulk-create-links.ts, the team accepts the risk of potential undefined results from links.find() operations when building invalidLinks arrays, because existing links are fetched from the database based on the input links, so matches are expected to always exist.
Applied to files:
apps/web/lib/rewardful/import-partners.tsapps/web/lib/rewardful/import-customers.ts
𧬠Code Graph Analysis (10)
apps/web/lib/tolt/api.ts (1)
apps/web/lib/tolt/schemas.ts (1)
ToltProgramSchema(21-27)
apps/web/lib/actions/partners/start-partnerstack-import.ts (1)
apps/web/lib/api/create-id.ts (1)
createId(55-64)
apps/web/lib/partnerstack/import-commissions.ts (1)
apps/web/lib/analytics/convert-currency.ts (1)
convertCurrency(22-56)
apps/web/lib/actions/partners/start-rewardful-import.ts (1)
apps/web/lib/api/create-id.ts (1)
createId(55-64)
apps/web/lib/actions/partners/start-tolt-import.ts (1)
apps/web/lib/api/create-id.ts (1)
createId(55-64)
apps/web/lib/types.ts (1)
apps/web/lib/zod/schemas/import-logs.ts (1)
importLogSchema(3-20)
apps/web/lib/tinybird/get-import-logs.ts (1)
apps/web/lib/zod/schemas/import-logs.ts (1)
importLogSchema(3-20)
apps/web/lib/tinybird/record-import-logs.ts (1)
apps/web/lib/zod/schemas/import-logs.ts (1)
importLogSchema(3-20)
apps/web/lib/actions/partners/create-program.ts (3)
apps/web/lib/api/create-id.ts (1)
createId(55-64)apps/web/lib/tolt/importer.ts (1)
toltImporter(78-78)apps/web/lib/partnerstack/importer.ts (1)
partnerStackImporter(47-47)
apps/web/lib/rewardful/import-commissions.ts (4)
apps/web/lib/rewardful/types.ts (1)
RewardfulCommission(88-100)apps/web/lib/types.ts (1)
ImportLogInput(518-521)apps/web/lib/tinybird/record-import-logs.ts (1)
recordImportLog(10-20)apps/web/lib/analytics/convert-currency.ts (1)
convertCurrency(22-56)
π Additional comments (35)
apps/web/lib/analytics/convert-currency.ts (3)
25-25: LGTM! Performance optimization with optional pre-fetched exchange rates.This parameter allows callers to pass pre-fetched exchange rates, reducing Redis calls when processing multiple currency conversions.
31-34: Good improvement to currency handling and rate lookup.The uppercase conversion ensures consistent currency code handling, and the nullish coalescing operator provides clean fallback logic from passed rates to Redis lookup.
36-38: Simplified conditional logic with single fxRate variable.The change from checking
fxRates?.[currencyCode]to a singlefxRatevariable improves readability and maintains the same functionality.apps/web/lib/tolt/api.ts (1)
68-68: LGTM! Unnecessary object spread removed.Clean simplification that removes redundant object spread operation while maintaining the same parsing functionality. This aligns well with the updated ToltProgramSchema that now includes the currency_code field.
apps/web/lib/rewardful/schemas.ts (2)
11-11: LGTM! Import tracking support added.The required
importIdfield enables consistent import operation tracking and logging across the Rewardful import system.
17-17: Good practice: Trailing comma added.Improves maintainability for future field additions.
apps/web/lib/actions/partners/start-partnerstack-import.ts (2)
3-3: LGTM! Standard ID generation utility imported.Proper import of the createId utility for generating unique import identifiers.
50-50: LGTM! Import tracking ID generation added.Proper usage of createId() to generate a unique identifier for tracking this PartnerStack import operation. This enables import logging and retrieval functionality.
apps/web/lib/actions/partners/start-tolt-import.ts (2)
3-3: LGTM! Clean import addition for import tracking.The import of
createIdfunction supports the new import logging infrastructure by enabling unique identification of import operations.
45-45: LGTM! Proper integration of import tracking.The addition of
importIdusingcreateId()enables unique identification and logging of import operations, aligning with the broader import logging infrastructure.apps/web/lib/actions/partners/start-rewardful-import.ts (2)
3-3: LGTM! Consistent import tracking implementation.The import addition follows the same pattern as other partner import actions, enabling unified import logging across different integrations.
37-37: LGTM! Unified import tracking approach.The
importIdaddition maintains consistency across partner integrations and enables comprehensive import operation tracking.apps/web/lib/tolt/schemas.ts (2)
13-13: LGTM! Essential for import tracking.The required
importIdfield ensures all Tolt import operations can be uniquely identified and logged, supporting the new import logging infrastructure.
26-26: LGTM! Critical for accurate currency conversion.The
currency_codefield directly supports the PR objective of ensuring amounts are accurately converted to USD by providing the source currency information needed for proper conversion calculations.apps/web/lib/partnerstack/schemas.ts (2)
17-17: LGTM! Maintains consistency across partner integrations.The required
importIdfield ensures PartnerStack imports follow the same tracking pattern as other partner integrations, enabling unified import logging.
67-68: Clarify currency handling for commission amounts.The addition of the
currencyfield supports the PR objective of accurate USD conversion. However, there's a potential inconsistency: Line 67 describesamountas "in cents (USD)" while the newcurrencyfield suggests commissions may be in other currencies.Please clarify whether:
- The
amountfield comment should be updated to remove the "(USD)" specification- The amount field will now contain values in the currency specified by the
currencyfieldThis clarification ensures proper handling of multi-currency commission data during import and conversion processes.
apps/web/lib/tinybird/get-import-logs.ts (1)
1-12: LGTM! Well-structured import log retrieval implementation.The implementation follows best practices:
- Proper type validation for parameters and returned data using Zod schemas
- Clear, descriptive parameter names (
workspaceId,importId)- Consistent with the established Tinybird pipe pattern
- Supports the new import logging infrastructure effectively
apps/web/lib/actions/partners/create-program.ts (1)
146-166: LGTM! Consistent implementation of import tracking.The addition of
importIdgeneration usingcreateId()is consistent across all three import sources (Rewardful, Tolt, and PartnerStack). This enables proper tracking and logging of import operations throughout the system.apps/web/lib/types.ts (2)
38-38: LGTM! Proper schema import placement.The import for
importLogSchemais correctly placed with other schema imports, maintaining consistency with the file structure.
516-521: LGTM! Well-structured type definitions.The
ImportLogandImportLogInputtypes are properly defined. UsingPickto createImportLogInputas a subset ofImportLogis a good pattern for scenarios where only specific fields are needed for logging operations.apps/web/lib/api/create-id.ts (1)
59-59: LGTM! Enables parameterless function calls.Adding the default empty object
= {}allowscreateId()to be called without arguments, which is exactly how it's used in the import functionality. This maintains backward compatibility while enabling the new usage pattern.packages/email/src/templates/campaign-imported.tsx (1)
26-36: LGTM! Good addition of optional importId parameter.The optional
importIdparameter with a default value is well-structured and enables flexible usage of the component.packages/tinybird/pipes/get_import_logs.pipe (1)
8-30: LGTM! Well-structured Tinybird pipe with proper parameterization.The SQL query correctly uses parameterized inputs with validation, includes appropriate ordering and limits for performance. The default values appear to be sample identifiers for testing purposes.
packages/tinybird/datasources/dub_import_logs.datasource (1)
4-17: Excellent datasource design with optimized performance characteristics.The schema uses appropriate data types, the MergeTree engine with time-based partitioning is optimal for log data, and the 180-day TTL provides reasonable retention. The sorting key aligns well with expected query patterns.
apps/web/lib/partnerstack/import-commissions.ts (2)
45-46: LGTM! Proper FX rates fetching for currency conversion.The implementation correctly fetches foreign exchange rates from Redis to enable currency normalization across commission imports.
144-171: LGTM! Well-implemented currency conversion logic.The currency conversion logic correctly handles both sale amounts and earnings, only converting when the currency differs from USD and FX rates are available. The converted values properly replace the original amounts for all subsequent operations.
apps/web/lib/rewardful/import-partners.ts (3)
14-21: LGTM! Proper destructuring with importId for logging.The payload destructuring correctly includes the new importId field needed for the import logging infrastructure.
59-93: Excellent implementation of partner filtering and import logging.The logic correctly separates active partners (with leads > 0) from inactive ones, and generates structured import logs for partners that are not imported. This provides valuable visibility into why certain partners are skipped during the import process.
98-106: Well-structured bulk import logging.The bulk logging approach is efficient and correctly enriches each log entry with workspace ID, import ID, and source information. This aligns with the logging patterns established in other import modules.
apps/web/lib/tolt/import-commissions.ts (1)
42-46: LGTM! Currency conversion setup looks good.The function correctly fetches the program details and FX rates before processing commissions. The currency code is appropriately normalized to lowercase for consistency.
Also applies to: 68-69
apps/web/lib/rewardful/import-customers.ts (2)
15-15: Excellent structured logging implementation!The import logging setup is well-designed with bulk recording after processing all referrals, which is more efficient than individual log writes. The metadata enrichment with workspace_id, import_id, and source provides good traceability.
Also applies to: 33-33, 61-69
113-119: Well-structured error logging!The replacement of console.log with structured import logs is a significant improvement. The error codes (
LINK_NOT_FOUND,STRIPE_CUSTOMER_ID_NOT_FOUND) are descriptive and will make debugging and monitoring much easier.Also applies to: 127-133
apps/web/lib/rewardful/import-commissions.ts (3)
19-24: Good refactoring and consistent logging pattern!Moving
toDubStatusoutside the function is a good optimization. The import logging implementation is consistent with other importers and provides proper error tracking.Also applies to: 39-39, 44-44, 72-79
173-199: Robust currency conversion and error handling!The currency conversion logic correctly handles both sale amounts and earnings, converting them to USD when needed. The use of converted amounts throughout the function (including in the duplicate check query) ensures data consistency. The comprehensive structured logging for all error scenarios is excellent.
Also applies to: 217-217, 318-318
149-154: Comprehensive structured error logging!Excellent replacement of console.log statements with structured import logs. Each error case has a unique, descriptive code that will make debugging and monitoring much more effective. The consistent logging pattern across all error scenarios is commendable.
Also applies to: 222-227, 242-247, 252-283, 290-295
|
@CodeRabbit full review |
β Actions performedFull review triggered. |
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: 6
π§Ή Nitpick comments (2)
packages/tinybird/datasources/dub_import_logs.datasource (1)
4-17: Well-designed datasource for import logging.The schema and engine configuration are appropriate for time-series logging data. The monthly partitioning, sorting key, and 180-day TTL are well-suited for debugging and tracking import issues.
Consider adding compression settings for storage efficiency:
ENGINE "MergeTree" +ENGINE_SETTINGS "compress_method=LZ4" ENGINE_PARTITION_KEY "toYYYYMM(timestamp)" ENGINE_SORTING_KEY "timestamp, workspace_id, import_id" ENGINE_TTL "toDateTime(timestamp) + toIntervalDay(180)"apps/web/lib/rewardful/import-commissions.ts (1)
252-283: Consider consolidating validation checks.The separate validation checks for linkId, clickId, and partnerId create multiple similar log entries. Consider combining these checks for cleaner code.
- if (!customerFound.linkId) { - importLogs.push({ - entity: "commission", - entity_id: commission.id, - code: "LINK_NOT_FOUND", - message: `No link found for customer ${customerFound.id}.`, - }); - - return; - } - - if (!customerFound.clickId) { - importLogs.push({ - entity: "commission", - entity_id: commission.id, - code: "CLICK_NOT_FOUND", - message: `No click ID found for customer ${customerFound.id}.`, - }); - - return; - } - - if (!customerFound.link?.partnerId) { - importLogs.push({ - entity: "commission", - entity_id: commission.id, - code: "PARTNER_NOT_FOUND", - message: `No partner ID found for customer ${customerFound.id}.`, - }); - - return; - } + const missingFields = []; + if (!customerFound.linkId) missingFields.push("link"); + if (!customerFound.clickId) missingFields.push("click ID"); + if (!customerFound.link?.partnerId) missingFields.push("partner ID"); + + if (missingFields.length > 0) { + importLogs.push({ + entity: "commission", + entity_id: commission.id, + code: "MISSING_REQUIRED_FIELDS", + message: `Missing ${missingFields.join(", ")} for customer ${customerFound.id}.`, + }); + return; + }
π Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
π Files selected for processing (24)
apps/web/app/api/workspaces/[idOrSlug]/import/[importId]/download/route.ts(1 hunks)apps/web/lib/actions/partners/create-program.ts(1 hunks)apps/web/lib/actions/partners/start-partnerstack-import.ts(2 hunks)apps/web/lib/actions/partners/start-rewardful-import.ts(2 hunks)apps/web/lib/actions/partners/start-tolt-import.ts(2 hunks)apps/web/lib/analytics/convert-currency.ts(1 hunks)apps/web/lib/api/create-id.ts(1 hunks)apps/web/lib/partnerstack/import-commissions.ts(9 hunks)apps/web/lib/partnerstack/schemas.ts(2 hunks)apps/web/lib/rewardful/api.ts(0 hunks)apps/web/lib/rewardful/import-commissions.ts(13 hunks)apps/web/lib/rewardful/import-customers.ts(7 hunks)apps/web/lib/rewardful/import-partners.ts(4 hunks)apps/web/lib/rewardful/schemas.ts(1 hunks)apps/web/lib/tinybird/get-import-logs.ts(1 hunks)apps/web/lib/tinybird/record-import-logs.ts(1 hunks)apps/web/lib/tolt/api.ts(1 hunks)apps/web/lib/tolt/import-commissions.ts(10 hunks)apps/web/lib/tolt/schemas.ts(2 hunks)apps/web/lib/types.ts(2 hunks)apps/web/lib/zod/schemas/import-logs.ts(1 hunks)packages/email/src/templates/campaign-imported.tsx(3 hunks)packages/tinybird/datasources/dub_import_logs.datasource(1 hunks)packages/tinybird/pipes/get_import_logs.pipe(1 hunks)
π€ Files with no reviewable changes (1)
- apps/web/lib/rewardful/api.ts
π§° Additional context used
π§ Learnings (4)
π Learning: in apps/web/ui/partners/rewards/rewards-logic.tsx, when setting the entity field in a reward conditi...
Learnt from: TWilson023
PR: dubinc/dub#2673
File: apps/web/ui/partners/rewards/rewards-logic.tsx:268-275
Timestamp: 2025-07-30T15:29:54.131Z
Learning: In apps/web/ui/partners/rewards/rewards-logic.tsx, when setting the entity field in a reward condition, dependent fields (attribute, operator, value) should be reset rather than preserved because different entities (customer vs sale) have different available attributes. Maintaining existing fields when the entity changes would create invalid state combinations and confusing UX.
Applied to files:
apps/web/lib/actions/partners/start-rewardful-import.tsapps/web/lib/rewardful/schemas.tsapps/web/lib/partnerstack/schemas.tsapps/web/lib/actions/partners/create-program.tsapps/web/lib/rewardful/import-partners.tsapps/web/lib/rewardful/import-customers.tsapps/web/lib/rewardful/import-commissions.ts
π Learning: in apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx, the form schema uses partial condition ob...
Learnt from: TWilson023
PR: dubinc/dub#2673
File: apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx:56-66
Timestamp: 2025-07-30T15:25:13.936Z
Learning: In apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx, the form schema uses partial condition objects to allow users to add empty/unconfigured condition fields without type errors, while submission validation uses strict schemas to ensure data integrity. This two-stage validation pattern improves UX by allowing progressive completion of complex forms.
Applied to files:
apps/web/lib/rewardful/schemas.tsapps/web/lib/partnerstack/schemas.tsapps/web/lib/tolt/schemas.tsapps/web/lib/types.tsapps/web/lib/zod/schemas/import-logs.ts
π Learning: in apps/web/lib/api/links/bulk-create-links.ts, the team accepts the risk of potential undefined res...
Learnt from: devkiran
PR: dubinc/dub#2177
File: apps/web/lib/api/links/bulk-create-links.ts:66-84
Timestamp: 2025-06-06T07:59:03.120Z
Learning: In apps/web/lib/api/links/bulk-create-links.ts, the team accepts the risk of potential undefined results from links.find() operations when building invalidLinks arrays, because existing links are fetched from the database based on the input links, so matches are expected to always exist.
Applied to files:
apps/web/lib/rewardful/import-partners.tsapps/web/lib/rewardful/import-customers.ts
π Learning: in the partnerprogramsummary email template (packages/email/src/templates/partner-program-summary.ts...
Learnt from: devkiran
PR: dubinc/dub#2448
File: packages/email/src/templates/partner-program-summary.tsx:0-0
Timestamp: 2025-05-29T04:45:18.504Z
Learning: In the PartnerProgramSummary email template (packages/email/src/templates/partner-program-summary.tsx), the stat titles are hardcoded constants ("Clicks", "Leads", "Sales", "Earnings") that will always match the ICONS object keys after toLowerCase() conversion, so icon lookup failures are not possible.
Applied to files:
apps/web/lib/partnerstack/import-commissions.tsapps/web/lib/tolt/import-commissions.ts
𧬠Code Graph Analysis (9)
apps/web/lib/tolt/api.ts (1)
apps/web/lib/tolt/schemas.ts (1)
ToltProgramSchema(21-27)
apps/web/lib/actions/partners/start-rewardful-import.ts (1)
apps/web/lib/api/create-id.ts (1)
createId(55-64)
apps/web/lib/actions/partners/start-partnerstack-import.ts (1)
apps/web/lib/api/create-id.ts (1)
createId(55-64)
apps/web/lib/tinybird/record-import-logs.ts (1)
apps/web/lib/zod/schemas/import-logs.ts (1)
importLogSchema(3-20)
apps/web/lib/actions/partners/start-tolt-import.ts (1)
apps/web/lib/api/create-id.ts (1)
createId(55-64)
apps/web/lib/actions/partners/create-program.ts (3)
apps/web/lib/api/create-id.ts (1)
createId(55-64)apps/web/lib/tolt/importer.ts (1)
toltImporter(78-78)apps/web/lib/partnerstack/importer.ts (1)
partnerStackImporter(47-47)
apps/web/lib/types.ts (1)
apps/web/lib/zod/schemas/import-logs.ts (1)
importLogSchema(3-20)
apps/web/lib/tinybird/get-import-logs.ts (1)
apps/web/lib/zod/schemas/import-logs.ts (1)
importLogSchema(3-20)
apps/web/lib/partnerstack/import-commissions.ts (1)
apps/web/lib/analytics/convert-currency.ts (1)
convertCurrency(22-61)
π Additional comments (31)
apps/web/lib/api/create-id.ts (1)
59-59: LGTM! Improved function safety.Adding the default empty object parameter prevents potential destructuring errors when
createId()is called without arguments, making the API more robust and user-friendly.apps/web/lib/tolt/api.ts (1)
68-68: LGTM! Clean code simplification.Removing the unnecessary object spread operation improves readability and performance without changing functionality. The direct parsing of
partner.programis cleaner and more efficient.apps/web/lib/rewardful/schemas.ts (1)
11-17: LGTM! Consistent import tracking enhancement.Adding the required
importIdfield aligns with the broader import logging infrastructure and enables linking import operations with their detailed logs. The trailing comma addition is also good practice.apps/web/lib/actions/partners/start-partnerstack-import.ts (2)
3-3: LGTM! Proper integration of import tracking.The import statement correctly brings in the
createIdutility for generating unique import identifiers.
50-50: LGTM! Consistent import ID generation.Adding the
importIdusingcreateId()enables tracking and logging for this import operation, consistent with the broader import infrastructure enhancements across the codebase.apps/web/lib/actions/partners/start-rewardful-import.ts (1)
3-3: LGTM! Import ID tracking properly implemented.The addition of
createIdimport and its usage to generate a uniqueimportIdfor the Rewardful import operation aligns well with the broader import tracking infrastructure being introduced across the codebase.Also applies to: 37-37
apps/web/lib/actions/partners/start-tolt-import.ts (1)
3-3: LGTM! Consistent import ID implementation.The changes mirror the pattern established in the Rewardful import action, correctly generating and passing a unique
importIdto enable import tracking and logging.Also applies to: 45-45
apps/web/lib/tinybird/get-import-logs.ts (1)
1-12: LGTM! Well-structured Tinybird pipe implementation.The
getImportLogsfunction is properly implemented with:
- Correct parameter validation using Zod schema
- Appropriate data validation against
importLogSchema- Clean import structure and pipe naming convention
This integrates well with the new import logging infrastructure.
apps/web/lib/tolt/schemas.ts (1)
13-13: Schema usage verifiedβno action needed.All calls to toltImportPayloadSchema include the new importId and userId fields, and every instantiation of ToltProgramSchema (parse or extend) is backed by data that includes currency_code. No missing or outdated usages were found.
apps/web/lib/actions/partners/create-program.ts (1)
146-146: LGTM! Consistent addition of import tracking.The addition of
importIdto all three importer queue calls (Rewardful, Tolt, and PartnerStack) is consistent and follows the same pattern. This enables tracking of import operations across different providers, which aligns well with the structured import logging system being introduced.Also applies to: 154-154, 162-162
apps/web/lib/types.ts (1)
38-38: LGTM! Well-structured type definitions for import logging.The addition of
ImportLogandImportLogInputtypes follows good TypeScript practices:
ImportLogprovides the complete type definition inferred from the schemaImportLogInputappropriately restricts to only the fields needed for input operations- The types align with the
importLogSchemastructure shown in the relevant code snippetsAlso applies to: 516-521
packages/tinybird/pipes/get_import_logs.pipe (1)
1-30: LGTM! Well-structured Tinybird pipe for import log retrieval.The pipe implementation is solid:
- Clear description and appropriate SQL query structure
- Proper parameter definitions with
required=Truefor bothworkspaceIdandimportId- Sensible ordering by
timestamp DESCto get recent logs first- Reasonable limit of 5000 records to prevent performance issues
- Good default values for testing/documentation purposes
apps/web/lib/tinybird/record-import-logs.ts (1)
5-20: LGTM! Clean and focused import log recording implementation.The implementation follows good practices:
- Proper Tinybird ingest endpoint configuration with the correct datasource and schema
- Type-safe function signature using Zod schema inference
- Efficient early return for empty arrays
- Useful console logging for monitoring import operations
- Clean async/await pattern
The function has a clear single responsibility and integrates well with the broader import logging system.
packages/email/src/templates/campaign-imported.tsx (1)
26-26: LGTM! Good addition of optional import tracking.The addition of the optional
importIdprop with a sensible default value is well-implemented and maintains backward compatibility.Also applies to: 36-36
apps/web/lib/zod/schemas/import-logs.ts (1)
3-20: Well-structured import log schema.The schema design is comprehensive and follows good practices:
- Uses enums to constrain valid values for source, entity, and code fields
- Covers all partner integrations (rewardful, tolt, partnerstack) and entities (partner, link, customer, commission)
- Includes specific error codes that provide clear categorization of import issues
apps/web/lib/rewardful/import-partners.ts (3)
14-21: LGTM!The payload destructuring correctly extracts the
importIdneeded for import logging correlation.
59-92: Good separation of active vs inactive partners with proper logging.The filtering logic correctly identifies partners worth importing (active with leads > 0) and provides structured logging for those that are skipped. The error message is descriptive and will help with debugging import issues.
98-105: Efficient bulk logging implementation.The bulk recording of import logs with proper context enrichment (workspace_id, import_id, source) follows best practices and integrates well with the structured logging infrastructure.
apps/web/lib/partnerstack/import-commissions.ts (4)
45-45: Efficient FX rates fetching approach.Fetching exchange rates once per batch and reusing them for all commissions is more efficient than fetching rates individually for each commission.
89-98: LGTM!The function signature update correctly adds the
fxRatesparameter with appropriate typing to support currency conversion.
144-156: Correct currency conversion implementation for sale amounts.The conversion logic properly:
- Checks for non-USD currency before converting
- Only converts when fxRates are available
- Uses the updated convertCurrency function with fxRates parameter
- Replaces the original amount with the converted value
158-170: Consistent earnings conversion implementation.The earnings conversion logic correctly mirrors the sale amount conversion approach, ensuring both monetary values are consistently normalized to USD when possible.
apps/web/lib/analytics/convert-currency.ts (2)
22-30: Well-designed function signature enhancement.The addition of the optional
fxRatesparameter maintains backward compatibility while enabling performance optimization by allowing callers to provide pre-fetched exchange rates.
31-39: Correct implementation of fxRates prioritization and currency normalization.The logic properly:
- Normalizes currency code to uppercase for consistent lookups
- Prioritizes provided fxRates over Redis lookup for better performance
- Maintains the same fallback behavior when fxRates are not provided
apps/web/lib/rewardful/import-customers.ts (3)
6-8: Import logging implementation looks good!The addition of structured import logging with unique import IDs provides excellent traceability for debugging import issues. The logs are properly accumulated and batch recorded at the end of processing.
Also applies to: 15-15, 33-33, 47-53, 61-69
78-78: Function rename improves clarity.Renaming from
createReferraltocreateCustomerbetter reflects the function's purpose of creating customer records.
113-119: Structured error logging is well implemented.Replacing console.log with structured import logs provides better tracking and debugging capabilities. The log entries include all necessary fields (entity, entity_id, code, message) for comprehensive error reporting.
Also applies to: 127-133
apps/web/lib/tolt/import-commissions.ts (1)
42-45: Currency normalization implementation looks good!The implementation properly fetches currency information from the Tolt program and converts amounts to USD using exchange rates from Redis. The converted amounts are consistently used throughout all database operations.
Also applies to: 68-69, 133-140, 183-206, 222-222, 272-273, 286-286, 288-288, 303-303, 318-318
apps/web/lib/rewardful/import-commissions.ts (3)
19-24: Good refactoring of status mapping.Moving the
toDubStatusmapping outside the function improves reusability and makes the code cleaner.
39-39: Excellent implementation of structured import logging!The comprehensive import logging with specific error codes and detailed messages will greatly improve debugging and monitoring of import operations. The logs are properly accumulated and batch recorded for efficiency.
Also applies to: 62-63, 72-79, 149-155, 222-228, 242-248, 290-296
174-199: Currency conversion implementation is thorough.The code properly converts both sale amounts and earnings to USD, and consistently uses the converted amounts throughout all database operations and event recording.
Also applies to: 217-217, 316-317, 330-330, 343-343, 352-352
apps/web/app/api/workspaces/[idOrSlug]/import/[importId]/download/route.ts
Show resolved
Hide resolved
|
@CodeRabbit final review please. Is there anything we missed during the refactoring? |
|
Tip For best results, initiate chat on the files or code changes. π§© Analysis chain@steven-tey I'll conduct a thorough final review to check for any missed items in the currency conversion refactoring. Let me examine the codebase comprehensively. π Script executed: Length of output: 24176 π Script executed: Length of output: 7850 π Script executed: Length of output: 11844 π Script executed: Length of output: 2994 π Script executed: Length of output: 559 π Script executed: Length of output: 77214 π Script executed: Length of output: 7806 π Script executed: Length of output: 445 @steven-tey Based on my comprehensive final review of the currency conversion refactoring, here are the key findings and potential issues that may need attention: β What's Working Well
|
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
π Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
π Files selected for processing (2)
apps/web/scripts/bulk-delete-links.ts(1 hunks)packages/email/src/templates/program-imported.tsx(4 hunks)
π§ Files skipped from review as they are similar to previous changes (1)
- packages/email/src/templates/program-imported.tsx
π§° Additional context used
π§ Learnings (1)
π Learning: in apps/web/lib/api/links/bulk-create-links.ts, the team accepts the risk of potential undefined res...
Learnt from: devkiran
PR: dubinc/dub#2177
File: apps/web/lib/api/links/bulk-create-links.ts:66-84
Timestamp: 2025-06-06T07:59:03.120Z
Learning: In apps/web/lib/api/links/bulk-create-links.ts, the team accepts the risk of potential undefined results from links.find() operations when building invalidLinks arrays, because existing links are fetched from the database based on the input links, so matches are expected to always exist.
Applied to files:
apps/web/scripts/bulk-delete-links.ts
𧬠Code Graph Analysis (1)
apps/web/scripts/bulk-delete-links.ts (1)
apps/web/lib/tinybird/record-link.ts (2)
recordLinkTB(46-50)transformLinkTB(52-71)
β° 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: build
π Additional comments (5)
apps/web/scripts/bulk-delete-links.ts (5)
3-3: Import path change looks good.The change from absolute to relative import path is acceptable. Ensure this aligns with the project's import path conventions.
10-12: LGTM! Filtering change aligns with program-based approach.The switch from domain-based to programId-based filtering is appropriate, and removing the unnecessary tags include improves query performance.
14-15: Good addition of preview logging.The logging provides helpful visibility into the links that will be deleted. Showing the last 10 links gives a good preview without overwhelming output.
17-24: Well-structured Tinybird deletion logic.The sequential approach of updating Tinybird first with the
deleted: trueflag before database deletion is good practice. This ensures audit trail preservation and data consistency.
26-34: Improved precision with ID-based deletion.The change from domain-based to ID-based deletion is more precise and safer. It ensures only the specific links that were processed are deleted, and the logging provides good confirmation.
|
@CodeRabbit I made a few final changes, could you please review again? |
|
Tip For best results, initiate chat on the files or code changes. π§© Analysis chainπ Script executed: Length of output: 10948 π Script executed: Length of output: 3962 π Script executed: Length of output: 3477 @steven-tey I've reviewed the current state after your final changes. Here's what I found: β Improvements Made
|
|
@CodeRabbit OK I updated based on your feedback for |
|
Tip For best results, initiate chat on the files or code changes. π§© Analysis chainπ Script executed: Length of output: 2557 @steven-tey I've checked the updated export const convertCurrencyWithFxRates = ({
currency,
amount,
fxRates,
}: {
currency: string;
amount: number;
fxRates: Record<string, string>;
}) => {
const currencyCode = currency.toUpperCase();
const isZeroDecimalCurrency = ZERO_DECIMAL_CURRENCIES.includes(currencyCode);
if (fxRates) {
const fxRate = fxRates[currencyCode];
// β οΈ No validation here - fxRate could be undefined, null, or invalid
let convertedAmount = amount / Number(fxRate); // Potential division by zero/NaN
// ...
}
// ...
};The issue: Recommended fix: if (fxRates) {
const fxRate = fxRates[currencyCode];
// Add validation here
if (!fxRate || isNaN(Number(fxRate)) || Number(fxRate) <= 0) {
// Return original currency/amount if FX rate is invalid
return { currency, amount };
}
let convertedAmount = amount / Number(fxRate);
// ... rest of the logic
}This will prevent runtime errors when FX rates are missing or invalid for specific currencies. |
|
@CodeRabbit ok I fixed it, can you check one last time? |
|
Tip For best results, initiate chat on the files or code changes. π§© Analysis chain@steven-tey I'll check the updated π Script executed: Length of output: 3356 @steven-tey Perfect! β The FX rate validation has been properly implemented. The const fxRate = fxRates[currencyCode];
// if the FX rate is not found, we return the original amount
if (!fxRate) {
return {
currency,
amount,
};
}This fix:
π Currency Conversion Refactoring CompleteThe refactoring now provides a robust foundation for accurate currency conversion to USD across all import systems (Rewardful, Tolt, and PartnerStack). The key improvements include:
Great work on addressing all the critical issues! The currency conversion system is now production-ready and maintainable. If you found this review helpful, would you consider giving us a shout-out on X? Thank you for using CodeRabbit! |
Summary by CodeRabbit
New Features
Bug Fixes
Refactor
Chores