← back to Norma
app/api/partners/route.ts
140 lines
import { NextRequest, NextResponse } from 'next/server';
import { query } from '@/lib/db';
import { requireRole } from '@/lib/require-role';
import { getOrgId } from '@/lib/orgId';
/**
* GET /api/partners?type=&status=&limit=&offset=
* Returns current partners, optionally filtered. Supports pagination.
*/
export async function GET(request: NextRequest) {
const auth = requireRole(request, 'admin', 'staff');
if (auth instanceof NextResponse) return auth;
const { searchParams } = new URL(request.url);
const pType = searchParams.get('type');
const status = searchParams.get('status');
const orgId = auth.role === 'admin' ? getOrgId(request) : auth.orgId;
let limit = parseInt(searchParams.get('limit') || '50', 10);
if (isNaN(limit) || limit < 1) limit = 50;
if (limit > 200) limit = 200;
let offset = parseInt(searchParams.get('offset') || '0', 10);
if (isNaN(offset) || offset < 0) offset = 0;
const conditions: string[] = [];
const params: unknown[] = [];
let idx = 1;
if (orgId) {
conditions.push(`org_id = $${idx++}`);
params.push(orgId);
}
if (pType) {
conditions.push(`partner_type = $${idx++}`);
params.push(pType);
}
if (status) {
conditions.push(`status = $${idx++}`);
params.push(status);
}
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
try {
const countResult = await query(
`SELECT COUNT(*)::int AS total FROM partners ${whereClause}`,
params
);
const total = countResult.rows[0]?.total ?? 0;
const { rows } = await query(
`SELECT * FROM partners ${whereClause}
ORDER BY partnership_since DESC NULLS LAST, created_at DESC
LIMIT $${idx} OFFSET $${idx + 1}`,
[...params, limit, offset]
);
return NextResponse.json({ partners: rows, total, limit, offset });
} catch (err) {
console.error('[partners] GET error:', (err as Error).message);
return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
}
}
/**
* POST /api/partners
* Create or update a partner.
*/
export async function POST(request: NextRequest) {
const auth = requireRole(request, 'admin', 'staff');
if (auth instanceof NextResponse) return auth;
try {
const body = await request.json();
const {
partner_type, name, contact_name, contact_title, email, phone,
website_url, city, state, partnership_since, partnership_value,
focus_areas, description, status: pStatus, notes,
} = body;
if (!partner_type || !name) {
return NextResponse.json({ error: 'partner_type and name required' }, { status: 400 });
}
const orgId = auth.role === 'admin' ? getOrgId(request) : auth.orgId;
const { rows } = await query(
`INSERT INTO partners (
partner_type, name, contact_name, contact_title, email, phone,
website_url, city, state, partnership_since, partnership_value,
focus_areas, description, status, notes, last_interaction, org_id
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15, CURRENT_DATE, $16)
RETURNING *`,
[
partner_type, name, contact_name || null, contact_title || null,
email || null, phone || null, website_url || null, city || null,
state || null, partnership_since || null, partnership_value || null,
focus_areas || null, description || null, pStatus || 'active', notes || null,
orgId,
]
);
return NextResponse.json({ partner: rows[0] });
} catch (err) {
console.error('[partners] POST error:', (err as Error).message);
return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
}
}
/**
* PATCH /api/partners
* Update partner status or details.
*/
export async function PATCH(request: NextRequest) {
const auth = requireRole(request, 'admin', 'staff');
if (auth instanceof NextResponse) return auth;
try {
const body = await request.json();
const { id, ...updates } = body;
if (!id) return NextResponse.json({ error: 'id required' }, { status: 400 });
const allowedFields = ['status', 'name', 'type', 'website', 'contact_name', 'contact_email', 'contact_phone', 'notes', 'tags', 'priority', 'partnership_type'];
const fields = Object.keys(updates).filter(f => f !== 'id' && allowedFields.includes(f));
if (fields.length === 0) return NextResponse.json({ error: 'No fields to update' }, { status: 400 });
const setClauses = fields.map((f, i) => `${f} = $${i + 2}`);
const values = fields.map(f => updates[f]);
const { rows } = await query(
`UPDATE partners SET ${setClauses.join(', ')} WHERE id = $1 RETURNING *`,
[id, ...values]
);
return NextResponse.json({ partner: rows[0] });
} catch (err) {
console.error('[partners] PATCH error:', (err as Error).message);
return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
}
}