Report API

Report API для бизнес-отчетности и генерации аналитики с 8 методами для создания различных типов отчетов.

Обзор

Report API предоставляет комплексные инструменты для создания бизнес-отчетов, аналитики продаж, финансовых отчетов и управления данными.

Основные возможности:

  • 💰 Финансовые отчеты и анализ денежных потоков
  • 📦 Отчеты по товарам и остаткам на складах
  • 📊 Аналитика отправлений и заказов
  • 🔄 Отчеты о возвратах и уценках
  • 📈 Мониторинг статусов отчетов
  • 📋 Управление списком созданных отчетов
  • 📁 Скачивание готовых отчетов в различных форматах

Доступные методы

Финансовые отчеты

getFinanceCashFlowStatement(request) - Финансовый отчет

const financialReport = await reportApi.getFinanceCashFlowStatement({
  date: { from: '2024-01-01', to: '2024-01-31' },
  page: 1,
  page_size: 100
});

Создание отчетов

createDiscountedReport(request) - Отчет об уценённых товарах

const discountedReport = await reportApi.createDiscountedReport({});

createPostingsReport(request) - Отчет об отправлениях

const postingsReport = await reportApi.createPostingsReport({
  filter: {
    since: '2024-01-01',
    to: '2024-01-31'
  }
});

createProductsReport(request) - Отчет по товарам

const productsReport = await reportApi.createProductsReport({
  sku: [123456789, 987654321],
  visibility: 'VISIBLE'
});

createStockByWarehouseReport(request) - Отчет об остатках на FBS-складе

const stockReport = await reportApi.createStockByWarehouseReport({
  warehouseId: ['12345', '67890']
});

createReturnsReport(request) - Отчет о возвратах

const returnsReport = await reportApi.createReturnsReport({
  date_from: '2024-01-01',
  date_to: '2024-01-31'
});

Управление отчетами

getReportInfo(request) - Информация об отчете

const reportInfo = await reportApi.getReportInfo({
  code: 'report_code_123'
});

getReportList(request) - Список отчетов

const reportList = await reportApi.getReportList({
  page: 1,
  page_size: 50
});

TypeScript интерфейсы

// Основные запросы
interface ReportFinanceCashFlowStatementListRequest {
  date: {
    from: string;
    to: string;
  };
  page: number;
  page_size: number;
  with_details?: boolean;
}

interface ReportCreateDiscountedRequest {
  // Пустой объект - параметры не требуются
}

interface ReportInfoRequest {
  code: string;
}

interface ReportListRequest {
  page: number;
  page_size: number;
  report_type?: "PRODUCTS" | "POSTINGS" | "DISCOUNTED" | "STOCK" | "RETURNS" | "FINANCE";
}

interface ReportCreatePostingsRequest {
  filter: {
    since: string;
    to: string;
    status?: string[];
  };
  language?: "RU" | "EN";
}

interface ReportCreateProductsRequest {
  sku?: number[];
  visibility?: "VISIBLE" | "INVISIBLE" | "ALL";
  language?: "RU" | "EN";
}

interface ReportCreateStockByWarehouseRequest {
  warehouseId: string[];
  language?: "RU" | "EN";
}

interface ReportCreateReturnsRequest {
  date_from: string;
  date_to: string;
  language?: "RU" | "EN";
}

// Ответы
interface ReportFinanceCashFlowStatementListResponse {
  result: {
    operations: Array<{
      operation_id: string;
      operation_type: string;
      operation_date: string;
      operation_type_name: string;
      delivery_charge: string;
      return_delivery_charge: string;
      accruals_for_sale: string;
      sale_commission: string;
      amount: string;
      currency: string;
      items: Array<{
        sku: number;
        name: string;
        offer_id: string;
        price: string;
        commission_amount: string;
        commission_percent: string;
        quantity: number;
      }>;
    }>;
    page_count: number;
    page_size: number;
    page: number;
    total_count: number;
  };
}

interface ReportCreateDiscountedResponse {
  code: string;
  result: "ok" | "error";
}

interface ReportInfoResponse {
  result: {
    code: string;
    created_at: string;
    error: string;
    file_name: string;
    status: "PROCESSING" | "SUCCESS" | "FAILED";
    download_url?: string;
    report_type: string;
    params: Record<string, any>;
  };
}

interface ReportListResponse {
  result: {
    reports: Array<{
      code: string;
      created_at: string;
      error: string;
      file_name: string;
      status: "PROCESSING" | "SUCCESS" | "FAILED";
      download_url?: string;
      report_type: "PRODUCTS" | "POSTINGS" | "DISCOUNTED" | "STOCK" | "RETURNS" | "FINANCE";
      params: Record<string, any>;
    }>;
    count: number;
  };
}

interface ReportCreateResponse {
  result: {
    code: string;
  };
}

interface ReportCreateReturnsResponse {
  code: string;
  result: "ok" | "error";
}

Примеры использования

Создание финансового отчета

// Получение финансового отчета за январь 2024
const financialReport = await reportApi.getFinanceCashFlowStatement({
  date: {
    from: '2024-01-01',
    to: '2024-01-31'
  },
  page: 1,
  page_size: 100,
  with_details: true
});

console.log(`\n=== Финансовый отчет за ${financialReport.result.page} из ${financialReport.result.page_count} ===`);
console.log(`Общее количество операций: ${financialReport.result.total_count}`);

let totalAmount = 0;
const operationsSummary = new Map<string, { count: number; amount: number }>();

financialReport.result.operations.forEach(operation => {
  const amount = parseFloat(operation.amount);
  totalAmount += amount;

  const existing = operationsSummary.get(operation.operation_type_name) || { count: 0, amount: 0 };
  existing.count++;
  existing.amount += amount;
  operationsSummary.set(operation.operation_type_name, existing);

  console.log(`\n${operation.operation_date}: ${operation.operation_type_name}`);
  console.log(`Сумма: ${operation.amount} ${operation.currency}`);
  
  if (operation.items.length > 0) {
    console.log(`Товары (${operation.items.length}):`);
    operation.items.slice(0, 3).forEach(item => {
      console.log(`  - ${item.name}: ${item.quantity} шт × ${item.price} руб (комиссия: ${item.commission_percent}%)`);
    });
    if (operation.items.length > 3) {
      console.log(`  ... и ещё ${operation.items.length - 3} товаров`);
    }
  }
});

console.log(`\n=== Сводка по типам операций ===`);
operationsSummary.forEach((summary, operationType) => {
  console.log(`${operationType}: ${summary.count} операций на сумму ${summary.amount.toFixed(2)} руб`);
});

console.log(`\nОбщая сумма: ${totalAmount.toFixed(2)} руб`);

Создание и мониторинг отчетов

// Создание отчета по товарам
console.log("Создание отчета по товарам...");
const productsReport = await reportApi.createProductsReport({
  visibility: 'VISIBLE',
  language: 'RU'
});

console.log(`Отчет создан с кодом: ${productsReport.result.code}`);

// Создание отчета об отправлениях
console.log("\nСоздание отчета об отправлениях...");
const postingsReport = await reportApi.createPostingsReport({
  filter: {
    since: '2024-01-01',
    to: '2024-01-31',
    status: ['DELIVERED', 'CANCELLED', 'RETURNED']
  },
  language: 'RU'
});

console.log(`Отчет об отправлениях создан: ${postingsReport.result.code}`);

// Создание отчета о возвратах
console.log("\nСоздание отчета о возвратах...");
const returnsReport = await reportApi.createReturnsReport({
  date_from: '2024-01-01',
  date_to: '2024-01-31',
  language: 'RU'
});

console.log(`Отчет о возвратах создан: ${returnsReport.code}`);

// Мониторинг статуса отчетов
const reportCodes = [
  productsReport.result.code,
  postingsReport.result.code,
  returnsReport.code
];

console.log("\n=== Мониторинг статуса отчетов ===");
const checkReportStatus = async (code: string): Promise<void> => {
  let attempts = 0;
  const maxAttempts = 30; // максимум 5 минут ожидания

  while (attempts < maxAttempts) {
    const reportInfo = await reportApi.getReportInfo({ code });
    
    console.log(`Отчет ${code}: ${reportInfo.result.status}`);
    
    if (reportInfo.result.status === 'SUCCESS') {
      console.log(`✅ Отчет готов: ${reportInfo.result.file_name}`);
      if (reportInfo.result.download_url) {
        console.log(`🔗 Ссылка для скачивания: ${reportInfo.result.download_url}`);
      }
      return;
    } else if (reportInfo.result.status === 'FAILED') {
      console.log(`❌ Ошибка создания отчета: ${reportInfo.result.error}`);
      return;
    }
    
    // Ждем 10 секунд перед следующей проверкой
    await new Promise(resolve => setTimeout(resolve, 10000));
    attempts++;
  }
  
  console.log(`⏱️ Превышено время ожидания для отчета ${code}`);
};

// Проверяем статус всех отчетов параллельно
await Promise.all(reportCodes.map(code => checkReportStatus(code)));

Управление списком отчетов

// Получение списка всех отчетов
const allReports = await reportApi.getReportList({
  page: 1,
  page_size: 100
});

console.log(`\n=== Управление отчетами (${allReports.result.count} всего) ===`);

// Группировка отчетов по типам и статусам
const reportsByType = new Map<string, any[]>();
const reportsByStatus = new Map<string, any[]>();

allReports.result.reports.forEach(report => {
  // Группировка по типам
  const byType = reportsByType.get(report.report_type) || [];
  byType.push(report);
  reportsByType.set(report.report_type, byType);

  // Группировка по статусам  
  const byStatus = reportsByStatus.get(report.status) || [];
  byStatus.push(report);
  reportsByStatus.set(report.status, byStatus);
});

console.log("\nОтчеты по типам:");
reportsByType.forEach((reports, type) => {
  console.log(`  ${type}: ${reports.length} отчетов`);
  
  // Показываем последние 3 отчета этого типа
  reports
    .sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())
    .slice(0, 3)
    .forEach(report => {
      const date = new Date(report.created_at).toLocaleDateString('ru-RU');
      const status = report.status === 'SUCCESS' ? '' : report.status === 'FAILED' ? '' : '';
      console.log(`    ${status} ${date}: ${report.file_name || report.code}`);
    });
});

console.log("\nОтчеты по статусам:");
reportsByStatus.forEach((reports, status) => {
  console.log(`  ${status}: ${reports.length} отчетов`);
});

// Поиск и скачивание успешных отчетов за последнюю неделю
const weekAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
const recentSuccessfulReports = allReports.result.reports.filter(report => 
  report.status === 'SUCCESS' && 
  new Date(report.created_at) > weekAgo &&
  report.download_url
);

if (recentSuccessfulReports.length > 0) {
  console.log(`\n📁 Готовые отчеты за последнюю неделю (${recentSuccessfulReports.length}):`);
  recentSuccessfulReports.forEach(report => {
    const date = new Date(report.created_at).toLocaleDateString('ru-RU');
    console.log(`  📊 ${date}: ${report.file_name} (${report.report_type})`);
    console.log(`     🔗 ${report.download_url}`);
  });
}

Анализ уценённых товаров

// Создание отчета об уценённых товарах
console.log("Создание отчета об уценённых товарах...");
const discountedReport = await reportApi.createDiscountedReport({});

console.log(`Отчет об уценках создан: ${discountedReport.code}`);

// Ожидание готовности отчета
let discountedReportInfo;
let attempts = 0;
const maxAttempts = 20;

while (attempts < maxAttempts) {
  discountedReportInfo = await reportApi.getReportInfo({ 
    code: discountedReport.code 
  });
  
  if (discountedReportInfo.result.status === 'SUCCESS') {
    console.log("✅ Отчет об уценках готов!");
    break;
  } else if (discountedReportInfo.result.status === 'FAILED') {
    console.log(`❌ Ошибка создания отчета об уценках: ${discountedReportInfo.result.error}`);
    return;
  }
  
  console.log(`⏳ Создание отчета... (попытка ${attempts + 1}/${maxAttempts})`);
  await new Promise(resolve => setTimeout(resolve, 15000)); // ждем 15 секунд
  attempts++;
}

if (discountedReportInfo?.result.status === 'SUCCESS') {
  console.log(`📊 Отчет: ${discountedReportInfo.result.file_name}`);
  if (discountedReportInfo.result.download_url) {
    console.log(`🔗 Скачать: ${discountedReportInfo.result.download_url}`);
  }
  
  // Здесь можно добавить логику для анализа содержимого отчета
  // после его скачивания и парсинга
}

Сложные сценарии

ReportingDashboard - Система автоматической отчетности

class ReportingDashboard {
  constructor(private api: ReportApi) {}

  async generateComprehensiveReport(period: ReportPeriod): Promise<ComprehensiveReport> {
    console.log(`🚀 Создание комплексного отчета за период: ${period.from} - ${period.to}`);

    // Создание всех типов отчетов параллельно
    const reportCreationPromises = await Promise.allSettled([
      this.createFinancialReport(period),
      this.createPostingsReport(period),
      this.createProductsReport(),
      this.createReturnsReport(period),
      this.createDiscountedReport(),
      this.createStockReport()
    ]);

    // Ожидание готовности всех отчетов
    const readyReports = await this.waitForReportsCompletion(reportCreationPromises);
    
    // Анализ и агрегация данных
    const analytics = await this.generateAnalytics(readyReports, period);
    
    return {
      period,
      reports: readyReports,
      analytics,
      recommendations: this.generateRecommendations(analytics),
      created_at: new Date().toISOString()
    };
  }

  private async createFinancialReport(period: ReportPeriod): Promise<FinancialReportData> {
    console.log("📊 Создание финансового отчета...");
    
    const report = await this.api.getFinanceCashFlowStatement({
      date: { from: period.from, to: period.to },
      page: 1,
      page_size: 1000,
      with_details: true
    });

    return {
      type: 'FINANCIAL',
      data: report.result,
      summary: this.analyzeFinancialData(report.result)
    };
  }

  private async createPostingsReport(period: ReportPeriod): Promise<string> {
    console.log("📦 Создание отчета об отправлениях...");
    
    const report = await this.api.createPostingsReport({
      filter: {
        since: period.from,
        to: period.to
      },
      language: 'RU'
    });

    return report.result.code;
  }

  private async waitForReportsCompletion(
    creationPromises: PromiseSettledResult<any>[]
  ): Promise<ReportInfo[]> {
    const reportCodes: string[] = [];
    
    // Извлекаем коды отчетов из успешных запросов создания
    creationPromises.forEach((result, index) => {
      if (result.status === 'fulfilled') {
        const reportTypes = ['FINANCIAL', 'POSTINGS', 'PRODUCTS', 'RETURNS', 'DISCOUNTED', 'STOCK'];
        if (result.value && (result.value.result?.code || result.value.code)) {
          reportCodes.push(result.value.result?.code || result.value.code);
          console.log(`✅ ${reportTypes[index]} отчет создан`);
        }
      } else {
        console.error(`❌ Ошибка создания отчета:`, result.reason);
      }
    });

    // Мониторинг готовности отчетов
    const readyReports: ReportInfo[] = [];
    const maxWaitTime = 10 * 60 * 1000; // 10 минут
    const checkInterval = 15 * 1000; // 15 секунд
    const startTime = Date.now();

    while (readyReports.length < reportCodes.length && (Date.now() - startTime) < maxWaitTime) {
      const pendingCodes = reportCodes.filter(code => 
        !readyReports.some(report => report.code === code)
      );

      for (const code of pendingCodes) {
        try {
          const reportInfo = await this.api.getReportInfo({ code });
          
          if (reportInfo.result.status === 'SUCCESS') {
            readyReports.push(reportInfo.result);
            console.log(`✅ Отчет ${code} готов: ${reportInfo.result.file_name}`);
          } else if (reportInfo.result.status === 'FAILED') {
            console.error(`❌ Отчет ${code} завершился с ошибкой: ${reportInfo.result.error}`);
            // Добавляем неудачный отчет в список, чтобы не ждать его бесконечно
            readyReports.push(reportInfo.result);
          }
        } catch (error) {
          console.error(`Ошибка получения статуса отчета ${code}:`, error);
        }
      }

      if (readyReports.length < reportCodes.length) {
        console.log(`⏳ Ожидание готовности отчетов: ${readyReports.length}/${reportCodes.length}`);
        await new Promise(resolve => setTimeout(resolve, checkInterval));
      }
    }

    return readyReports;
  }

  private async generateAnalytics(reports: ReportInfo[], period: ReportPeriod): Promise<BusinessAnalytics> {
    return {
      revenue_analysis: this.analyzeRevenue(reports),
      product_performance: this.analyzeProductPerformance(reports),
      logistics_efficiency: this.analyzeLogistics(reports),
      return_analysis: this.analyzeReturns(reports),
      cost_analysis: this.analyzeCosts(reports),
      trend_analysis: this.analyzeTrends(reports, period)
    };
  }

  private analyzeFinancialData(financialData: any): FinancialSummary {
    const totalRevenue = financialData.operations.reduce((sum: number, op: any) => {
      return sum + parseFloat(op.accruals_for_sale || '0');
    }, 0);

    const totalCommissions = financialData.operations.reduce((sum: number, op: any) => {
      return sum + parseFloat(op.sale_commission || '0');
    }, 0);

    const totalDeliveryCharges = financialData.operations.reduce((sum: number, op: any) => {
      return sum + parseFloat(op.delivery_charge || '0');
    }, 0);

    return {
      total_revenue: totalRevenue,
      total_commissions: totalCommissions,
      total_delivery_charges: totalDeliveryCharges,
      net_profit: totalRevenue - totalCommissions - totalDeliveryCharges,
      average_order_value: totalRevenue / financialData.operations.length,
      commission_rate: totalCommissions / totalRevenue * 100
    };
  }

  private generateRecommendations(analytics: BusinessAnalytics): BusinessRecommendation[] {
    const recommendations: BusinessRecommendation[] = [];

    // Анализ выручки
    if (analytics.revenue_analysis.growth_rate < 0) {
      recommendations.push({
        category: 'REVENUE',
        priority: 'HIGH',
        title: 'Снижение выручки требует внимания',
        description: `Выручка снизилась на ${Math.abs(analytics.revenue_analysis.growth_rate).toFixed(1)}%`,
        actions: [
          'Проанализировать причины снижения продаж',
          'Рассмотреть расширение ассортимента',
          'Оптимизировать ценовую стратегию'
        ]
      });
    }

    // Анализ возвратов
    if (analytics.return_analysis.return_rate > 0.15) {
      recommendations.push({
        category: 'QUALITY',
        priority: 'MEDIUM',
        title: 'Высокий уровень возвратов',
        description: `Уровень возвратов составляет ${(analytics.return_analysis.return_rate * 100).toFixed(1)}%`,
        actions: [
          'Улучшить качество описаний товаров',
          'Проверить качество упаковки',
          'Проанализировать причины возвратов'
        ]
      });
    }

    return recommendations.sort((a, b) => {
      const priorityOrder = { 'HIGH': 3, 'MEDIUM': 2, 'LOW': 1 };
      return priorityOrder[b.priority] - priorityOrder[a.priority];
    });
  }
}

interface ReportPeriod {
  from: string;
  to: string;
}

interface ComprehensiveReport {
  period: ReportPeriod;
  reports: ReportInfo[];
  analytics: BusinessAnalytics;
  recommendations: BusinessRecommendation[];
  created_at: string;
}

interface BusinessAnalytics {
  revenue_analysis: RevenueAnalysis;
  product_performance: ProductPerformance;
  logistics_efficiency: LogisticsEfficiency;
  return_analysis: ReturnAnalysis;
  cost_analysis: CostAnalysis;
  trend_analysis: TrendAnalysis;
}

interface BusinessRecommendation {
  category: 'REVENUE' | 'COSTS' | 'LOGISTICS' | 'QUALITY' | 'MARKETING';
  priority: 'HIGH' | 'MEDIUM' | 'LOW';
  title: string;
  description: string;
  actions: string[];
}

AutomatedReportScheduler - Планировщик автоматических отчетов

class AutomatedReportScheduler {
  private scheduledJobs = new Map<string, NodeJS.Timeout>();

  constructor(private api: ReportApi) {}

  scheduleRegularReports(): void {
    // Еженедельные отчеты (каждый понедельник)
    this.scheduleWeeklyReports();
    
    // Ежемесячные отчеты (1-го числа каждого месяца)
    this.scheduleMonthlyReports();
    
    // Ежедневные быстрые отчеты
    this.scheduleDailyReports();
  }

  private scheduleWeeklyReports(): void {
    const weeklyJob = setInterval(async () => {
      if (new Date().getDay() === 1) { // понедельник
        console.log("📅 Запуск еженедельных отчетов...");
        
        const lastWeek = this.getLastWeekPeriod();
        await this.generateWeeklyReportSuite(lastWeek);
      }
    }, 24 * 60 * 60 * 1000); // проверяем каждые 24 часа

    this.scheduledJobs.set('weekly', weeklyJob);
  }

  private async generateWeeklyReportSuite(period: ReportPeriod): Promise<void> {
    try {
      // Создаем набор еженедельных отчетов
      const reports = await Promise.allSettled([
        this.api.createPostingsReport({
          filter: {
            since: period.from,
            to: period.to
          },
          language: 'RU'
        }),
        this.api.createReturnsReport({
          date_from: period.from,
          date_to: period.to,
          language: 'RU'
        }),
        this.api.createDiscountedReport({})
      ]);

      console.log(`✅ Еженедельные отчеты за ${period.from} - ${period.to} созданы`);
      
      // Отправка уведомления о готовности отчетов
      this.notifyReportsReady('weekly', period);
      
    } catch (error) {
      console.error("❌ Ошибка создания еженедельных отчетов:", error);
    }
  }

  private getLastWeekPeriod(): ReportPeriod {
    const now = new Date();
    const lastWeek = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
    
    // Начало недели (понедельник)
    const weekStart = new Date(lastWeek);
    weekStart.setDate(lastWeek.getDate() - lastWeek.getDay() + 1);
    weekStart.setHours(0, 0, 0, 0);
    
    // Конец недели (воскресенье)
    const weekEnd = new Date(weekStart);
    weekEnd.setDate(weekStart.getDate() + 6);
    weekEnd.setHours(23, 59, 59, 999);

    return {
      from: weekStart.toISOString().split('T')[0],
      to: weekEnd.toISOString().split('T')[0]
    };
  }

  private async notifyReportsReady(reportType: string, period: ReportPeriod): Promise<void> {
    // Здесь можно добавить интеграцию с системами уведомлений:
    // - отправка email
    // - Slack/Teams уведомления
    // - сохранение в базе данных
    // - интеграция с внешними системами аналитики
    
    console.log(`📨 Уведомление: ${reportType} отчеты за ${period.from} - ${period.to} готовы`);
  }

  stopAllScheduledJobs(): void {
    this.scheduledJobs.forEach((job, name) => {
      clearInterval(job);
      console.log(`⏹️ Остановлен планировщик: ${name}`);
    });
    this.scheduledJobs.clear();
  }
}

Обработка ошибок

try {
  const report = await reportApi.createProductsReport({
    visibility: 'VISIBLE'
  });

  // Ожидание готовности отчета
  let reportInfo;
  let attempts = 0;
  
  while (attempts < 20) {
    reportInfo = await reportApi.getReportInfo({ code: report.result.code });
    
    if (reportInfo.result.status === 'SUCCESS') {
      console.log("Отчет готов:", reportInfo.result.download_url);
      break;
    } else if (reportInfo.result.status === 'FAILED') {
      throw new Error(`Ошибка создания отчета: ${reportInfo.result.error}`);
    }
    
    await new Promise(resolve => setTimeout(resolve, 10000));
    attempts++;
  }
  
} catch (error) {
  if (error.response?.status === 400) {
    console.error("Некорректные параметры отчета:", error.response.data);
  } else if (error.response?.status === 429) {
    console.error("Превышен лимит создания отчетов");
  } else {
    console.error("Ошибка создания отчета:", error.message);
  }
}

Лучшие практики

Эффективное управление отчетами

// Планирование создания отчетов с учетом лимитов
class ReportManager {
  private reportQueue: ReportTask[] = [];
  private processing = false;

  async queueReport(reportTask: ReportTask): Promise<string> {
    return new Promise((resolve, reject) => {
      this.reportQueue.push({
        ...reportTask,
        resolve,
        reject
      });
      
      this.processQueue();
    });
  }

  private async processQueue(): Promise<void> {
    if (this.processing || this.reportQueue.length === 0) return;
    
    this.processing = true;
    
    while (this.reportQueue.length > 0) {
      const task = this.reportQueue.shift()!;
      
      try {
        const reportCode = await this.executeReportCreation(task);
        task.resolve(reportCode);
        
        // Пауза между запросами для соблюдения лимитов
        await new Promise(resolve => setTimeout(resolve, 5000));
        
      } catch (error) {
        task.reject(error);
      }
    }
    
    this.processing = false;
  }
}

interface ReportTask {
  type: 'products' | 'postings' | 'returns' | 'discounted' | 'stock';
  params: any;
  resolve?: (code: string) => void;
  reject?: (error: Error) => void;
}

Кэширование и оптимизация

// Система кэширования отчетов
class ReportCache {
  private cache = new Map<string, CachedReport>();
  private readonly cacheTime = 6 * 60 * 60 * 1000; // 6 часов

  async getOrCreateReport(
    reportType: string, 
    params: any, 
    createFn: () => Promise<string>
  ): Promise<string> {
    const cacheKey = this.getCacheKey(reportType, params);
    const cached = this.cache.get(cacheKey);
    
    if (cached && (Date.now() - cached.created) < this.cacheTime) {
      console.log(`📋 Используем кэшированный отчет: ${cached.code}`);
      return cached.code;
    }
    
    console.log(`🔄 Создаем новый отчет: ${reportType}`);
    const reportCode = await createFn();
    
    this.cache.set(cacheKey, {
      code: reportCode,
      created: Date.now(),
      type: reportType,
      params
    });
    
    return reportCode;
  }

  private getCacheKey(reportType: string, params: any): string {
    return `${reportType}_${JSON.stringify(params)}`;
  }
}

interface CachedReport {
  code: string;
  created: number;
  type: string;
  params: any;
}

Интеграционные заметки

  • Report Lifecycle: Отчеты создаются асинхронно, требуется отслеживание статуса
  • Rate Limiting: API поддерживает до 50 запросов создания отчетов в час
  • File Formats: Отчеты доступны в форматах XLS, CSV в зависимости от типа
  • Download Links: Ссылки для скачивания имеют ограниченное время жизни (24 часа)
  • Storage Period: Готовые отчеты хранятся в системе 30 дней
  • Data Freshness: Финансовые данные обновляются с задержкой до 2 часов
  • Language Support: Отчеты поддерживают локализацию на русский и английский языки
  • Integration: Отчеты можно интегрировать с внешними системами аналитики и BI