Improve markApplicationEventSubmitted - #3987
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThe PR passes partner network status through application event submission, refactors markApplicationEventSubmitted to find and update a single event (with conditional referralSource rewrite), updates callers to send partnerNetworkStatus, and renders referral source in the applications table and partner info cards. ChangesPartner Application Referral Source Tracking and Display
Sequence DiagramsequenceDiagram
participant ProgramCreation as Program<br/>Application Flow
participant EventService as markApplication<br/>EventSubmitted
participant Database as programApplication<br/>Event DB
participant UI as Referral Source<br/>Display
ProgramCreation->>EventService: Pass programEnrollment + partnerNetworkStatus
EventService->>Database: findUnique event by id or (programId, partnerId)
alt Event exists
Database-->>EventService: Return event record
EventService->>EventService: Check: referralSource = "marketplace" && networkStatus not approved/trusted?
alt Rewrite needed
EventService->>Database: update with referralSource = "direct"
else Keep existing
EventService->>Database: update with submittedAt
end
else No event
Database-->>EventService: null
EventService->>EventService: Log and return
end
Database-->>UI: Event with resolved referralSource
UI->>UI: Render PartnerApplicationSource component
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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 |
|
@coderabbitai full review |
✅ Action performedFull review finished. |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
apps/web/lib/application-events/update-application-event.ts (1)
52-57: 💤 Low valueUse constant for referral source literals.
The code uses string literals
"marketplace"and"direct"directly. The codebase definesMARKETPLACE_REFERRAL_SOURCE = "marketplace"inapps/web/lib/application-events/utils.ts. For consistency and maintainability, import and use this constant (and consider defining aDIRECT_REFERRAL_SOURCEconstant as well).♻️ Proposed refactor
+import { getApplicationEventCookieName, MARKETPLACE_REFERRAL_SOURCE } from "./utils"; -import { getApplicationEventCookieName } from "./utils"; + +const DIRECT_REFERRAL_SOURCE = "direct";Then update the condition:
- ...(applicationEvent.referralSource === "marketplace" && + ...(applicationEvent.referralSource === MARKETPLACE_REFERRAL_SOURCE && !["approved", "trusted"].includes(partnerNetworkStatus) ? { - referralSource: "direct", + referralSource: DIRECT_REFERRAL_SOURCE, } : {}),🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/lib/application-events/update-application-event.ts` around lines 52 - 57, Replace the string literals "marketplace" and "direct" with shared constants: import MARKETPLACE_REFERRAL_SOURCE from apps/web/lib/application-events/utils.ts and add/consume a DIRECT_REFERRAL_SOURCE constant there (e.g., export const DIRECT_REFERRAL_SOURCE = "direct"); then update the conditional in update-application-event.ts to compare applicationEvent.referralSource === MARKETPLACE_REFERRAL_SOURCE and to set referralSource: DIRECT_REFERRAL_SOURCE when the condition matches; keep the existing partnerNetworkStatus check and object spread logic unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@apps/web/lib/application-events/update-application-event.ts`:
- Around line 52-57: Replace the string literals "marketplace" and "direct" with
shared constants: import MARKETPLACE_REFERRAL_SOURCE from
apps/web/lib/application-events/utils.ts and add/consume a
DIRECT_REFERRAL_SOURCE constant there (e.g., export const DIRECT_REFERRAL_SOURCE
= "direct"); then update the conditional in update-application-event.ts to
compare applicationEvent.referralSource === MARKETPLACE_REFERRAL_SOURCE and to
set referralSource: DIRECT_REFERRAL_SOURCE when the condition matches; keep the
existing partnerNetworkStatus check and object spread logic unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 96decfcd-3e5a-4504-b7ca-4e85f232af2a
📒 Files selected for processing (5)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/applications/page-client.tsxapps/web/lib/actions/partners/create-program-application.tsapps/web/lib/application-events/update-application-event.tsapps/web/lib/partners/complete-program-applications.tsapps/web/ui/partners/partner-info-cards.tsx
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/web/lib/application-events/update-application-event.ts`:
- Around line 28-40: The current lookup returns early if
prisma.programApplicationEvent.findUnique with applicationEventId yields no row,
skipping the fallback (programId_partnerId) lookup; update
markApplicationEventSubmitted so that when applicationEventId was provided but
findUnique returns null, it performs a second findUnique using {
programId_partnerId: { programId, partnerId } } before returning. In other
words, keep the initial attempt with applicationEventId (the call to
prisma.programApplicationEvent.findUnique), and if that result is null and
applicationEventId was present, run the fallback query for the (programId,
partnerId) composite key and only return/log when both queries fail.
- Around line 44-59: The current prisma.programApplicationEvent.update call
rewrites submittedAt and may reapply referralSource changes on retries; change
the DB write to enforce the one-way transition by adding submittedAt: null to
the where clause (e.g., use updateMany or an update with that predicate) so the
update only succeeds when submittedAt is still null, and keep the existing data
payload (submittedAt: new Date(), partnerId, programApplicationId, and the
conditional referralSource rewrite) so it remains idempotent under
retries/concurrency; after switching to updateMany, handle the returned count
(zero means the transition was already applied) if the caller needs to know.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d64e6c1e-604e-4535-b062-4befd417777d
📒 Files selected for processing (5)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/applications/page-client.tsxapps/web/lib/actions/partners/create-program-application.tsapps/web/lib/application-events/update-application-event.tsapps/web/lib/partners/complete-program-applications.tsapps/web/ui/partners/partner-info-cards.tsx
| const applicationEvent = await prisma.programApplicationEvent.findUnique({ | ||
| where: { | ||
| ...(applicationEventId | ||
| ? { id: applicationEventId } | ||
| : { programId_partnerId: { programId, partnerId } }), | ||
| }, | ||
| }); | ||
|
|
||
| if (!applicationEvent) { | ||
| console.error( | ||
| "[markApplicationEventSubmitted]: No application event found, skipping...", | ||
| ); | ||
| return; |
There was a problem hiding this comment.
Fallback lookup is skipped when cookie ID is stale.
If applicationEventId exists but resolves to no row, the function returns early and never attempts the (programId, partnerId) unique lookup. That drops valid submission tracking for stale/deleted cookie IDs.
🔧 Proposed fix
- const applicationEvent = await prisma.programApplicationEvent.findUnique({
- where: {
- ...(applicationEventId
- ? { id: applicationEventId }
- : { programId_partnerId: { programId, partnerId } }),
- },
- });
+ let applicationEvent = applicationEventId
+ ? await prisma.programApplicationEvent.findUnique({
+ where: { id: applicationEventId },
+ })
+ : null;
+
+ if (!applicationEvent && partnerId) {
+ applicationEvent = await prisma.programApplicationEvent.findUnique({
+ where: {
+ programId_partnerId: { programId, partnerId },
+ },
+ });
+ }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/lib/application-events/update-application-event.ts` around lines 28
- 40, The current lookup returns early if
prisma.programApplicationEvent.findUnique with applicationEventId yields no row,
skipping the fallback (programId_partnerId) lookup; update
markApplicationEventSubmitted so that when applicationEventId was provided but
findUnique returns null, it performs a second findUnique using {
programId_partnerId: { programId, partnerId } } before returning. In other
words, keep the initial attempt with applicationEventId (the call to
prisma.programApplicationEvent.findUnique), and if that result is null and
applicationEventId was present, run the fallback query for the (programId,
partnerId) composite key and only return/log when both queries fail.
| await prisma.programApplicationEvent.update({ | ||
| where: { | ||
| ...(applicationEventId | ||
| ? { id: applicationEventId } | ||
| : { programId, partnerId }), | ||
| submittedAt: null, | ||
| id: applicationEvent.id, | ||
| }, | ||
| data: { | ||
| partnerId, | ||
| submittedAt: new Date(), | ||
| partnerId, | ||
| programApplicationId: applicationId, | ||
| ...(applicationEvent.referralSource === "marketplace" && | ||
| !["approved", "trusted"].includes(partnerNetworkStatus) | ||
| ? { | ||
| referralSource: "direct", | ||
| } | ||
| : {}), | ||
| }, | ||
| }); |
There was a problem hiding this comment.
Submission update lost its one-way transition guard.
update() now rewrites submittedAt on every retry/re-entry. This corrupts first-submission timestamps and can reapply referral-source rewrites. Guard the transition in the DB write (submittedAt: null) so it stays idempotent under retries/concurrency.
🔒 Proposed fix
- await prisma.programApplicationEvent.update({
- where: {
- id: applicationEvent.id,
- },
- data: {
- submittedAt: new Date(),
- partnerId,
- programApplicationId: applicationId,
- ...(applicationEvent.referralSource === "marketplace" &&
- !["approved", "trusted"].includes(partnerNetworkStatus)
- ? {
- referralSource: "direct",
- }
- : {}),
- },
- });
+ const { count } = await prisma.programApplicationEvent.updateMany({
+ where: {
+ id: applicationEvent.id,
+ submittedAt: null,
+ },
+ data: {
+ submittedAt: new Date(),
+ partnerId,
+ programApplicationId: applicationId,
+ ...(applicationEvent.referralSource === "marketplace" &&
+ !["approved", "trusted"].includes(partnerNetworkStatus)
+ ? { referralSource: "direct" }
+ : {}),
+ },
+ });
+
+ if (count === 0) {
+ return;
+ }Based on learnings: the codebase prefers enforcing state-transition preconditions directly in Prisma where clauses.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| await prisma.programApplicationEvent.update({ | |
| where: { | |
| ...(applicationEventId | |
| ? { id: applicationEventId } | |
| : { programId, partnerId }), | |
| submittedAt: null, | |
| id: applicationEvent.id, | |
| }, | |
| data: { | |
| partnerId, | |
| submittedAt: new Date(), | |
| partnerId, | |
| programApplicationId: applicationId, | |
| ...(applicationEvent.referralSource === "marketplace" && | |
| !["approved", "trusted"].includes(partnerNetworkStatus) | |
| ? { | |
| referralSource: "direct", | |
| } | |
| : {}), | |
| }, | |
| }); | |
| const { count } = await prisma.programApplicationEvent.updateMany({ | |
| where: { | |
| id: applicationEvent.id, | |
| submittedAt: null, | |
| }, | |
| data: { | |
| submittedAt: new Date(), | |
| partnerId, | |
| programApplicationId: applicationId, | |
| ...(applicationEvent.referralSource === "marketplace" && | |
| !["approved", "trusted"].includes(partnerNetworkStatus) | |
| ? { referralSource: "direct" } | |
| : {}), | |
| }, | |
| }); | |
| if (count === 0) { | |
| return; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/lib/application-events/update-application-event.ts` around lines 44
- 59, The current prisma.programApplicationEvent.update call rewrites
submittedAt and may reapply referralSource changes on retries; change the DB
write to enforce the one-way transition by adding submittedAt: null to the where
clause (e.g., use updateMany or an update with that predicate) so the update
only succeeds when submittedAt is still null, and keep the existing data payload
(submittedAt: new Date(), partnerId, programApplicationId, and the conditional
referralSource rewrite) so it remains idempotent under retries/concurrency;
after switching to updateMany, handle the returned count (zero means the
transition was already applied) if the caller needs to know.
|
closing in favor of #3988 |
Summary by CodeRabbit
New Features
Bug Fixes / Reliability