import { DomaApplication, DomaApplicationStatus } from '../types'; import { backendApi } from './apiClient'; import { domaGraphQLClient, DomaTicket } from './domaGraphQLClient'; import { settingsService } from './settingsService'; /** * Сервис для работы с Doma AI API * Интегрирует GraphQL API Doma AI для получения заявок */ export const domaService = { /** * Инициализация подключения к Doma AI * Выполняет аутентификацию, если токен не сохранен * Использует настройки из localStorage или переменные окружения как fallback */ async initialize(): Promise { // Обновляем настройки в клиенте domaGraphQLClient.updateSettings(); // Получаем настройки из localStorage const settings = settingsService.getDomaAISettings(); // Проверяем, настроен ли URL API (из настроек или переменных окружения) const apiUrl = settings?.apiUrl || import.meta.env.VITE_DOMA_AI_API_URL; if (!apiUrl) { console.warn( '[domaService] URL API Doma AI не настроен. ' + 'Укажите URL в настройках интеграций или в переменных окружения.' ); return false; } // Если в настройках уже есть токен, просто используем его (без health-check запроса) if (settings?.token) { domaGraphQLClient.setToken(settings.token); return true; } // Если токен уже есть в клиенте, считаем, что авторизация настроена if (domaGraphQLClient.hasToken()) { return true; } // Пытаемся получить учетные данные из настроек или переменных окружения const email = settings?.email || import.meta.env.VITE_DOMA_AI_EMAIL; const password = settings?.password || import.meta.env.VITE_DOMA_AI_PASSWORD; const phone = settings?.phone || import.meta.env.VITE_DOMA_AI_PHONE; if (!email && !phone) { console.warn( '[domaService] Учетные данные Doma AI не настроены. ' + 'Укажите email/телефон и пароль в настройках интеграций или в переменных окружения.' ); return false; } if (!password) { console.warn('[domaService] Пароль Doma AI не настроен. Укажите пароль в настройках интеграций.'); return false; } try { if (email && password) { await domaGraphQLClient.authenticate(email, password); } else if (phone && password) { await domaGraphQLClient.authenticateWithPhone(phone, password); } else { return false; } return true; } catch (error) { console.error('[domaService] Ошибка авторизации в Doma AI:', error); return false; } }, /** * Преобразует заявку из формата Doma AI в формат приложения */ mapDomaTicketToApplication(ticket: DomaTicket): DomaApplication { // Маппинг статусов Doma AI в статусы приложения const statusMap: Record = { 'new': 'new', 'in_progress': 'in_progress', 'inProgress': 'in_progress', 'done': 'done', 'completed': 'done', 'canceled': 'canceled', 'cancelled': 'canceled', }; const statusType = ticket.status?.type?.toLowerCase() || ticket.status?.name?.toLowerCase() || 'new'; const mappedStatus = statusMap[statusType] || 'new'; return { id: parseInt(ticket.id) || Date.now(), // Если ID не число, используем timestamp number: ticket.number || ticket.id, status: mappedStatus, description: ticket.description || ticket.details || 'Без описания', address: ticket.property?.address || 'Адрес не указан', apartment: ticket.property?.unitName || '—', clientName: ticket.client?.name || 'Клиент не указан', createdAt: ticket.createdAt || new Date().toISOString(), deadlineAt: ticket.deadline || new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(), // По умолчанию +7 дней performer: ticket.assignee ? { name: ticket.assignee.name } : undefined, }; }, /** * Получает список заявок из Doma AI * @param filters - Фильтры для запроса заявок * @returns Массив заявок в формате приложения */ async getApplications(filters?: { status?: DomaApplicationStatus; limit?: number; }): Promise { console.log('[domaService] Получение заявок из Doma AI...'); // Проверяем и инициализируем подключение, если нужно if (!domaGraphQLClient.hasToken()) { const initialized = await this.initialize(); if (!initialized) { console.warn('[domaService] Не удалось подключиться к Doma AI, используем fallback'); return this.getApplicationsFallback(); } } try { // Преобразуем фильтры для Doma AI const domaFilters: any = {}; if (filters?.status) { // Маппинг статусов обратно (упрощенный вариант) // В реальности нужно знать ID статусов в Doma AI domaFilters.status = filters.status; } // Получаем заявки из Doma AI const tickets = await domaGraphQLClient.getTickets({ ...domaFilters, limit: filters?.limit || 100, }); // Преобразуем в формат приложения const applications = tickets.map(ticket => this.mapDomaTicketToApplication(ticket)); console.log(`[domaService] Получено ${applications.length} заявок из Doma AI`); return applications; } catch (error) { console.error('[domaService] Ошибка при получении заявок из Doma AI:', error); // Fallback: пробуем получить из бэкенда return this.getApplicationsFallback(); } }, /** * Fallback метод: получает заявки из бэкенда * Важно: демо-мок-данные больше не используются, чтобы не путать с реальной интеграцией */ async getApplicationsFallback(): Promise { try { console.log('[domaService] Попытка получить заявки из бэкенда...'); const apps = await backendApi.getApplications(); return apps; } catch (error) { console.warn('[domaService] Бэкенд недоступен, возвращаем пустой список заявок:', error); return []; } }, /** * Обновление статуса заявки в Doma AI * @param ticketId - ID заявки в Doma AI * @param status - Новый статус */ async updateApplicationStatus(ticketId: string, status: DomaApplicationStatus): Promise { if (!domaGraphQLClient.hasToken()) { const initialized = await this.initialize(); if (!initialized) { throw new Error('Не удалось авторизоваться в Doma AI'); } } // TODO: Реализовать мутацию для обновления статуса заявки // Это зависит от схемы GraphQL в Doma AI console.warn('[domaService] Обновление статуса заявки в Doma AI пока не реализовано'); return false; }, };