diff --git a/prisma/migrations/20260303220000_add_event_campaign_type/migration.sql b/prisma/migrations/20260303220000_add_event_campaign_type/migration.sql new file mode 100644 index 0000000..bca3626 --- /dev/null +++ b/prisma/migrations/20260303220000_add_event_campaign_type/migration.sql @@ -0,0 +1,50 @@ +-- AlterEnum +ALTER TYPE "CampaignType" ADD VALUE 'EVENT'; + +-- CreateTable +CREATE TABLE "campaign_items" ( + "id" TEXT NOT NULL, + "campaign_id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "category" TEXT, + "price" DECIMAL(12,2) NOT NULL, + "max_quantity" INTEGER, + "min_per_order" INTEGER NOT NULL DEFAULT 0, + "max_per_order" INTEGER, + "is_required" BOOLEAN NOT NULL DEFAULT false, + "sort_order" INTEGER NOT NULL DEFAULT 0, + "is_active" BOOLEAN NOT NULL DEFAULT true, + + CONSTRAINT "campaign_items_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "donation_line_items" ( + "id" TEXT NOT NULL, + "donation_id" TEXT NOT NULL, + "campaign_item_id" TEXT NOT NULL, + "quantity" INTEGER NOT NULL, + "unit_price" DECIMAL(12,2) NOT NULL, + "subtotal" DECIMAL(12,2) NOT NULL, + + CONSTRAINT "donation_line_items_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE INDEX "idx_campaign_item_campaign" ON "campaign_items"("campaign_id"); + +-- CreateIndex +CREATE INDEX "idx_line_item_donation" ON "donation_line_items"("donation_id"); + +-- CreateIndex +CREATE INDEX "idx_line_item_campaign_item" ON "donation_line_items"("campaign_item_id"); + +-- AddForeignKey +ALTER TABLE "campaign_items" ADD CONSTRAINT "campaign_items_campaign_id_fkey" FOREIGN KEY ("campaign_id") REFERENCES "campaigns"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "donation_line_items" ADD CONSTRAINT "donation_line_items_donation_id_fkey" FOREIGN KEY ("donation_id") REFERENCES "donations"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "donation_line_items" ADD CONSTRAINT "donation_line_items_campaign_item_id_fkey" FOREIGN KEY ("campaign_item_id") REFERENCES "campaign_items"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 570db93..2195533 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -755,6 +755,7 @@ model Campaign { // Relations donations Donation[] tiers CampaignTier[] + items CampaignItem[] @@index([organizationId, status], name: "idx_campaign_org_status") @@map("campaigns") @@ -771,6 +772,7 @@ enum CampaignType { OPEN // Default: any amount, no capacity limit FIXED_UNIT // Fixed price per unit, optional max units TIERED // Predefined donation levels with optional per-tier caps + EVENT // Multiple purchasable items with categories, prices, and capacity } model CampaignTier { @@ -788,6 +790,27 @@ model CampaignTier { @@map("campaign_tiers") } +model CampaignItem { + id String @id @default(uuid()) + campaignId String @map("campaign_id") + name String // "Adult Plate", "Child Plate", "Gift" + description String? @db.Text + category String? // Grouping label: "Plates", "Extras" + price Decimal @db.Decimal(12, 2) + maxQuantity Int? @map("max_quantity") // Total capacity (null = unlimited) + minPerOrder Int @default(0) @map("min_per_order") // 0 = optional + maxPerOrder Int? @map("max_per_order") // null = unlimited + isRequired Boolean @default(false) @map("is_required") // Must select ≥1 + sortOrder Int @default(0) @map("sort_order") + isActive Boolean @default(true) @map("is_active") + + campaign Campaign @relation(fields: [campaignId], references: [id]) + donationLineItems DonationLineItem[] + + @@index([campaignId], name: "idx_campaign_item_campaign") + @@map("campaign_items") +} + // ============================================ // DONATIONS // ============================================ @@ -832,8 +855,9 @@ model Donation { updatedAt DateTime @updatedAt @map("updated_at") // Relations - campaign Campaign? @relation(fields: [campaignId], references: [id]) - tier CampaignTier? @relation(fields: [tierId], references: [id]) + campaign Campaign? @relation(fields: [campaignId], references: [id]) + tier CampaignTier? @relation(fields: [tierId], references: [id]) + lineItems DonationLineItem[] @@index([organizationId, status], name: "idx_donation_org_status") @@index([organizationId, campaignId], name: "idx_donation_org_campaign") @@ -842,6 +866,22 @@ model Donation { @@map("donations") } +model DonationLineItem { + id String @id @default(uuid()) + donationId String @map("donation_id") + campaignItemId String @map("campaign_item_id") + quantity Int + unitPrice Decimal @map("unit_price") @db.Decimal(12, 2) // Snapshot of price at donation time + subtotal Decimal @map("subtotal") @db.Decimal(12, 2) // quantity × unitPrice + + donation Donation @relation(fields: [donationId], references: [id]) + campaignItem CampaignItem @relation(fields: [campaignItemId], references: [id]) + + @@index([donationId], name: "idx_line_item_donation") + @@index([campaignItemId], name: "idx_line_item_campaign_item") + @@map("donation_line_items") +} + enum DonationType { ONE_TIME PLEDGE diff --git a/src/__tests__/services/campaign-constraints.test.ts b/src/__tests__/services/campaign-constraints.test.ts index 6a2a9f0..60b7b20 100644 --- a/src/__tests__/services/campaign-constraints.test.ts +++ b/src/__tests__/services/campaign-constraints.test.ts @@ -21,6 +21,12 @@ jest.mock('@/lib/prisma', () => ({ aggregate: jest.fn(), count: jest.fn(), }, + donationLineItem: { + aggregate: jest.fn(), + }, + campaignItem: { + findMany: jest.fn(), + }, }, })); @@ -34,6 +40,7 @@ import { checkAndAutoCompleteCampaign, getUnitsSold, getTierSlotsFilled, + getItemQuantitySold, } from '@/services/campaign.service'; describe('Campaign Constraints', () => { @@ -208,6 +215,117 @@ describe('Campaign Constraints', () => { ).resolves.toBeUndefined(); }); }); + + describe('EVENT campaigns', () => { + const eventCampaign = { + id: 'camp-dinner', + campaignType: 'EVENT', + status: 'ACTIVE', + tiers: [], + items: [ + { id: 'item-adult', name: 'Adult Plate', price: 35, maxQuantity: 100, minPerOrder: 0, maxPerOrder: 10, isRequired: false, isActive: true }, + { id: 'item-child', name: 'Child Plate', price: 20, maxQuantity: 50, minPerOrder: 0, maxPerOrder: 5, isRequired: false, isActive: true }, + { id: 'item-gift', name: 'Gift', price: 30, maxQuantity: null, minPerOrder: 0, maxPerOrder: null, isRequired: true, isActive: true }, + ], + }; + + it('should accept valid EVENT donation with line items', async () => { + (prisma.campaign.findUnique as jest.Mock).mockResolvedValue(eventCampaign); + (prisma.donationLineItem.aggregate as jest.Mock).mockResolvedValue({ _sum: { quantity: 0 } }); + + await expect( + validateDonationAgainstCampaign('camp-dinner', 100, null, null, [ + { campaignItemId: 'item-adult', quantity: 2 }, // 2×35 = 70 + { campaignItemId: 'item-gift', quantity: 1 }, // 1×30 = 30 + ]) + ).resolves.toBeUndefined(); + }); + + it('should reject EVENT donation without line items', async () => { + (prisma.campaign.findUnique as jest.Mock).mockResolvedValue(eventCampaign); + + await expect( + validateDonationAgainstCampaign('camp-dinner', 100) + ).rejects.toThrow('require selecting at least one item'); + }); + + it('should reject EVENT donation with empty line items', async () => { + (prisma.campaign.findUnique as jest.Mock).mockResolvedValue(eventCampaign); + + await expect( + validateDonationAgainstCampaign('camp-dinner', 100, null, null, []) + ).rejects.toThrow('require selecting at least one item'); + }); + + it('should reject when required item is missing', async () => { + (prisma.campaign.findUnique as jest.Mock).mockResolvedValue(eventCampaign); + (prisma.donationLineItem.aggregate as jest.Mock).mockResolvedValue({ _sum: { quantity: 0 } }); + + await expect( + validateDonationAgainstCampaign('camp-dinner', 35, null, null, [ + { campaignItemId: 'item-adult', quantity: 1 }, + ]) + ).rejects.toThrow('"Gift" is required'); + }); + + it('should reject when amount does not match item total', async () => { + (prisma.campaign.findUnique as jest.Mock).mockResolvedValue(eventCampaign); + (prisma.donationLineItem.aggregate as jest.Mock).mockResolvedValue({ _sum: { quantity: 0 } }); + + await expect( + validateDonationAgainstCampaign('camp-dinner', 50, null, null, [ + { campaignItemId: 'item-adult', quantity: 1 }, + { campaignItemId: 'item-gift', quantity: 1 }, + ]) + ).rejects.toThrow('does not match item total ($65.00)'); + }); + + it('should reject when exceeding maxPerOrder', async () => { + (prisma.campaign.findUnique as jest.Mock).mockResolvedValue(eventCampaign); + (prisma.donationLineItem.aggregate as jest.Mock).mockResolvedValue({ _sum: { quantity: 0 } }); + + await expect( + validateDonationAgainstCampaign('camp-dinner', 385, null, null, [ + { campaignItemId: 'item-adult', quantity: 11 }, // max is 10 + { campaignItemId: 'item-gift', quantity: 1 }, + ]) + ).rejects.toThrow('Maximum 10 of "Adult Plate" per order'); + }); + + it('should reject when capacity exceeded', async () => { + (prisma.campaign.findUnique as jest.Mock).mockResolvedValue(eventCampaign); + // Adult plate: 98 sold, trying to buy 5 more + (prisma.donationLineItem.aggregate as jest.Mock) + .mockResolvedValueOnce({ _sum: { quantity: 98 } }); + + await expect( + validateDonationAgainstCampaign('camp-dinner', 205, null, null, [ + { campaignItemId: 'item-adult', quantity: 5 }, + { campaignItemId: 'item-gift', quantity: 1 }, + ]) + ).rejects.toThrow('Only 2 of "Adult Plate" remaining (requested 5)'); + }); + + it('should reject invalid campaign item ID', async () => { + (prisma.campaign.findUnique as jest.Mock).mockResolvedValue(eventCampaign); + + await expect( + validateDonationAgainstCampaign('camp-dinner', 30, null, null, [ + { campaignItemId: 'item-nonexistent', quantity: 1 }, + ]) + ).rejects.toThrow('Campaign item not found or inactive'); + }); + + it('should reject quantity less than 1', async () => { + (prisma.campaign.findUnique as jest.Mock).mockResolvedValue(eventCampaign); + + await expect( + validateDonationAgainstCampaign('camp-dinner', 0, null, null, [ + { campaignItemId: 'item-adult', quantity: 0 }, + ]) + ).rejects.toThrow('Quantity must be at least 1'); + }); + }); }); // ── getUnitsSold ──────────────────────────────────────────────────── @@ -258,6 +376,35 @@ describe('Campaign Constraints', () => { }); }); + // ── getItemQuantitySold ─────────────────────────────────────────────── + + describe('getItemQuantitySold', () => { + it('should sum quantity for non-cancelled donations', async () => { + (prisma.donationLineItem.aggregate as jest.Mock).mockResolvedValue({ + _sum: { quantity: 15 }, + }); + + const result = await getItemQuantitySold('item-adult'); + + expect(result).toBe(15); + expect(prisma.donationLineItem.aggregate).toHaveBeenCalledWith({ + where: { + campaignItemId: 'item-adult', + donation: { status: { notIn: ['CANCELLED'] } }, + }, + _sum: { quantity: true }, + }); + }); + + it('should return 0 when no line items', async () => { + (prisma.donationLineItem.aggregate as jest.Mock).mockResolvedValue({ + _sum: { quantity: null }, + }); + + expect(await getItemQuantitySold('item-empty')).toBe(0); + }); + }); + // ── checkAndAutoCompleteCampaign ──────────────────────────────────── describe('checkAndAutoCompleteCampaign', () => { @@ -351,6 +498,64 @@ describe('Campaign Constraints', () => { expect(prisma.campaign.update).not.toHaveBeenCalled(); }); + + it('should auto-complete EVENT campaign when all capped items are sold out', async () => { + (prisma.campaign.findUnique as jest.Mock).mockResolvedValue({ + id: 'camp-dinner', + campaignType: 'EVENT', + status: 'ACTIVE', + tiers: [], + }); + (prisma.campaignItem.findMany as jest.Mock).mockResolvedValue([ + { id: 'item-adult', maxQuantity: 100 }, + { id: 'item-child', maxQuantity: 50 }, + ]); + // Both at capacity + (prisma.donationLineItem.aggregate as jest.Mock) + .mockResolvedValueOnce({ _sum: { quantity: 100 } }) + .mockResolvedValueOnce({ _sum: { quantity: 50 } }); + + await checkAndAutoCompleteCampaign('camp-dinner'); + + expect(prisma.campaign.update).toHaveBeenCalledWith({ + where: { id: 'camp-dinner' }, + data: { status: 'COMPLETED' }, + }); + }); + + it('should NOT auto-complete EVENT when some items still have capacity', async () => { + (prisma.campaign.findUnique as jest.Mock).mockResolvedValue({ + id: 'camp-dinner', + campaignType: 'EVENT', + status: 'ACTIVE', + tiers: [], + }); + (prisma.campaignItem.findMany as jest.Mock).mockResolvedValue([ + { id: 'item-adult', maxQuantity: 100 }, + { id: 'item-child', maxQuantity: 50 }, + ]); + (prisma.donationLineItem.aggregate as jest.Mock) + .mockResolvedValueOnce({ _sum: { quantity: 100 } }) + .mockResolvedValueOnce({ _sum: { quantity: 30 } }); // still 20 remaining + + await checkAndAutoCompleteCampaign('camp-dinner'); + + expect(prisma.campaign.update).not.toHaveBeenCalled(); + }); + + it('should NOT auto-complete EVENT when no items have capacity limits', async () => { + (prisma.campaign.findUnique as jest.Mock).mockResolvedValue({ + id: 'camp-dinner', + campaignType: 'EVENT', + status: 'ACTIVE', + tiers: [], + }); + (prisma.campaignItem.findMany as jest.Mock).mockResolvedValue([]); + + await checkAndAutoCompleteCampaign('camp-dinner'); + + expect(prisma.campaign.update).not.toHaveBeenCalled(); + }); }); }); @@ -379,6 +584,14 @@ describe('Campaign API Contract', () => { amount: z.number(), maxSlots: z.number().nullable(), })).optional(), + items: z.array(z.object({ + id: z.string(), + name: z.string(), + price: z.number(), + category: z.string().nullable().optional(), + maxQuantity: z.number().nullable().optional(), + isRequired: z.boolean().optional(), + })).optional(), }); it('should validate OPEN campaign response', () => { @@ -440,7 +653,29 @@ describe('Campaign API Contract', () => { expect(CampaignResponseSchema.safeParse(response).success).toBe(true); }); - it('should validate donation creation schema accepts unitCount and tierId', () => { + it('should validate EVENT campaign response', () => { + const response = { + id: 'camp-4', + name: 'Dinner Event', + description: 'Annual fundraising dinner', + targetAmount: 5000, + campaignType: 'EVENT', + unitPrice: null, + maxUnits: null, + unitLabel: null, + allowMultiUnit: true, + status: 'ACTIVE', + amountRaised: 1200, + tiers: [], + items: [ + { id: 'item-1', name: 'Adult Plate', price: 35, category: 'Plates', maxQuantity: 100, isRequired: false }, + { id: 'item-2', name: 'Gift', price: 30, category: 'Extras', maxQuantity: null, isRequired: true }, + ], + }; + expect(CampaignResponseSchema.safeParse(response).success).toBe(true); + }); + + it('should validate donation creation schema accepts lineItems', () => { const CreateDonationSchema = z.object({ type: z.enum(['ONE_TIME', 'PLEDGE']), amount: z.number().positive(), @@ -448,6 +683,10 @@ describe('Campaign API Contract', () => { campaignId: z.string().uuid().nullable().optional(), unitCount: z.number().int().positive().nullable().optional(), tierId: z.string().uuid().nullable().optional(), + lineItems: z.array(z.object({ + campaignItemId: z.string(), + quantity: z.number().int().positive(), + })).optional(), }); expect(CreateDonationSchema.safeParse({ @@ -470,5 +709,16 @@ describe('Campaign API Contract', () => { type: 'PLEDGE', amount: 100, }).success).toBe(true); + + // EVENT with lineItems + expect(CreateDonationSchema.safeParse({ + type: 'PLEDGE', + amount: 100, + campaignId: '550e8400-e29b-41d4-a716-446655440000', + lineItems: [ + { campaignItemId: 'item-1', quantity: 2 }, + { campaignItemId: 'item-2', quantity: 1 }, + ], + }).success).toBe(true); }); }); diff --git a/src/app/api/organizations/[slug]/campaigns/[id]/items/route.ts b/src/app/api/organizations/[slug]/campaigns/[id]/items/route.ts new file mode 100644 index 0000000..95349ad --- /dev/null +++ b/src/app/api/organizations/[slug]/campaigns/[id]/items/route.ts @@ -0,0 +1,145 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { prisma } from '@/lib/prisma'; +import { z } from 'zod'; +import { withOrgAuth, AuthError, authErrorResponse } from '@/lib/auth/with-org-auth'; +import { addCampaignItem, updateCampaignItem, deleteCampaignItem } from '@/services/campaign.service'; + +const itemSchema = z.object({ + name: z.string().min(1), + description: z.string().nullable().optional(), + category: z.string().nullable().optional(), + price: z.number().positive(), + maxQuantity: z.number().int().positive().nullable().optional(), + minPerOrder: z.number().int().min(0).optional(), + maxPerOrder: z.number().int().positive().nullable().optional(), + isRequired: z.boolean().optional(), + sortOrder: z.number().int().optional(), +}); + +const updateItemSchema = itemSchema.partial().extend({ + isActive: z.boolean().optional(), +}); + +/** + * GET /api/organizations/[slug]/campaigns/[id]/items + */ +export async function GET( + request: NextRequest, + { params }: { params: Promise<{ slug: string; id: string }> } +) { + try { + const { id } = await params; + const items = await prisma.campaignItem.findMany({ + where: { campaignId: id, isActive: true }, + orderBy: { sortOrder: 'asc' }, + }); + return NextResponse.json(items.map(i => ({ ...i, price: Number(i.price) }))); + } catch (error) { + console.error('Error listing campaign items:', error); + return NextResponse.json({ error: 'Internal server error' }, { status: 500 }); + } +} + +/** + * POST /api/organizations/[slug]/campaigns/[id]/items + */ +export async function POST( + request: NextRequest, + { params }: { params: Promise<{ slug: string; id: string }> } +) { + try { + const { slug, id } = await params; + const ctx = await withOrgAuth(slug, { requiredRole: 'ORG_ADMIN' }); + + const campaign = await prisma.campaign.findUnique({ where: { id } }); + if (!campaign || campaign.organizationId !== ctx.orgId) { + return NextResponse.json({ error: 'Campaign not found' }, { status: 404 }); + } + if (campaign.campaignType !== 'EVENT') { + return NextResponse.json({ error: 'Items can only be added to EVENT campaigns' }, { status: 400 }); + } + + const body = await request.json(); + const validated = itemSchema.parse(body); + const item = await addCampaignItem(id, validated); + + return NextResponse.json({ ...item, price: Number(item.price) }, { status: 201 }); + } catch (error) { + if (error instanceof AuthError) return authErrorResponse(error); + if (error instanceof z.ZodError) { + return NextResponse.json({ error: 'Invalid input', details: error.errors }, { status: 400 }); + } + console.error('Error creating campaign item:', error); + return NextResponse.json({ error: 'Internal server error' }, { status: 500 }); + } +} + +/** + * PATCH /api/organizations/[slug]/campaigns/[id]/items + * Body must include `itemId` to identify which item to update. + */ +export async function PATCH( + request: NextRequest, + { params }: { params: Promise<{ slug: string; id: string }> } +) { + try { + const { slug, id } = await params; + await withOrgAuth(slug, { requiredRole: 'ORG_ADMIN' }); + + const body = await request.json(); + const { itemId, ...updates } = body; + if (!itemId) { + return NextResponse.json({ error: 'itemId is required' }, { status: 400 }); + } + + // Verify item belongs to this campaign + const existing = await prisma.campaignItem.findUnique({ where: { id: itemId } }); + if (!existing || existing.campaignId !== id) { + return NextResponse.json({ error: 'Item not found' }, { status: 404 }); + } + + const validated = updateItemSchema.parse(updates); + const item = await updateCampaignItem(itemId, validated); + + return NextResponse.json({ ...item, price: Number(item.price) }); + } catch (error) { + if (error instanceof AuthError) return authErrorResponse(error); + if (error instanceof z.ZodError) { + return NextResponse.json({ error: 'Invalid input', details: error.errors }, { status: 400 }); + } + console.error('Error updating campaign item:', error); + return NextResponse.json({ error: 'Internal server error' }, { status: 500 }); + } +} + +/** + * DELETE /api/organizations/[slug]/campaigns/[id]/items + * Body must include `itemId`. + */ +export async function DELETE( + request: NextRequest, + { params }: { params: Promise<{ slug: string; id: string }> } +) { + try { + const { slug, id } = await params; + await withOrgAuth(slug, { requiredRole: 'ORG_ADMIN' }); + + const body = await request.json(); + const { itemId } = body; + if (!itemId) { + return NextResponse.json({ error: 'itemId is required' }, { status: 400 }); + } + + const existing = await prisma.campaignItem.findUnique({ where: { id: itemId } }); + if (!existing || existing.campaignId !== id) { + return NextResponse.json({ error: 'Item not found' }, { status: 404 }); + } + + await deleteCampaignItem(itemId); + return NextResponse.json({ success: true }); + } catch (error) { + if (error instanceof AuthError) return authErrorResponse(error); + console.error('Error deleting campaign item:', error); + return NextResponse.json({ error: 'Internal server error' }, { status: 500 }); + } +} diff --git a/src/app/api/organizations/[slug]/campaigns/[id]/route.ts b/src/app/api/organizations/[slug]/campaigns/[id]/route.ts index 5bd9a1e..fc9cdbf 100644 --- a/src/app/api/organizations/[slug]/campaigns/[id]/route.ts +++ b/src/app/api/organizations/[slug]/campaigns/[id]/route.ts @@ -16,6 +16,25 @@ const updateCampaignSchema = z.object({ maxUnits: z.number().int().positive().nullable().optional(), unitLabel: z.string().nullable().optional(), allowMultiUnit: z.boolean().optional(), + tiers: z.array(z.object({ + id: z.string().optional(), + name: z.string().min(1), + amount: z.number().positive(), + maxSlots: z.number().int().positive().nullable().optional(), + sortOrder: z.number().int().optional(), + })).optional(), + items: z.array(z.object({ + id: z.string().optional(), + name: z.string().min(1), + description: z.string().nullable().optional(), + category: z.string().nullable().optional(), + price: z.number().positive(), + maxQuantity: z.number().int().positive().nullable().optional(), + minPerOrder: z.number().int().min(0).optional(), + maxPerOrder: z.number().int().positive().nullable().optional(), + isRequired: z.boolean().optional(), + sortOrder: z.number().int().optional(), + })).optional(), }); /** @@ -43,6 +62,7 @@ export async function GET( } const campaignTiers = (campaign as any).tiers || []; + const campaignItems = (campaign as any).items || []; const enrichedTiers = await Promise.all( campaignTiers.map(async (t: any) => ({ ...t, @@ -56,6 +76,7 @@ export async function GET( targetAmount: campaign.targetAmount ? Number(campaign.targetAmount) : null, unitPrice: campaign.unitPrice ? Number(campaign.unitPrice) : null, tiers: enrichedTiers, + items: campaignItems.map((i: any) => ({ ...i, price: Number(i.price) })), }); } catch (error) { console.error('Error getting campaign:', error); @@ -112,20 +133,101 @@ export async function PATCH( const body = await request.json(); const validated = updateCampaignSchema.parse(body); + const { tiers, items, ...campaignFields } = validated; + const updated = await updateCampaign(id, { - ...validated, - startDate: validated.startDate !== undefined - ? (validated.startDate ? new Date(validated.startDate) : null) + ...campaignFields, + startDate: campaignFields.startDate !== undefined + ? (campaignFields.startDate ? new Date(campaignFields.startDate) : null) : undefined, - endDate: validated.endDate !== undefined - ? (validated.endDate ? new Date(validated.endDate) : null) + endDate: campaignFields.endDate !== undefined + ? (campaignFields.endDate ? new Date(campaignFields.endDate) : null) : undefined, }); + // Sync TIERED tiers: upsert provided, deactivate removed + if (tiers !== undefined && existing.campaignType === 'TIERED') { + const existingTiers = await prisma.campaignTier.findMany({ where: { campaignId: id } }); + const existingIds = new Set(existingTiers.map(t => t.id)); + const incomingIds = new Set(tiers.filter(t => t.id).map(t => t.id!)); + + for (const [i, tier] of tiers.entries()) { + if (tier.id && existingIds.has(tier.id)) { + await prisma.campaignTier.update({ + where: { id: tier.id }, + data: { name: tier.name, amount: tier.amount, maxSlots: tier.maxSlots ?? null, sortOrder: tier.sortOrder ?? i }, + }); + } else { + await prisma.campaignTier.create({ + data: { campaignId: id, name: tier.name, amount: tier.amount, maxSlots: tier.maxSlots ?? null, sortOrder: tier.sortOrder ?? i }, + }); + } + } + // Delete tiers that were removed (only if no donations reference them) + for (const existing of existingTiers) { + if (!incomingIds.has(existing.id)) { + const donationCount = await prisma.donation.count({ where: { tierId: existing.id } }); + if (donationCount === 0) { + await prisma.campaignTier.delete({ where: { id: existing.id } }); + } + } + } + } + + // Sync EVENT items: upsert provided, soft-delete removed + if (items !== undefined && existing.campaignType === 'EVENT') { + const existingItems = await prisma.campaignItem.findMany({ where: { campaignId: id } }); + const existingIds = new Set(existingItems.map(i => i.id)); + const incomingIds = new Set(items.filter(i => i.id).map(i => i.id!)); + + for (const [i, item] of items.entries()) { + if (item.id && existingIds.has(item.id)) { + await prisma.campaignItem.update({ + where: { id: item.id }, + data: { + name: item.name, description: item.description ?? null, category: item.category ?? null, + price: item.price, maxQuantity: item.maxQuantity ?? null, + minPerOrder: item.minPerOrder ?? 0, maxPerOrder: item.maxPerOrder ?? null, + isRequired: item.isRequired ?? false, sortOrder: item.sortOrder ?? i, + }, + }); + } else { + await prisma.campaignItem.create({ + data: { + campaignId: id, name: item.name, description: item.description ?? null, + category: item.category ?? null, price: item.price, maxQuantity: item.maxQuantity ?? null, + minPerOrder: item.minPerOrder ?? 0, maxPerOrder: item.maxPerOrder ?? null, + isRequired: item.isRequired ?? false, sortOrder: item.sortOrder ?? i, + }, + }); + } + } + // Soft-delete items that were removed (preserve FK references) + for (const existing of existingItems) { + if (!incomingIds.has(existing.id)) { + await prisma.campaignItem.update({ + where: { id: existing.id }, + data: { isActive: false }, + }); + } + } + } + + // Re-fetch with tiers + items for response + const result = await prisma.campaign.findUnique({ + where: { id }, + include: { + tiers: { orderBy: { sortOrder: 'asc' } }, + items: { where: { isActive: true }, orderBy: { sortOrder: 'asc' } }, + }, + }); + return NextResponse.json({ - ...updated, - targetAmount: updated.targetAmount ? Number(updated.targetAmount) : null, - unitPrice: updated.unitPrice ? Number(updated.unitPrice) : null, + ...result, + targetAmount: result?.targetAmount ? Number(result.targetAmount) : null, + unitPrice: result?.unitPrice ? Number(result.unitPrice) : null, + tiers: (result as any)?.tiers?.map((t: any) => ({ ...t, amount: Number(t.amount) })) || [], + items: (result as any)?.items?.map((i: any) => ({ ...i, price: Number(i.price) })) || [], }); } catch (error: any) { if (error instanceof z.ZodError) { diff --git a/src/app/api/organizations/[slug]/campaigns/route.ts b/src/app/api/organizations/[slug]/campaigns/route.ts index a4f6829..4778516 100644 --- a/src/app/api/organizations/[slug]/campaigns/route.ts +++ b/src/app/api/organizations/[slug]/campaigns/route.ts @@ -13,7 +13,7 @@ const createCampaignSchema = z.object({ startDate: z.string().nullable().optional(), endDate: z.string().nullable().optional(), // Campaign constraint fields - campaignType: z.enum(['OPEN', 'FIXED_UNIT', 'TIERED']).optional(), + campaignType: z.enum(['OPEN', 'FIXED_UNIT', 'TIERED', 'EVENT']).optional(), unitPrice: z.number().positive().nullable().optional(), maxUnits: z.number().int().positive().nullable().optional(), unitLabel: z.string().nullable().optional(), @@ -25,6 +25,18 @@ const createCampaignSchema = z.object({ maxSlots: z.number().int().positive().nullable().optional(), sortOrder: z.number().int().optional(), })).optional(), + // Items for EVENT campaigns + items: z.array(z.object({ + name: z.string().min(1), + description: z.string().nullable().optional(), + category: z.string().nullable().optional(), + price: z.number().positive(), + maxQuantity: z.number().int().positive().nullable().optional(), + minPerOrder: z.number().int().min(0).optional(), + maxPerOrder: z.number().int().positive().nullable().optional(), + isRequired: z.boolean().optional(), + sortOrder: z.number().int().optional(), + })).optional(), }); /** @@ -66,9 +78,10 @@ export async function GET( const statusFilter = isAdmin ? undefined : 'ACTIVE'; const campaigns = await listCampaigns(organization.id, { statusFilter }); - // Serialize Decimal fields and enrich tiers + // Serialize Decimal fields and enrich tiers/items const serialized = await Promise.all(campaigns.map(async (c) => { const campaignTiers = (c as any).tiers || []; + const campaignItems = (c as any).items || []; const enrichedTiers = await Promise.all( campaignTiers.map(async (t: any) => ({ ...t, @@ -81,6 +94,7 @@ export async function GET( targetAmount: c.targetAmount ? Number(c.targetAmount) : null, unitPrice: c.unitPrice ? Number(c.unitPrice) : null, tiers: enrichedTiers, + items: campaignItems.map((i: any) => ({ ...i, price: Number(i.price) })), }; })); @@ -151,6 +165,7 @@ export async function POST( maxUnits: validated.maxUnits, unitLabel: validated.unitLabel, allowMultiUnit: validated.allowMultiUnit, + items: validated.items, }); // Create tiers for TIERED campaigns @@ -168,10 +183,13 @@ export async function POST( } } - // Re-fetch with tiers + // Re-fetch with tiers and items const result = await prisma.campaign.findUnique({ where: { id: campaign.id }, - include: { tiers: { orderBy: { sortOrder: 'asc' } } }, + include: { + tiers: { orderBy: { sortOrder: 'asc' } }, + items: { orderBy: { sortOrder: 'asc' } }, + }, }); return NextResponse.json(result, { status: 201 }); diff --git a/src/app/api/organizations/[slug]/donations/checkout/route.ts b/src/app/api/organizations/[slug]/donations/checkout/route.ts index ebb4d2b..ec07028 100644 --- a/src/app/api/organizations/[slug]/donations/checkout/route.ts +++ b/src/app/api/organizations/[slug]/donations/checkout/route.ts @@ -10,6 +10,10 @@ const checkoutSchema = z.object({ campaignId: z.string().nullable().optional(), tierId: z.string().nullable().optional(), unitCount: z.number().int().positive().nullable().optional(), + lineItems: z.array(z.object({ + campaignItemId: z.string().uuid(), + quantity: z.number().int().positive(), + })).optional(), donorName: z.string().min(1).optional(), donorEmail: z.string().email().optional(), donorMessage: z.string().optional(), @@ -90,26 +94,68 @@ export async function POST( stripeMethod.stripeFeeFixed ); + // Build Stripe line items + let stripeLineItems; + if (validated.lineItems && validated.lineItems.length > 0 && validated.campaignId) { + // EVENT campaign: one Stripe line item per campaign item + const campaign = await prisma.campaign.findUnique({ + where: { id: validated.campaignId }, + include: { items: { where: { isActive: true } } }, + }); + const itemMap = new Map( + (campaign?.items || []).map(i => [i.id, i]) + ); + stripeLineItems = validated.lineItems.map(li => { + const item = itemMap.get(li.campaignItemId); + const unitPrice = item ? Number(item.price) : 0; + // Apply fees proportionally to each item + const itemTotal = unitPrice * li.quantity; + const feeShare = itemTotal / validated.amount; + const itemWithFees = calculateTotalWithFees( + itemTotal, + stripeMethod.stripeFeePercent * feeShare, + stripeMethod.stripeFeeFixed * feeShare + ); + return { + price_data: { + currency: 'usd' as const, + product_data: { + name: item?.name || 'Event Item', + ...(item?.category ? { description: item.category } : {}), + }, + unit_amount: Math.round((itemWithFees / li.quantity) * 100), + }, + quantity: li.quantity, + }; + }); + description = campaign?.name + ? `${organization.name} — ${campaign.name}` + : description; + } else { + // Standard single line item + stripeLineItems = [ + { + price_data: { + currency: 'usd' as const, + product_data: { + name: description, + ...(validated.donorMessage + ? { description: validated.donorMessage } + : {}), + }, + unit_amount: Math.round(chargeAmount * 100), + }, + quantity: 1, + }, + ]; + } + // Create Checkout Session on the connected account const session = await getStripe().checkout.sessions.create( { mode: "payment", payment_method_types: ["card"], - line_items: [ - { - price_data: { - currency: "usd", - product_data: { - name: description, - ...(validated.donorMessage - ? { description: validated.donorMessage } - : {}), - }, - unit_amount: Math.round(chargeAmount * 100), // cents - }, - quantity: 1, - }, - ], + line_items: stripeLineItems, ...(validated.donorEmail ? { customer_email: validated.donorEmail } : {}), metadata: { organizationId: organization.id, @@ -122,6 +168,7 @@ export async function POST( isAnonymous: String(validated.isAnonymous || false), donationAmount: String(validated.amount), donationId: validated.donationId || "", + lineItems: validated.lineItems ? JSON.stringify(validated.lineItems) : "", }, success_url: `${baseUrl}/org/${slug}/donate/success?session_id={CHECKOUT_SESSION_ID}`, cancel_url: validated.campaignId diff --git a/src/app/api/organizations/[slug]/donations/route.ts b/src/app/api/organizations/[slug]/donations/route.ts index a1b03a1..bf44652 100644 --- a/src/app/api/organizations/[slug]/donations/route.ts +++ b/src/app/api/organizations/[slug]/donations/route.ts @@ -16,6 +16,10 @@ const createDonationSchema = z.object({ campaignId: z.string().uuid().nullable().optional(), unitCount: z.number().int().positive().nullable().optional(), tierId: z.string().uuid().nullable().optional(), + lineItems: z.array(z.object({ + campaignItemId: z.string().uuid(), + quantity: z.number().int().positive(), + })).optional(), }); /** @@ -230,6 +234,7 @@ export async function POST( campaignId, unitCount: validated.unitCount ?? undefined, tierId: validated.tierId ?? undefined, + lineItems: validated.lineItems ?? undefined, arAccountId: arAccount.id, revenueAccountId: revenueAccount.id, cashAccountId, diff --git a/src/app/api/webhooks/stripe/route.ts b/src/app/api/webhooks/stripe/route.ts index 6b94281..e999b98 100644 --- a/src/app/api/webhooks/stripe/route.ts +++ b/src/app/api/webhooks/stripe/route.ts @@ -293,6 +293,33 @@ async function handleNewDonation( }, }); + // Create line items for EVENT campaign donations + if (metadata.lineItems) { + try { + const lineItems = JSON.parse(metadata.lineItems) as Array<{ campaignItemId: string; quantity: number }>; + if (lineItems.length > 0) { + const items = await tx.campaignItem.findMany({ + where: { id: { in: lineItems.map(li => li.campaignItemId) } }, + }); + const itemMap = new Map(items.map(i => [i.id, i])); + for (const li of lineItems) { + const item = itemMap.get(li.campaignItemId); + if (!item) continue; + const unitPrice = Number(item.price); + await tx.donationLineItem.create({ + data: { + donationId: donation.id, + campaignItemId: li.campaignItemId, + quantity: li.quantity, + unitPrice, + subtotal: unitPrice * li.quantity, + }, + }); + } + } + } catch { /* ignore malformed lineItems */ } + } + donationRecord = donation; // Create StripePayment record for idempotency and audit trail diff --git a/src/app/org/[slug]/donate/[campaignId]/page.tsx b/src/app/org/[slug]/donate/[campaignId]/page.tsx index 64b5d54..d52d7d8 100644 --- a/src/app/org/[slug]/donate/[campaignId]/page.tsx +++ b/src/app/org/[slug]/donate/[campaignId]/page.tsx @@ -53,6 +53,17 @@ export default async function DonateCampaignPage({ params }: Props) { maxSlots: t.maxSlots, slotsFilled: t.slotsFilled ?? 0, })), + items: ((campaign as any).items || []).map((i: any) => ({ + id: i.id, + name: i.name, + description: i.description, + category: i.category, + price: Number(i.price), + maxQuantity: i.maxQuantity, + minPerOrder: i.minPerOrder, + maxPerOrder: i.maxPerOrder, + isRequired: i.isRequired, + })), }; return ( diff --git a/src/app/org/[slug]/donate/page.tsx b/src/app/org/[slug]/donate/page.tsx index 9247292..3319747 100644 --- a/src/app/org/[slug]/donate/page.tsx +++ b/src/app/org/[slug]/donate/page.tsx @@ -23,15 +23,44 @@ export default async function DonatePage({ params, searchParams }: Props) { notFound(); } - // If a campaign is specified, look it up for context - let campaignName: string | null = null; + // If a campaign is specified, fetch full campaign data for type-specific UI + let campaignData: any = null; if (campaignId) { const campaign = await prisma.campaign.findUnique({ where: { id: campaignId }, - select: { name: true, organizationId: true, status: true }, + include: { + tiers: { orderBy: { sortOrder: 'asc' } }, + items: { where: { isActive: true }, orderBy: { sortOrder: 'asc' } }, + }, }); if (campaign && campaign.organizationId === organization.id && campaign.status === 'ACTIVE') { - campaignName = campaign.name; + campaignData = { + id: campaign.id, + name: campaign.name, + description: campaign.description, + campaignType: campaign.campaignType, + unitPrice: campaign.unitPrice ? Number(campaign.unitPrice) : null, + unitLabel: campaign.unitLabel, + maxUnits: campaign.maxUnits, + allowMultiUnit: campaign.allowMultiUnit, + tiers: campaign.tiers.map((t) => ({ + id: t.id, + name: t.name, + amount: Number(t.amount), + maxSlots: t.maxSlots, + })), + items: campaign.items.map((i) => ({ + id: i.id, + name: i.name, + description: i.description, + category: i.category, + price: Number(i.price), + maxQuantity: i.maxQuantity, + minPerOrder: i.minPerOrder, + maxPerOrder: i.maxPerOrder, + isRequired: i.isRequired, + })), + }; } } @@ -42,7 +71,8 @@ export default async function DonatePage({ params, searchParams }: Props) { organizationName={organization.name} primaryColor={organization.primaryColor} campaignId={campaignId || null} - campaignName={campaignName} + campaignName={campaignData?.name || null} + campaign={campaignData} /> ); diff --git a/src/components/campaigns/CampaignForm.tsx b/src/components/campaigns/CampaignForm.tsx index a168779..0b111bc 100644 --- a/src/components/campaigns/CampaignForm.tsx +++ b/src/components/campaigns/CampaignForm.tsx @@ -22,6 +22,17 @@ interface TierInput { maxSlots: string; } +interface EventItemInput { + id?: string; + name: string; + category: string; + price: string; + maxQuantity: string; + minPerOrder: string; + maxPerOrder: string; + isRequired: boolean; +} + interface CampaignFormProps { organizationSlug: string; donationsAccountId?: string | null; @@ -40,6 +51,7 @@ interface CampaignFormProps { unitLabel?: string | null; allowMultiUnit?: boolean; tiers?: { id: string; name: string; amount: number; maxSlots: number | null; sortOrder?: number }[]; + items?: { id: string; name: string; category: string | null; price: number; maxQuantity: number | null; minPerOrder: number; maxPerOrder: number | null; isRequired: boolean; sortOrder?: number }[]; } | null; onSuccess: () => void; onCancel: () => void; @@ -90,6 +102,18 @@ export function CampaignForm({ maxSlots: t.maxSlots ? String(t.maxSlots) : "", })) || [] ); + const [eventItems, setEventItems] = useState( + campaign?.items?.map(i => ({ + id: i.id, + name: i.name, + category: i.category || "", + price: String(i.price), + maxQuantity: i.maxQuantity ? String(i.maxQuantity) : "", + minPerOrder: String(i.minPerOrder), + maxPerOrder: i.maxPerOrder ? String(i.maxPerOrder) : "", + isRequired: i.isRequired, + })) || [] + ); const isEditing = !!campaign; @@ -194,6 +218,24 @@ export function CampaignForm({ maxUnits: campaignType === 'FIXED_UNIT' && maxUnits ? parseInt(maxUnits) : null, unitLabel: campaignType === 'FIXED_UNIT' ? unitLabel || null : null, allowMultiUnit: campaignType === 'FIXED_UNIT' ? allowMultiUnit : true, + tiers: campaignType === 'TIERED' ? tiers.map((t, i) => ({ + id: t.id || undefined, + name: t.name, + amount: parseFloat(t.amount), + maxSlots: t.maxSlots ? parseInt(t.maxSlots) : null, + sortOrder: i, + })) : undefined, + items: campaignType === 'EVENT' ? eventItems.map((item, i) => ({ + id: item.id || undefined, + name: item.name, + category: item.category || null, + price: parseFloat(item.price), + maxQuantity: item.maxQuantity ? parseInt(item.maxQuantity) : null, + minPerOrder: parseInt(item.minPerOrder) || 0, + maxPerOrder: item.maxPerOrder ? parseInt(item.maxPerOrder) : null, + isRequired: item.isRequired, + sortOrder: i, + })) : undefined, } : { accountId: resolvedAccountId, @@ -213,6 +255,16 @@ export function CampaignForm({ maxSlots: t.maxSlots ? parseInt(t.maxSlots) : null, sortOrder: i, })) : undefined, + items: campaignType === 'EVENT' ? eventItems.map((item, i) => ({ + name: item.name, + category: item.category || null, + price: parseFloat(item.price), + maxQuantity: item.maxQuantity ? parseInt(item.maxQuantity) : null, + minPerOrder: parseInt(item.minPerOrder) || 0, + maxPerOrder: item.maxPerOrder ? parseInt(item.maxPerOrder) : null, + isRequired: item.isRequired, + sortOrder: i, + })) : undefined, }; const res = await fetch(url, { @@ -285,9 +337,21 @@ export function CampaignForm({ + )} + {isEditing && ( +
+ +

+ {campaignType === 'OPEN' && 'Open — Any donation amount'} + {campaignType === 'FIXED_UNIT' && 'Fixed Unit — Fixed price per unit'} + {campaignType === 'TIERED' && 'Tiered — Predefined donation levels'} + {campaignType === 'EVENT' && 'Event — Multiple purchasable items'} +

+
+ )} {/* FIXED_UNIT fields */} {campaignType === "FIXED_UNIT" && ( @@ -350,7 +414,7 @@ export function CampaignForm({ )} {/* TIERED fields */} - {campaignType === "TIERED" && !isEditing && ( + {campaignType === "TIERED" && (

Sponsorship Tiers

@@ -425,6 +489,137 @@ export function CampaignForm({
)} + {/* EVENT fields */} + {campaignType === "EVENT" && ( +
+
+

Event Items

+ +
+ {eventItems.length === 0 && ( +

Add items for donors to select (e.g., Adult Plate, Child Plate, Gift).

+ )} + {eventItems.map((item, i) => ( +
+
+
+ + { + const updated = [...eventItems]; + updated[i] = { ...item, name: e.target.value }; + setEventItems(updated); + }} + placeholder="e.g., Adult Dinner Plate" + required + /> +
+
+ + { + const updated = [...eventItems]; + updated[i] = { ...item, price: e.target.value }; + setEventItems(updated); + }} + placeholder="35.00" + required + /> +
+
+ + { + const updated = [...eventItems]; + updated[i] = { ...item, category: e.target.value }; + setEventItems(updated); + }} + placeholder="e.g., Plates" + /> +
+ +
+
+
+ + { + const updated = [...eventItems]; + updated[i] = { ...item, maxQuantity: e.target.value }; + setEventItems(updated); + }} + placeholder="∞" + /> +
+
+ + { + const updated = [...eventItems]; + updated[i] = { ...item, maxPerOrder: e.target.value }; + setEventItems(updated); + }} + placeholder="∞" + /> +
+
+ { + const updated = [...eventItems]; + updated[i] = { ...item, isRequired: e.target.checked }; + setEventItems(updated); + }} + className="h-4 w-4" + /> + +
+
+
+ ))} + {eventItems.length > 0 && eventItems.some(i => i.price) && ( +

+ {eventItems.filter(i => i.price && i.maxQuantity).length === eventItems.length && eventItems.length > 0 + ? `Max revenue: $${eventItems.reduce((sum, i) => sum + (parseFloat(i.price) || 0) * (parseInt(i.maxQuantity) || 0), 0).toFixed(2)}` + : `${eventItems.length} item(s) configured`} +

+ )} +
+ )} +
diff --git a/src/components/campaigns/CampaignList.tsx b/src/components/campaigns/CampaignList.tsx index dea6a1f..68266fe 100644 --- a/src/components/campaigns/CampaignList.tsx +++ b/src/components/campaigns/CampaignList.tsx @@ -41,6 +41,7 @@ interface Campaign { unitsSold?: number; unitsRemaining?: number; tiers?: { id: string; name: string; amount: number; maxSlots: number | null; sortOrder?: number; slotsFilled?: number }[]; + items?: { id: string; name: string; description?: string | null; category: string | null; price: number; maxQuantity: number | null; minPerOrder: number; maxPerOrder: number | null; isRequired: boolean; sortOrder?: number }[]; } interface CampaignListProps { diff --git a/src/components/campaigns/PublicCampaignPage.tsx b/src/components/campaigns/PublicCampaignPage.tsx index 619fa63..472c387 100644 --- a/src/components/campaigns/PublicCampaignPage.tsx +++ b/src/components/campaigns/PublicCampaignPage.tsx @@ -15,6 +15,18 @@ interface CampaignTier { slotsFilled: number; } +interface CampaignItem { + id: string; + name: string; + description: string | null; + category: string | null; + price: number; + maxQuantity: number | null; + minPerOrder: number; + maxPerOrder: number | null; + isRequired: boolean; +} + interface CampaignData { id: string; name: string; @@ -33,6 +45,7 @@ interface CampaignData { startDate: string | null; endDate: string | null; tiers: CampaignTier[]; + items?: CampaignItem[]; } interface PublicCampaignPageProps { @@ -94,6 +107,9 @@ export function PublicCampaignPage({ {campaign.campaignType === 'OPEN' && ( )} + {campaign.campaignType === 'EVENT' && ( + + )}
{/* Stats */} @@ -164,6 +180,47 @@ export function PublicCampaignPage({
)} + {/* Event Items */} + {campaign.campaignType === 'EVENT' && campaign.items && campaign.items.length > 0 && ( +
+

+ Available Items +

+ {(() => { + const grouped = campaign.items!.reduce((g: Record, item) => { + const cat = item.category || 'Items'; + if (!g[cat]) g[cat] = []; + g[cat].push(item); + return g; + }, {} as Record); + return Object.entries(grouped).map(([category, items]) => ( +
+

{category}

+ {items.map((item) => ( +
+
+

+ {item.name} + {item.isRequired && Required} +

+ {item.description && ( +

{item.description}

+ )} +
+

+ {formatCurrency(item.price)} +

+
+ ))} +
+ )); + })()} +
+ )} + {/* CTA */}
- {/* Step 1: Amount */} + {/* Step 1: Amount / Campaign-type selection */} {step === 'amount' && (
-
- -
- - $ - - setAmount(e.target.value)} - className="pl-7 text-lg" - placeholder="0.00" - autoFocus - /> + {/* FIXED_UNIT: Quantity selector */} + {isFixedUnit && ( +
+ + {campaign!.allowMultiUnit !== false ? ( +
+ + {unitQuantity} + +
+ ) : ( +

1 {campaign!.unitLabel || 'unit'}

+ )} +

Total: ${(campaign!.unitPrice! * unitQuantity).toFixed(2)}

- {/* Quick amounts */} -
- {[25, 50, 100, 250].map((val) => ( - + )} + + {/* TIERED: Tier picker */} + {isTiered && ( +
+ +
+ {campaign!.tiers.map(tier => ( + + ))} +
+
+ )} + + {/* EVENT: Item selector */} + {isEvent && ( +
+ + {Object.entries(eventItemsByCategory).map(([category, items]) => ( +
+

{category}

+
+ {items.map(item => { + const qty = eventQuantities[item.id] || 0; + const maxQty = item.maxPerOrder || item.maxQuantity || 99; + return ( +
+
+ {item.name} + {item.isRequired && *required} + ${item.price.toFixed(2)} + {item.description &&

{item.description}

} +
+
+ + {qty} + +
+
+ ); + })} +
+
))} + {hasRequiredItems && !allRequiredSelected && ( +

Please select all required items.

+ )} +

Total: ${eventTotal.toFixed(2)}

-
+ )} + + {/* OPEN / default: free-form amount */} + {!isFixedUnit && !isTiered && !isEvent && ( +
+ +
+ + $ + + setAmount(e.target.value)} + className="pl-7 text-lg" + placeholder="0.00" + autoFocus + /> +
+ {/* Quick amounts */} +
+ {[25, 50, 100, 250].map((val) => ( + + ))} +
+
+ )} +

- Donating ${parsedAmount.toFixed(2)} — choose a payment method: + Donating ${donationAmount.toFixed(2)} — choose a payment method:

{methods.map((method) => { @@ -309,7 +523,7 @@ export function DonationFlow({ Back

- ${parsedAmount.toFixed(2)} via{' '} + ${donationAmount.toFixed(2)} via{' '} {selectedMethod.label || selectedMethod.type} @@ -362,18 +576,18 @@ export function DonationFlow({ {/* Stripe: show fee info + direct checkout */} {selectedMethod.type === 'STRIPE' && (

- {!isValidStripeAmount && ( + {!isValidStripeAmount && donationAmount < 5 && (

Minimum donation amount for card payments is $5.

)}

- A processing fee of ${feeAmount.toFixed(2)} will be added — you'll be charged ${totalWithFees.toFixed(2)} so {organizationName} receives the full ${parsedAmount.toFixed(2)}. + A processing fee of ${feeAmount.toFixed(2)} will be added — you'll be charged ${totalWithFees.toFixed(2)} so {organizationName} receives the full ${donationAmount.toFixed(2)}.

)} + {/* EVENT: Item selector with quantities */} + {isEvent && selectedCampaign?.items?.length > 0 && ( +
+ + {Object.entries(eventItemsByCategory).map(([category, items]) => ( +
+

{category}

+ {(items as any[]).map((item: any) => { + const qty = eventQuantities[item.id] || 0; + const maxQty = item.maxPerOrder || item.maxQuantity || 99; + return ( +
0 + ? 'border-amber-400 bg-amber-50' + : 'border-gray-200' + }`} + > +
+

+ {item.name} + {item.isRequired && ( + * + )} +

+ {item.description && ( +

{item.description}

+ )} +
+
+ + {formatCurrency(Number(item.price))} + +
+ + {qty} + +
+
+
+ ); + })} +
+ ))} + {eventTotal > 0 && ( +
+ Total: + {formatCurrency(eventTotal)} +
+ )} +
+ )} + {/* Amount field — hidden for constrained campaigns */} - {!isFixedUnit && !isTiered && ( + {!isFixedUnit && !isTiered && !isEvent && ( { @@ -378,6 +378,16 @@ export interface PrismaClient< */ get campaignTier(): Prisma.CampaignTierDelegate; + /** + * `prisma.campaignItem`: Exposes CRUD operations for the **CampaignItem** model. + * Example usage: + * ```ts + * // Fetch zero or more CampaignItems + * const campaignItems = await prisma.campaignItem.findMany() + * ``` + */ + get campaignItem(): Prisma.CampaignItemDelegate; + /** * `prisma.donation`: Exposes CRUD operations for the **Donation** model. * Example usage: @@ -388,6 +398,16 @@ export interface PrismaClient< */ get donation(): Prisma.DonationDelegate; + /** + * `prisma.donationLineItem`: Exposes CRUD operations for the **DonationLineItem** model. + * Example usage: + * ```ts + * // Fetch zero or more DonationLineItems + * const donationLineItems = await prisma.donationLineItem.findMany() + * ``` + */ + get donationLineItem(): Prisma.DonationLineItemDelegate; + /** * `prisma.contact`: Exposes CRUD operations for the **Contact** model. * Example usage: diff --git a/src/generated/prisma/internal/prismaNamespace.ts b/src/generated/prisma/internal/prismaNamespace.ts index c2857e6..78e7106 100644 --- a/src/generated/prisma/internal/prismaNamespace.ts +++ b/src/generated/prisma/internal/prismaNamespace.ts @@ -403,7 +403,9 @@ export const ModelName = { AccessRequest: 'AccessRequest', Campaign: 'Campaign', CampaignTier: 'CampaignTier', + CampaignItem: 'CampaignItem', Donation: 'Donation', + DonationLineItem: 'DonationLineItem', Contact: 'Contact', Bill: 'Bill', BillPayment: 'BillPayment', @@ -425,7 +427,7 @@ export type TypeMap + fields: Prisma.CampaignItemFieldRefs + operations: { + findUnique: { + args: Prisma.CampaignItemFindUniqueArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findUniqueOrThrow: { + args: Prisma.CampaignItemFindUniqueOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findFirst: { + args: Prisma.CampaignItemFindFirstArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findFirstOrThrow: { + args: Prisma.CampaignItemFindFirstOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findMany: { + args: Prisma.CampaignItemFindManyArgs + result: runtime.Types.Utils.PayloadToResult[] + } + create: { + args: Prisma.CampaignItemCreateArgs + result: runtime.Types.Utils.PayloadToResult + } + createMany: { + args: Prisma.CampaignItemCreateManyArgs + result: BatchPayload + } + createManyAndReturn: { + args: Prisma.CampaignItemCreateManyAndReturnArgs + result: runtime.Types.Utils.PayloadToResult[] + } + delete: { + args: Prisma.CampaignItemDeleteArgs + result: runtime.Types.Utils.PayloadToResult + } + update: { + args: Prisma.CampaignItemUpdateArgs + result: runtime.Types.Utils.PayloadToResult + } + deleteMany: { + args: Prisma.CampaignItemDeleteManyArgs + result: BatchPayload + } + updateMany: { + args: Prisma.CampaignItemUpdateManyArgs + result: BatchPayload + } + updateManyAndReturn: { + args: Prisma.CampaignItemUpdateManyAndReturnArgs + result: runtime.Types.Utils.PayloadToResult[] + } + upsert: { + args: Prisma.CampaignItemUpsertArgs + result: runtime.Types.Utils.PayloadToResult + } + aggregate: { + args: Prisma.CampaignItemAggregateArgs + result: runtime.Types.Utils.Optional + } + groupBy: { + args: Prisma.CampaignItemGroupByArgs + result: runtime.Types.Utils.Optional[] + } + count: { + args: Prisma.CampaignItemCountArgs + result: runtime.Types.Utils.Optional | number + } + } + } Donation: { payload: Prisma.$DonationPayload fields: Prisma.DonationFieldRefs @@ -1909,6 +1985,80 @@ export type TypeMap + fields: Prisma.DonationLineItemFieldRefs + operations: { + findUnique: { + args: Prisma.DonationLineItemFindUniqueArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findUniqueOrThrow: { + args: Prisma.DonationLineItemFindUniqueOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findFirst: { + args: Prisma.DonationLineItemFindFirstArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findFirstOrThrow: { + args: Prisma.DonationLineItemFindFirstOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findMany: { + args: Prisma.DonationLineItemFindManyArgs + result: runtime.Types.Utils.PayloadToResult[] + } + create: { + args: Prisma.DonationLineItemCreateArgs + result: runtime.Types.Utils.PayloadToResult + } + createMany: { + args: Prisma.DonationLineItemCreateManyArgs + result: BatchPayload + } + createManyAndReturn: { + args: Prisma.DonationLineItemCreateManyAndReturnArgs + result: runtime.Types.Utils.PayloadToResult[] + } + delete: { + args: Prisma.DonationLineItemDeleteArgs + result: runtime.Types.Utils.PayloadToResult + } + update: { + args: Prisma.DonationLineItemUpdateArgs + result: runtime.Types.Utils.PayloadToResult + } + deleteMany: { + args: Prisma.DonationLineItemDeleteManyArgs + result: BatchPayload + } + updateMany: { + args: Prisma.DonationLineItemUpdateManyArgs + result: BatchPayload + } + updateManyAndReturn: { + args: Prisma.DonationLineItemUpdateManyAndReturnArgs + result: runtime.Types.Utils.PayloadToResult[] + } + upsert: { + args: Prisma.DonationLineItemUpsertArgs + result: runtime.Types.Utils.PayloadToResult + } + aggregate: { + args: Prisma.DonationLineItemAggregateArgs + result: runtime.Types.Utils.Optional + } + groupBy: { + args: Prisma.DonationLineItemGroupByArgs + result: runtime.Types.Utils.Optional[] + } + count: { + args: Prisma.DonationLineItemCountArgs + result: runtime.Types.Utils.Optional | number + } + } + } Contact: { payload: Prisma.$ContactPayload fields: Prisma.ContactFieldRefs @@ -2790,6 +2940,24 @@ export const CampaignTierScalarFieldEnum = { export type CampaignTierScalarFieldEnum = (typeof CampaignTierScalarFieldEnum)[keyof typeof CampaignTierScalarFieldEnum] +export const CampaignItemScalarFieldEnum = { + id: 'id', + campaignId: 'campaignId', + name: 'name', + description: 'description', + category: 'category', + price: 'price', + maxQuantity: 'maxQuantity', + minPerOrder: 'minPerOrder', + maxPerOrder: 'maxPerOrder', + isRequired: 'isRequired', + sortOrder: 'sortOrder', + isActive: 'isActive' +} as const + +export type CampaignItemScalarFieldEnum = (typeof CampaignItemScalarFieldEnum)[keyof typeof CampaignItemScalarFieldEnum] + + export const DonationScalarFieldEnum = { id: 'id', organizationId: 'organizationId', @@ -2819,6 +2987,18 @@ export const DonationScalarFieldEnum = { export type DonationScalarFieldEnum = (typeof DonationScalarFieldEnum)[keyof typeof DonationScalarFieldEnum] +export const DonationLineItemScalarFieldEnum = { + id: 'id', + donationId: 'donationId', + campaignItemId: 'campaignItemId', + quantity: 'quantity', + unitPrice: 'unitPrice', + subtotal: 'subtotal' +} as const + +export type DonationLineItemScalarFieldEnum = (typeof DonationLineItemScalarFieldEnum)[keyof typeof DonationLineItemScalarFieldEnum] + + export const ContactScalarFieldEnum = { versionId: 'versionId', id: 'id', @@ -3544,7 +3724,9 @@ export type GlobalOmitConfig = { accessRequest?: Prisma.AccessRequestOmit campaign?: Prisma.CampaignOmit campaignTier?: Prisma.CampaignTierOmit + campaignItem?: Prisma.CampaignItemOmit donation?: Prisma.DonationOmit + donationLineItem?: Prisma.DonationLineItemOmit contact?: Prisma.ContactOmit bill?: Prisma.BillOmit billPayment?: Prisma.BillPaymentOmit diff --git a/src/generated/prisma/internal/prismaNamespaceBrowser.ts b/src/generated/prisma/internal/prismaNamespaceBrowser.ts index 1c095d4..87637e4 100644 --- a/src/generated/prisma/internal/prismaNamespaceBrowser.ts +++ b/src/generated/prisma/internal/prismaNamespaceBrowser.ts @@ -70,7 +70,9 @@ export const ModelName = { AccessRequest: 'AccessRequest', Campaign: 'Campaign', CampaignTier: 'CampaignTier', + CampaignItem: 'CampaignItem', Donation: 'Donation', + DonationLineItem: 'DonationLineItem', Contact: 'Contact', Bill: 'Bill', BillPayment: 'BillPayment', @@ -493,6 +495,24 @@ export const CampaignTierScalarFieldEnum = { export type CampaignTierScalarFieldEnum = (typeof CampaignTierScalarFieldEnum)[keyof typeof CampaignTierScalarFieldEnum] +export const CampaignItemScalarFieldEnum = { + id: 'id', + campaignId: 'campaignId', + name: 'name', + description: 'description', + category: 'category', + price: 'price', + maxQuantity: 'maxQuantity', + minPerOrder: 'minPerOrder', + maxPerOrder: 'maxPerOrder', + isRequired: 'isRequired', + sortOrder: 'sortOrder', + isActive: 'isActive' +} as const + +export type CampaignItemScalarFieldEnum = (typeof CampaignItemScalarFieldEnum)[keyof typeof CampaignItemScalarFieldEnum] + + export const DonationScalarFieldEnum = { id: 'id', organizationId: 'organizationId', @@ -522,6 +542,18 @@ export const DonationScalarFieldEnum = { export type DonationScalarFieldEnum = (typeof DonationScalarFieldEnum)[keyof typeof DonationScalarFieldEnum] +export const DonationLineItemScalarFieldEnum = { + id: 'id', + donationId: 'donationId', + campaignItemId: 'campaignItemId', + quantity: 'quantity', + unitPrice: 'unitPrice', + subtotal: 'subtotal' +} as const + +export type DonationLineItemScalarFieldEnum = (typeof DonationLineItemScalarFieldEnum)[keyof typeof DonationLineItemScalarFieldEnum] + + export const ContactScalarFieldEnum = { versionId: 'versionId', id: 'id', diff --git a/src/generated/prisma/models.ts b/src/generated/prisma/models.ts index a680597..1f9ab54 100644 --- a/src/generated/prisma/models.ts +++ b/src/generated/prisma/models.ts @@ -27,7 +27,9 @@ export type * from './models/Invitation' export type * from './models/AccessRequest' export type * from './models/Campaign' export type * from './models/CampaignTier' +export type * from './models/CampaignItem' export type * from './models/Donation' +export type * from './models/DonationLineItem' export type * from './models/Contact' export type * from './models/Bill' export type * from './models/BillPayment' diff --git a/src/generated/prisma/models/Campaign.ts b/src/generated/prisma/models/Campaign.ts index a3fa045..77cde0c 100644 --- a/src/generated/prisma/models/Campaign.ts +++ b/src/generated/prisma/models/Campaign.ts @@ -322,6 +322,7 @@ export type CampaignWhereInput = { updatedAt?: Prisma.DateTimeFilter<"Campaign"> | Date | string donations?: Prisma.DonationListRelationFilter tiers?: Prisma.CampaignTierListRelationFilter + items?: Prisma.CampaignItemListRelationFilter } export type CampaignOrderByWithRelationInput = { @@ -344,6 +345,7 @@ export type CampaignOrderByWithRelationInput = { updatedAt?: Prisma.SortOrder donations?: Prisma.DonationOrderByRelationAggregateInput tiers?: Prisma.CampaignTierOrderByRelationAggregateInput + items?: Prisma.CampaignItemOrderByRelationAggregateInput } export type CampaignWhereUniqueInput = Prisma.AtLeast<{ @@ -369,6 +371,7 @@ export type CampaignWhereUniqueInput = Prisma.AtLeast<{ updatedAt?: Prisma.DateTimeFilter<"Campaign"> | Date | string donations?: Prisma.DonationListRelationFilter tiers?: Prisma.CampaignTierListRelationFilter + items?: Prisma.CampaignItemListRelationFilter }, "id"> export type CampaignOrderByWithAggregationInput = { @@ -439,6 +442,7 @@ export type CampaignCreateInput = { updatedAt?: Date | string donations?: Prisma.DonationCreateNestedManyWithoutCampaignInput tiers?: Prisma.CampaignTierCreateNestedManyWithoutCampaignInput + items?: Prisma.CampaignItemCreateNestedManyWithoutCampaignInput } export type CampaignUncheckedCreateInput = { @@ -461,6 +465,7 @@ export type CampaignUncheckedCreateInput = { updatedAt?: Date | string donations?: Prisma.DonationUncheckedCreateNestedManyWithoutCampaignInput tiers?: Prisma.CampaignTierUncheckedCreateNestedManyWithoutCampaignInput + items?: Prisma.CampaignItemUncheckedCreateNestedManyWithoutCampaignInput } export type CampaignUpdateInput = { @@ -483,6 +488,7 @@ export type CampaignUpdateInput = { updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string donations?: Prisma.DonationUpdateManyWithoutCampaignNestedInput tiers?: Prisma.CampaignTierUpdateManyWithoutCampaignNestedInput + items?: Prisma.CampaignItemUpdateManyWithoutCampaignNestedInput } export type CampaignUncheckedUpdateInput = { @@ -505,6 +511,7 @@ export type CampaignUncheckedUpdateInput = { updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string donations?: Prisma.DonationUncheckedUpdateManyWithoutCampaignNestedInput tiers?: Prisma.CampaignTierUncheckedUpdateManyWithoutCampaignNestedInput + items?: Prisma.CampaignItemUncheckedUpdateManyWithoutCampaignNestedInput } export type CampaignCreateManyInput = { @@ -679,6 +686,20 @@ export type CampaignUpdateOneRequiredWithoutTiersNestedInput = { update?: Prisma.XOR, Prisma.CampaignUncheckedUpdateWithoutTiersInput> } +export type CampaignCreateNestedOneWithoutItemsInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.CampaignCreateOrConnectWithoutItemsInput + connect?: Prisma.CampaignWhereUniqueInput +} + +export type CampaignUpdateOneRequiredWithoutItemsNestedInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.CampaignCreateOrConnectWithoutItemsInput + upsert?: Prisma.CampaignUpsertWithoutItemsInput + connect?: Prisma.CampaignWhereUniqueInput + update?: Prisma.XOR, Prisma.CampaignUncheckedUpdateWithoutItemsInput> +} + export type CampaignCreateNestedOneWithoutDonationsInput = { create?: Prisma.XOR connectOrCreate?: Prisma.CampaignCreateOrConnectWithoutDonationsInput @@ -714,6 +735,7 @@ export type CampaignCreateWithoutTiersInput = { createdAt?: Date | string updatedAt?: Date | string donations?: Prisma.DonationCreateNestedManyWithoutCampaignInput + items?: Prisma.CampaignItemCreateNestedManyWithoutCampaignInput } export type CampaignUncheckedCreateWithoutTiersInput = { @@ -735,6 +757,7 @@ export type CampaignUncheckedCreateWithoutTiersInput = { createdAt?: Date | string updatedAt?: Date | string donations?: Prisma.DonationUncheckedCreateNestedManyWithoutCampaignInput + items?: Prisma.CampaignItemUncheckedCreateNestedManyWithoutCampaignInput } export type CampaignCreateOrConnectWithoutTiersInput = { @@ -772,6 +795,7 @@ export type CampaignUpdateWithoutTiersInput = { createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string donations?: Prisma.DonationUpdateManyWithoutCampaignNestedInput + items?: Prisma.CampaignItemUpdateManyWithoutCampaignNestedInput } export type CampaignUncheckedUpdateWithoutTiersInput = { @@ -793,6 +817,111 @@ export type CampaignUncheckedUpdateWithoutTiersInput = { createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string donations?: Prisma.DonationUncheckedUpdateManyWithoutCampaignNestedInput + items?: Prisma.CampaignItemUncheckedUpdateManyWithoutCampaignNestedInput +} + +export type CampaignCreateWithoutItemsInput = { + id?: string + organizationId: string + accountId: string + name: string + description?: string | null + targetAmount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null + status?: $Enums.CampaignStatus + campaignType?: $Enums.CampaignType + unitPrice?: runtime.Decimal | runtime.DecimalJsLike | number | string | null + maxUnits?: number | null + unitLabel?: string | null + allowMultiUnit?: boolean + startDate?: Date | string | null + endDate?: Date | string | null + createdBy?: string | null + createdAt?: Date | string + updatedAt?: Date | string + donations?: Prisma.DonationCreateNestedManyWithoutCampaignInput + tiers?: Prisma.CampaignTierCreateNestedManyWithoutCampaignInput +} + +export type CampaignUncheckedCreateWithoutItemsInput = { + id?: string + organizationId: string + accountId: string + name: string + description?: string | null + targetAmount?: runtime.Decimal | runtime.DecimalJsLike | number | string | null + status?: $Enums.CampaignStatus + campaignType?: $Enums.CampaignType + unitPrice?: runtime.Decimal | runtime.DecimalJsLike | number | string | null + maxUnits?: number | null + unitLabel?: string | null + allowMultiUnit?: boolean + startDate?: Date | string | null + endDate?: Date | string | null + createdBy?: string | null + createdAt?: Date | string + updatedAt?: Date | string + donations?: Prisma.DonationUncheckedCreateNestedManyWithoutCampaignInput + tiers?: Prisma.CampaignTierUncheckedCreateNestedManyWithoutCampaignInput +} + +export type CampaignCreateOrConnectWithoutItemsInput = { + where: Prisma.CampaignWhereUniqueInput + create: Prisma.XOR +} + +export type CampaignUpsertWithoutItemsInput = { + update: Prisma.XOR + create: Prisma.XOR + where?: Prisma.CampaignWhereInput +} + +export type CampaignUpdateToOneWithWhereWithoutItemsInput = { + where?: Prisma.CampaignWhereInput + data: Prisma.XOR +} + +export type CampaignUpdateWithoutItemsInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + organizationId?: Prisma.StringFieldUpdateOperationsInput | string + accountId?: Prisma.StringFieldUpdateOperationsInput | string + name?: Prisma.StringFieldUpdateOperationsInput | string + description?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + targetAmount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null + status?: Prisma.EnumCampaignStatusFieldUpdateOperationsInput | $Enums.CampaignStatus + campaignType?: Prisma.EnumCampaignTypeFieldUpdateOperationsInput | $Enums.CampaignType + unitPrice?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null + maxUnits?: Prisma.NullableIntFieldUpdateOperationsInput | number | null + unitLabel?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + allowMultiUnit?: Prisma.BoolFieldUpdateOperationsInput | boolean + startDate?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + endDate?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + createdBy?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + donations?: Prisma.DonationUpdateManyWithoutCampaignNestedInput + tiers?: Prisma.CampaignTierUpdateManyWithoutCampaignNestedInput +} + +export type CampaignUncheckedUpdateWithoutItemsInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + organizationId?: Prisma.StringFieldUpdateOperationsInput | string + accountId?: Prisma.StringFieldUpdateOperationsInput | string + name?: Prisma.StringFieldUpdateOperationsInput | string + description?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + targetAmount?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null + status?: Prisma.EnumCampaignStatusFieldUpdateOperationsInput | $Enums.CampaignStatus + campaignType?: Prisma.EnumCampaignTypeFieldUpdateOperationsInput | $Enums.CampaignType + unitPrice?: Prisma.NullableDecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string | null + maxUnits?: Prisma.NullableIntFieldUpdateOperationsInput | number | null + unitLabel?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + allowMultiUnit?: Prisma.BoolFieldUpdateOperationsInput | boolean + startDate?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + endDate?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + createdBy?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + donations?: Prisma.DonationUncheckedUpdateManyWithoutCampaignNestedInput + tiers?: Prisma.CampaignTierUncheckedUpdateManyWithoutCampaignNestedInput } export type CampaignCreateWithoutDonationsInput = { @@ -814,6 +943,7 @@ export type CampaignCreateWithoutDonationsInput = { createdAt?: Date | string updatedAt?: Date | string tiers?: Prisma.CampaignTierCreateNestedManyWithoutCampaignInput + items?: Prisma.CampaignItemCreateNestedManyWithoutCampaignInput } export type CampaignUncheckedCreateWithoutDonationsInput = { @@ -835,6 +965,7 @@ export type CampaignUncheckedCreateWithoutDonationsInput = { createdAt?: Date | string updatedAt?: Date | string tiers?: Prisma.CampaignTierUncheckedCreateNestedManyWithoutCampaignInput + items?: Prisma.CampaignItemUncheckedCreateNestedManyWithoutCampaignInput } export type CampaignCreateOrConnectWithoutDonationsInput = { @@ -872,6 +1003,7 @@ export type CampaignUpdateWithoutDonationsInput = { createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string tiers?: Prisma.CampaignTierUpdateManyWithoutCampaignNestedInput + items?: Prisma.CampaignItemUpdateManyWithoutCampaignNestedInput } export type CampaignUncheckedUpdateWithoutDonationsInput = { @@ -893,6 +1025,7 @@ export type CampaignUncheckedUpdateWithoutDonationsInput = { createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string tiers?: Prisma.CampaignTierUncheckedUpdateManyWithoutCampaignNestedInput + items?: Prisma.CampaignItemUncheckedUpdateManyWithoutCampaignNestedInput } @@ -903,11 +1036,13 @@ export type CampaignUncheckedUpdateWithoutDonationsInput = { export type CampaignCountOutputType = { donations: number tiers: number + items: number } export type CampaignCountOutputTypeSelect = { donations?: boolean | CampaignCountOutputTypeCountDonationsArgs tiers?: boolean | CampaignCountOutputTypeCountTiersArgs + items?: boolean | CampaignCountOutputTypeCountItemsArgs } /** @@ -934,6 +1069,13 @@ export type CampaignCountOutputTypeCountTiersArgs = { + where?: Prisma.CampaignItemWhereInput +} + export type CampaignSelect = runtime.Types.Extensions.GetSelect<{ id?: boolean @@ -955,6 +1097,7 @@ export type CampaignSelect tiers?: boolean | Prisma.Campaign$tiersArgs + items?: boolean | Prisma.Campaign$itemsArgs _count?: boolean | Prisma.CampaignCountOutputTypeDefaultArgs }, ExtArgs["result"]["campaign"]> @@ -1022,6 +1165,7 @@ export type CampaignOmit = { donations?: boolean | Prisma.Campaign$donationsArgs tiers?: boolean | Prisma.Campaign$tiersArgs + items?: boolean | Prisma.Campaign$itemsArgs _count?: boolean | Prisma.CampaignCountOutputTypeDefaultArgs } export type CampaignIncludeCreateManyAndReturn = {} @@ -1032,6 +1176,7 @@ export type $CampaignPayload[] tiers: Prisma.$CampaignTierPayload[] + items: Prisma.$CampaignItemPayload[] } scalars: runtime.Types.Extensions.GetPayloadResult<{ id: string @@ -1447,6 +1592,7 @@ export interface Prisma__CampaignClient = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions> | Null> tiers = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions> | Null> + items = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions> | Null> /** * Attaches callbacks for the resolution and/or rejection of the Promise. * @param onfulfilled The callback to execute when the Promise is resolved. @@ -1928,6 +2074,30 @@ export type Campaign$tiersArgs = { + /** + * Select specific fields to fetch from the CampaignItem + */ + select?: Prisma.CampaignItemSelect | null + /** + * Omit specific fields from the CampaignItem + */ + omit?: Prisma.CampaignItemOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.CampaignItemInclude | null + where?: Prisma.CampaignItemWhereInput + orderBy?: Prisma.CampaignItemOrderByWithRelationInput | Prisma.CampaignItemOrderByWithRelationInput[] + cursor?: Prisma.CampaignItemWhereUniqueInput + take?: number + skip?: number + distinct?: Prisma.CampaignItemScalarFieldEnum | Prisma.CampaignItemScalarFieldEnum[] +} + /** * Campaign without action */ diff --git a/src/generated/prisma/models/CampaignItem.ts b/src/generated/prisma/models/CampaignItem.ts new file mode 100644 index 0000000..dd1b59b --- /dev/null +++ b/src/generated/prisma/models/CampaignItem.ts @@ -0,0 +1,1818 @@ + +/* !!! This is code generated by Prisma. Do not edit directly. !!! */ +/* eslint-disable */ +// biome-ignore-all lint: generated file +// @ts-nocheck +/* + * This file exports the `CampaignItem` model and its related types. + * + * 🟢 You can import this file directly. + */ +import type * as runtime from "@prisma/client/runtime/client" +import type * as $Enums from "../enums" +import type * as Prisma from "../internal/prismaNamespace" + +/** + * Model CampaignItem + * + */ +export type CampaignItemModel = runtime.Types.Result.DefaultSelection + +export type AggregateCampaignItem = { + _count: CampaignItemCountAggregateOutputType | null + _avg: CampaignItemAvgAggregateOutputType | null + _sum: CampaignItemSumAggregateOutputType | null + _min: CampaignItemMinAggregateOutputType | null + _max: CampaignItemMaxAggregateOutputType | null +} + +export type CampaignItemAvgAggregateOutputType = { + price: runtime.Decimal | null + maxQuantity: number | null + minPerOrder: number | null + maxPerOrder: number | null + sortOrder: number | null +} + +export type CampaignItemSumAggregateOutputType = { + price: runtime.Decimal | null + maxQuantity: number | null + minPerOrder: number | null + maxPerOrder: number | null + sortOrder: number | null +} + +export type CampaignItemMinAggregateOutputType = { + id: string | null + campaignId: string | null + name: string | null + description: string | null + category: string | null + price: runtime.Decimal | null + maxQuantity: number | null + minPerOrder: number | null + maxPerOrder: number | null + isRequired: boolean | null + sortOrder: number | null + isActive: boolean | null +} + +export type CampaignItemMaxAggregateOutputType = { + id: string | null + campaignId: string | null + name: string | null + description: string | null + category: string | null + price: runtime.Decimal | null + maxQuantity: number | null + minPerOrder: number | null + maxPerOrder: number | null + isRequired: boolean | null + sortOrder: number | null + isActive: boolean | null +} + +export type CampaignItemCountAggregateOutputType = { + id: number + campaignId: number + name: number + description: number + category: number + price: number + maxQuantity: number + minPerOrder: number + maxPerOrder: number + isRequired: number + sortOrder: number + isActive: number + _all: number +} + + +export type CampaignItemAvgAggregateInputType = { + price?: true + maxQuantity?: true + minPerOrder?: true + maxPerOrder?: true + sortOrder?: true +} + +export type CampaignItemSumAggregateInputType = { + price?: true + maxQuantity?: true + minPerOrder?: true + maxPerOrder?: true + sortOrder?: true +} + +export type CampaignItemMinAggregateInputType = { + id?: true + campaignId?: true + name?: true + description?: true + category?: true + price?: true + maxQuantity?: true + minPerOrder?: true + maxPerOrder?: true + isRequired?: true + sortOrder?: true + isActive?: true +} + +export type CampaignItemMaxAggregateInputType = { + id?: true + campaignId?: true + name?: true + description?: true + category?: true + price?: true + maxQuantity?: true + minPerOrder?: true + maxPerOrder?: true + isRequired?: true + sortOrder?: true + isActive?: true +} + +export type CampaignItemCountAggregateInputType = { + id?: true + campaignId?: true + name?: true + description?: true + category?: true + price?: true + maxQuantity?: true + minPerOrder?: true + maxPerOrder?: true + isRequired?: true + sortOrder?: true + isActive?: true + _all?: true +} + +export type CampaignItemAggregateArgs = { + /** + * Filter which CampaignItem to aggregate. + */ + where?: Prisma.CampaignItemWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of CampaignItems to fetch. + */ + orderBy?: Prisma.CampaignItemOrderByWithRelationInput | Prisma.CampaignItemOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the start position + */ + cursor?: Prisma.CampaignItemWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` CampaignItems from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` CampaignItems. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Count returned CampaignItems + **/ + _count?: true | CampaignItemCountAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to average + **/ + _avg?: CampaignItemAvgAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to sum + **/ + _sum?: CampaignItemSumAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the minimum value + **/ + _min?: CampaignItemMinAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the maximum value + **/ + _max?: CampaignItemMaxAggregateInputType +} + +export type GetCampaignItemAggregateType = { + [P in keyof T & keyof AggregateCampaignItem]: P extends '_count' | 'count' + ? T[P] extends true + ? number + : Prisma.GetScalarType + : Prisma.GetScalarType +} + + + + +export type CampaignItemGroupByArgs = { + where?: Prisma.CampaignItemWhereInput + orderBy?: Prisma.CampaignItemOrderByWithAggregationInput | Prisma.CampaignItemOrderByWithAggregationInput[] + by: Prisma.CampaignItemScalarFieldEnum[] | Prisma.CampaignItemScalarFieldEnum + having?: Prisma.CampaignItemScalarWhereWithAggregatesInput + take?: number + skip?: number + _count?: CampaignItemCountAggregateInputType | true + _avg?: CampaignItemAvgAggregateInputType + _sum?: CampaignItemSumAggregateInputType + _min?: CampaignItemMinAggregateInputType + _max?: CampaignItemMaxAggregateInputType +} + +export type CampaignItemGroupByOutputType = { + id: string + campaignId: string + name: string + description: string | null + category: string | null + price: runtime.Decimal + maxQuantity: number | null + minPerOrder: number + maxPerOrder: number | null + isRequired: boolean + sortOrder: number + isActive: boolean + _count: CampaignItemCountAggregateOutputType | null + _avg: CampaignItemAvgAggregateOutputType | null + _sum: CampaignItemSumAggregateOutputType | null + _min: CampaignItemMinAggregateOutputType | null + _max: CampaignItemMaxAggregateOutputType | null +} + +type GetCampaignItemGroupByPayload = Prisma.PrismaPromise< + Array< + Prisma.PickEnumerable & + { + [P in ((keyof T) & (keyof CampaignItemGroupByOutputType))]: P extends '_count' + ? T[P] extends boolean + ? number + : Prisma.GetScalarType + : Prisma.GetScalarType + } + > + > + + + +export type CampaignItemWhereInput = { + AND?: Prisma.CampaignItemWhereInput | Prisma.CampaignItemWhereInput[] + OR?: Prisma.CampaignItemWhereInput[] + NOT?: Prisma.CampaignItemWhereInput | Prisma.CampaignItemWhereInput[] + id?: Prisma.StringFilter<"CampaignItem"> | string + campaignId?: Prisma.StringFilter<"CampaignItem"> | string + name?: Prisma.StringFilter<"CampaignItem"> | string + description?: Prisma.StringNullableFilter<"CampaignItem"> | string | null + category?: Prisma.StringNullableFilter<"CampaignItem"> | string | null + price?: Prisma.DecimalFilter<"CampaignItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string + maxQuantity?: Prisma.IntNullableFilter<"CampaignItem"> | number | null + minPerOrder?: Prisma.IntFilter<"CampaignItem"> | number + maxPerOrder?: Prisma.IntNullableFilter<"CampaignItem"> | number | null + isRequired?: Prisma.BoolFilter<"CampaignItem"> | boolean + sortOrder?: Prisma.IntFilter<"CampaignItem"> | number + isActive?: Prisma.BoolFilter<"CampaignItem"> | boolean + campaign?: Prisma.XOR + donationLineItems?: Prisma.DonationLineItemListRelationFilter +} + +export type CampaignItemOrderByWithRelationInput = { + id?: Prisma.SortOrder + campaignId?: Prisma.SortOrder + name?: Prisma.SortOrder + description?: Prisma.SortOrderInput | Prisma.SortOrder + category?: Prisma.SortOrderInput | Prisma.SortOrder + price?: Prisma.SortOrder + maxQuantity?: Prisma.SortOrderInput | Prisma.SortOrder + minPerOrder?: Prisma.SortOrder + maxPerOrder?: Prisma.SortOrderInput | Prisma.SortOrder + isRequired?: Prisma.SortOrder + sortOrder?: Prisma.SortOrder + isActive?: Prisma.SortOrder + campaign?: Prisma.CampaignOrderByWithRelationInput + donationLineItems?: Prisma.DonationLineItemOrderByRelationAggregateInput +} + +export type CampaignItemWhereUniqueInput = Prisma.AtLeast<{ + id?: string + AND?: Prisma.CampaignItemWhereInput | Prisma.CampaignItemWhereInput[] + OR?: Prisma.CampaignItemWhereInput[] + NOT?: Prisma.CampaignItemWhereInput | Prisma.CampaignItemWhereInput[] + campaignId?: Prisma.StringFilter<"CampaignItem"> | string + name?: Prisma.StringFilter<"CampaignItem"> | string + description?: Prisma.StringNullableFilter<"CampaignItem"> | string | null + category?: Prisma.StringNullableFilter<"CampaignItem"> | string | null + price?: Prisma.DecimalFilter<"CampaignItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string + maxQuantity?: Prisma.IntNullableFilter<"CampaignItem"> | number | null + minPerOrder?: Prisma.IntFilter<"CampaignItem"> | number + maxPerOrder?: Prisma.IntNullableFilter<"CampaignItem"> | number | null + isRequired?: Prisma.BoolFilter<"CampaignItem"> | boolean + sortOrder?: Prisma.IntFilter<"CampaignItem"> | number + isActive?: Prisma.BoolFilter<"CampaignItem"> | boolean + campaign?: Prisma.XOR + donationLineItems?: Prisma.DonationLineItemListRelationFilter +}, "id"> + +export type CampaignItemOrderByWithAggregationInput = { + id?: Prisma.SortOrder + campaignId?: Prisma.SortOrder + name?: Prisma.SortOrder + description?: Prisma.SortOrderInput | Prisma.SortOrder + category?: Prisma.SortOrderInput | Prisma.SortOrder + price?: Prisma.SortOrder + maxQuantity?: Prisma.SortOrderInput | Prisma.SortOrder + minPerOrder?: Prisma.SortOrder + maxPerOrder?: Prisma.SortOrderInput | Prisma.SortOrder + isRequired?: Prisma.SortOrder + sortOrder?: Prisma.SortOrder + isActive?: Prisma.SortOrder + _count?: Prisma.CampaignItemCountOrderByAggregateInput + _avg?: Prisma.CampaignItemAvgOrderByAggregateInput + _max?: Prisma.CampaignItemMaxOrderByAggregateInput + _min?: Prisma.CampaignItemMinOrderByAggregateInput + _sum?: Prisma.CampaignItemSumOrderByAggregateInput +} + +export type CampaignItemScalarWhereWithAggregatesInput = { + AND?: Prisma.CampaignItemScalarWhereWithAggregatesInput | Prisma.CampaignItemScalarWhereWithAggregatesInput[] + OR?: Prisma.CampaignItemScalarWhereWithAggregatesInput[] + NOT?: Prisma.CampaignItemScalarWhereWithAggregatesInput | Prisma.CampaignItemScalarWhereWithAggregatesInput[] + id?: Prisma.StringWithAggregatesFilter<"CampaignItem"> | string + campaignId?: Prisma.StringWithAggregatesFilter<"CampaignItem"> | string + name?: Prisma.StringWithAggregatesFilter<"CampaignItem"> | string + description?: Prisma.StringNullableWithAggregatesFilter<"CampaignItem"> | string | null + category?: Prisma.StringNullableWithAggregatesFilter<"CampaignItem"> | string | null + price?: Prisma.DecimalWithAggregatesFilter<"CampaignItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string + maxQuantity?: Prisma.IntNullableWithAggregatesFilter<"CampaignItem"> | number | null + minPerOrder?: Prisma.IntWithAggregatesFilter<"CampaignItem"> | number + maxPerOrder?: Prisma.IntNullableWithAggregatesFilter<"CampaignItem"> | number | null + isRequired?: Prisma.BoolWithAggregatesFilter<"CampaignItem"> | boolean + sortOrder?: Prisma.IntWithAggregatesFilter<"CampaignItem"> | number + isActive?: Prisma.BoolWithAggregatesFilter<"CampaignItem"> | boolean +} + +export type CampaignItemCreateInput = { + id?: string + name: string + description?: string | null + category?: string | null + price: runtime.Decimal | runtime.DecimalJsLike | number | string + maxQuantity?: number | null + minPerOrder?: number + maxPerOrder?: number | null + isRequired?: boolean + sortOrder?: number + isActive?: boolean + campaign: Prisma.CampaignCreateNestedOneWithoutItemsInput + donationLineItems?: Prisma.DonationLineItemCreateNestedManyWithoutCampaignItemInput +} + +export type CampaignItemUncheckedCreateInput = { + id?: string + campaignId: string + name: string + description?: string | null + category?: string | null + price: runtime.Decimal | runtime.DecimalJsLike | number | string + maxQuantity?: number | null + minPerOrder?: number + maxPerOrder?: number | null + isRequired?: boolean + sortOrder?: number + isActive?: boolean + donationLineItems?: Prisma.DonationLineItemUncheckedCreateNestedManyWithoutCampaignItemInput +} + +export type CampaignItemUpdateInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + name?: Prisma.StringFieldUpdateOperationsInput | string + description?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + category?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + maxQuantity?: Prisma.NullableIntFieldUpdateOperationsInput | number | null + minPerOrder?: Prisma.IntFieldUpdateOperationsInput | number + maxPerOrder?: Prisma.NullableIntFieldUpdateOperationsInput | number | null + isRequired?: Prisma.BoolFieldUpdateOperationsInput | boolean + sortOrder?: Prisma.IntFieldUpdateOperationsInput | number + isActive?: Prisma.BoolFieldUpdateOperationsInput | boolean + campaign?: Prisma.CampaignUpdateOneRequiredWithoutItemsNestedInput + donationLineItems?: Prisma.DonationLineItemUpdateManyWithoutCampaignItemNestedInput +} + +export type CampaignItemUncheckedUpdateInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + campaignId?: Prisma.StringFieldUpdateOperationsInput | string + name?: Prisma.StringFieldUpdateOperationsInput | string + description?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + category?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + maxQuantity?: Prisma.NullableIntFieldUpdateOperationsInput | number | null + minPerOrder?: Prisma.IntFieldUpdateOperationsInput | number + maxPerOrder?: Prisma.NullableIntFieldUpdateOperationsInput | number | null + isRequired?: Prisma.BoolFieldUpdateOperationsInput | boolean + sortOrder?: Prisma.IntFieldUpdateOperationsInput | number + isActive?: Prisma.BoolFieldUpdateOperationsInput | boolean + donationLineItems?: Prisma.DonationLineItemUncheckedUpdateManyWithoutCampaignItemNestedInput +} + +export type CampaignItemCreateManyInput = { + id?: string + campaignId: string + name: string + description?: string | null + category?: string | null + price: runtime.Decimal | runtime.DecimalJsLike | number | string + maxQuantity?: number | null + minPerOrder?: number + maxPerOrder?: number | null + isRequired?: boolean + sortOrder?: number + isActive?: boolean +} + +export type CampaignItemUpdateManyMutationInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + name?: Prisma.StringFieldUpdateOperationsInput | string + description?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + category?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + maxQuantity?: Prisma.NullableIntFieldUpdateOperationsInput | number | null + minPerOrder?: Prisma.IntFieldUpdateOperationsInput | number + maxPerOrder?: Prisma.NullableIntFieldUpdateOperationsInput | number | null + isRequired?: Prisma.BoolFieldUpdateOperationsInput | boolean + sortOrder?: Prisma.IntFieldUpdateOperationsInput | number + isActive?: Prisma.BoolFieldUpdateOperationsInput | boolean +} + +export type CampaignItemUncheckedUpdateManyInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + campaignId?: Prisma.StringFieldUpdateOperationsInput | string + name?: Prisma.StringFieldUpdateOperationsInput | string + description?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + category?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + maxQuantity?: Prisma.NullableIntFieldUpdateOperationsInput | number | null + minPerOrder?: Prisma.IntFieldUpdateOperationsInput | number + maxPerOrder?: Prisma.NullableIntFieldUpdateOperationsInput | number | null + isRequired?: Prisma.BoolFieldUpdateOperationsInput | boolean + sortOrder?: Prisma.IntFieldUpdateOperationsInput | number + isActive?: Prisma.BoolFieldUpdateOperationsInput | boolean +} + +export type CampaignItemListRelationFilter = { + every?: Prisma.CampaignItemWhereInput + some?: Prisma.CampaignItemWhereInput + none?: Prisma.CampaignItemWhereInput +} + +export type CampaignItemOrderByRelationAggregateInput = { + _count?: Prisma.SortOrder +} + +export type CampaignItemCountOrderByAggregateInput = { + id?: Prisma.SortOrder + campaignId?: Prisma.SortOrder + name?: Prisma.SortOrder + description?: Prisma.SortOrder + category?: Prisma.SortOrder + price?: Prisma.SortOrder + maxQuantity?: Prisma.SortOrder + minPerOrder?: Prisma.SortOrder + maxPerOrder?: Prisma.SortOrder + isRequired?: Prisma.SortOrder + sortOrder?: Prisma.SortOrder + isActive?: Prisma.SortOrder +} + +export type CampaignItemAvgOrderByAggregateInput = { + price?: Prisma.SortOrder + maxQuantity?: Prisma.SortOrder + minPerOrder?: Prisma.SortOrder + maxPerOrder?: Prisma.SortOrder + sortOrder?: Prisma.SortOrder +} + +export type CampaignItemMaxOrderByAggregateInput = { + id?: Prisma.SortOrder + campaignId?: Prisma.SortOrder + name?: Prisma.SortOrder + description?: Prisma.SortOrder + category?: Prisma.SortOrder + price?: Prisma.SortOrder + maxQuantity?: Prisma.SortOrder + minPerOrder?: Prisma.SortOrder + maxPerOrder?: Prisma.SortOrder + isRequired?: Prisma.SortOrder + sortOrder?: Prisma.SortOrder + isActive?: Prisma.SortOrder +} + +export type CampaignItemMinOrderByAggregateInput = { + id?: Prisma.SortOrder + campaignId?: Prisma.SortOrder + name?: Prisma.SortOrder + description?: Prisma.SortOrder + category?: Prisma.SortOrder + price?: Prisma.SortOrder + maxQuantity?: Prisma.SortOrder + minPerOrder?: Prisma.SortOrder + maxPerOrder?: Prisma.SortOrder + isRequired?: Prisma.SortOrder + sortOrder?: Prisma.SortOrder + isActive?: Prisma.SortOrder +} + +export type CampaignItemSumOrderByAggregateInput = { + price?: Prisma.SortOrder + maxQuantity?: Prisma.SortOrder + minPerOrder?: Prisma.SortOrder + maxPerOrder?: Prisma.SortOrder + sortOrder?: Prisma.SortOrder +} + +export type CampaignItemScalarRelationFilter = { + is?: Prisma.CampaignItemWhereInput + isNot?: Prisma.CampaignItemWhereInput +} + +export type CampaignItemCreateNestedManyWithoutCampaignInput = { + create?: Prisma.XOR | Prisma.CampaignItemCreateWithoutCampaignInput[] | Prisma.CampaignItemUncheckedCreateWithoutCampaignInput[] + connectOrCreate?: Prisma.CampaignItemCreateOrConnectWithoutCampaignInput | Prisma.CampaignItemCreateOrConnectWithoutCampaignInput[] + createMany?: Prisma.CampaignItemCreateManyCampaignInputEnvelope + connect?: Prisma.CampaignItemWhereUniqueInput | Prisma.CampaignItemWhereUniqueInput[] +} + +export type CampaignItemUncheckedCreateNestedManyWithoutCampaignInput = { + create?: Prisma.XOR | Prisma.CampaignItemCreateWithoutCampaignInput[] | Prisma.CampaignItemUncheckedCreateWithoutCampaignInput[] + connectOrCreate?: Prisma.CampaignItemCreateOrConnectWithoutCampaignInput | Prisma.CampaignItemCreateOrConnectWithoutCampaignInput[] + createMany?: Prisma.CampaignItemCreateManyCampaignInputEnvelope + connect?: Prisma.CampaignItemWhereUniqueInput | Prisma.CampaignItemWhereUniqueInput[] +} + +export type CampaignItemUpdateManyWithoutCampaignNestedInput = { + create?: Prisma.XOR | Prisma.CampaignItemCreateWithoutCampaignInput[] | Prisma.CampaignItemUncheckedCreateWithoutCampaignInput[] + connectOrCreate?: Prisma.CampaignItemCreateOrConnectWithoutCampaignInput | Prisma.CampaignItemCreateOrConnectWithoutCampaignInput[] + upsert?: Prisma.CampaignItemUpsertWithWhereUniqueWithoutCampaignInput | Prisma.CampaignItemUpsertWithWhereUniqueWithoutCampaignInput[] + createMany?: Prisma.CampaignItemCreateManyCampaignInputEnvelope + set?: Prisma.CampaignItemWhereUniqueInput | Prisma.CampaignItemWhereUniqueInput[] + disconnect?: Prisma.CampaignItemWhereUniqueInput | Prisma.CampaignItemWhereUniqueInput[] + delete?: Prisma.CampaignItemWhereUniqueInput | Prisma.CampaignItemWhereUniqueInput[] + connect?: Prisma.CampaignItemWhereUniqueInput | Prisma.CampaignItemWhereUniqueInput[] + update?: Prisma.CampaignItemUpdateWithWhereUniqueWithoutCampaignInput | Prisma.CampaignItemUpdateWithWhereUniqueWithoutCampaignInput[] + updateMany?: Prisma.CampaignItemUpdateManyWithWhereWithoutCampaignInput | Prisma.CampaignItemUpdateManyWithWhereWithoutCampaignInput[] + deleteMany?: Prisma.CampaignItemScalarWhereInput | Prisma.CampaignItemScalarWhereInput[] +} + +export type CampaignItemUncheckedUpdateManyWithoutCampaignNestedInput = { + create?: Prisma.XOR | Prisma.CampaignItemCreateWithoutCampaignInput[] | Prisma.CampaignItemUncheckedCreateWithoutCampaignInput[] + connectOrCreate?: Prisma.CampaignItemCreateOrConnectWithoutCampaignInput | Prisma.CampaignItemCreateOrConnectWithoutCampaignInput[] + upsert?: Prisma.CampaignItemUpsertWithWhereUniqueWithoutCampaignInput | Prisma.CampaignItemUpsertWithWhereUniqueWithoutCampaignInput[] + createMany?: Prisma.CampaignItemCreateManyCampaignInputEnvelope + set?: Prisma.CampaignItemWhereUniqueInput | Prisma.CampaignItemWhereUniqueInput[] + disconnect?: Prisma.CampaignItemWhereUniqueInput | Prisma.CampaignItemWhereUniqueInput[] + delete?: Prisma.CampaignItemWhereUniqueInput | Prisma.CampaignItemWhereUniqueInput[] + connect?: Prisma.CampaignItemWhereUniqueInput | Prisma.CampaignItemWhereUniqueInput[] + update?: Prisma.CampaignItemUpdateWithWhereUniqueWithoutCampaignInput | Prisma.CampaignItemUpdateWithWhereUniqueWithoutCampaignInput[] + updateMany?: Prisma.CampaignItemUpdateManyWithWhereWithoutCampaignInput | Prisma.CampaignItemUpdateManyWithWhereWithoutCampaignInput[] + deleteMany?: Prisma.CampaignItemScalarWhereInput | Prisma.CampaignItemScalarWhereInput[] +} + +export type CampaignItemCreateNestedOneWithoutDonationLineItemsInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.CampaignItemCreateOrConnectWithoutDonationLineItemsInput + connect?: Prisma.CampaignItemWhereUniqueInput +} + +export type CampaignItemUpdateOneRequiredWithoutDonationLineItemsNestedInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.CampaignItemCreateOrConnectWithoutDonationLineItemsInput + upsert?: Prisma.CampaignItemUpsertWithoutDonationLineItemsInput + connect?: Prisma.CampaignItemWhereUniqueInput + update?: Prisma.XOR, Prisma.CampaignItemUncheckedUpdateWithoutDonationLineItemsInput> +} + +export type CampaignItemCreateWithoutCampaignInput = { + id?: string + name: string + description?: string | null + category?: string | null + price: runtime.Decimal | runtime.DecimalJsLike | number | string + maxQuantity?: number | null + minPerOrder?: number + maxPerOrder?: number | null + isRequired?: boolean + sortOrder?: number + isActive?: boolean + donationLineItems?: Prisma.DonationLineItemCreateNestedManyWithoutCampaignItemInput +} + +export type CampaignItemUncheckedCreateWithoutCampaignInput = { + id?: string + name: string + description?: string | null + category?: string | null + price: runtime.Decimal | runtime.DecimalJsLike | number | string + maxQuantity?: number | null + minPerOrder?: number + maxPerOrder?: number | null + isRequired?: boolean + sortOrder?: number + isActive?: boolean + donationLineItems?: Prisma.DonationLineItemUncheckedCreateNestedManyWithoutCampaignItemInput +} + +export type CampaignItemCreateOrConnectWithoutCampaignInput = { + where: Prisma.CampaignItemWhereUniqueInput + create: Prisma.XOR +} + +export type CampaignItemCreateManyCampaignInputEnvelope = { + data: Prisma.CampaignItemCreateManyCampaignInput | Prisma.CampaignItemCreateManyCampaignInput[] + skipDuplicates?: boolean +} + +export type CampaignItemUpsertWithWhereUniqueWithoutCampaignInput = { + where: Prisma.CampaignItemWhereUniqueInput + update: Prisma.XOR + create: Prisma.XOR +} + +export type CampaignItemUpdateWithWhereUniqueWithoutCampaignInput = { + where: Prisma.CampaignItemWhereUniqueInput + data: Prisma.XOR +} + +export type CampaignItemUpdateManyWithWhereWithoutCampaignInput = { + where: Prisma.CampaignItemScalarWhereInput + data: Prisma.XOR +} + +export type CampaignItemScalarWhereInput = { + AND?: Prisma.CampaignItemScalarWhereInput | Prisma.CampaignItemScalarWhereInput[] + OR?: Prisma.CampaignItemScalarWhereInput[] + NOT?: Prisma.CampaignItemScalarWhereInput | Prisma.CampaignItemScalarWhereInput[] + id?: Prisma.StringFilter<"CampaignItem"> | string + campaignId?: Prisma.StringFilter<"CampaignItem"> | string + name?: Prisma.StringFilter<"CampaignItem"> | string + description?: Prisma.StringNullableFilter<"CampaignItem"> | string | null + category?: Prisma.StringNullableFilter<"CampaignItem"> | string | null + price?: Prisma.DecimalFilter<"CampaignItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string + maxQuantity?: Prisma.IntNullableFilter<"CampaignItem"> | number | null + minPerOrder?: Prisma.IntFilter<"CampaignItem"> | number + maxPerOrder?: Prisma.IntNullableFilter<"CampaignItem"> | number | null + isRequired?: Prisma.BoolFilter<"CampaignItem"> | boolean + sortOrder?: Prisma.IntFilter<"CampaignItem"> | number + isActive?: Prisma.BoolFilter<"CampaignItem"> | boolean +} + +export type CampaignItemCreateWithoutDonationLineItemsInput = { + id?: string + name: string + description?: string | null + category?: string | null + price: runtime.Decimal | runtime.DecimalJsLike | number | string + maxQuantity?: number | null + minPerOrder?: number + maxPerOrder?: number | null + isRequired?: boolean + sortOrder?: number + isActive?: boolean + campaign: Prisma.CampaignCreateNestedOneWithoutItemsInput +} + +export type CampaignItemUncheckedCreateWithoutDonationLineItemsInput = { + id?: string + campaignId: string + name: string + description?: string | null + category?: string | null + price: runtime.Decimal | runtime.DecimalJsLike | number | string + maxQuantity?: number | null + minPerOrder?: number + maxPerOrder?: number | null + isRequired?: boolean + sortOrder?: number + isActive?: boolean +} + +export type CampaignItemCreateOrConnectWithoutDonationLineItemsInput = { + where: Prisma.CampaignItemWhereUniqueInput + create: Prisma.XOR +} + +export type CampaignItemUpsertWithoutDonationLineItemsInput = { + update: Prisma.XOR + create: Prisma.XOR + where?: Prisma.CampaignItemWhereInput +} + +export type CampaignItemUpdateToOneWithWhereWithoutDonationLineItemsInput = { + where?: Prisma.CampaignItemWhereInput + data: Prisma.XOR +} + +export type CampaignItemUpdateWithoutDonationLineItemsInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + name?: Prisma.StringFieldUpdateOperationsInput | string + description?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + category?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + maxQuantity?: Prisma.NullableIntFieldUpdateOperationsInput | number | null + minPerOrder?: Prisma.IntFieldUpdateOperationsInput | number + maxPerOrder?: Prisma.NullableIntFieldUpdateOperationsInput | number | null + isRequired?: Prisma.BoolFieldUpdateOperationsInput | boolean + sortOrder?: Prisma.IntFieldUpdateOperationsInput | number + isActive?: Prisma.BoolFieldUpdateOperationsInput | boolean + campaign?: Prisma.CampaignUpdateOneRequiredWithoutItemsNestedInput +} + +export type CampaignItemUncheckedUpdateWithoutDonationLineItemsInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + campaignId?: Prisma.StringFieldUpdateOperationsInput | string + name?: Prisma.StringFieldUpdateOperationsInput | string + description?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + category?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + maxQuantity?: Prisma.NullableIntFieldUpdateOperationsInput | number | null + minPerOrder?: Prisma.IntFieldUpdateOperationsInput | number + maxPerOrder?: Prisma.NullableIntFieldUpdateOperationsInput | number | null + isRequired?: Prisma.BoolFieldUpdateOperationsInput | boolean + sortOrder?: Prisma.IntFieldUpdateOperationsInput | number + isActive?: Prisma.BoolFieldUpdateOperationsInput | boolean +} + +export type CampaignItemCreateManyCampaignInput = { + id?: string + name: string + description?: string | null + category?: string | null + price: runtime.Decimal | runtime.DecimalJsLike | number | string + maxQuantity?: number | null + minPerOrder?: number + maxPerOrder?: number | null + isRequired?: boolean + sortOrder?: number + isActive?: boolean +} + +export type CampaignItemUpdateWithoutCampaignInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + name?: Prisma.StringFieldUpdateOperationsInput | string + description?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + category?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + maxQuantity?: Prisma.NullableIntFieldUpdateOperationsInput | number | null + minPerOrder?: Prisma.IntFieldUpdateOperationsInput | number + maxPerOrder?: Prisma.NullableIntFieldUpdateOperationsInput | number | null + isRequired?: Prisma.BoolFieldUpdateOperationsInput | boolean + sortOrder?: Prisma.IntFieldUpdateOperationsInput | number + isActive?: Prisma.BoolFieldUpdateOperationsInput | boolean + donationLineItems?: Prisma.DonationLineItemUpdateManyWithoutCampaignItemNestedInput +} + +export type CampaignItemUncheckedUpdateWithoutCampaignInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + name?: Prisma.StringFieldUpdateOperationsInput | string + description?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + category?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + maxQuantity?: Prisma.NullableIntFieldUpdateOperationsInput | number | null + minPerOrder?: Prisma.IntFieldUpdateOperationsInput | number + maxPerOrder?: Prisma.NullableIntFieldUpdateOperationsInput | number | null + isRequired?: Prisma.BoolFieldUpdateOperationsInput | boolean + sortOrder?: Prisma.IntFieldUpdateOperationsInput | number + isActive?: Prisma.BoolFieldUpdateOperationsInput | boolean + donationLineItems?: Prisma.DonationLineItemUncheckedUpdateManyWithoutCampaignItemNestedInput +} + +export type CampaignItemUncheckedUpdateManyWithoutCampaignInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + name?: Prisma.StringFieldUpdateOperationsInput | string + description?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + category?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + price?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + maxQuantity?: Prisma.NullableIntFieldUpdateOperationsInput | number | null + minPerOrder?: Prisma.IntFieldUpdateOperationsInput | number + maxPerOrder?: Prisma.NullableIntFieldUpdateOperationsInput | number | null + isRequired?: Prisma.BoolFieldUpdateOperationsInput | boolean + sortOrder?: Prisma.IntFieldUpdateOperationsInput | number + isActive?: Prisma.BoolFieldUpdateOperationsInput | boolean +} + + +/** + * Count Type CampaignItemCountOutputType + */ + +export type CampaignItemCountOutputType = { + donationLineItems: number +} + +export type CampaignItemCountOutputTypeSelect = { + donationLineItems?: boolean | CampaignItemCountOutputTypeCountDonationLineItemsArgs +} + +/** + * CampaignItemCountOutputType without action + */ +export type CampaignItemCountOutputTypeDefaultArgs = { + /** + * Select specific fields to fetch from the CampaignItemCountOutputType + */ + select?: Prisma.CampaignItemCountOutputTypeSelect | null +} + +/** + * CampaignItemCountOutputType without action + */ +export type CampaignItemCountOutputTypeCountDonationLineItemsArgs = { + where?: Prisma.DonationLineItemWhereInput +} + + +export type CampaignItemSelect = runtime.Types.Extensions.GetSelect<{ + id?: boolean + campaignId?: boolean + name?: boolean + description?: boolean + category?: boolean + price?: boolean + maxQuantity?: boolean + minPerOrder?: boolean + maxPerOrder?: boolean + isRequired?: boolean + sortOrder?: boolean + isActive?: boolean + campaign?: boolean | Prisma.CampaignDefaultArgs + donationLineItems?: boolean | Prisma.CampaignItem$donationLineItemsArgs + _count?: boolean | Prisma.CampaignItemCountOutputTypeDefaultArgs +}, ExtArgs["result"]["campaignItem"]> + +export type CampaignItemSelectCreateManyAndReturn = runtime.Types.Extensions.GetSelect<{ + id?: boolean + campaignId?: boolean + name?: boolean + description?: boolean + category?: boolean + price?: boolean + maxQuantity?: boolean + minPerOrder?: boolean + maxPerOrder?: boolean + isRequired?: boolean + sortOrder?: boolean + isActive?: boolean + campaign?: boolean | Prisma.CampaignDefaultArgs +}, ExtArgs["result"]["campaignItem"]> + +export type CampaignItemSelectUpdateManyAndReturn = runtime.Types.Extensions.GetSelect<{ + id?: boolean + campaignId?: boolean + name?: boolean + description?: boolean + category?: boolean + price?: boolean + maxQuantity?: boolean + minPerOrder?: boolean + maxPerOrder?: boolean + isRequired?: boolean + sortOrder?: boolean + isActive?: boolean + campaign?: boolean | Prisma.CampaignDefaultArgs +}, ExtArgs["result"]["campaignItem"]> + +export type CampaignItemSelectScalar = { + id?: boolean + campaignId?: boolean + name?: boolean + description?: boolean + category?: boolean + price?: boolean + maxQuantity?: boolean + minPerOrder?: boolean + maxPerOrder?: boolean + isRequired?: boolean + sortOrder?: boolean + isActive?: boolean +} + +export type CampaignItemOmit = runtime.Types.Extensions.GetOmit<"id" | "campaignId" | "name" | "description" | "category" | "price" | "maxQuantity" | "minPerOrder" | "maxPerOrder" | "isRequired" | "sortOrder" | "isActive", ExtArgs["result"]["campaignItem"]> +export type CampaignItemInclude = { + campaign?: boolean | Prisma.CampaignDefaultArgs + donationLineItems?: boolean | Prisma.CampaignItem$donationLineItemsArgs + _count?: boolean | Prisma.CampaignItemCountOutputTypeDefaultArgs +} +export type CampaignItemIncludeCreateManyAndReturn = { + campaign?: boolean | Prisma.CampaignDefaultArgs +} +export type CampaignItemIncludeUpdateManyAndReturn = { + campaign?: boolean | Prisma.CampaignDefaultArgs +} + +export type $CampaignItemPayload = { + name: "CampaignItem" + objects: { + campaign: Prisma.$CampaignPayload + donationLineItems: Prisma.$DonationLineItemPayload[] + } + scalars: runtime.Types.Extensions.GetPayloadResult<{ + id: string + campaignId: string + name: string + description: string | null + category: string | null + price: runtime.Decimal + maxQuantity: number | null + minPerOrder: number + maxPerOrder: number | null + isRequired: boolean + sortOrder: number + isActive: boolean + }, ExtArgs["result"]["campaignItem"]> + composites: {} +} + +export type CampaignItemGetPayload = runtime.Types.Result.GetResult + +export type CampaignItemCountArgs = + Omit & { + select?: CampaignItemCountAggregateInputType | true + } + +export interface CampaignItemDelegate { + [K: symbol]: { types: Prisma.TypeMap['model']['CampaignItem'], meta: { name: 'CampaignItem' } } + /** + * Find zero or one CampaignItem that matches the filter. + * @param {CampaignItemFindUniqueArgs} args - Arguments to find a CampaignItem + * @example + * // Get one CampaignItem + * const campaignItem = await prisma.campaignItem.findUnique({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUnique(args: Prisma.SelectSubset>): Prisma.Prisma__CampaignItemClient, T, "findUnique", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + + /** + * Find one CampaignItem that matches the filter or throw an error with `error.code='P2025'` + * if no matches were found. + * @param {CampaignItemFindUniqueOrThrowArgs} args - Arguments to find a CampaignItem + * @example + * // Get one CampaignItem + * const campaignItem = await prisma.campaignItem.findUniqueOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUniqueOrThrow(args: Prisma.SelectSubset>): Prisma.Prisma__CampaignItemClient, T, "findUniqueOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Find the first CampaignItem that matches the filter. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {CampaignItemFindFirstArgs} args - Arguments to find a CampaignItem + * @example + * // Get one CampaignItem + * const campaignItem = await prisma.campaignItem.findFirst({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirst(args?: Prisma.SelectSubset>): Prisma.Prisma__CampaignItemClient, T, "findFirst", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + + /** + * Find the first CampaignItem that matches the filter or + * throw `PrismaKnownClientError` with `P2025` code if no matches were found. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {CampaignItemFindFirstOrThrowArgs} args - Arguments to find a CampaignItem + * @example + * // Get one CampaignItem + * const campaignItem = await prisma.campaignItem.findFirstOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirstOrThrow(args?: Prisma.SelectSubset>): Prisma.Prisma__CampaignItemClient, T, "findFirstOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Find zero or more CampaignItems that matches the filter. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {CampaignItemFindManyArgs} args - Arguments to filter and select certain fields only. + * @example + * // Get all CampaignItems + * const campaignItems = await prisma.campaignItem.findMany() + * + * // Get first 10 CampaignItems + * const campaignItems = await prisma.campaignItem.findMany({ take: 10 }) + * + * // Only select the `id` + * const campaignItemWithIdOnly = await prisma.campaignItem.findMany({ select: { id: true } }) + * + */ + findMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions>> + + /** + * Create a CampaignItem. + * @param {CampaignItemCreateArgs} args - Arguments to create a CampaignItem. + * @example + * // Create one CampaignItem + * const CampaignItem = await prisma.campaignItem.create({ + * data: { + * // ... data to create a CampaignItem + * } + * }) + * + */ + create(args: Prisma.SelectSubset>): Prisma.Prisma__CampaignItemClient, T, "create", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Create many CampaignItems. + * @param {CampaignItemCreateManyArgs} args - Arguments to create many CampaignItems. + * @example + * // Create many CampaignItems + * const campaignItem = await prisma.campaignItem.createMany({ + * data: [ + * // ... provide data here + * ] + * }) + * + */ + createMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Create many CampaignItems and returns the data saved in the database. + * @param {CampaignItemCreateManyAndReturnArgs} args - Arguments to create many CampaignItems. + * @example + * // Create many CampaignItems + * const campaignItem = await prisma.campaignItem.createManyAndReturn({ + * data: [ + * // ... provide data here + * ] + * }) + * + * // Create many CampaignItems and only return the `id` + * const campaignItemWithIdOnly = await prisma.campaignItem.createManyAndReturn({ + * select: { id: true }, + * data: [ + * // ... provide data here + * ] + * }) + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * + */ + createManyAndReturn(args?: Prisma.SelectSubset>): Prisma.PrismaPromise, T, "createManyAndReturn", GlobalOmitOptions>> + + /** + * Delete a CampaignItem. + * @param {CampaignItemDeleteArgs} args - Arguments to delete one CampaignItem. + * @example + * // Delete one CampaignItem + * const CampaignItem = await prisma.campaignItem.delete({ + * where: { + * // ... filter to delete one CampaignItem + * } + * }) + * + */ + delete(args: Prisma.SelectSubset>): Prisma.Prisma__CampaignItemClient, T, "delete", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Update one CampaignItem. + * @param {CampaignItemUpdateArgs} args - Arguments to update one CampaignItem. + * @example + * // Update one CampaignItem + * const campaignItem = await prisma.campaignItem.update({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + update(args: Prisma.SelectSubset>): Prisma.Prisma__CampaignItemClient, T, "update", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Delete zero or more CampaignItems. + * @param {CampaignItemDeleteManyArgs} args - Arguments to filter CampaignItems to delete. + * @example + * // Delete a few CampaignItems + * const { count } = await prisma.campaignItem.deleteMany({ + * where: { + * // ... provide filter here + * } + * }) + * + */ + deleteMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Update zero or more CampaignItems. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {CampaignItemUpdateManyArgs} args - Arguments to update one or more rows. + * @example + * // Update many CampaignItems + * const campaignItem = await prisma.campaignItem.updateMany({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + updateMany(args: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Update zero or more CampaignItems and returns the data updated in the database. + * @param {CampaignItemUpdateManyAndReturnArgs} args - Arguments to update many CampaignItems. + * @example + * // Update many CampaignItems + * const campaignItem = await prisma.campaignItem.updateManyAndReturn({ + * where: { + * // ... provide filter here + * }, + * data: [ + * // ... provide data here + * ] + * }) + * + * // Update zero or more CampaignItems and only return the `id` + * const campaignItemWithIdOnly = await prisma.campaignItem.updateManyAndReturn({ + * select: { id: true }, + * where: { + * // ... provide filter here + * }, + * data: [ + * // ... provide data here + * ] + * }) + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * + */ + updateManyAndReturn(args: Prisma.SelectSubset>): Prisma.PrismaPromise, T, "updateManyAndReturn", GlobalOmitOptions>> + + /** + * Create or update one CampaignItem. + * @param {CampaignItemUpsertArgs} args - Arguments to update or create a CampaignItem. + * @example + * // Update or create a CampaignItem + * const campaignItem = await prisma.campaignItem.upsert({ + * create: { + * // ... data to create a CampaignItem + * }, + * update: { + * // ... in case it already exists, update + * }, + * where: { + * // ... the filter for the CampaignItem we want to update + * } + * }) + */ + upsert(args: Prisma.SelectSubset>): Prisma.Prisma__CampaignItemClient, T, "upsert", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + + /** + * Count the number of CampaignItems. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {CampaignItemCountArgs} args - Arguments to filter CampaignItems to count. + * @example + * // Count the number of CampaignItems + * const count = await prisma.campaignItem.count({ + * where: { + * // ... the filter for the CampaignItems we want to count + * } + * }) + **/ + count( + args?: Prisma.Subset, + ): Prisma.PrismaPromise< + T extends runtime.Types.Utils.Record<'select', any> + ? T['select'] extends true + ? number + : Prisma.GetScalarType + : number + > + + /** + * Allows you to perform aggregations operations on a CampaignItem. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {CampaignItemAggregateArgs} args - Select which aggregations you would like to apply and on what fields. + * @example + * // Ordered by age ascending + * // Where email contains prisma.io + * // Limited to the 10 users + * const aggregations = await prisma.user.aggregate({ + * _avg: { + * age: true, + * }, + * where: { + * email: { + * contains: "prisma.io", + * }, + * }, + * orderBy: { + * age: "asc", + * }, + * take: 10, + * }) + **/ + aggregate(args: Prisma.Subset): Prisma.PrismaPromise> + + /** + * Group by CampaignItem. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {CampaignItemGroupByArgs} args - Group by arguments. + * @example + * // Group by city, order by createdAt, get count + * const result = await prisma.user.groupBy({ + * by: ['city', 'createdAt'], + * orderBy: { + * createdAt: true + * }, + * _count: { + * _all: true + * }, + * }) + * + **/ + groupBy< + T extends CampaignItemGroupByArgs, + HasSelectOrTake extends Prisma.Or< + Prisma.Extends<'skip', Prisma.Keys>, + Prisma.Extends<'take', Prisma.Keys> + >, + OrderByArg extends Prisma.True extends HasSelectOrTake + ? { orderBy: CampaignItemGroupByArgs['orderBy'] } + : { orderBy?: CampaignItemGroupByArgs['orderBy'] }, + OrderFields extends Prisma.ExcludeUnderscoreKeys>>, + ByFields extends Prisma.MaybeTupleToUnion, + ByValid extends Prisma.Has, + HavingFields extends Prisma.GetHavingFields, + HavingValid extends Prisma.Has, + ByEmpty extends T['by'] extends never[] ? Prisma.True : Prisma.False, + InputErrors extends ByEmpty extends Prisma.True + ? `Error: "by" must not be empty.` + : HavingValid extends Prisma.False + ? { + [P in HavingFields]: P extends ByFields + ? never + : P extends string + ? `Error: Field "${P}" used in "having" needs to be provided in "by".` + : [ + Error, + 'Field ', + P, + ` in "having" needs to be provided in "by"`, + ] + }[HavingFields] + : 'take' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "take", you also need to provide "orderBy"' + : 'skip' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "skip", you also need to provide "orderBy"' + : ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + >(args: Prisma.SubsetIntersection & InputErrors): {} extends InputErrors ? GetCampaignItemGroupByPayload : Prisma.PrismaPromise +/** + * Fields of the CampaignItem model + */ +readonly fields: CampaignItemFieldRefs; +} + +/** + * The delegate class that acts as a "Promise-like" for CampaignItem. + * Why is this prefixed with `Prisma__`? + * Because we want to prevent naming conflicts as mentioned in + * https://github.com/prisma/prisma-client-js/issues/707 + */ +export interface Prisma__CampaignItemClient extends Prisma.PrismaPromise { + readonly [Symbol.toStringTag]: "PrismaPromise" + campaign = {}>(args?: Prisma.Subset>): Prisma.Prisma__CampaignClient, T, "findUniqueOrThrow", GlobalOmitOptions> | Null, Null, ExtArgs, GlobalOmitOptions> + donationLineItems = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions> | Null> + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): runtime.Types.Utils.JsPromise + /** + * Attaches a callback for only the rejection of the Promise. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of the callback. + */ + catch(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): runtime.Types.Utils.JsPromise + /** + * Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The + * resolved value cannot be modified from the callback. + * @param onfinally The callback to execute when the Promise is settled (fulfilled or rejected). + * @returns A Promise for the completion of the callback. + */ + finally(onfinally?: (() => void) | undefined | null): runtime.Types.Utils.JsPromise +} + + + + +/** + * Fields of the CampaignItem model + */ +export interface CampaignItemFieldRefs { + readonly id: Prisma.FieldRef<"CampaignItem", 'String'> + readonly campaignId: Prisma.FieldRef<"CampaignItem", 'String'> + readonly name: Prisma.FieldRef<"CampaignItem", 'String'> + readonly description: Prisma.FieldRef<"CampaignItem", 'String'> + readonly category: Prisma.FieldRef<"CampaignItem", 'String'> + readonly price: Prisma.FieldRef<"CampaignItem", 'Decimal'> + readonly maxQuantity: Prisma.FieldRef<"CampaignItem", 'Int'> + readonly minPerOrder: Prisma.FieldRef<"CampaignItem", 'Int'> + readonly maxPerOrder: Prisma.FieldRef<"CampaignItem", 'Int'> + readonly isRequired: Prisma.FieldRef<"CampaignItem", 'Boolean'> + readonly sortOrder: Prisma.FieldRef<"CampaignItem", 'Int'> + readonly isActive: Prisma.FieldRef<"CampaignItem", 'Boolean'> +} + + +// Custom InputTypes +/** + * CampaignItem findUnique + */ +export type CampaignItemFindUniqueArgs = { + /** + * Select specific fields to fetch from the CampaignItem + */ + select?: Prisma.CampaignItemSelect | null + /** + * Omit specific fields from the CampaignItem + */ + omit?: Prisma.CampaignItemOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.CampaignItemInclude | null + /** + * Filter, which CampaignItem to fetch. + */ + where: Prisma.CampaignItemWhereUniqueInput +} + +/** + * CampaignItem findUniqueOrThrow + */ +export type CampaignItemFindUniqueOrThrowArgs = { + /** + * Select specific fields to fetch from the CampaignItem + */ + select?: Prisma.CampaignItemSelect | null + /** + * Omit specific fields from the CampaignItem + */ + omit?: Prisma.CampaignItemOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.CampaignItemInclude | null + /** + * Filter, which CampaignItem to fetch. + */ + where: Prisma.CampaignItemWhereUniqueInput +} + +/** + * CampaignItem findFirst + */ +export type CampaignItemFindFirstArgs = { + /** + * Select specific fields to fetch from the CampaignItem + */ + select?: Prisma.CampaignItemSelect | null + /** + * Omit specific fields from the CampaignItem + */ + omit?: Prisma.CampaignItemOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.CampaignItemInclude | null + /** + * Filter, which CampaignItem to fetch. + */ + where?: Prisma.CampaignItemWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of CampaignItems to fetch. + */ + orderBy?: Prisma.CampaignItemOrderByWithRelationInput | Prisma.CampaignItemOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for CampaignItems. + */ + cursor?: Prisma.CampaignItemWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` CampaignItems from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` CampaignItems. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of CampaignItems. + */ + distinct?: Prisma.CampaignItemScalarFieldEnum | Prisma.CampaignItemScalarFieldEnum[] +} + +/** + * CampaignItem findFirstOrThrow + */ +export type CampaignItemFindFirstOrThrowArgs = { + /** + * Select specific fields to fetch from the CampaignItem + */ + select?: Prisma.CampaignItemSelect | null + /** + * Omit specific fields from the CampaignItem + */ + omit?: Prisma.CampaignItemOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.CampaignItemInclude | null + /** + * Filter, which CampaignItem to fetch. + */ + where?: Prisma.CampaignItemWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of CampaignItems to fetch. + */ + orderBy?: Prisma.CampaignItemOrderByWithRelationInput | Prisma.CampaignItemOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for CampaignItems. + */ + cursor?: Prisma.CampaignItemWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` CampaignItems from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` CampaignItems. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of CampaignItems. + */ + distinct?: Prisma.CampaignItemScalarFieldEnum | Prisma.CampaignItemScalarFieldEnum[] +} + +/** + * CampaignItem findMany + */ +export type CampaignItemFindManyArgs = { + /** + * Select specific fields to fetch from the CampaignItem + */ + select?: Prisma.CampaignItemSelect | null + /** + * Omit specific fields from the CampaignItem + */ + omit?: Prisma.CampaignItemOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.CampaignItemInclude | null + /** + * Filter, which CampaignItems to fetch. + */ + where?: Prisma.CampaignItemWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of CampaignItems to fetch. + */ + orderBy?: Prisma.CampaignItemOrderByWithRelationInput | Prisma.CampaignItemOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for listing CampaignItems. + */ + cursor?: Prisma.CampaignItemWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` CampaignItems from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` CampaignItems. + */ + skip?: number + distinct?: Prisma.CampaignItemScalarFieldEnum | Prisma.CampaignItemScalarFieldEnum[] +} + +/** + * CampaignItem create + */ +export type CampaignItemCreateArgs = { + /** + * Select specific fields to fetch from the CampaignItem + */ + select?: Prisma.CampaignItemSelect | null + /** + * Omit specific fields from the CampaignItem + */ + omit?: Prisma.CampaignItemOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.CampaignItemInclude | null + /** + * The data needed to create a CampaignItem. + */ + data: Prisma.XOR +} + +/** + * CampaignItem createMany + */ +export type CampaignItemCreateManyArgs = { + /** + * The data used to create many CampaignItems. + */ + data: Prisma.CampaignItemCreateManyInput | Prisma.CampaignItemCreateManyInput[] + skipDuplicates?: boolean +} + +/** + * CampaignItem createManyAndReturn + */ +export type CampaignItemCreateManyAndReturnArgs = { + /** + * Select specific fields to fetch from the CampaignItem + */ + select?: Prisma.CampaignItemSelectCreateManyAndReturn | null + /** + * Omit specific fields from the CampaignItem + */ + omit?: Prisma.CampaignItemOmit | null + /** + * The data used to create many CampaignItems. + */ + data: Prisma.CampaignItemCreateManyInput | Prisma.CampaignItemCreateManyInput[] + skipDuplicates?: boolean + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.CampaignItemIncludeCreateManyAndReturn | null +} + +/** + * CampaignItem update + */ +export type CampaignItemUpdateArgs = { + /** + * Select specific fields to fetch from the CampaignItem + */ + select?: Prisma.CampaignItemSelect | null + /** + * Omit specific fields from the CampaignItem + */ + omit?: Prisma.CampaignItemOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.CampaignItemInclude | null + /** + * The data needed to update a CampaignItem. + */ + data: Prisma.XOR + /** + * Choose, which CampaignItem to update. + */ + where: Prisma.CampaignItemWhereUniqueInput +} + +/** + * CampaignItem updateMany + */ +export type CampaignItemUpdateManyArgs = { + /** + * The data used to update CampaignItems. + */ + data: Prisma.XOR + /** + * Filter which CampaignItems to update + */ + where?: Prisma.CampaignItemWhereInput + /** + * Limit how many CampaignItems to update. + */ + limit?: number +} + +/** + * CampaignItem updateManyAndReturn + */ +export type CampaignItemUpdateManyAndReturnArgs = { + /** + * Select specific fields to fetch from the CampaignItem + */ + select?: Prisma.CampaignItemSelectUpdateManyAndReturn | null + /** + * Omit specific fields from the CampaignItem + */ + omit?: Prisma.CampaignItemOmit | null + /** + * The data used to update CampaignItems. + */ + data: Prisma.XOR + /** + * Filter which CampaignItems to update + */ + where?: Prisma.CampaignItemWhereInput + /** + * Limit how many CampaignItems to update. + */ + limit?: number + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.CampaignItemIncludeUpdateManyAndReturn | null +} + +/** + * CampaignItem upsert + */ +export type CampaignItemUpsertArgs = { + /** + * Select specific fields to fetch from the CampaignItem + */ + select?: Prisma.CampaignItemSelect | null + /** + * Omit specific fields from the CampaignItem + */ + omit?: Prisma.CampaignItemOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.CampaignItemInclude | null + /** + * The filter to search for the CampaignItem to update in case it exists. + */ + where: Prisma.CampaignItemWhereUniqueInput + /** + * In case the CampaignItem found by the `where` argument doesn't exist, create a new CampaignItem with this data. + */ + create: Prisma.XOR + /** + * In case the CampaignItem was found with the provided `where` argument, update it with this data. + */ + update: Prisma.XOR +} + +/** + * CampaignItem delete + */ +export type CampaignItemDeleteArgs = { + /** + * Select specific fields to fetch from the CampaignItem + */ + select?: Prisma.CampaignItemSelect | null + /** + * Omit specific fields from the CampaignItem + */ + omit?: Prisma.CampaignItemOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.CampaignItemInclude | null + /** + * Filter which CampaignItem to delete. + */ + where: Prisma.CampaignItemWhereUniqueInput +} + +/** + * CampaignItem deleteMany + */ +export type CampaignItemDeleteManyArgs = { + /** + * Filter which CampaignItems to delete + */ + where?: Prisma.CampaignItemWhereInput + /** + * Limit how many CampaignItems to delete. + */ + limit?: number +} + +/** + * CampaignItem.donationLineItems + */ +export type CampaignItem$donationLineItemsArgs = { + /** + * Select specific fields to fetch from the DonationLineItem + */ + select?: Prisma.DonationLineItemSelect | null + /** + * Omit specific fields from the DonationLineItem + */ + omit?: Prisma.DonationLineItemOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.DonationLineItemInclude | null + where?: Prisma.DonationLineItemWhereInput + orderBy?: Prisma.DonationLineItemOrderByWithRelationInput | Prisma.DonationLineItemOrderByWithRelationInput[] + cursor?: Prisma.DonationLineItemWhereUniqueInput + take?: number + skip?: number + distinct?: Prisma.DonationLineItemScalarFieldEnum | Prisma.DonationLineItemScalarFieldEnum[] +} + +/** + * CampaignItem without action + */ +export type CampaignItemDefaultArgs = { + /** + * Select specific fields to fetch from the CampaignItem + */ + select?: Prisma.CampaignItemSelect | null + /** + * Omit specific fields from the CampaignItem + */ + omit?: Prisma.CampaignItemOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.CampaignItemInclude | null +} diff --git a/src/generated/prisma/models/Donation.ts b/src/generated/prisma/models/Donation.ts index d4b918d..c9c2090 100644 --- a/src/generated/prisma/models/Donation.ts +++ b/src/generated/prisma/models/Donation.ts @@ -370,6 +370,7 @@ export type DonationWhereInput = { updatedAt?: Prisma.DateTimeFilter<"Donation"> | Date | string campaign?: Prisma.XOR | null tier?: Prisma.XOR | null + lineItems?: Prisma.DonationLineItemListRelationFilter } export type DonationOrderByWithRelationInput = { @@ -398,6 +399,7 @@ export type DonationOrderByWithRelationInput = { updatedAt?: Prisma.SortOrder campaign?: Prisma.CampaignOrderByWithRelationInput tier?: Prisma.CampaignTierOrderByWithRelationInput + lineItems?: Prisma.DonationLineItemOrderByRelationAggregateInput } export type DonationWhereUniqueInput = Prisma.AtLeast<{ @@ -429,6 +431,7 @@ export type DonationWhereUniqueInput = Prisma.AtLeast<{ updatedAt?: Prisma.DateTimeFilter<"Donation"> | Date | string campaign?: Prisma.XOR | null tier?: Prisma.XOR | null + lineItems?: Prisma.DonationLineItemListRelationFilter }, "id" | "transactionId" | "billId"> export type DonationOrderByWithAggregationInput = { @@ -515,6 +518,7 @@ export type DonationCreateInput = { updatedAt?: Date | string campaign?: Prisma.CampaignCreateNestedOneWithoutDonationsInput tier?: Prisma.CampaignTierCreateNestedOneWithoutDonationsInput + lineItems?: Prisma.DonationLineItemCreateNestedManyWithoutDonationInput } export type DonationUncheckedCreateInput = { @@ -541,6 +545,7 @@ export type DonationUncheckedCreateInput = { createdBy?: string | null createdAt?: Date | string updatedAt?: Date | string + lineItems?: Prisma.DonationLineItemUncheckedCreateNestedManyWithoutDonationInput } export type DonationUpdateInput = { @@ -567,6 +572,7 @@ export type DonationUpdateInput = { updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string campaign?: Prisma.CampaignUpdateOneWithoutDonationsNestedInput tier?: Prisma.CampaignTierUpdateOneWithoutDonationsNestedInput + lineItems?: Prisma.DonationLineItemUpdateManyWithoutDonationNestedInput } export type DonationUncheckedUpdateInput = { @@ -593,6 +599,7 @@ export type DonationUncheckedUpdateInput = { createdBy?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + lineItems?: Prisma.DonationLineItemUncheckedUpdateManyWithoutDonationNestedInput } export type DonationCreateManyInput = { @@ -771,6 +778,11 @@ export type DonationSumOrderByAggregateInput = { unitCount?: Prisma.SortOrder } +export type DonationScalarRelationFilter = { + is?: Prisma.DonationWhereInput + isNot?: Prisma.DonationWhereInput +} + export type DonationCreateNestedManyWithoutCampaignInput = { create?: Prisma.XOR | Prisma.DonationCreateWithoutCampaignInput[] | Prisma.DonationUncheckedCreateWithoutCampaignInput[] connectOrCreate?: Prisma.DonationCreateOrConnectWithoutCampaignInput | Prisma.DonationCreateOrConnectWithoutCampaignInput[] @@ -863,6 +875,20 @@ export type EnumDonationStatusFieldUpdateOperationsInput = { set?: $Enums.DonationStatus } +export type DonationCreateNestedOneWithoutLineItemsInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.DonationCreateOrConnectWithoutLineItemsInput + connect?: Prisma.DonationWhereUniqueInput +} + +export type DonationUpdateOneRequiredWithoutLineItemsNestedInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.DonationCreateOrConnectWithoutLineItemsInput + upsert?: Prisma.DonationUpsertWithoutLineItemsInput + connect?: Prisma.DonationWhereUniqueInput + update?: Prisma.XOR, Prisma.DonationUncheckedUpdateWithoutLineItemsInput> +} + export type DonationCreateWithoutCampaignInput = { id?: string organizationId: string @@ -886,6 +912,7 @@ export type DonationCreateWithoutCampaignInput = { createdAt?: Date | string updatedAt?: Date | string tier?: Prisma.CampaignTierCreateNestedOneWithoutDonationsInput + lineItems?: Prisma.DonationLineItemCreateNestedManyWithoutDonationInput } export type DonationUncheckedCreateWithoutCampaignInput = { @@ -911,6 +938,7 @@ export type DonationUncheckedCreateWithoutCampaignInput = { createdBy?: string | null createdAt?: Date | string updatedAt?: Date | string + lineItems?: Prisma.DonationLineItemUncheckedCreateNestedManyWithoutDonationInput } export type DonationCreateOrConnectWithoutCampaignInput = { @@ -991,6 +1019,7 @@ export type DonationCreateWithoutTierInput = { createdAt?: Date | string updatedAt?: Date | string campaign?: Prisma.CampaignCreateNestedOneWithoutDonationsInput + lineItems?: Prisma.DonationLineItemCreateNestedManyWithoutDonationInput } export type DonationUncheckedCreateWithoutTierInput = { @@ -1016,6 +1045,7 @@ export type DonationUncheckedCreateWithoutTierInput = { createdBy?: string | null createdAt?: Date | string updatedAt?: Date | string + lineItems?: Prisma.DonationLineItemUncheckedCreateNestedManyWithoutDonationInput } export type DonationCreateOrConnectWithoutTierInput = { @@ -1044,6 +1074,126 @@ export type DonationUpdateManyWithWhereWithoutTierInput = { data: Prisma.XOR } +export type DonationCreateWithoutLineItemsInput = { + id?: string + organizationId: string + contactId: string + type?: $Enums.DonationType + status?: $Enums.DonationStatus + amount: runtime.Decimal | runtime.DecimalJsLike | number | string + amountReceived?: runtime.Decimal | runtime.DecimalJsLike | number | string + description?: string | null + donorMessage?: string | null + isAnonymous?: boolean + isTaxDeductible?: boolean + donationDate: Date | string + receivedDate?: Date | string | null + dueDate?: Date | string | null + unitCount?: number | null + transactionId?: string | null + billId?: string | null + paymentMethod?: $Enums.PaymentMethod | null + createdBy?: string | null + createdAt?: Date | string + updatedAt?: Date | string + campaign?: Prisma.CampaignCreateNestedOneWithoutDonationsInput + tier?: Prisma.CampaignTierCreateNestedOneWithoutDonationsInput +} + +export type DonationUncheckedCreateWithoutLineItemsInput = { + id?: string + organizationId: string + contactId: string + type?: $Enums.DonationType + status?: $Enums.DonationStatus + amount: runtime.Decimal | runtime.DecimalJsLike | number | string + amountReceived?: runtime.Decimal | runtime.DecimalJsLike | number | string + description?: string | null + donorMessage?: string | null + isAnonymous?: boolean + isTaxDeductible?: boolean + donationDate: Date | string + receivedDate?: Date | string | null + dueDate?: Date | string | null + campaignId?: string | null + unitCount?: number | null + tierId?: string | null + transactionId?: string | null + billId?: string | null + paymentMethod?: $Enums.PaymentMethod | null + createdBy?: string | null + createdAt?: Date | string + updatedAt?: Date | string +} + +export type DonationCreateOrConnectWithoutLineItemsInput = { + where: Prisma.DonationWhereUniqueInput + create: Prisma.XOR +} + +export type DonationUpsertWithoutLineItemsInput = { + update: Prisma.XOR + create: Prisma.XOR + where?: Prisma.DonationWhereInput +} + +export type DonationUpdateToOneWithWhereWithoutLineItemsInput = { + where?: Prisma.DonationWhereInput + data: Prisma.XOR +} + +export type DonationUpdateWithoutLineItemsInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + organizationId?: Prisma.StringFieldUpdateOperationsInput | string + contactId?: Prisma.StringFieldUpdateOperationsInput | string + type?: Prisma.EnumDonationTypeFieldUpdateOperationsInput | $Enums.DonationType + status?: Prisma.EnumDonationStatusFieldUpdateOperationsInput | $Enums.DonationStatus + amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + amountReceived?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + description?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + donorMessage?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + isAnonymous?: Prisma.BoolFieldUpdateOperationsInput | boolean + isTaxDeductible?: Prisma.BoolFieldUpdateOperationsInput | boolean + donationDate?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + receivedDate?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + dueDate?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + unitCount?: Prisma.NullableIntFieldUpdateOperationsInput | number | null + transactionId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + billId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + paymentMethod?: Prisma.NullableEnumPaymentMethodFieldUpdateOperationsInput | $Enums.PaymentMethod | null + createdBy?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + campaign?: Prisma.CampaignUpdateOneWithoutDonationsNestedInput + tier?: Prisma.CampaignTierUpdateOneWithoutDonationsNestedInput +} + +export type DonationUncheckedUpdateWithoutLineItemsInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + organizationId?: Prisma.StringFieldUpdateOperationsInput | string + contactId?: Prisma.StringFieldUpdateOperationsInput | string + type?: Prisma.EnumDonationTypeFieldUpdateOperationsInput | $Enums.DonationType + status?: Prisma.EnumDonationStatusFieldUpdateOperationsInput | $Enums.DonationStatus + amount?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + amountReceived?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + description?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + donorMessage?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + isAnonymous?: Prisma.BoolFieldUpdateOperationsInput | boolean + isTaxDeductible?: Prisma.BoolFieldUpdateOperationsInput | boolean + donationDate?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + receivedDate?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + dueDate?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + campaignId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + unitCount?: Prisma.NullableIntFieldUpdateOperationsInput | number | null + tierId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + transactionId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + billId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + paymentMethod?: Prisma.NullableEnumPaymentMethodFieldUpdateOperationsInput | $Enums.PaymentMethod | null + createdBy?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + export type DonationCreateManyCampaignInput = { id?: string organizationId: string @@ -1092,6 +1242,7 @@ export type DonationUpdateWithoutCampaignInput = { createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string tier?: Prisma.CampaignTierUpdateOneWithoutDonationsNestedInput + lineItems?: Prisma.DonationLineItemUpdateManyWithoutDonationNestedInput } export type DonationUncheckedUpdateWithoutCampaignInput = { @@ -1117,6 +1268,7 @@ export type DonationUncheckedUpdateWithoutCampaignInput = { createdBy?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + lineItems?: Prisma.DonationLineItemUncheckedUpdateManyWithoutDonationNestedInput } export type DonationUncheckedUpdateManyWithoutCampaignInput = { @@ -1192,6 +1344,7 @@ export type DonationUpdateWithoutTierInput = { createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string campaign?: Prisma.CampaignUpdateOneWithoutDonationsNestedInput + lineItems?: Prisma.DonationLineItemUpdateManyWithoutDonationNestedInput } export type DonationUncheckedUpdateWithoutTierInput = { @@ -1217,6 +1370,7 @@ export type DonationUncheckedUpdateWithoutTierInput = { createdBy?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + lineItems?: Prisma.DonationLineItemUncheckedUpdateManyWithoutDonationNestedInput } export type DonationUncheckedUpdateManyWithoutTierInput = { @@ -1245,6 +1399,35 @@ export type DonationUncheckedUpdateManyWithoutTierInput = { } +/** + * Count Type DonationCountOutputType + */ + +export type DonationCountOutputType = { + lineItems: number +} + +export type DonationCountOutputTypeSelect = { + lineItems?: boolean | DonationCountOutputTypeCountLineItemsArgs +} + +/** + * DonationCountOutputType without action + */ +export type DonationCountOutputTypeDefaultArgs = { + /** + * Select specific fields to fetch from the DonationCountOutputType + */ + select?: Prisma.DonationCountOutputTypeSelect | null +} + +/** + * DonationCountOutputType without action + */ +export type DonationCountOutputTypeCountLineItemsArgs = { + where?: Prisma.DonationLineItemWhereInput +} + export type DonationSelect = runtime.Types.Extensions.GetSelect<{ id?: boolean @@ -1272,6 +1455,8 @@ export type DonationSelect tier?: boolean | Prisma.Donation$tierArgs + lineItems?: boolean | Prisma.Donation$lineItemsArgs + _count?: boolean | Prisma.DonationCountOutputTypeDefaultArgs }, ExtArgs["result"]["donation"]> export type DonationSelectCreateManyAndReturn = runtime.Types.Extensions.GetSelect<{ @@ -1360,6 +1545,8 @@ export type DonationOmit = { campaign?: boolean | Prisma.Donation$campaignArgs tier?: boolean | Prisma.Donation$tierArgs + lineItems?: boolean | Prisma.Donation$lineItemsArgs + _count?: boolean | Prisma.DonationCountOutputTypeDefaultArgs } export type DonationIncludeCreateManyAndReturn = { campaign?: boolean | Prisma.Donation$campaignArgs @@ -1375,6 +1562,7 @@ export type $DonationPayload | null tier: Prisma.$CampaignTierPayload | null + lineItems: Prisma.$DonationLineItemPayload[] } scalars: runtime.Types.Extensions.GetPayloadResult<{ id: string @@ -1796,6 +1984,7 @@ export interface Prisma__DonationClient = {}>(args?: Prisma.Subset>): Prisma.Prisma__CampaignClient, T, "findUniqueOrThrow", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> tier = {}>(args?: Prisma.Subset>): Prisma.Prisma__CampaignTierClient, T, "findUniqueOrThrow", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + lineItems = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions> | Null> /** * Attaches callbacks for the resolution and/or rejection of the Promise. * @param onfulfilled The callback to execute when the Promise is resolved. @@ -2281,6 +2470,30 @@ export type Donation$tierArgs = { + /** + * Select specific fields to fetch from the DonationLineItem + */ + select?: Prisma.DonationLineItemSelect | null + /** + * Omit specific fields from the DonationLineItem + */ + omit?: Prisma.DonationLineItemOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.DonationLineItemInclude | null + where?: Prisma.DonationLineItemWhereInput + orderBy?: Prisma.DonationLineItemOrderByWithRelationInput | Prisma.DonationLineItemOrderByWithRelationInput[] + cursor?: Prisma.DonationLineItemWhereUniqueInput + take?: number + skip?: number + distinct?: Prisma.DonationLineItemScalarFieldEnum | Prisma.DonationLineItemScalarFieldEnum[] +} + /** * Donation without action */ diff --git a/src/generated/prisma/models/DonationLineItem.ts b/src/generated/prisma/models/DonationLineItem.ts new file mode 100644 index 0000000..9513552 --- /dev/null +++ b/src/generated/prisma/models/DonationLineItem.ts @@ -0,0 +1,1557 @@ + +/* !!! This is code generated by Prisma. Do not edit directly. !!! */ +/* eslint-disable */ +// biome-ignore-all lint: generated file +// @ts-nocheck +/* + * This file exports the `DonationLineItem` model and its related types. + * + * 🟢 You can import this file directly. + */ +import type * as runtime from "@prisma/client/runtime/client" +import type * as $Enums from "../enums" +import type * as Prisma from "../internal/prismaNamespace" + +/** + * Model DonationLineItem + * + */ +export type DonationLineItemModel = runtime.Types.Result.DefaultSelection + +export type AggregateDonationLineItem = { + _count: DonationLineItemCountAggregateOutputType | null + _avg: DonationLineItemAvgAggregateOutputType | null + _sum: DonationLineItemSumAggregateOutputType | null + _min: DonationLineItemMinAggregateOutputType | null + _max: DonationLineItemMaxAggregateOutputType | null +} + +export type DonationLineItemAvgAggregateOutputType = { + quantity: number | null + unitPrice: runtime.Decimal | null + subtotal: runtime.Decimal | null +} + +export type DonationLineItemSumAggregateOutputType = { + quantity: number | null + unitPrice: runtime.Decimal | null + subtotal: runtime.Decimal | null +} + +export type DonationLineItemMinAggregateOutputType = { + id: string | null + donationId: string | null + campaignItemId: string | null + quantity: number | null + unitPrice: runtime.Decimal | null + subtotal: runtime.Decimal | null +} + +export type DonationLineItemMaxAggregateOutputType = { + id: string | null + donationId: string | null + campaignItemId: string | null + quantity: number | null + unitPrice: runtime.Decimal | null + subtotal: runtime.Decimal | null +} + +export type DonationLineItemCountAggregateOutputType = { + id: number + donationId: number + campaignItemId: number + quantity: number + unitPrice: number + subtotal: number + _all: number +} + + +export type DonationLineItemAvgAggregateInputType = { + quantity?: true + unitPrice?: true + subtotal?: true +} + +export type DonationLineItemSumAggregateInputType = { + quantity?: true + unitPrice?: true + subtotal?: true +} + +export type DonationLineItemMinAggregateInputType = { + id?: true + donationId?: true + campaignItemId?: true + quantity?: true + unitPrice?: true + subtotal?: true +} + +export type DonationLineItemMaxAggregateInputType = { + id?: true + donationId?: true + campaignItemId?: true + quantity?: true + unitPrice?: true + subtotal?: true +} + +export type DonationLineItemCountAggregateInputType = { + id?: true + donationId?: true + campaignItemId?: true + quantity?: true + unitPrice?: true + subtotal?: true + _all?: true +} + +export type DonationLineItemAggregateArgs = { + /** + * Filter which DonationLineItem to aggregate. + */ + where?: Prisma.DonationLineItemWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of DonationLineItems to fetch. + */ + orderBy?: Prisma.DonationLineItemOrderByWithRelationInput | Prisma.DonationLineItemOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the start position + */ + cursor?: Prisma.DonationLineItemWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` DonationLineItems from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` DonationLineItems. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Count returned DonationLineItems + **/ + _count?: true | DonationLineItemCountAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to average + **/ + _avg?: DonationLineItemAvgAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to sum + **/ + _sum?: DonationLineItemSumAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the minimum value + **/ + _min?: DonationLineItemMinAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the maximum value + **/ + _max?: DonationLineItemMaxAggregateInputType +} + +export type GetDonationLineItemAggregateType = { + [P in keyof T & keyof AggregateDonationLineItem]: P extends '_count' | 'count' + ? T[P] extends true + ? number + : Prisma.GetScalarType + : Prisma.GetScalarType +} + + + + +export type DonationLineItemGroupByArgs = { + where?: Prisma.DonationLineItemWhereInput + orderBy?: Prisma.DonationLineItemOrderByWithAggregationInput | Prisma.DonationLineItemOrderByWithAggregationInput[] + by: Prisma.DonationLineItemScalarFieldEnum[] | Prisma.DonationLineItemScalarFieldEnum + having?: Prisma.DonationLineItemScalarWhereWithAggregatesInput + take?: number + skip?: number + _count?: DonationLineItemCountAggregateInputType | true + _avg?: DonationLineItemAvgAggregateInputType + _sum?: DonationLineItemSumAggregateInputType + _min?: DonationLineItemMinAggregateInputType + _max?: DonationLineItemMaxAggregateInputType +} + +export type DonationLineItemGroupByOutputType = { + id: string + donationId: string + campaignItemId: string + quantity: number + unitPrice: runtime.Decimal + subtotal: runtime.Decimal + _count: DonationLineItemCountAggregateOutputType | null + _avg: DonationLineItemAvgAggregateOutputType | null + _sum: DonationLineItemSumAggregateOutputType | null + _min: DonationLineItemMinAggregateOutputType | null + _max: DonationLineItemMaxAggregateOutputType | null +} + +type GetDonationLineItemGroupByPayload = Prisma.PrismaPromise< + Array< + Prisma.PickEnumerable & + { + [P in ((keyof T) & (keyof DonationLineItemGroupByOutputType))]: P extends '_count' + ? T[P] extends boolean + ? number + : Prisma.GetScalarType + : Prisma.GetScalarType + } + > + > + + + +export type DonationLineItemWhereInput = { + AND?: Prisma.DonationLineItemWhereInput | Prisma.DonationLineItemWhereInput[] + OR?: Prisma.DonationLineItemWhereInput[] + NOT?: Prisma.DonationLineItemWhereInput | Prisma.DonationLineItemWhereInput[] + id?: Prisma.StringFilter<"DonationLineItem"> | string + donationId?: Prisma.StringFilter<"DonationLineItem"> | string + campaignItemId?: Prisma.StringFilter<"DonationLineItem"> | string + quantity?: Prisma.IntFilter<"DonationLineItem"> | number + unitPrice?: Prisma.DecimalFilter<"DonationLineItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string + subtotal?: Prisma.DecimalFilter<"DonationLineItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string + donation?: Prisma.XOR + campaignItem?: Prisma.XOR +} + +export type DonationLineItemOrderByWithRelationInput = { + id?: Prisma.SortOrder + donationId?: Prisma.SortOrder + campaignItemId?: Prisma.SortOrder + quantity?: Prisma.SortOrder + unitPrice?: Prisma.SortOrder + subtotal?: Prisma.SortOrder + donation?: Prisma.DonationOrderByWithRelationInput + campaignItem?: Prisma.CampaignItemOrderByWithRelationInput +} + +export type DonationLineItemWhereUniqueInput = Prisma.AtLeast<{ + id?: string + AND?: Prisma.DonationLineItemWhereInput | Prisma.DonationLineItemWhereInput[] + OR?: Prisma.DonationLineItemWhereInput[] + NOT?: Prisma.DonationLineItemWhereInput | Prisma.DonationLineItemWhereInput[] + donationId?: Prisma.StringFilter<"DonationLineItem"> | string + campaignItemId?: Prisma.StringFilter<"DonationLineItem"> | string + quantity?: Prisma.IntFilter<"DonationLineItem"> | number + unitPrice?: Prisma.DecimalFilter<"DonationLineItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string + subtotal?: Prisma.DecimalFilter<"DonationLineItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string + donation?: Prisma.XOR + campaignItem?: Prisma.XOR +}, "id"> + +export type DonationLineItemOrderByWithAggregationInput = { + id?: Prisma.SortOrder + donationId?: Prisma.SortOrder + campaignItemId?: Prisma.SortOrder + quantity?: Prisma.SortOrder + unitPrice?: Prisma.SortOrder + subtotal?: Prisma.SortOrder + _count?: Prisma.DonationLineItemCountOrderByAggregateInput + _avg?: Prisma.DonationLineItemAvgOrderByAggregateInput + _max?: Prisma.DonationLineItemMaxOrderByAggregateInput + _min?: Prisma.DonationLineItemMinOrderByAggregateInput + _sum?: Prisma.DonationLineItemSumOrderByAggregateInput +} + +export type DonationLineItemScalarWhereWithAggregatesInput = { + AND?: Prisma.DonationLineItemScalarWhereWithAggregatesInput | Prisma.DonationLineItemScalarWhereWithAggregatesInput[] + OR?: Prisma.DonationLineItemScalarWhereWithAggregatesInput[] + NOT?: Prisma.DonationLineItemScalarWhereWithAggregatesInput | Prisma.DonationLineItemScalarWhereWithAggregatesInput[] + id?: Prisma.StringWithAggregatesFilter<"DonationLineItem"> | string + donationId?: Prisma.StringWithAggregatesFilter<"DonationLineItem"> | string + campaignItemId?: Prisma.StringWithAggregatesFilter<"DonationLineItem"> | string + quantity?: Prisma.IntWithAggregatesFilter<"DonationLineItem"> | number + unitPrice?: Prisma.DecimalWithAggregatesFilter<"DonationLineItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string + subtotal?: Prisma.DecimalWithAggregatesFilter<"DonationLineItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string +} + +export type DonationLineItemCreateInput = { + id?: string + quantity: number + unitPrice: runtime.Decimal | runtime.DecimalJsLike | number | string + subtotal: runtime.Decimal | runtime.DecimalJsLike | number | string + donation: Prisma.DonationCreateNestedOneWithoutLineItemsInput + campaignItem: Prisma.CampaignItemCreateNestedOneWithoutDonationLineItemsInput +} + +export type DonationLineItemUncheckedCreateInput = { + id?: string + donationId: string + campaignItemId: string + quantity: number + unitPrice: runtime.Decimal | runtime.DecimalJsLike | number | string + subtotal: runtime.Decimal | runtime.DecimalJsLike | number | string +} + +export type DonationLineItemUpdateInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + quantity?: Prisma.IntFieldUpdateOperationsInput | number + unitPrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + subtotal?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + donation?: Prisma.DonationUpdateOneRequiredWithoutLineItemsNestedInput + campaignItem?: Prisma.CampaignItemUpdateOneRequiredWithoutDonationLineItemsNestedInput +} + +export type DonationLineItemUncheckedUpdateInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + donationId?: Prisma.StringFieldUpdateOperationsInput | string + campaignItemId?: Prisma.StringFieldUpdateOperationsInput | string + quantity?: Prisma.IntFieldUpdateOperationsInput | number + unitPrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + subtotal?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string +} + +export type DonationLineItemCreateManyInput = { + id?: string + donationId: string + campaignItemId: string + quantity: number + unitPrice: runtime.Decimal | runtime.DecimalJsLike | number | string + subtotal: runtime.Decimal | runtime.DecimalJsLike | number | string +} + +export type DonationLineItemUpdateManyMutationInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + quantity?: Prisma.IntFieldUpdateOperationsInput | number + unitPrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + subtotal?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string +} + +export type DonationLineItemUncheckedUpdateManyInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + donationId?: Prisma.StringFieldUpdateOperationsInput | string + campaignItemId?: Prisma.StringFieldUpdateOperationsInput | string + quantity?: Prisma.IntFieldUpdateOperationsInput | number + unitPrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + subtotal?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string +} + +export type DonationLineItemListRelationFilter = { + every?: Prisma.DonationLineItemWhereInput + some?: Prisma.DonationLineItemWhereInput + none?: Prisma.DonationLineItemWhereInput +} + +export type DonationLineItemOrderByRelationAggregateInput = { + _count?: Prisma.SortOrder +} + +export type DonationLineItemCountOrderByAggregateInput = { + id?: Prisma.SortOrder + donationId?: Prisma.SortOrder + campaignItemId?: Prisma.SortOrder + quantity?: Prisma.SortOrder + unitPrice?: Prisma.SortOrder + subtotal?: Prisma.SortOrder +} + +export type DonationLineItemAvgOrderByAggregateInput = { + quantity?: Prisma.SortOrder + unitPrice?: Prisma.SortOrder + subtotal?: Prisma.SortOrder +} + +export type DonationLineItemMaxOrderByAggregateInput = { + id?: Prisma.SortOrder + donationId?: Prisma.SortOrder + campaignItemId?: Prisma.SortOrder + quantity?: Prisma.SortOrder + unitPrice?: Prisma.SortOrder + subtotal?: Prisma.SortOrder +} + +export type DonationLineItemMinOrderByAggregateInput = { + id?: Prisma.SortOrder + donationId?: Prisma.SortOrder + campaignItemId?: Prisma.SortOrder + quantity?: Prisma.SortOrder + unitPrice?: Prisma.SortOrder + subtotal?: Prisma.SortOrder +} + +export type DonationLineItemSumOrderByAggregateInput = { + quantity?: Prisma.SortOrder + unitPrice?: Prisma.SortOrder + subtotal?: Prisma.SortOrder +} + +export type DonationLineItemCreateNestedManyWithoutCampaignItemInput = { + create?: Prisma.XOR | Prisma.DonationLineItemCreateWithoutCampaignItemInput[] | Prisma.DonationLineItemUncheckedCreateWithoutCampaignItemInput[] + connectOrCreate?: Prisma.DonationLineItemCreateOrConnectWithoutCampaignItemInput | Prisma.DonationLineItemCreateOrConnectWithoutCampaignItemInput[] + createMany?: Prisma.DonationLineItemCreateManyCampaignItemInputEnvelope + connect?: Prisma.DonationLineItemWhereUniqueInput | Prisma.DonationLineItemWhereUniqueInput[] +} + +export type DonationLineItemUncheckedCreateNestedManyWithoutCampaignItemInput = { + create?: Prisma.XOR | Prisma.DonationLineItemCreateWithoutCampaignItemInput[] | Prisma.DonationLineItemUncheckedCreateWithoutCampaignItemInput[] + connectOrCreate?: Prisma.DonationLineItemCreateOrConnectWithoutCampaignItemInput | Prisma.DonationLineItemCreateOrConnectWithoutCampaignItemInput[] + createMany?: Prisma.DonationLineItemCreateManyCampaignItemInputEnvelope + connect?: Prisma.DonationLineItemWhereUniqueInput | Prisma.DonationLineItemWhereUniqueInput[] +} + +export type DonationLineItemUpdateManyWithoutCampaignItemNestedInput = { + create?: Prisma.XOR | Prisma.DonationLineItemCreateWithoutCampaignItemInput[] | Prisma.DonationLineItemUncheckedCreateWithoutCampaignItemInput[] + connectOrCreate?: Prisma.DonationLineItemCreateOrConnectWithoutCampaignItemInput | Prisma.DonationLineItemCreateOrConnectWithoutCampaignItemInput[] + upsert?: Prisma.DonationLineItemUpsertWithWhereUniqueWithoutCampaignItemInput | Prisma.DonationLineItemUpsertWithWhereUniqueWithoutCampaignItemInput[] + createMany?: Prisma.DonationLineItemCreateManyCampaignItemInputEnvelope + set?: Prisma.DonationLineItemWhereUniqueInput | Prisma.DonationLineItemWhereUniqueInput[] + disconnect?: Prisma.DonationLineItemWhereUniqueInput | Prisma.DonationLineItemWhereUniqueInput[] + delete?: Prisma.DonationLineItemWhereUniqueInput | Prisma.DonationLineItemWhereUniqueInput[] + connect?: Prisma.DonationLineItemWhereUniqueInput | Prisma.DonationLineItemWhereUniqueInput[] + update?: Prisma.DonationLineItemUpdateWithWhereUniqueWithoutCampaignItemInput | Prisma.DonationLineItemUpdateWithWhereUniqueWithoutCampaignItemInput[] + updateMany?: Prisma.DonationLineItemUpdateManyWithWhereWithoutCampaignItemInput | Prisma.DonationLineItemUpdateManyWithWhereWithoutCampaignItemInput[] + deleteMany?: Prisma.DonationLineItemScalarWhereInput | Prisma.DonationLineItemScalarWhereInput[] +} + +export type DonationLineItemUncheckedUpdateManyWithoutCampaignItemNestedInput = { + create?: Prisma.XOR | Prisma.DonationLineItemCreateWithoutCampaignItemInput[] | Prisma.DonationLineItemUncheckedCreateWithoutCampaignItemInput[] + connectOrCreate?: Prisma.DonationLineItemCreateOrConnectWithoutCampaignItemInput | Prisma.DonationLineItemCreateOrConnectWithoutCampaignItemInput[] + upsert?: Prisma.DonationLineItemUpsertWithWhereUniqueWithoutCampaignItemInput | Prisma.DonationLineItemUpsertWithWhereUniqueWithoutCampaignItemInput[] + createMany?: Prisma.DonationLineItemCreateManyCampaignItemInputEnvelope + set?: Prisma.DonationLineItemWhereUniqueInput | Prisma.DonationLineItemWhereUniqueInput[] + disconnect?: Prisma.DonationLineItemWhereUniqueInput | Prisma.DonationLineItemWhereUniqueInput[] + delete?: Prisma.DonationLineItemWhereUniqueInput | Prisma.DonationLineItemWhereUniqueInput[] + connect?: Prisma.DonationLineItemWhereUniqueInput | Prisma.DonationLineItemWhereUniqueInput[] + update?: Prisma.DonationLineItemUpdateWithWhereUniqueWithoutCampaignItemInput | Prisma.DonationLineItemUpdateWithWhereUniqueWithoutCampaignItemInput[] + updateMany?: Prisma.DonationLineItemUpdateManyWithWhereWithoutCampaignItemInput | Prisma.DonationLineItemUpdateManyWithWhereWithoutCampaignItemInput[] + deleteMany?: Prisma.DonationLineItemScalarWhereInput | Prisma.DonationLineItemScalarWhereInput[] +} + +export type DonationLineItemCreateNestedManyWithoutDonationInput = { + create?: Prisma.XOR | Prisma.DonationLineItemCreateWithoutDonationInput[] | Prisma.DonationLineItemUncheckedCreateWithoutDonationInput[] + connectOrCreate?: Prisma.DonationLineItemCreateOrConnectWithoutDonationInput | Prisma.DonationLineItemCreateOrConnectWithoutDonationInput[] + createMany?: Prisma.DonationLineItemCreateManyDonationInputEnvelope + connect?: Prisma.DonationLineItemWhereUniqueInput | Prisma.DonationLineItemWhereUniqueInput[] +} + +export type DonationLineItemUncheckedCreateNestedManyWithoutDonationInput = { + create?: Prisma.XOR | Prisma.DonationLineItemCreateWithoutDonationInput[] | Prisma.DonationLineItemUncheckedCreateWithoutDonationInput[] + connectOrCreate?: Prisma.DonationLineItemCreateOrConnectWithoutDonationInput | Prisma.DonationLineItemCreateOrConnectWithoutDonationInput[] + createMany?: Prisma.DonationLineItemCreateManyDonationInputEnvelope + connect?: Prisma.DonationLineItemWhereUniqueInput | Prisma.DonationLineItemWhereUniqueInput[] +} + +export type DonationLineItemUpdateManyWithoutDonationNestedInput = { + create?: Prisma.XOR | Prisma.DonationLineItemCreateWithoutDonationInput[] | Prisma.DonationLineItemUncheckedCreateWithoutDonationInput[] + connectOrCreate?: Prisma.DonationLineItemCreateOrConnectWithoutDonationInput | Prisma.DonationLineItemCreateOrConnectWithoutDonationInput[] + upsert?: Prisma.DonationLineItemUpsertWithWhereUniqueWithoutDonationInput | Prisma.DonationLineItemUpsertWithWhereUniqueWithoutDonationInput[] + createMany?: Prisma.DonationLineItemCreateManyDonationInputEnvelope + set?: Prisma.DonationLineItemWhereUniqueInput | Prisma.DonationLineItemWhereUniqueInput[] + disconnect?: Prisma.DonationLineItemWhereUniqueInput | Prisma.DonationLineItemWhereUniqueInput[] + delete?: Prisma.DonationLineItemWhereUniqueInput | Prisma.DonationLineItemWhereUniqueInput[] + connect?: Prisma.DonationLineItemWhereUniqueInput | Prisma.DonationLineItemWhereUniqueInput[] + update?: Prisma.DonationLineItemUpdateWithWhereUniqueWithoutDonationInput | Prisma.DonationLineItemUpdateWithWhereUniqueWithoutDonationInput[] + updateMany?: Prisma.DonationLineItemUpdateManyWithWhereWithoutDonationInput | Prisma.DonationLineItemUpdateManyWithWhereWithoutDonationInput[] + deleteMany?: Prisma.DonationLineItemScalarWhereInput | Prisma.DonationLineItemScalarWhereInput[] +} + +export type DonationLineItemUncheckedUpdateManyWithoutDonationNestedInput = { + create?: Prisma.XOR | Prisma.DonationLineItemCreateWithoutDonationInput[] | Prisma.DonationLineItemUncheckedCreateWithoutDonationInput[] + connectOrCreate?: Prisma.DonationLineItemCreateOrConnectWithoutDonationInput | Prisma.DonationLineItemCreateOrConnectWithoutDonationInput[] + upsert?: Prisma.DonationLineItemUpsertWithWhereUniqueWithoutDonationInput | Prisma.DonationLineItemUpsertWithWhereUniqueWithoutDonationInput[] + createMany?: Prisma.DonationLineItemCreateManyDonationInputEnvelope + set?: Prisma.DonationLineItemWhereUniqueInput | Prisma.DonationLineItemWhereUniqueInput[] + disconnect?: Prisma.DonationLineItemWhereUniqueInput | Prisma.DonationLineItemWhereUniqueInput[] + delete?: Prisma.DonationLineItemWhereUniqueInput | Prisma.DonationLineItemWhereUniqueInput[] + connect?: Prisma.DonationLineItemWhereUniqueInput | Prisma.DonationLineItemWhereUniqueInput[] + update?: Prisma.DonationLineItemUpdateWithWhereUniqueWithoutDonationInput | Prisma.DonationLineItemUpdateWithWhereUniqueWithoutDonationInput[] + updateMany?: Prisma.DonationLineItemUpdateManyWithWhereWithoutDonationInput | Prisma.DonationLineItemUpdateManyWithWhereWithoutDonationInput[] + deleteMany?: Prisma.DonationLineItemScalarWhereInput | Prisma.DonationLineItemScalarWhereInput[] +} + +export type DonationLineItemCreateWithoutCampaignItemInput = { + id?: string + quantity: number + unitPrice: runtime.Decimal | runtime.DecimalJsLike | number | string + subtotal: runtime.Decimal | runtime.DecimalJsLike | number | string + donation: Prisma.DonationCreateNestedOneWithoutLineItemsInput +} + +export type DonationLineItemUncheckedCreateWithoutCampaignItemInput = { + id?: string + donationId: string + quantity: number + unitPrice: runtime.Decimal | runtime.DecimalJsLike | number | string + subtotal: runtime.Decimal | runtime.DecimalJsLike | number | string +} + +export type DonationLineItemCreateOrConnectWithoutCampaignItemInput = { + where: Prisma.DonationLineItemWhereUniqueInput + create: Prisma.XOR +} + +export type DonationLineItemCreateManyCampaignItemInputEnvelope = { + data: Prisma.DonationLineItemCreateManyCampaignItemInput | Prisma.DonationLineItemCreateManyCampaignItemInput[] + skipDuplicates?: boolean +} + +export type DonationLineItemUpsertWithWhereUniqueWithoutCampaignItemInput = { + where: Prisma.DonationLineItemWhereUniqueInput + update: Prisma.XOR + create: Prisma.XOR +} + +export type DonationLineItemUpdateWithWhereUniqueWithoutCampaignItemInput = { + where: Prisma.DonationLineItemWhereUniqueInput + data: Prisma.XOR +} + +export type DonationLineItemUpdateManyWithWhereWithoutCampaignItemInput = { + where: Prisma.DonationLineItemScalarWhereInput + data: Prisma.XOR +} + +export type DonationLineItemScalarWhereInput = { + AND?: Prisma.DonationLineItemScalarWhereInput | Prisma.DonationLineItemScalarWhereInput[] + OR?: Prisma.DonationLineItemScalarWhereInput[] + NOT?: Prisma.DonationLineItemScalarWhereInput | Prisma.DonationLineItemScalarWhereInput[] + id?: Prisma.StringFilter<"DonationLineItem"> | string + donationId?: Prisma.StringFilter<"DonationLineItem"> | string + campaignItemId?: Prisma.StringFilter<"DonationLineItem"> | string + quantity?: Prisma.IntFilter<"DonationLineItem"> | number + unitPrice?: Prisma.DecimalFilter<"DonationLineItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string + subtotal?: Prisma.DecimalFilter<"DonationLineItem"> | runtime.Decimal | runtime.DecimalJsLike | number | string +} + +export type DonationLineItemCreateWithoutDonationInput = { + id?: string + quantity: number + unitPrice: runtime.Decimal | runtime.DecimalJsLike | number | string + subtotal: runtime.Decimal | runtime.DecimalJsLike | number | string + campaignItem: Prisma.CampaignItemCreateNestedOneWithoutDonationLineItemsInput +} + +export type DonationLineItemUncheckedCreateWithoutDonationInput = { + id?: string + campaignItemId: string + quantity: number + unitPrice: runtime.Decimal | runtime.DecimalJsLike | number | string + subtotal: runtime.Decimal | runtime.DecimalJsLike | number | string +} + +export type DonationLineItemCreateOrConnectWithoutDonationInput = { + where: Prisma.DonationLineItemWhereUniqueInput + create: Prisma.XOR +} + +export type DonationLineItemCreateManyDonationInputEnvelope = { + data: Prisma.DonationLineItemCreateManyDonationInput | Prisma.DonationLineItemCreateManyDonationInput[] + skipDuplicates?: boolean +} + +export type DonationLineItemUpsertWithWhereUniqueWithoutDonationInput = { + where: Prisma.DonationLineItemWhereUniqueInput + update: Prisma.XOR + create: Prisma.XOR +} + +export type DonationLineItemUpdateWithWhereUniqueWithoutDonationInput = { + where: Prisma.DonationLineItemWhereUniqueInput + data: Prisma.XOR +} + +export type DonationLineItemUpdateManyWithWhereWithoutDonationInput = { + where: Prisma.DonationLineItemScalarWhereInput + data: Prisma.XOR +} + +export type DonationLineItemCreateManyCampaignItemInput = { + id?: string + donationId: string + quantity: number + unitPrice: runtime.Decimal | runtime.DecimalJsLike | number | string + subtotal: runtime.Decimal | runtime.DecimalJsLike | number | string +} + +export type DonationLineItemUpdateWithoutCampaignItemInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + quantity?: Prisma.IntFieldUpdateOperationsInput | number + unitPrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + subtotal?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + donation?: Prisma.DonationUpdateOneRequiredWithoutLineItemsNestedInput +} + +export type DonationLineItemUncheckedUpdateWithoutCampaignItemInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + donationId?: Prisma.StringFieldUpdateOperationsInput | string + quantity?: Prisma.IntFieldUpdateOperationsInput | number + unitPrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + subtotal?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string +} + +export type DonationLineItemUncheckedUpdateManyWithoutCampaignItemInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + donationId?: Prisma.StringFieldUpdateOperationsInput | string + quantity?: Prisma.IntFieldUpdateOperationsInput | number + unitPrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + subtotal?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string +} + +export type DonationLineItemCreateManyDonationInput = { + id?: string + campaignItemId: string + quantity: number + unitPrice: runtime.Decimal | runtime.DecimalJsLike | number | string + subtotal: runtime.Decimal | runtime.DecimalJsLike | number | string +} + +export type DonationLineItemUpdateWithoutDonationInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + quantity?: Prisma.IntFieldUpdateOperationsInput | number + unitPrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + subtotal?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + campaignItem?: Prisma.CampaignItemUpdateOneRequiredWithoutDonationLineItemsNestedInput +} + +export type DonationLineItemUncheckedUpdateWithoutDonationInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + campaignItemId?: Prisma.StringFieldUpdateOperationsInput | string + quantity?: Prisma.IntFieldUpdateOperationsInput | number + unitPrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + subtotal?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string +} + +export type DonationLineItemUncheckedUpdateManyWithoutDonationInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + campaignItemId?: Prisma.StringFieldUpdateOperationsInput | string + quantity?: Prisma.IntFieldUpdateOperationsInput | number + unitPrice?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string + subtotal?: Prisma.DecimalFieldUpdateOperationsInput | runtime.Decimal | runtime.DecimalJsLike | number | string +} + + + +export type DonationLineItemSelect = runtime.Types.Extensions.GetSelect<{ + id?: boolean + donationId?: boolean + campaignItemId?: boolean + quantity?: boolean + unitPrice?: boolean + subtotal?: boolean + donation?: boolean | Prisma.DonationDefaultArgs + campaignItem?: boolean | Prisma.CampaignItemDefaultArgs +}, ExtArgs["result"]["donationLineItem"]> + +export type DonationLineItemSelectCreateManyAndReturn = runtime.Types.Extensions.GetSelect<{ + id?: boolean + donationId?: boolean + campaignItemId?: boolean + quantity?: boolean + unitPrice?: boolean + subtotal?: boolean + donation?: boolean | Prisma.DonationDefaultArgs + campaignItem?: boolean | Prisma.CampaignItemDefaultArgs +}, ExtArgs["result"]["donationLineItem"]> + +export type DonationLineItemSelectUpdateManyAndReturn = runtime.Types.Extensions.GetSelect<{ + id?: boolean + donationId?: boolean + campaignItemId?: boolean + quantity?: boolean + unitPrice?: boolean + subtotal?: boolean + donation?: boolean | Prisma.DonationDefaultArgs + campaignItem?: boolean | Prisma.CampaignItemDefaultArgs +}, ExtArgs["result"]["donationLineItem"]> + +export type DonationLineItemSelectScalar = { + id?: boolean + donationId?: boolean + campaignItemId?: boolean + quantity?: boolean + unitPrice?: boolean + subtotal?: boolean +} + +export type DonationLineItemOmit = runtime.Types.Extensions.GetOmit<"id" | "donationId" | "campaignItemId" | "quantity" | "unitPrice" | "subtotal", ExtArgs["result"]["donationLineItem"]> +export type DonationLineItemInclude = { + donation?: boolean | Prisma.DonationDefaultArgs + campaignItem?: boolean | Prisma.CampaignItemDefaultArgs +} +export type DonationLineItemIncludeCreateManyAndReturn = { + donation?: boolean | Prisma.DonationDefaultArgs + campaignItem?: boolean | Prisma.CampaignItemDefaultArgs +} +export type DonationLineItemIncludeUpdateManyAndReturn = { + donation?: boolean | Prisma.DonationDefaultArgs + campaignItem?: boolean | Prisma.CampaignItemDefaultArgs +} + +export type $DonationLineItemPayload = { + name: "DonationLineItem" + objects: { + donation: Prisma.$DonationPayload + campaignItem: Prisma.$CampaignItemPayload + } + scalars: runtime.Types.Extensions.GetPayloadResult<{ + id: string + donationId: string + campaignItemId: string + quantity: number + unitPrice: runtime.Decimal + subtotal: runtime.Decimal + }, ExtArgs["result"]["donationLineItem"]> + composites: {} +} + +export type DonationLineItemGetPayload = runtime.Types.Result.GetResult + +export type DonationLineItemCountArgs = + Omit & { + select?: DonationLineItemCountAggregateInputType | true + } + +export interface DonationLineItemDelegate { + [K: symbol]: { types: Prisma.TypeMap['model']['DonationLineItem'], meta: { name: 'DonationLineItem' } } + /** + * Find zero or one DonationLineItem that matches the filter. + * @param {DonationLineItemFindUniqueArgs} args - Arguments to find a DonationLineItem + * @example + * // Get one DonationLineItem + * const donationLineItem = await prisma.donationLineItem.findUnique({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUnique(args: Prisma.SelectSubset>): Prisma.Prisma__DonationLineItemClient, T, "findUnique", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + + /** + * Find one DonationLineItem that matches the filter or throw an error with `error.code='P2025'` + * if no matches were found. + * @param {DonationLineItemFindUniqueOrThrowArgs} args - Arguments to find a DonationLineItem + * @example + * // Get one DonationLineItem + * const donationLineItem = await prisma.donationLineItem.findUniqueOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUniqueOrThrow(args: Prisma.SelectSubset>): Prisma.Prisma__DonationLineItemClient, T, "findUniqueOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Find the first DonationLineItem that matches the filter. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {DonationLineItemFindFirstArgs} args - Arguments to find a DonationLineItem + * @example + * // Get one DonationLineItem + * const donationLineItem = await prisma.donationLineItem.findFirst({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirst(args?: Prisma.SelectSubset>): Prisma.Prisma__DonationLineItemClient, T, "findFirst", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + + /** + * Find the first DonationLineItem that matches the filter or + * throw `PrismaKnownClientError` with `P2025` code if no matches were found. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {DonationLineItemFindFirstOrThrowArgs} args - Arguments to find a DonationLineItem + * @example + * // Get one DonationLineItem + * const donationLineItem = await prisma.donationLineItem.findFirstOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirstOrThrow(args?: Prisma.SelectSubset>): Prisma.Prisma__DonationLineItemClient, T, "findFirstOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Find zero or more DonationLineItems that matches the filter. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {DonationLineItemFindManyArgs} args - Arguments to filter and select certain fields only. + * @example + * // Get all DonationLineItems + * const donationLineItems = await prisma.donationLineItem.findMany() + * + * // Get first 10 DonationLineItems + * const donationLineItems = await prisma.donationLineItem.findMany({ take: 10 }) + * + * // Only select the `id` + * const donationLineItemWithIdOnly = await prisma.donationLineItem.findMany({ select: { id: true } }) + * + */ + findMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions>> + + /** + * Create a DonationLineItem. + * @param {DonationLineItemCreateArgs} args - Arguments to create a DonationLineItem. + * @example + * // Create one DonationLineItem + * const DonationLineItem = await prisma.donationLineItem.create({ + * data: { + * // ... data to create a DonationLineItem + * } + * }) + * + */ + create(args: Prisma.SelectSubset>): Prisma.Prisma__DonationLineItemClient, T, "create", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Create many DonationLineItems. + * @param {DonationLineItemCreateManyArgs} args - Arguments to create many DonationLineItems. + * @example + * // Create many DonationLineItems + * const donationLineItem = await prisma.donationLineItem.createMany({ + * data: [ + * // ... provide data here + * ] + * }) + * + */ + createMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Create many DonationLineItems and returns the data saved in the database. + * @param {DonationLineItemCreateManyAndReturnArgs} args - Arguments to create many DonationLineItems. + * @example + * // Create many DonationLineItems + * const donationLineItem = await prisma.donationLineItem.createManyAndReturn({ + * data: [ + * // ... provide data here + * ] + * }) + * + * // Create many DonationLineItems and only return the `id` + * const donationLineItemWithIdOnly = await prisma.donationLineItem.createManyAndReturn({ + * select: { id: true }, + * data: [ + * // ... provide data here + * ] + * }) + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * + */ + createManyAndReturn(args?: Prisma.SelectSubset>): Prisma.PrismaPromise, T, "createManyAndReturn", GlobalOmitOptions>> + + /** + * Delete a DonationLineItem. + * @param {DonationLineItemDeleteArgs} args - Arguments to delete one DonationLineItem. + * @example + * // Delete one DonationLineItem + * const DonationLineItem = await prisma.donationLineItem.delete({ + * where: { + * // ... filter to delete one DonationLineItem + * } + * }) + * + */ + delete(args: Prisma.SelectSubset>): Prisma.Prisma__DonationLineItemClient, T, "delete", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Update one DonationLineItem. + * @param {DonationLineItemUpdateArgs} args - Arguments to update one DonationLineItem. + * @example + * // Update one DonationLineItem + * const donationLineItem = await prisma.donationLineItem.update({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + update(args: Prisma.SelectSubset>): Prisma.Prisma__DonationLineItemClient, T, "update", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Delete zero or more DonationLineItems. + * @param {DonationLineItemDeleteManyArgs} args - Arguments to filter DonationLineItems to delete. + * @example + * // Delete a few DonationLineItems + * const { count } = await prisma.donationLineItem.deleteMany({ + * where: { + * // ... provide filter here + * } + * }) + * + */ + deleteMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Update zero or more DonationLineItems. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {DonationLineItemUpdateManyArgs} args - Arguments to update one or more rows. + * @example + * // Update many DonationLineItems + * const donationLineItem = await prisma.donationLineItem.updateMany({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + updateMany(args: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Update zero or more DonationLineItems and returns the data updated in the database. + * @param {DonationLineItemUpdateManyAndReturnArgs} args - Arguments to update many DonationLineItems. + * @example + * // Update many DonationLineItems + * const donationLineItem = await prisma.donationLineItem.updateManyAndReturn({ + * where: { + * // ... provide filter here + * }, + * data: [ + * // ... provide data here + * ] + * }) + * + * // Update zero or more DonationLineItems and only return the `id` + * const donationLineItemWithIdOnly = await prisma.donationLineItem.updateManyAndReturn({ + * select: { id: true }, + * where: { + * // ... provide filter here + * }, + * data: [ + * // ... provide data here + * ] + * }) + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * + */ + updateManyAndReturn(args: Prisma.SelectSubset>): Prisma.PrismaPromise, T, "updateManyAndReturn", GlobalOmitOptions>> + + /** + * Create or update one DonationLineItem. + * @param {DonationLineItemUpsertArgs} args - Arguments to update or create a DonationLineItem. + * @example + * // Update or create a DonationLineItem + * const donationLineItem = await prisma.donationLineItem.upsert({ + * create: { + * // ... data to create a DonationLineItem + * }, + * update: { + * // ... in case it already exists, update + * }, + * where: { + * // ... the filter for the DonationLineItem we want to update + * } + * }) + */ + upsert(args: Prisma.SelectSubset>): Prisma.Prisma__DonationLineItemClient, T, "upsert", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + + /** + * Count the number of DonationLineItems. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {DonationLineItemCountArgs} args - Arguments to filter DonationLineItems to count. + * @example + * // Count the number of DonationLineItems + * const count = await prisma.donationLineItem.count({ + * where: { + * // ... the filter for the DonationLineItems we want to count + * } + * }) + **/ + count( + args?: Prisma.Subset, + ): Prisma.PrismaPromise< + T extends runtime.Types.Utils.Record<'select', any> + ? T['select'] extends true + ? number + : Prisma.GetScalarType + : number + > + + /** + * Allows you to perform aggregations operations on a DonationLineItem. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {DonationLineItemAggregateArgs} args - Select which aggregations you would like to apply and on what fields. + * @example + * // Ordered by age ascending + * // Where email contains prisma.io + * // Limited to the 10 users + * const aggregations = await prisma.user.aggregate({ + * _avg: { + * age: true, + * }, + * where: { + * email: { + * contains: "prisma.io", + * }, + * }, + * orderBy: { + * age: "asc", + * }, + * take: 10, + * }) + **/ + aggregate(args: Prisma.Subset): Prisma.PrismaPromise> + + /** + * Group by DonationLineItem. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {DonationLineItemGroupByArgs} args - Group by arguments. + * @example + * // Group by city, order by createdAt, get count + * const result = await prisma.user.groupBy({ + * by: ['city', 'createdAt'], + * orderBy: { + * createdAt: true + * }, + * _count: { + * _all: true + * }, + * }) + * + **/ + groupBy< + T extends DonationLineItemGroupByArgs, + HasSelectOrTake extends Prisma.Or< + Prisma.Extends<'skip', Prisma.Keys>, + Prisma.Extends<'take', Prisma.Keys> + >, + OrderByArg extends Prisma.True extends HasSelectOrTake + ? { orderBy: DonationLineItemGroupByArgs['orderBy'] } + : { orderBy?: DonationLineItemGroupByArgs['orderBy'] }, + OrderFields extends Prisma.ExcludeUnderscoreKeys>>, + ByFields extends Prisma.MaybeTupleToUnion, + ByValid extends Prisma.Has, + HavingFields extends Prisma.GetHavingFields, + HavingValid extends Prisma.Has, + ByEmpty extends T['by'] extends never[] ? Prisma.True : Prisma.False, + InputErrors extends ByEmpty extends Prisma.True + ? `Error: "by" must not be empty.` + : HavingValid extends Prisma.False + ? { + [P in HavingFields]: P extends ByFields + ? never + : P extends string + ? `Error: Field "${P}" used in "having" needs to be provided in "by".` + : [ + Error, + 'Field ', + P, + ` in "having" needs to be provided in "by"`, + ] + }[HavingFields] + : 'take' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "take", you also need to provide "orderBy"' + : 'skip' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "skip", you also need to provide "orderBy"' + : ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + >(args: Prisma.SubsetIntersection & InputErrors): {} extends InputErrors ? GetDonationLineItemGroupByPayload : Prisma.PrismaPromise +/** + * Fields of the DonationLineItem model + */ +readonly fields: DonationLineItemFieldRefs; +} + +/** + * The delegate class that acts as a "Promise-like" for DonationLineItem. + * Why is this prefixed with `Prisma__`? + * Because we want to prevent naming conflicts as mentioned in + * https://github.com/prisma/prisma-client-js/issues/707 + */ +export interface Prisma__DonationLineItemClient extends Prisma.PrismaPromise { + readonly [Symbol.toStringTag]: "PrismaPromise" + donation = {}>(args?: Prisma.Subset>): Prisma.Prisma__DonationClient, T, "findUniqueOrThrow", GlobalOmitOptions> | Null, Null, ExtArgs, GlobalOmitOptions> + campaignItem = {}>(args?: Prisma.Subset>): Prisma.Prisma__CampaignItemClient, T, "findUniqueOrThrow", GlobalOmitOptions> | Null, Null, ExtArgs, GlobalOmitOptions> + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): runtime.Types.Utils.JsPromise + /** + * Attaches a callback for only the rejection of the Promise. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of the callback. + */ + catch(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): runtime.Types.Utils.JsPromise + /** + * Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The + * resolved value cannot be modified from the callback. + * @param onfinally The callback to execute when the Promise is settled (fulfilled or rejected). + * @returns A Promise for the completion of the callback. + */ + finally(onfinally?: (() => void) | undefined | null): runtime.Types.Utils.JsPromise +} + + + + +/** + * Fields of the DonationLineItem model + */ +export interface DonationLineItemFieldRefs { + readonly id: Prisma.FieldRef<"DonationLineItem", 'String'> + readonly donationId: Prisma.FieldRef<"DonationLineItem", 'String'> + readonly campaignItemId: Prisma.FieldRef<"DonationLineItem", 'String'> + readonly quantity: Prisma.FieldRef<"DonationLineItem", 'Int'> + readonly unitPrice: Prisma.FieldRef<"DonationLineItem", 'Decimal'> + readonly subtotal: Prisma.FieldRef<"DonationLineItem", 'Decimal'> +} + + +// Custom InputTypes +/** + * DonationLineItem findUnique + */ +export type DonationLineItemFindUniqueArgs = { + /** + * Select specific fields to fetch from the DonationLineItem + */ + select?: Prisma.DonationLineItemSelect | null + /** + * Omit specific fields from the DonationLineItem + */ + omit?: Prisma.DonationLineItemOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.DonationLineItemInclude | null + /** + * Filter, which DonationLineItem to fetch. + */ + where: Prisma.DonationLineItemWhereUniqueInput +} + +/** + * DonationLineItem findUniqueOrThrow + */ +export type DonationLineItemFindUniqueOrThrowArgs = { + /** + * Select specific fields to fetch from the DonationLineItem + */ + select?: Prisma.DonationLineItemSelect | null + /** + * Omit specific fields from the DonationLineItem + */ + omit?: Prisma.DonationLineItemOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.DonationLineItemInclude | null + /** + * Filter, which DonationLineItem to fetch. + */ + where: Prisma.DonationLineItemWhereUniqueInput +} + +/** + * DonationLineItem findFirst + */ +export type DonationLineItemFindFirstArgs = { + /** + * Select specific fields to fetch from the DonationLineItem + */ + select?: Prisma.DonationLineItemSelect | null + /** + * Omit specific fields from the DonationLineItem + */ + omit?: Prisma.DonationLineItemOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.DonationLineItemInclude | null + /** + * Filter, which DonationLineItem to fetch. + */ + where?: Prisma.DonationLineItemWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of DonationLineItems to fetch. + */ + orderBy?: Prisma.DonationLineItemOrderByWithRelationInput | Prisma.DonationLineItemOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for DonationLineItems. + */ + cursor?: Prisma.DonationLineItemWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` DonationLineItems from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` DonationLineItems. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of DonationLineItems. + */ + distinct?: Prisma.DonationLineItemScalarFieldEnum | Prisma.DonationLineItemScalarFieldEnum[] +} + +/** + * DonationLineItem findFirstOrThrow + */ +export type DonationLineItemFindFirstOrThrowArgs = { + /** + * Select specific fields to fetch from the DonationLineItem + */ + select?: Prisma.DonationLineItemSelect | null + /** + * Omit specific fields from the DonationLineItem + */ + omit?: Prisma.DonationLineItemOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.DonationLineItemInclude | null + /** + * Filter, which DonationLineItem to fetch. + */ + where?: Prisma.DonationLineItemWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of DonationLineItems to fetch. + */ + orderBy?: Prisma.DonationLineItemOrderByWithRelationInput | Prisma.DonationLineItemOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for DonationLineItems. + */ + cursor?: Prisma.DonationLineItemWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` DonationLineItems from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` DonationLineItems. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of DonationLineItems. + */ + distinct?: Prisma.DonationLineItemScalarFieldEnum | Prisma.DonationLineItemScalarFieldEnum[] +} + +/** + * DonationLineItem findMany + */ +export type DonationLineItemFindManyArgs = { + /** + * Select specific fields to fetch from the DonationLineItem + */ + select?: Prisma.DonationLineItemSelect | null + /** + * Omit specific fields from the DonationLineItem + */ + omit?: Prisma.DonationLineItemOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.DonationLineItemInclude | null + /** + * Filter, which DonationLineItems to fetch. + */ + where?: Prisma.DonationLineItemWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of DonationLineItems to fetch. + */ + orderBy?: Prisma.DonationLineItemOrderByWithRelationInput | Prisma.DonationLineItemOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for listing DonationLineItems. + */ + cursor?: Prisma.DonationLineItemWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` DonationLineItems from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` DonationLineItems. + */ + skip?: number + distinct?: Prisma.DonationLineItemScalarFieldEnum | Prisma.DonationLineItemScalarFieldEnum[] +} + +/** + * DonationLineItem create + */ +export type DonationLineItemCreateArgs = { + /** + * Select specific fields to fetch from the DonationLineItem + */ + select?: Prisma.DonationLineItemSelect | null + /** + * Omit specific fields from the DonationLineItem + */ + omit?: Prisma.DonationLineItemOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.DonationLineItemInclude | null + /** + * The data needed to create a DonationLineItem. + */ + data: Prisma.XOR +} + +/** + * DonationLineItem createMany + */ +export type DonationLineItemCreateManyArgs = { + /** + * The data used to create many DonationLineItems. + */ + data: Prisma.DonationLineItemCreateManyInput | Prisma.DonationLineItemCreateManyInput[] + skipDuplicates?: boolean +} + +/** + * DonationLineItem createManyAndReturn + */ +export type DonationLineItemCreateManyAndReturnArgs = { + /** + * Select specific fields to fetch from the DonationLineItem + */ + select?: Prisma.DonationLineItemSelectCreateManyAndReturn | null + /** + * Omit specific fields from the DonationLineItem + */ + omit?: Prisma.DonationLineItemOmit | null + /** + * The data used to create many DonationLineItems. + */ + data: Prisma.DonationLineItemCreateManyInput | Prisma.DonationLineItemCreateManyInput[] + skipDuplicates?: boolean + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.DonationLineItemIncludeCreateManyAndReturn | null +} + +/** + * DonationLineItem update + */ +export type DonationLineItemUpdateArgs = { + /** + * Select specific fields to fetch from the DonationLineItem + */ + select?: Prisma.DonationLineItemSelect | null + /** + * Omit specific fields from the DonationLineItem + */ + omit?: Prisma.DonationLineItemOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.DonationLineItemInclude | null + /** + * The data needed to update a DonationLineItem. + */ + data: Prisma.XOR + /** + * Choose, which DonationLineItem to update. + */ + where: Prisma.DonationLineItemWhereUniqueInput +} + +/** + * DonationLineItem updateMany + */ +export type DonationLineItemUpdateManyArgs = { + /** + * The data used to update DonationLineItems. + */ + data: Prisma.XOR + /** + * Filter which DonationLineItems to update + */ + where?: Prisma.DonationLineItemWhereInput + /** + * Limit how many DonationLineItems to update. + */ + limit?: number +} + +/** + * DonationLineItem updateManyAndReturn + */ +export type DonationLineItemUpdateManyAndReturnArgs = { + /** + * Select specific fields to fetch from the DonationLineItem + */ + select?: Prisma.DonationLineItemSelectUpdateManyAndReturn | null + /** + * Omit specific fields from the DonationLineItem + */ + omit?: Prisma.DonationLineItemOmit | null + /** + * The data used to update DonationLineItems. + */ + data: Prisma.XOR + /** + * Filter which DonationLineItems to update + */ + where?: Prisma.DonationLineItemWhereInput + /** + * Limit how many DonationLineItems to update. + */ + limit?: number + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.DonationLineItemIncludeUpdateManyAndReturn | null +} + +/** + * DonationLineItem upsert + */ +export type DonationLineItemUpsertArgs = { + /** + * Select specific fields to fetch from the DonationLineItem + */ + select?: Prisma.DonationLineItemSelect | null + /** + * Omit specific fields from the DonationLineItem + */ + omit?: Prisma.DonationLineItemOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.DonationLineItemInclude | null + /** + * The filter to search for the DonationLineItem to update in case it exists. + */ + where: Prisma.DonationLineItemWhereUniqueInput + /** + * In case the DonationLineItem found by the `where` argument doesn't exist, create a new DonationLineItem with this data. + */ + create: Prisma.XOR + /** + * In case the DonationLineItem was found with the provided `where` argument, update it with this data. + */ + update: Prisma.XOR +} + +/** + * DonationLineItem delete + */ +export type DonationLineItemDeleteArgs = { + /** + * Select specific fields to fetch from the DonationLineItem + */ + select?: Prisma.DonationLineItemSelect | null + /** + * Omit specific fields from the DonationLineItem + */ + omit?: Prisma.DonationLineItemOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.DonationLineItemInclude | null + /** + * Filter which DonationLineItem to delete. + */ + where: Prisma.DonationLineItemWhereUniqueInput +} + +/** + * DonationLineItem deleteMany + */ +export type DonationLineItemDeleteManyArgs = { + /** + * Filter which DonationLineItems to delete + */ + where?: Prisma.DonationLineItemWhereInput + /** + * Limit how many DonationLineItems to delete. + */ + limit?: number +} + +/** + * DonationLineItem without action + */ +export type DonationLineItemDefaultArgs = { + /** + * Select specific fields to fetch from the DonationLineItem + */ + select?: Prisma.DonationLineItemSelect | null + /** + * Omit specific fields from the DonationLineItem + */ + omit?: Prisma.DonationLineItemOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.DonationLineItemInclude | null +} diff --git a/src/middleware.ts b/src/middleware.ts index bfbb878..0322d61 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -14,6 +14,10 @@ const isPublicRoute = createRouteMatcher([ "/organizations", // Organization lists "/org/:slug", // Public organization dashboard "/org/:slug/donate(.*)", // Public donation page + "/api/organizations/:slug/payment-methods", // Public: donors need to see available payment methods + "/api/organizations/:slug/donations/checkout", // Public: Stripe checkout for unauthenticated donors + "/api/organizations/:slug/campaigns", // Public: campaign listing for public donate page + "/api/organizations/:slug/campaigns/:id", // Public: single campaign details for public donate page "/api/organizations/:slug/logo", // Org logo (public branding, used in emails) "/api/organizations/:slug/attachments/:id/public-image", // Public spending images "/invite/:token", // Invitation acceptance page (handles auth internally) diff --git a/src/services/campaign.service.ts b/src/services/campaign.service.ts index 9c10d24..71afc35 100644 --- a/src/services/campaign.service.ts +++ b/src/services/campaign.service.ts @@ -6,7 +6,7 @@ import { prisma } from '@/lib/prisma'; import { buildCurrentVersionWhere } from '@/lib/temporal/temporal-utils'; import { getCampaignDonationSummary } from '@/services/donation.service'; -import type { Campaign } from '@/generated/prisma/client'; +import type { Campaign, CampaignItem } from '@/generated/prisma/client'; export interface CreateCampaignInput { organizationId: string; @@ -18,11 +18,24 @@ export interface CreateCampaignInput { endDate?: Date | null; createdBy?: string; // Campaign constraint fields - campaignType?: 'OPEN' | 'FIXED_UNIT' | 'TIERED'; + campaignType?: 'OPEN' | 'FIXED_UNIT' | 'TIERED' | 'EVENT'; unitPrice?: number | null; maxUnits?: number | null; unitLabel?: string | null; allowMultiUnit?: boolean; + items?: CreateCampaignItemInput[]; +} + +export interface CreateCampaignItemInput { + name: string; + description?: string | null; + category?: string | null; + price: number; + maxQuantity?: number | null; + minPerOrder?: number; + maxPerOrder?: number | null; + isRequired?: boolean; + sortOrder?: number; } export interface UpdateCampaignInput { @@ -88,11 +101,30 @@ export async function createCampaign(input: CreateCampaignInput): Promise i.maxQuantity != null); + if (allHaveMax) { + targetAmount = input.items.reduce( + (sum, i) => sum + i.price * (i.maxQuantity ?? 0), 0 + ); + } + } return await prisma.campaign.create({ data: { @@ -109,7 +141,23 @@ export async function createCampaign(input: CreateCampaignInput): Promise ({ + name: item.name, + description: item.description ?? null, + category: item.category ?? null, + price: item.price, + maxQuantity: item.maxQuantity ?? null, + minPerOrder: item.minPerOrder ?? 0, + maxPerOrder: item.maxPerOrder ?? null, + isRequired: item.isRequired ?? false, + sortOrder: item.sortOrder ?? idx, + })), + }, + }), }, + include: campaignType === 'EVENT' ? { items: { orderBy: { sortOrder: 'asc' } } } : undefined, }); } @@ -159,7 +207,10 @@ export async function listCampaigns( const campaigns = await prisma.campaign.findMany({ where, - include: { tiers: { orderBy: { sortOrder: 'asc' } } }, + include: { + tiers: { orderBy: { sortOrder: 'asc' } }, + items: { orderBy: { sortOrder: 'asc' } }, + }, orderBy: { createdAt: 'desc' }, }); @@ -180,7 +231,10 @@ export async function getCampaignById( ): Promise { const campaign = await prisma.campaign.findUnique({ where: { id: campaignId }, - include: { tiers: { orderBy: { sortOrder: 'asc' } } }, + include: { + tiers: { orderBy: { sortOrder: 'asc' } }, + items: { where: { isActive: true }, orderBy: { sortOrder: 'asc' } }, + }, }); if (!campaign) return null; @@ -271,6 +325,11 @@ export async function getTierSlotsFilled(tierId: string): Promise { }); } +export interface EventLineItemInput { + campaignItemId: string; + quantity: number; +} + /** * Validate a donation against campaign constraints. * Throws if the donation violates any campaign rules. @@ -279,11 +338,12 @@ export async function validateDonationAgainstCampaign( campaignId: string, amount: number, unitCount?: number | null, - tierId?: string | null + tierId?: string | null, + lineItems?: EventLineItemInput[] ): Promise { const campaign = await prisma.campaign.findUnique({ where: { id: campaignId }, - include: { tiers: true }, + include: { tiers: true, items: { where: { isActive: true } } }, }); if (!campaign) throw new Error('Campaign not found'); @@ -335,6 +395,13 @@ export async function validateDonationAgainstCampaign( } break; } + case 'EVENT': { + if (!lineItems || lineItems.length === 0) { + throw new Error('EVENT campaigns require selecting at least one item'); + } + await validateEventLineItems(campaign, lineItems, amount); + break; + } // OPEN: no constraints } } @@ -357,7 +424,6 @@ export async function checkAndAutoCompleteCampaign(campaignId: string): Promise< } else if (campaign.campaignType === 'TIERED') { const tiersWithCaps = campaign.tiers.filter(t => t.maxSlots != null); if (tiersWithCaps.length > 0 && tiersWithCaps.length === campaign.tiers.length) { - // All tiers have caps — check if all are full const checks = await Promise.all( tiersWithCaps.map(async (t) => { const filled = await getTierSlotsFilled(t.id); @@ -366,6 +432,19 @@ export async function checkAndAutoCompleteCampaign(campaignId: string): Promise< ); shouldComplete = checks.every(Boolean); } + } else if (campaign.campaignType === 'EVENT') { + const items = await prisma.campaignItem.findMany({ + where: { campaignId, isActive: true, maxQuantity: { not: null } }, + }); + if (items.length > 0) { + const checks = await Promise.all( + items.map(async (item) => { + const sold = await getItemQuantitySold(item.id); + return sold >= item.maxQuantity!; + }) + ); + shouldComplete = checks.every(Boolean); + } } if (shouldComplete) { @@ -375,3 +454,155 @@ export async function checkAndAutoCompleteCampaign(campaignId: string): Promise< }); } } + +/** + * Get total quantity sold for a specific campaign item. + */ +export async function getItemQuantitySold(campaignItemId: string): Promise { + const result = await prisma.donationLineItem.aggregate({ + where: { + campaignItemId, + donation: { status: { notIn: ['CANCELLED'] } }, + }, + _sum: { quantity: true }, + }); + return result._sum.quantity ?? 0; +} + +/** + * Validate EVENT line items against campaign item constraints. + */ +async function validateEventLineItems( + campaign: Campaign & { items: CampaignItem[] }, + lineItems: EventLineItemInput[], + amount: number +): Promise { + const itemMap = new Map(campaign.items.map(i => [i.id, i])); + + // Check all line items reference valid active items in this campaign + let expectedTotal = 0; + for (const li of lineItems) { + const item = itemMap.get(li.campaignItemId); + if (!item) { + throw new Error(`Campaign item not found or inactive: ${li.campaignItemId}`); + } + if (li.quantity < 1) { + throw new Error(`Quantity must be at least 1 for "${item.name}"`); + } + if (item.maxPerOrder != null && li.quantity > item.maxPerOrder) { + throw new Error(`Maximum ${item.maxPerOrder} of "${item.name}" per order`); + } + if (item.minPerOrder > 0 && li.quantity < item.minPerOrder) { + throw new Error(`Minimum ${item.minPerOrder} of "${item.name}" per order`); + } + // Check total capacity + if (item.maxQuantity != null) { + const sold = await getItemQuantitySold(item.id); + if (sold + li.quantity > item.maxQuantity) { + const remaining = item.maxQuantity - sold; + throw new Error(`Only ${remaining} of "${item.name}" remaining (requested ${li.quantity})`); + } + } + expectedTotal += Number(item.price) * li.quantity; + } + + // Check required items are present + for (const item of campaign.items) { + if (item.isRequired) { + const selected = lineItems.find(li => li.campaignItemId === item.id); + if (!selected || selected.quantity < 1) { + throw new Error(`"${item.name}" is required`); + } + } + } + + // Verify total amount matches + if (Math.abs(amount - expectedTotal) > 0.01) { + throw new Error( + `Donation amount ($${amount.toFixed(2)}) does not match item total ($${expectedTotal.toFixed(2)})` + ); + } +} + +// ============================================ +// CAMPAIGN ITEM CRUD +// ============================================ + +/** + * Add an item to an EVENT campaign. + */ +export async function addCampaignItem( + campaignId: string, + input: CreateCampaignItemInput +): Promise { + const campaign = await prisma.campaign.findUnique({ where: { id: campaignId } }); + if (!campaign) throw new Error('Campaign not found'); + if (campaign.campaignType !== 'EVENT') { + throw new Error('Items can only be added to EVENT campaigns'); + } + + return await prisma.campaignItem.create({ + data: { + campaignId, + name: input.name, + description: input.description ?? null, + category: input.category ?? null, + price: input.price, + maxQuantity: input.maxQuantity ?? null, + minPerOrder: input.minPerOrder ?? 0, + maxPerOrder: input.maxPerOrder ?? null, + isRequired: input.isRequired ?? false, + sortOrder: input.sortOrder ?? 0, + }, + }); +} + +/** + * Update a campaign item. + */ +export async function updateCampaignItem( + itemId: string, + updates: Partial & { isActive?: boolean } +): Promise { + return await prisma.campaignItem.update({ + where: { id: itemId }, + data: { + ...(updates.name !== undefined && { name: updates.name }), + ...(updates.description !== undefined && { description: updates.description }), + ...(updates.category !== undefined && { category: updates.category }), + ...(updates.price !== undefined && { price: updates.price }), + ...(updates.maxQuantity !== undefined && { maxQuantity: updates.maxQuantity }), + ...(updates.minPerOrder !== undefined && { minPerOrder: updates.minPerOrder }), + ...(updates.maxPerOrder !== undefined && { maxPerOrder: updates.maxPerOrder }), + ...(updates.isRequired !== undefined && { isRequired: updates.isRequired }), + ...(updates.sortOrder !== undefined && { sortOrder: updates.sortOrder }), + ...(updates.isActive !== undefined && { isActive: updates.isActive }), + }, + }); +} + +/** + * Delete (deactivate) a campaign item. Soft-delete to preserve line item references. + */ +export async function deleteCampaignItem(itemId: string): Promise { + return await prisma.campaignItem.update({ + where: { id: itemId }, + data: { isActive: false }, + }); +} + +/** + * List items for a campaign. + */ +export async function listCampaignItems( + campaignId: string, + includeInactive = false +): Promise { + return await prisma.campaignItem.findMany({ + where: { + campaignId, + ...(includeInactive ? {} : { isActive: true }), + }, + orderBy: { sortOrder: 'asc' }, + }); +} diff --git a/src/services/donation.service.ts b/src/services/donation.service.ts index 8d216c6..8e9ab51 100644 --- a/src/services/donation.service.ts +++ b/src/services/donation.service.ts @@ -27,6 +27,7 @@ export interface CreateDonationInput { campaignId?: string | null; unitCount?: number | null; // Number of units (FIXED_UNIT campaigns) tierId?: string | null; // Tier selection (TIERED campaigns) + lineItems?: Array<{ campaignItemId: string; quantity: number }>; // EVENT campaigns // Account IDs for the accounting entry arAccountId: string; // Accounts Receivable (for pledges) revenueAccountId: string; // Revenue / campaign account @@ -67,7 +68,7 @@ export async function createPledgeDonation(input: CreateDonationInput): Promise< // Validate against campaign constraints before starting transaction if (input.campaignId) { const { validateDonationAgainstCampaign } = await import('@/services/campaign.service'); - await validateDonationAgainstCampaign(input.campaignId, input.amount, input.unitCount, input.tierId); + await validateDonationAgainstCampaign(input.campaignId, input.amount, input.unitCount, input.tierId, input.lineItems); } const donation = await prisma.$transaction(async (tx) => { @@ -104,7 +105,7 @@ export async function createPledgeDonation(input: CreateDonationInput): Promise< }); // Create the donation record - return await tx.donation.create({ + const donation = await tx.donation.create({ data: { organizationId: input.organizationId, contactId: input.contactId, @@ -126,6 +127,13 @@ export async function createPledgeDonation(input: CreateDonationInput): Promise< createdBy: input.createdBy ?? null, }, }); + + // Create line items for EVENT campaigns + if (input.lineItems && input.lineItems.length > 0) { + await createDonationLineItems(tx, donation.id, input.lineItems); + } + + return donation; }); // After successful creation, check if campaign should auto-complete @@ -149,7 +157,7 @@ export async function createOneTimeDonation(input: CreateDonationInput): Promise // Validate against campaign constraints if (input.campaignId) { const { validateDonationAgainstCampaign } = await import('@/services/campaign.service'); - await validateDonationAgainstCampaign(input.campaignId, input.amount, input.unitCount, input.tierId); + await validateDonationAgainstCampaign(input.campaignId, input.amount, input.unitCount, input.tierId, input.lineItems); } const donation = await prisma.$transaction(async (tx) => { @@ -169,7 +177,7 @@ export async function createOneTimeDonation(input: CreateDonationInput): Promise }); // Create the donation record (immediately received) - return await tx.donation.create({ + const donation = await tx.donation.create({ data: { organizationId: input.organizationId, contactId: input.contactId, @@ -192,6 +200,13 @@ export async function createOneTimeDonation(input: CreateDonationInput): Promise createdBy: input.createdBy ?? null, }, }); + + // Create line items for EVENT campaigns + if (input.lineItems && input.lineItems.length > 0) { + await createDonationLineItems(tx, donation.id, input.lineItems); + } + + return donation; }); // After successful creation, check if campaign should auto-complete @@ -562,6 +577,39 @@ export async function syncDonationFromBill(billId: string, txClient?: any): Prom } } +// ── Line Items (EVENT campaigns) ──────────────────────────────────────── + +/** + * Create DonationLineItem records for an EVENT campaign donation. + * Looks up item prices to snapshot unitPrice and calculate subtotal. + */ +async function createDonationLineItems( + tx: Prisma.TransactionClient, + donationId: string, + lineItems: Array<{ campaignItemId: string; quantity: number }> +): Promise { + const itemIds = lineItems.map(li => li.campaignItemId); + const items = await tx.campaignItem.findMany({ + where: { id: { in: itemIds } }, + }); + const itemMap = new Map(items.map(i => [i.id, i])); + + for (const li of lineItems) { + const item = itemMap.get(li.campaignItemId); + if (!item) continue; + const unitPrice = Number(item.price); + await tx.donationLineItem.create({ + data: { + donationId, + campaignItemId: li.campaignItemId, + quantity: li.quantity, + unitPrice, + subtotal: unitPrice * li.quantity, + }, + }); + } +} + // ── Queries ───────────────────────────────────────────────────────────── /**