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

Skip to content

Conversation

@steven-tey
Copy link
Collaborator

@steven-tey steven-tey commented Sep 15, 2025

Summary by CodeRabbit

  • New Features

    • Added email filter to the partners list endpoint.
    • Reintroduced tenant ID filter with higher precedence over email and search.
    • Added optional parameter to include expanded stats fields (e.g., clicks, leads, conversions) in responses.
  • Documentation

    • Updated API parameter descriptions and examples for email, tenantId, and includeExpandedFields to reflect new filtering rules and usage.

@vercel
Copy link
Contributor

vercel bot commented Sep 15, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Updated (UTC)
dub Ready Ready Preview Sep 15, 2025 8:10pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 15, 2025

Walkthrough

Adds optional email-based filtering to GET /partners with precedence rules relative to tenantId and search. Updates Zod schema to include email and tenantId filters with clarified precedence and an optional includeExpandedFields flag. Adds an end-to-end test for email filtering and updates test resources with a partner email.

Changes

Cohort / File(s) Summary
API: partners listing
apps/web/lib/api/partners/get-partners.ts
Adds conditional email filter in SQL; establishes precedence: tenantId > email > search; retains existing filters and mapping.
Schema: query params
apps/web/lib/zod/schemas/partners.ts
Introduces optional email and tenantId filters with precedence descriptions; makes includeExpandedFields optional with description and example; updates ordering and OpenAPI metadata.
Tests: E2E email filter
apps/web/tests/partners/list-partners.test.ts
Adds test asserting filtering partners by email for GET /partners using EnrolledPartnerSchema.
Tests: shared resources
apps/web/tests/utils/resource.ts
Adds email to E2E_PARTNER fixture.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant C as Client
  participant API as GET /partners
  participant S as Zod Schema
  participant DB as Database

  C->>API: Request with query { tenantId?, email?, search?, includeExpandedFields? }
  API->>S: Validate query (email, tenantId, search, includeExpandedFields)
  S-->>API: Parsed filters
  alt tenantId provided
    API->>DB: SELECT ... WHERE tenantId = :tenantId [ignores email/search precedence]
  else email provided
    API->>DB: SELECT ... WHERE email = :email
  else search provided
    API->>DB: SELECT ... WHERE matches(search)
  else
    API->>DB: SELECT ... (no tenant/email/search filter)
  end
  DB-->>API: Rows
  API-->>C: 200 OK with partners[]
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • TWilson023

Poem

A whisk of whiskers, twitch of nose,
I sift through tenants, emails, rows.
Precedence hops: tenant, then mail—
Search can follow on the trail.
With stats optional, neat and tight,
I thump approval: filters right.
— (_/ ) 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "Filter GET /partners by email" is a short, single-sentence summary that directly describes the primary change in the changeset (adding an email filter to the GET /partners endpoint, along with schema and test updates), so it clearly communicates the PR's main purpose to reviewers.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch filter-partner-email

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

Comment @coderabbitai help to get the list of available commands and usage tips.

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 (8)
apps/web/tests/utils/resource.ts (1)

86-88: Avoid hard‑coding a personal email in E2E fixtures

Ensure this email exists in all envs used by CI; otherwise tests can flake. Prefer a test‑only alias via env with a safe default.

Proposed tweak:

 export const E2E_PARTNER = {
   id: "pn_H4TB2V5hDIjpqB7PwrxESoY3",
-  email: "[email protected]",
+  email: process.env.E2E_PARTNER_EMAIL ?? "[email protected]",
   tenantId: "4149092f-7265-4002-98d9-da9f8e67e1fb",
 };
apps/web/lib/zod/schemas/partners.ts (3)

137-144: Tighten email filter validation

Since the backend does exact equality on email, validate shape to reduce garbage inputs and align with createPartner constraints.

-    email: z
-      .string()
-      .optional()
+    email: z
+      .string()
+      .trim()
+      .max(190)
+      .email()
+      .optional()
       .describe(
         "Filter the partner list based on the partner's `email`. The value must be a string. Takes precedence over `search`.",
       )
       .openapi({ example: "[email protected]" }),

144-151: Precedence semantics: clarify and align with implementation

Docs say tenantId takes precedence over email and search. Backend currently still applies search alongside tenantId/email. Either:

  • update description to “combined with other filters,” or
  • gate search when tenantId or email is present (see get‑partners.ts suggestion).

158-163: Name consistency in description

Use the actual field name totalCommissions to avoid confusion.

-        "Whether to include stats fields on the partner (`clicks`, `leads`, `conversions`, `sales`, `saleAmount`, `commissions`, `netRevenue`). If false, those fields will be returned as 0.",
+        "Whether to include stats fields on the partner (`clicks`, `leads`, `conversions`, `sales`, `saleAmount`, `totalCommissions`, `netRevenue`). If false, those fields will be returned as 0.",
apps/web/tests/partners/list-partners.test.ts (1)

84-101: Add precedence and negative‑case tests

To lock semantics:

  • When both tenantId and email are provided, tenantId should win.
  • Non‑existent email should return 200 with an empty array.
   test("filters partners by email", async () => {
     const { data, status } = await http.get<EnrolledPartnerProps[]>({
       path: "/partners",
       query: {
         email: E2E_PARTNER.email,
       },
     });
     expect(status).toEqual(200);
     expect(Array.isArray(data)).toBe(true);
     data.forEach((partner) => {
       const parsed = EnrolledPartnerSchema.parse(partner);
       expect(parsed.email).toBe(E2E_PARTNER.email);
     });
   });
+
+  test("tenantId takes precedence over email when both are provided", async () => {
+    const { data, status } = await http.get<EnrolledPartnerProps[]>({
+      path: "/partners",
+      query: {
+        tenantId: E2E_PARTNER.tenantId,
+        email: "[email protected]",
+      },
+    });
+    expect(status).toEqual(200);
+    expect(Array.isArray(data)).toBe(true);
+    data.forEach((partner) => {
+      const parsed = EnrolledPartnerSchema.parse(partner);
+      expect(parsed.tenantId).toBe(E2E_PARTNER.tenantId);
+    });
+  });
+
+  test("returns empty list for non-existent email", async () => {
+    const { data, status } = await http.get<EnrolledPartnerProps[]>({
+      path: "/partners",
+      query: { email: "nope-" + Date.now() + "@invalid.tld" },
+    });
+    expect(status).toEqual(200);
+    expect(Array.isArray(data)).toBe(true);
+    expect(data.length).toBe(0);
+  });
apps/web/lib/api/partners/get-partners.ts (3)

137-137: Case‑insensitive email match (optional)

If Partner.email isn’t stored/lower‑cased or using a CI collation, consider case‑insensitive equality to avoid misses.

-      ${tenantId ? Prisma.sql`AND pe.tenantId = ${tenantId}` : email ? Prisma.sql`AND p.email = ${email}` : Prisma.sql``}
+      ${tenantId
+        ? Prisma.sql`AND pe.tenantId = ${tenantId}`
+        : email
+        ? Prisma.sql`AND LOWER(p.email) = LOWER(${email})`
+        : Prisma.sql``}

Note: Using functions can bypass indexes. If email is indexed and a CI collation is used, prefer relying on collation or storing normalized lowercase emails.


140-152: Enforce precedence by gating search when email/tenantId is present

This matches the schema’s “takes precedence” wording and avoids accidental over‑filtering.

-      ${
-        search
-          ? Prisma.sql`AND (
+      ${
+        !tenantId && !email && search
+          ? Prisma.sql`AND (
         LOWER(p.name) LIKE LOWER(${`%${search}%`}) 
         OR LOWER(p.email) LIKE LOWER(${`%${search}%`})
         OR EXISTS (
           SELECT 1 FROM Link searchLink 
           WHERE searchLink.programId = ${programId}
           AND searchLink.partnerId = p.id 
           AND searchLink.shortLink LIKE LOWER(${`%${search}%`})
         )
       )`
           : Prisma.sql``
       }

50-158: Indexing note for new filter

Ensure Partner.email has an index (and unique constraint, per schema doc) to keep the new equality filter fast at scale.

Suggested migration (MySQL):

ALTER TABLE Partner ADD UNIQUE KEY `uniq_partner_email` (`email`);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b457b3c and 3e69c19.

📒 Files selected for processing (4)
  • apps/web/lib/api/partners/get-partners.ts (2 hunks)
  • apps/web/lib/zod/schemas/partners.ts (1 hunks)
  • apps/web/tests/partners/list-partners.test.ts (1 hunks)
  • apps/web/tests/utils/resource.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
apps/web/tests/partners/list-partners.test.ts (3)
apps/web/lib/types.ts (1)
  • EnrolledPartnerProps (434-434)
apps/web/tests/utils/resource.ts (1)
  • E2E_PARTNER (84-88)
apps/web/lib/zod/schemas/partners.ts (1)
  • EnrolledPartnerSchema (306-369)
apps/web/lib/zod/schemas/partners.ts (1)
apps/web/lib/zod/schemas/misc.ts (1)
  • booleanQuerySchema (23-28)
🔇 Additional comments (1)
apps/web/tests/partners/list-partners.test.ts (1)

84-101: Good addition: positive path for email filter

Covers the new query param and validates response shape.

@steven-tey steven-tey merged commit 7cb2e48 into main Sep 15, 2025
8 of 9 checks passed
@steven-tey steven-tey deleted the filter-partner-email branch September 15, 2025 20:14
@coderabbitai coderabbitai bot mentioned this pull request Sep 24, 2025
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.

2 participants