klg-asutk-app/app/api/jira-tasks/route.ts
Yuriy 0150aba4f5 Consolidation: KLG ASUTK + PAPA integration
- Unify API: lib/api.ts uses /api/v1, inbox uses /api/inbox (rewrites)
- Remove localhost refs: openapi, inbox page
- Add rewrites: /api/inbox|tmc -> inbox-server, /api/v1 -> FastAPI
- Add stub routes: knowledge/insights, recommendations, search, log-error
- Transfer from PAPA: prompts (inspection, tmc), scripts, supabase, data/tmc-requests
- Fix inbox-server: ORDER BY created_at, package.json
- Remove redundant app/api/inbox/files route (rewrites handle it)
- knowledge/ in gitignore (large PDFs)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-08 17:18:31 +03:00

155 lines
5.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* API endpoint для работы с задачами Jira
* Данные импортируются из CSV файлов в папке "новая папка"
*/
import { NextRequest, NextResponse } from 'next/server';
import { pool } from '@/lib/database/connection';
import { getRateLimitIdentifier } from '@/lib/rate-limit';
import { rateLimit } from '@/lib/rate-limit';
import { handleError } from '@/lib/error-handler';
export const dynamic = 'force-dynamic';
export async function GET(request: NextRequest) {
try {
// Rate limiting
const rateLimitResult = rateLimit(getRateLimitIdentifier(request));
if (!rateLimitResult.allowed) {
return NextResponse.json(
{ error: 'Слишком много запросов' },
{ status: 429, headers: { 'Retry-After': String(rateLimitResult.resetTime) } }
);
}
const { searchParams } = new URL(request.url);
const type = searchParams.get('type'); // 'epic', 'story', 'subtask', 'all'
const epicId = searchParams.get('epic_id');
const storyId = searchParams.get('story_id');
const client = await pool.connect();
try {
let result;
if (type === 'epic' || !type) {
// Получаем все эпики
const epicsResult = await client.query(
`SELECT
issue_id as "issueId",
summary,
description,
priority,
components,
labels,
created_at as "createdAt",
updated_at as "updatedAt"
FROM jira_epics
ORDER BY
CASE priority
WHEN 'High' THEN 1
WHEN 'Medium' THEN 2
WHEN 'Low' THEN 3
ELSE 4
END,
created_at DESC`
);
// Для каждого эпика получаем связанные истории
for (const epic of epicsResult.rows) {
const storiesResult = await client.query(
`SELECT
issue_id as "issueId",
summary,
description,
priority,
story_points as "storyPoints",
components,
labels,
acceptance_criteria as "acceptanceCriteria",
created_at as "createdAt"
FROM jira_stories
WHERE parent_epic_id = $1
ORDER BY priority DESC, story_points DESC`,
[epic.issueId]
);
epic.stories = storiesResult.rows;
// Для каждой истории получаем подзадачи
for (const story of epic.stories) {
const subtasksResult = await client.query(
`SELECT
issue_id as "issueId",
summary,
description,
priority,
components,
labels,
created_at as "createdAt"
FROM jira_subtasks
WHERE parent_story_id = $1
ORDER BY priority DESC`,
[story.issueId]
);
story.subtasks = subtasksResult.rows;
}
}
result = epicsResult.rows;
} else if (type === 'story') {
const query = epicId
? `SELECT * FROM jira_stories WHERE parent_epic_id = $1 ORDER BY priority DESC, story_points DESC`
: `SELECT * FROM jira_stories ORDER BY priority DESC, story_points DESC`;
const params = epicId ? [epicId] : [];
result = (await client.query(query, params)).rows;
} else if (type === 'subtask') {
const query = storyId
? `SELECT * FROM jira_subtasks WHERE parent_story_id = $1 ORDER BY priority DESC`
: `SELECT * FROM jira_subtasks ORDER BY priority DESC`;
const params = storyId ? [storyId] : [];
result = (await client.query(query, params)).rows;
} else {
// Все задачи
const [epics, stories, subtasks] = await Promise.all([
client.query('SELECT * FROM jira_epics ORDER BY priority DESC'),
client.query('SELECT * FROM jira_stories ORDER BY priority DESC, story_points DESC'),
client.query('SELECT * FROM jira_subtasks ORDER BY priority DESC'),
]);
result = {
epics: epics.rows,
stories: stories.rows,
subtasks: subtasks.rows,
};
}
// Получаем зависимости
const dependenciesResult = await client.query(
`SELECT
from_issue_id as "fromIssueId",
to_issue_id as "toIssueId",
link_type as "linkType"
FROM jira_task_dependencies
ORDER BY created_at DESC`
);
return NextResponse.json({
data: result,
dependencies: dependenciesResult.rows,
meta: {
total: Array.isArray(result) ? result.length : Object.keys(result).length,
type: type || 'epic',
},
});
} finally {
client.release();
}
} catch (error) {
return handleError(error, {
path: '/api/jira-tasks',
method: 'GET',
});
}
}