152 lines
4.3 KiB
TypeScript
152 lines
4.3 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server';
|
|
|
|
import { adminApiDisabledResponse, isAdminApiEnabled } from '@/lib/runtime/adminApi';
|
|
|
|
interface RouteParams {
|
|
params: Promise<{
|
|
id: string;
|
|
}>;
|
|
}
|
|
|
|
// GET /api/funnels/[id]/history - получить историю изменений воронки
|
|
export async function GET(request: NextRequest, { params }: RouteParams) {
|
|
if (!isAdminApiEnabled()) {
|
|
return adminApiDisabledResponse();
|
|
}
|
|
|
|
try {
|
|
const { id } = await params;
|
|
const [
|
|
{ default: connectMongoDB },
|
|
{ default: FunnelHistoryModel },
|
|
] = await Promise.all([
|
|
import('@/lib/mongodb'),
|
|
import('@/lib/models/FunnelHistory'),
|
|
]);
|
|
|
|
await connectMongoDB();
|
|
|
|
const { searchParams } = new URL(request.url);
|
|
const sessionId = searchParams.get('sessionId');
|
|
const limit = parseInt(searchParams.get('limit') || '50');
|
|
const includeSnapshots = searchParams.get('snapshots') === 'true';
|
|
|
|
const filter: Record<string, unknown> = { funnelId: id };
|
|
if (sessionId) {
|
|
filter.sessionId = sessionId;
|
|
}
|
|
|
|
const historyQuery = FunnelHistoryModel
|
|
.find(filter)
|
|
.sort({ createdAt: -1, sequenceNumber: -1 })
|
|
.limit(limit);
|
|
|
|
// Включать снимки данных или только метаданные
|
|
if (!includeSnapshots) {
|
|
historyQuery.select('-funnelSnapshot');
|
|
}
|
|
|
|
const history = await historyQuery.lean();
|
|
|
|
return NextResponse.json({
|
|
history: history.map(entry => ({
|
|
...entry,
|
|
_id: entry._id.toString(),
|
|
funnelId: entry.funnelId.toString()
|
|
}))
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('GET /api/funnels/[id]/history error:', error);
|
|
return NextResponse.json(
|
|
{ error: 'Failed to fetch funnel history' },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|
|
|
|
// POST /api/funnels/[id]/history - создать новую запись в истории
|
|
export async function POST(request: NextRequest, { params }: RouteParams) {
|
|
if (!isAdminApiEnabled()) {
|
|
return adminApiDisabledResponse();
|
|
}
|
|
|
|
try {
|
|
const { id } = await params;
|
|
const [
|
|
{ default: connectMongoDB },
|
|
{ default: FunnelHistoryModel },
|
|
] = await Promise.all([
|
|
import('@/lib/mongodb'),
|
|
import('@/lib/models/FunnelHistory'),
|
|
]);
|
|
|
|
await connectMongoDB();
|
|
|
|
const body = await request.json();
|
|
const {
|
|
sessionId,
|
|
funnelSnapshot,
|
|
actionType,
|
|
description,
|
|
changeDetails
|
|
} = body;
|
|
|
|
// Валидация
|
|
if (!sessionId || !funnelSnapshot || !actionType) {
|
|
return NextResponse.json(
|
|
{ error: 'sessionId, funnelSnapshot and actionType are required' },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
// Получаем следующий номер последовательности
|
|
const lastEntry = await FunnelHistoryModel
|
|
.findOne({ funnelId: id, sessionId })
|
|
.sort({ sequenceNumber: -1 });
|
|
|
|
const nextSequenceNumber = (lastEntry?.sequenceNumber || -1) + 1;
|
|
|
|
// Создаем запись
|
|
const historyEntry = await FunnelHistoryModel.create({
|
|
funnelId: id,
|
|
sessionId,
|
|
funnelSnapshot,
|
|
actionType,
|
|
sequenceNumber: nextSequenceNumber,
|
|
description,
|
|
changeDetails
|
|
});
|
|
|
|
// Очищаем старые записи истории (оставляем последние 100)
|
|
const KEEP_ENTRIES = 100;
|
|
const entriesToDelete = await FunnelHistoryModel
|
|
.find({ funnelId: id, sessionId })
|
|
.sort({ sequenceNumber: -1 })
|
|
.skip(KEEP_ENTRIES)
|
|
.select('_id');
|
|
|
|
if (entriesToDelete.length > 0) {
|
|
const idsToDelete = entriesToDelete.map((entry: { _id: unknown }) => entry._id);
|
|
await FunnelHistoryModel.deleteMany({ _id: { $in: idsToDelete } });
|
|
}
|
|
|
|
return NextResponse.json({
|
|
_id: historyEntry._id,
|
|
actionType: historyEntry.actionType,
|
|
description: historyEntry.description,
|
|
sequenceNumber: historyEntry.sequenceNumber,
|
|
isBaseline: historyEntry.isBaseline,
|
|
createdAt: historyEntry.createdAt,
|
|
changeDetails: historyEntry.changeDetails
|
|
}, { status: 201 });
|
|
|
|
} catch (error) {
|
|
console.error('POST /api/funnels/[id]/history error:', error);
|
|
return NextResponse.json(
|
|
{ error: 'Failed to create history entry' },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|