-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Filter GET /partners by email
#2841
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 GitHub.
|
WalkthroughAdds 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
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[]
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ 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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (8)
apps/web/tests/utils/resource.ts (1)
86-88: Avoid hard‑coding a personal email in E2E fixturesEnsure 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 validationSince 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 implementationDocs say tenantId takes precedence over email and search. Backend currently still applies
searchalongsidetenantId/
- update description to “combined with other filters,” or
- gate
searchwhentenantIdor
158-163: Name consistency in descriptionUse the actual field name
totalCommissionsto 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 testsTo 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.emailisn’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
140-152: Enforce precedence by gating search when email/tenantId is presentThis 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 filterEnsure
Partner.emailhas 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
📒 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 filterCovers the new query param and validates response shape.
Summary by CodeRabbit
New Features
Documentation