Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@devkiran
Copy link
Collaborator

@devkiran devkiran commented Jun 13, 2025

Summary by CodeRabbit

  • New Features

    • Introduced the ability to create clawback entries for partner commissions, including a UI sheet for input and selection of clawback reasons.
    • Added tooltips and visual indicators for commissions with clawback reasons in earnings and commission tables.
    • Added a popover button for quick access to clawback creation from the commissions dashboard.
  • Enhancements

    • Commission and earnings filters now include both positive and negative (non-zero) earnings, providing a more comprehensive view.
    • Clawbacks are now processed alongside commissions in payout creation.
  • Bug Fixes

    • Improved validation and handling for clawback creation to ensure only enrolled partners are eligible.
  • Chores

    • Updated schemas and validation to support structured clawback reasons and descriptions.

@vercel
Copy link
Contributor

vercel bot commented Jun 13, 2025

The latest updates on your projects. Learn more about Vercel for Git β†—οΈŽ

Name Status Preview Updated (UTC)
dub βœ… Ready (Inspect) Visit Preview Jun 19, 2025 0:37am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 13, 2025

Walkthrough

This change introduces support for "clawbacks"β€”negative commissionsβ€”across the commissions and payouts system. It adds UI components for creating clawbacks, updates backend logic and schemas to handle negative earnings, and enhances tables to display reasons for clawbacks with tooltips. Filtering and aggregation logic is broadened to include both positive and negative (non-zero) earnings.

Changes

File(s) Change Summary
.../api/commissions/count/route.ts
.../api/commissions/route.ts
.../api/partner-profile/programs/[programId]/earnings/count/route.ts
.../api/partner-profile/programs/[programId]/earnings/route.ts
.../lib/api/partners/sync-total-commissions.ts
Commission queries updated: filter now includes all non-zero earnings (earnings != 0), not just positive.
.../api/cron/payouts/create-payout.ts Refactored payout creation to process both positive (commissions) and negative (clawbacks) earnings; queries split, results merged, payout period computed from both, and logging added.
.../partners.dub.co/(dashboard)/programs/[programSlug]/(enrolled)/earnings/earnings-table.tsx
.../app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/commission-table.tsx
Enhanced earnings/commission columns: negative earnings shown in red, tooltips added for clawback reasons using a mapping, conditional styling applied.
.../app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/commission-popover-buttons.tsx New component: CommissionPopoverButtons for popover UI with "Create clawback" action.
.../app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/create-clawback-sheet.tsx New component and hook: UI sheet for creating clawbacks, form with partner, amount, and reason, validation, and backend action integration.
.../app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/page.tsx Page controls updated to include both commission and clawback creation buttons.
.../app.dub.co/(dashboard)/[slug]/(ee)/program/partners/import-export-buttons.tsx Removed unused imports and state variables; no functional changes.
.../lib/actions/partners/create-clawback.ts New server action: createClawbackAction for creating validated, authenticated clawbacks for enrolled partners.
.../lib/partners/create-partner-commission.ts createPartnerCommission updated: added optional description parameter, passed to commission record.
.../lib/zod/schemas/commissions.ts Commission schema extended: optional description; added clawback reasons array and map; new createClawbackSchema for input validation.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant UI (Dashboard)
    participant CreateClawbackSheet
    participant Backend (createClawbackAction)
    participant DB

    User->>UI (Dashboard): Click "Create clawback"
    UI (Dashboard)->>CreateClawbackSheet: Open sheet/modal
    User->>CreateClawbackSheet: Fill partner, amount, reason, submit
    CreateClawbackSheet->>Backend (createClawbackAction): Submit validated data
    Backend (createClawbackAction)->>DB: Create negative commission (clawback)
    DB-->>Backend (createClawbackAction): Success/Failure
    Backend (createClawbackAction)-->>CreateClawbackSheet: Response
    CreateClawbackSheet-->>UI (Dashboard): Show toast, refresh commissions
Loading
sequenceDiagram
    participant Cron
    participant Backend (create-payout)
    participant DB

    Cron->>Backend (create-payout): Trigger payout creation
    Backend (create-payout)->>DB: Query positive commissions (earnings > 0)
    Backend (create-payout)->>DB: Query negative commissions (earnings < 0)
    DB-->>Backend (create-payout): Return commissions and clawbacks
    Backend (create-payout)->>DB: Create payout, update all commissions/clawbacks
    DB-->>Backend (create-payout): Success
Loading

Possibly related PRs

Poem

In the land of carrots and code so bright,
Clawbacks hop in, both left and right.
Negative numbers now join the fun,
With tooltips and sheets for everyone.
Earnings in red, reasons explainedβ€”
The commission garden, newly maintained!
πŸ₯•βœ¨


πŸ“œ Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 902cc92 and 2a7b69a.

πŸ“’ Files selected for processing (1)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/commission-popover-buttons.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/commission-popover-buttons.tsx
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
✨ Finishing Touches
  • πŸ“ Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share
πŸͺ§ Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need 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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 13, 2025

πŸ€– Bug0 QA Agent

Here are the results of the automated tests for PR #2525:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 13, 2025

πŸ€– Bug0 QA Agent

Here are the results of the automated tests for PR #2525:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 16, 2025

πŸ€– Bug0 QA Agent

Here are the results of the automated tests for PR #2525:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 16, 2025

πŸ€– Bug0 QA Agent

Here are the results of the automated tests for PR #2525:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 16, 2025

πŸ€– Bug0 QA Agent

Here are the results of the automated tests for PR #2525:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 18, 2025

πŸ€– Bug0 QA Agent

Here are the results of the automated tests for PR #2525:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 18, 2025

πŸ€– Bug0 QA Agent

Here are the results of the automated tests for PR #2525:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 18, 2025

πŸ€– Bug0 QA Agent

Here are the results of the automated tests for PR #2525:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

@devkiran devkiran marked this pull request as ready for review June 18, 2025 11:23
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

πŸ”­ Outside diff range comments (1)
apps/web/lib/partners/create-partner-commission.ts (1)

28-45: description param lacks basic sanitation / length guard

A free-text description is now forwarded straight to the DB.
Consider trimming and guarding length (e.g. 255 chars) at the boundary (here or in the zod schema) to prevent oversized payloads and UI truncation issues.

-  description?: string;
+  /** Optional, max 255 chars, trimmed */
+  description?: string;

A simple description?.trim().slice(0, 255) before the create would suffice.

♻️ Duplicate comments (3)
apps/web/app/(ee)/api/partner-profile/programs/[programId]/earnings/route.ts (1)

44-46: See previous comment about extracting a shared NON_ZERO_EARNINGS_FILTER.

apps/web/app/(ee)/api/partner-profile/programs/[programId]/earnings/count/route.ts (1)

36-38: See previous comment about extracting a shared NON_ZERO_EARNINGS_FILTER.

apps/web/app/(ee)/api/commissions/count/route.ts (1)

33-35: See previous comment about extracting a shared NON_ZERO_EARNINGS_FILTER.

🧹 Nitpick comments (6)
apps/web/app/(ee)/api/commissions/route.ts (1)

45-47: Consider centralising the β€œnon-zero earnings” filter

The new predicate { earnings: { not: 0 } } appears in several endpoints in this PR. Duplicating the literal across files risks future inconsistency. Extracting a small helper (e.g. NON_ZERO_EARNINGS_FILTER) in a shared module or util would keep these routes DRY and makes later changes trivial.

-earnings: { not: 0 },
+...NON_ZERO_EARNINGS_FILTER,
apps/web/lib/partners/create-partner-commission.ts (1)

180-182: Persisting empty strings

description is inserted even when it is an empty string, creating noisy data.
Either store null or omit the field when empty:

-        description,
+        ...(description?.trim()
+          ? { description: description.trim() }
+          : {}),
apps/web/app/(ee)/partners.dub.co/(dashboard)/programs/[programSlug]/(enrolled)/earnings/earnings-table.tsx (2)

6-6: Import order nit

CLAWBACK_REASONS_MAP is a domain constant; group it with other absolute imports to keep the block ordered & avoid merge churn.


166-204: Tooltip rendering logic duplicated across tables

The earnings-cell logic (tooltip, red negative, underline) is almost identical to the implementation in the commissions table. Extract into a small <EarningsCell /> component to avoid divergence and keep styles in sync.

No functional issues, just maintainability.

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/commission-popover-buttons.tsx (1)

41-46: Add an accessible label to the icon-only trigger

Screen-reader users receive no context for the three-dot button.

-        <Button
+        <Button
+          aria-label="More commission actions"
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/commission-table.tsx (1)

167-178: Long tooltip strings may overflow the viewport.

Some CLAWBACK_REASONS_MAP descriptions are lengthy; without width constraints, the tooltip can extend past the screen on narrow layouts.
Consider setting max-w-xs (or similar) on the tooltip content.

πŸ“œ Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 82b3876 and 2534e0e.

πŸ“’ Files selected for processing (15)
  • apps/web/app/(ee)/api/commissions/count/route.ts (1 hunks)
  • apps/web/app/(ee)/api/commissions/route.ts (1 hunks)
  • apps/web/app/(ee)/api/cron/payouts/create-payout.ts (4 hunks)
  • apps/web/app/(ee)/api/partner-profile/programs/[programId]/earnings/count/route.ts (1 hunks)
  • apps/web/app/(ee)/api/partner-profile/programs/[programId]/earnings/route.ts (1 hunks)
  • apps/web/app/(ee)/partners.dub.co/(dashboard)/programs/[programSlug]/(enrolled)/earnings/earnings-table.tsx (3 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/commission-popover-buttons.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/commission-table.tsx (4 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/create-clawback-sheet.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/page.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/import-export-buttons.tsx (1 hunks)
  • apps/web/lib/actions/partners/create-clawback.ts (1 hunks)
  • apps/web/lib/api/partners/sync-total-commissions.ts (1 hunks)
  • apps/web/lib/partners/create-partner-commission.ts (3 hunks)
  • apps/web/lib/zod/schemas/commissions.ts (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
apps/web/lib/actions/partners/create-clawback.ts (5)
apps/web/lib/actions/safe-action.ts (1)
  • authActionClient (33-81)
apps/web/lib/zod/schemas/commissions.ts (1)
  • createClawbackSchema (186-193)
apps/web/lib/api/programs/get-default-program-id-or-throw.ts (1)
  • getDefaultProgramIdOrThrow (4-17)
apps/web/lib/api/programs/get-program-enrollment-or-throw.ts (1)
  • getProgramEnrollmentOrThrow (6-80)
apps/web/lib/partners/create-partner-commission.ts (1)
  • createPartnerCommission (16-204)
apps/web/app/(ee)/partners.dub.co/(dashboard)/programs/[programSlug]/(enrolled)/earnings/earnings-table.tsx (2)
apps/web/lib/zod/schemas/commissions.ts (1)
  • CLAWBACK_REASONS_MAP (182-184)
packages/ui/src/tooltip.tsx (1)
  • Tooltip (32-88)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/commission-popover-buttons.tsx (1)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/create-clawback-sheet.tsx (1)
  • useCreateClawbackSheet (242-256)
πŸ”‡ Additional comments (4)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/import-export-buttons.tsx (1)

13-14: Null-safety for slug

useWorkspace() now only destructures { slug }. If slug can ever be undefined (e.g. initial loading state or error), pushing router.push(\/${slug}/…`)will generate a URL with"undefined"` and break navigation. Consider guarding or early-returning:

-router.push(`/${slug}/program/partners?import=rewardful`);
+if (!slug) return;          // or show error / spinner
+router.push(`/${slug}/program/partners?import=rewardful`);
apps/web/lib/api/partners/sync-total-commissions.ts (1)

14-18: Possible over-count if earnings can be NULL

earnings: { not: 0 } includes both negative & positive numbers, but also matches NULL values (NULL != 0).
If older rows or future migrations ever leave earnings nullable, those rows will be summed as 0, silently inflating totals.

-        earnings: { not: 0 },
+        // Exclude zero *and* NULL from the aggregation
+        earnings: { notIn: [0, null] },

Double-check the Prisma schema and existing data; if the column is defined as NOT NULL the fix is optional, otherwise apply the safeguard.

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/page.tsx (1)

12-20: πŸ‘ Nice contextual grouping of buttons

Adding CommissionPopoverButtons next to CreateCommissionButton keeps the primary action visible while hiding secondary actions behind a popover. Looks good.

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/commissions/create-clawback-sheet.tsx (1)

75-76: Keep client & server validation consistent.

The submit button disables zero amounts (!amount), but the Zod schema still allows it. Once the schema is tightened (see earlier comment), this divergence disappears; otherwise users could bypass the UI and call the action directly with amount = 0.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
apps/web/app/(ee)/api/cron/payouts/create-payout.ts (2)

55-60: commonWhere could be hoisted or memoised

commonWhere is re-allocated on every cron run. Moving it outside the function (or at least marking it const + reusing between the two queries) would shave a tiny amount off GC pressure and make the Promise.all block a bit cleaner.


107-118: Logging is asymmetric

The positive-commission log is still hard-coded to β€œpending commissions” while the second log says β€œpending clawbacks”.
Unify the wording or group them in a single structured log entry to avoid confusion in downstream log analysis.

πŸ“œ Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 2534e0e and 902cc92.

πŸ“’ Files selected for processing (2)
  • apps/web/app/(ee)/api/cron/payouts/create-payout.ts (4 hunks)
  • apps/web/lib/zod/schemas/commissions.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/lib/zod/schemas/commissions.ts
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
πŸ”‡ Additional comments (3)
apps/web/app/(ee)/api/cron/payouts/create-payout.ts (3)

119-123: Period boundary bug is fixed – good catch!

Explicitly sorting the concatenated array before deriving periodStart / periodEnd removes the ordering assumption flagged in the previous review. βœ…


190-204: Month-spanning payouts – verify business intent

periodEnd is always endOfMonth(latestCommissionDate). If allCommissions spans multiple months (e.g. July 25 – Aug 03) the payout will lump both months into an August period.
Confirm this matches finance’s expectations; otherwise compute separate payouts per month or cap periodEnd at the end of the earliest month.


135-160: ```shell
#!/bin/bash
set -e

echo "Locating Prisma schema files..."
fd schema.prisma

echo -e "\nInspecting Payout model in schema..."
rg "model Payout" -A20

echo -e "\nChecking for composite @@unique constraints..."
rg "@@unique" -A5


</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 18, 2025

πŸ€– Bug0 QA Agent

Here are the results of the automated tests for PR #2525:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

@devkiran devkiran requested a review from steven-tey June 18, 2025 18:40
@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 18, 2025

πŸ€– Bug0 QA Agent

Here are the results of the automated tests for PR #2525:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 19, 2025

πŸ€– Bug0 QA Agent

Here are the results of the automated tests for PR #2525:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 19, 2025

πŸ€– Bug0 QA Agent

Here are the results of the automated tests for PR #2525:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

@steven-tey
Copy link
Collaborator

@CodeRabbit final review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 19, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Let's examine the key files to conduct a thorough final review

# 1. Check the main clawback creation action for security and validation
echo "=== Clawback Creation Action ==="
cat apps/web/lib/actions/partners/create-clawback.ts

echo -e "\n=== Clawback Schema ==="
cat apps/web/lib/zod/schemas/commissions.ts

echo -e "\n=== Commission Popover Buttons ==="
cat apps/web/app/app.dub.co/\(dashboard\)/\[slug\]/\(ee\)/program/commissions/commission-popover-buttons.tsx

echo -e "\n=== Create Clawback Sheet ==="
head -50 apps/web/app/app.dub.co/\(dashboard\)/\[slug\]/\(ee\)/program/commissions/create-clawback-sheet.tsx

Length of output: 10240


🏁 Script executed:

#!/bin/bash
# Continue examining key implementation details

echo "=== Payout Creation Logic ==="
cat apps/web/app/\(ee\)/api/cron/payouts/create-payout.ts

echo -e "\n=== Commission Table Changes ==="
head -80 apps/web/app/app.dub.co/\(dashboard\)/\[slug\]/\(ee\)/program/commissions/commission-table.tsx

echo -e "\n=== API Route Changes - Commissions ==="
cat apps/web/app/\(ee\)/api/commissions/route.ts

Length of output: 9309


🏁 Script executed:

#!/bin/bash
# Check a few more critical details for the final review

echo "=== Commission Table Cell Rendering ==="
# Get the specific cell rendering logic for commissions
grep -A 20 -B 5 "Commission.*cell\|earnings.*cell\|amount.*cell" apps/web/app/app.dub.co/\(dashboard\)/\[slug\]/\(ee\)/program/commissions/commission-table.tsx

echo -e "\n=== Create Partner Commission Function ==="
cat apps/web/lib/partners/create-partner-commission.ts

echo -e "\n=== Sync Total Commissions Logic ==="
cat apps/web/lib/api/partners/sync-total-commissions.ts

Length of output: 6862


🏁 Script executed:

#!/bin/bash
# Get the actual table column definitions to see the cell rendering
echo "=== Commission Table Column Definitions ==="
grep -A 50 "columns.*=\|useTable\|cell:" apps/web/app/app.dub.co/\(dashboard\)/\[slug\]/\(ee\)/program/commissions/commission-table.tsx

echo -e "\n=== Check for any validation issues in schemas ==="
# Look for potential validation gaps
grep -n "gt\|lt\|min\|max" apps/web/lib/zod/schemas/commissions.ts

Length of output: 7853


@steven-tey Excellent work on this clawback implementation! πŸŽ‰ After conducting a comprehensive final review, I'm impressed with the thoroughness and quality of this feature. Here's my assessment:

βœ… Strengths & Implementation Quality

πŸ”’ Security & Validation

  • Proper authentication with authActionClient and comprehensive input validation
  • Partner enrollment verification before clawback creation
  • Well-structured Zod schemas with meaningful error messages

πŸ—οΈ Architecture & Data Consistency

  • Consistent database query changes across all endpoints (earnings != 0 instead of > 0)
  • Proper separation of positive commissions and negative clawbacks in payout logic
  • Smart handling of holding periods (clawbacks processed immediately, commissions wait for holding period)

πŸ’» User Experience

  • Excellent visual indicators: negative earnings displayed in red
  • Helpful tooltips showing clawback reasons using CLAWBACK_REASONS_MAP
  • Intuitive form with proper validation and loading states
  • Clear commission table enhancements with proper styling

πŸ”§ Edge Case Handling

  • Banned partner logic properly cancels positive commissions
  • Proper aggregation including both positive and negative earnings
  • Correct commission creation logic for custom events

🎯 Key Implementation Highlights

// Smart payout logic separating commissions and clawbacks
const [commissions, clawbacks] = await Promise.all([
  // Commissions wait for holding period
  prisma.commission.findMany({
    where: { earnings: { gt: 0 }, ...commonWhere, ...holdingPeriodFilter },
  }),
  // Clawbacks processed immediately
  prisma.commission.findMany({
    where: { earnings: { lt: 0 }, ...commonWhere },
  }),
]);
// Excellent UI feedback with tooltips
if (commission.description) {
  const reason = CLAWBACK_REASONS_MAP[commission.description]?.description;
  return (
    <Tooltip content={reason}>
      <span className={cn("underline decoration-dotted", 
        commission.earnings < 0 && "text-red-600")}>
        {earnings}
      </span>
    </Tooltip>
  );
}

πŸš€ Ready for Production

The implementation demonstrates:

  • βœ… Comprehensive testing (all automated tests passing)
  • βœ… Proper error handling and validation
  • βœ… Consistent data flow from frontend to database
  • βœ… Excellent user experience considerations
  • βœ… Maintainable and well-structured code

This clawback feature is production-ready and follows excellent engineering practices. The integration between positive commissions and negative clawbacks is seamless, and the user interface provides clear visual feedback for different types of earnings.

Outstanding work on delivering a feature that's both technically sound and user-friendly! πŸŽ‰

@steven-tey steven-tey merged commit d251b97 into main Jun 19, 2025
8 checks passed
@steven-tey steven-tey deleted the clawbacks branch June 19, 2025 01:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants