160 lines
4.8 KiB
TypeScript
160 lines
4.8 KiB
TypeScript
|
|
import { NextRequest, NextResponse } from 'next/server';
|
||
|
|
import { Pool } from 'pg';
|
||
|
|
import { getAuvikClient } from '@/lib/services/auvik-factory';
|
||
|
|
import { AuvikTenantMapping } from '@/lib/types/auvik';
|
||
|
|
|
||
|
|
const pool = new Pool({
|
||
|
|
host: process.env.POSTGRES_HOST,
|
||
|
|
port: parseInt(process.env.POSTGRES_PORT || '5432'),
|
||
|
|
database: process.env.POSTGRES_DB,
|
||
|
|
user: process.env.POSTGRES_USER,
|
||
|
|
password: process.env.POSTGRES_PASSWORD,
|
||
|
|
});
|
||
|
|
|
||
|
|
export async function GET(request: NextRequest) {
|
||
|
|
try {
|
||
|
|
const searchParams = request.nextUrl.searchParams;
|
||
|
|
const includeUnmapped = searchParams.get('includeUnmapped') === 'true';
|
||
|
|
|
||
|
|
// Get all mappings from database
|
||
|
|
const result = await pool.query<{
|
||
|
|
id: number;
|
||
|
|
auvik_tenant_id: string;
|
||
|
|
auvik_tenant_name: string;
|
||
|
|
autotask_company_id: number;
|
||
|
|
autotask_company_name: string;
|
||
|
|
created_at: string;
|
||
|
|
updated_at: string;
|
||
|
|
}>('SELECT * FROM auvik_tenant_mappings ORDER BY auvik_tenant_name');
|
||
|
|
|
||
|
|
const mappings: AuvikTenantMapping[] = result.rows.map((row) => ({
|
||
|
|
id: row.id,
|
||
|
|
auvikTenantId: row.auvik_tenant_id,
|
||
|
|
auvikTenantName: row.auvik_tenant_name,
|
||
|
|
autotaskCompanyId: row.autotask_company_id,
|
||
|
|
autotaskCompanyName: row.autotask_company_name,
|
||
|
|
createdAt: row.created_at,
|
||
|
|
updatedAt: row.updated_at,
|
||
|
|
}));
|
||
|
|
|
||
|
|
// If includeUnmapped is true, fetch all Auvik tenants and merge
|
||
|
|
if (includeUnmapped) {
|
||
|
|
const auvikClient = getAuvikClient();
|
||
|
|
const allTenants = await auvikClient.getTenants();
|
||
|
|
|
||
|
|
const mappedTenantIds = new Set(mappings.map((m) => m.auvikTenantId));
|
||
|
|
|
||
|
|
const unmappedTenants = allTenants
|
||
|
|
.filter((t) => !mappedTenantIds.has(t.id))
|
||
|
|
.map((t) => ({
|
||
|
|
id: 0, // Temporary ID for unmapped
|
||
|
|
auvikTenantId: t.id,
|
||
|
|
auvikTenantName: t.domainPrefix,
|
||
|
|
autotaskCompanyId: 0,
|
||
|
|
autotaskCompanyName: '',
|
||
|
|
createdAt: '',
|
||
|
|
updatedAt: '',
|
||
|
|
}));
|
||
|
|
|
||
|
|
return NextResponse.json({
|
||
|
|
mappings: [...mappings, ...unmappedTenants],
|
||
|
|
totalMapped: mappings.length,
|
||
|
|
totalUnmapped: unmappedTenants.length,
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
return NextResponse.json({ mappings });
|
||
|
|
} catch (error) {
|
||
|
|
console.error('Error fetching tenant mappings:', error);
|
||
|
|
return NextResponse.json(
|
||
|
|
{ error: 'Failed to fetch tenant mappings' },
|
||
|
|
{ status: 500 }
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function POST(request: NextRequest) {
|
||
|
|
try {
|
||
|
|
const body = await request.json();
|
||
|
|
const {
|
||
|
|
auvikTenantId,
|
||
|
|
auvikTenantName,
|
||
|
|
autotaskCompanyId,
|
||
|
|
autotaskCompanyName,
|
||
|
|
} = body;
|
||
|
|
|
||
|
|
if (!auvikTenantId || !autotaskCompanyId) {
|
||
|
|
return NextResponse.json(
|
||
|
|
{ error: 'Missing required fields' },
|
||
|
|
{ status: 400 }
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Insert or update mapping
|
||
|
|
const result = await pool.query<{
|
||
|
|
id: number;
|
||
|
|
auvik_tenant_id: string;
|
||
|
|
auvik_tenant_name: string;
|
||
|
|
autotask_company_id: number;
|
||
|
|
autotask_company_name: string;
|
||
|
|
created_at: string;
|
||
|
|
updated_at: string;
|
||
|
|
}>(
|
||
|
|
`INSERT INTO auvik_tenant_mappings
|
||
|
|
(auvik_tenant_id, auvik_tenant_name, autotask_company_id, autotask_company_name)
|
||
|
|
VALUES ($1, $2, $3, $4)
|
||
|
|
ON CONFLICT (auvik_tenant_id)
|
||
|
|
DO UPDATE SET
|
||
|
|
autotask_company_id = EXCLUDED.autotask_company_id,
|
||
|
|
autotask_company_name = EXCLUDED.autotask_company_name,
|
||
|
|
updated_at = CURRENT_TIMESTAMP
|
||
|
|
RETURNING *`,
|
||
|
|
[auvikTenantId, auvikTenantName, autotaskCompanyId, autotaskCompanyName]
|
||
|
|
);
|
||
|
|
|
||
|
|
const mapping: AuvikTenantMapping = {
|
||
|
|
id: result.rows[0].id,
|
||
|
|
auvikTenantId: result.rows[0].auvik_tenant_id,
|
||
|
|
auvikTenantName: result.rows[0].auvik_tenant_name,
|
||
|
|
autotaskCompanyId: result.rows[0].autotask_company_id,
|
||
|
|
autotaskCompanyName: result.rows[0].autotask_company_name,
|
||
|
|
createdAt: result.rows[0].created_at,
|
||
|
|
updatedAt: result.rows[0].updated_at,
|
||
|
|
};
|
||
|
|
|
||
|
|
return NextResponse.json({ mapping });
|
||
|
|
} catch (error) {
|
||
|
|
console.error('Error creating tenant mapping:', error);
|
||
|
|
return NextResponse.json(
|
||
|
|
{ error: 'Failed to create tenant mapping' },
|
||
|
|
{ status: 500 }
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function DELETE(request: NextRequest) {
|
||
|
|
try {
|
||
|
|
const searchParams = request.nextUrl.searchParams;
|
||
|
|
const id = searchParams.get('id');
|
||
|
|
|
||
|
|
if (!id) {
|
||
|
|
return NextResponse.json(
|
||
|
|
{ error: 'Missing mapping ID' },
|
||
|
|
{ status: 400 }
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
await pool.query('DELETE FROM auvik_tenant_mappings WHERE id = $1', [
|
||
|
|
parseInt(id),
|
||
|
|
]);
|
||
|
|
|
||
|
|
return NextResponse.json({ success: true });
|
||
|
|
} catch (error) {
|
||
|
|
console.error('Error deleting tenant mapping:', error);
|
||
|
|
return NextResponse.json(
|
||
|
|
{ error: 'Failed to delete tenant mapping' },
|
||
|
|
{ status: 500 }
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|