backgroundbackground
Назад
Назад

Выгрузка отчета реализации за большой период

Обсуждение
1
91125
# Документы и бухгалтерия
Обсуждение

Добрый день. Прошу помощи в получении отчетов реализации.

Моя цель - получить отчет реализации за период с 2024-01-29 по 2025-08-31.

Поскольку количество строк в итоговом отчете превышает 100 000, то я использую метод выгрузки отчета через параметр rrd_id (id строки в предыдущем отчете).

Распишу, что я получаю по шагам:

1. Формирую первый запрос с параметрами:

"dateFrom": 2024-01-29T00:00:00,
"dateTo": 2025-08-31T23:59:59,
"rrdid": 0

В ответе я получаю отчет реализации за период

date_from: 2024-01-29
date_to: 2024-12-08
rrd_id: 4141247912

На этом этапе все ок.

2. Формирую второй запрос:

"dateFrom": 2024-01-29T00:00:00,
"dateTo": 2025-08-31T23:59:59,
"rrdid": 4141247912

В ответе я получаю отчет реализации за период

date_from: 2024-12-02
date_to: 2024-12-15
rrd_id: 4242339810

На этом этапе возникает ошибка: пересеклись недели с предыдущим запросом. Ок, идем дальше.

3. Формирую третий запрос:

"dateFrom": 2024-01-29T00:00:00,
"dateTo": 2025-08-31T23:59:59,
"rrdid": 4242339810

Я получаю пустой отчет.

Таким образом, я смог получить отчеты за период с 2024-01-29 по 2024-12-15. Куда делся остальной период? Если передавать запросы через даты, то отчеты за оставшийся период выгружаются, но при использовании подхода через использование id последней строки предыдущего отчета не работает. Приходится на каждом шаге определять максимальную дату и формировать период следующего запроса вручную. Причем формировать его таким образом, чтобы случайно не получить больше 100 000 строк, поскольку метод выгрузки через rrd_id не работает.

+1
Комментарий

Добрый день!

Коротко: с отчётом всё ок — «остаток периода» никуда не делся. Проблема в том, что пагинация по rrd_id у /api/v5/supplier/reportDetailByPeriod не гарантирует строгую «возрастающую по датам» выборку на длинных интервалах. После очередной «границы» (неделя/репорт) в вашем кейсе записи за 2025 год имеют rrd_id меньше, чем последний rrd_id декабрьского блока — поэтому запрос с rrdid=4242339810 отсекает их, и вы получаете пустой ответ. В документации сказано лишь, что rrdid — это уникальный ID строки для разбиения отчёта и что нужно вызывать метод до пустого массива, но не обещано соответствие хронологии датам. Отчёт еженедельный, данные доступны «с 29.01.2024» и dateTo — это дата (день), а не дата-время, время считается по Мск (UTC+3). 

Как надёжно вытянуть весь период >100 000 строк

Используйте гибрид: даты + rrd_id.

  1. Базовые параметры
  • endpoint: /api/v5/supplier/reportDetailByPeriod
  • dateFrom — RFC3339 (можно с временем), dateTo — дата в формате YYYY-MM-DD; лучше без T23:59:59. Время — по Мск.
  • limit оставьте 100000 (по умолчанию). 
  1. Итерация по “недельным окнам”
  • Старт: cursorStart = 2024-01-29, end = 2025-08-31.
  • Запускаете цикл:
    • Делаете запрос с dateFrom=cursorStart, dateTo=end, rrdid=0.
    • Если ответ пуст — стоп (мы исчерпали период для этого окна).
    • Сохраняете строки + maxDateTo = max(date_to) из ответа.
    • Пока ответ не пуст:
      • Берёте maxRrd = max(rrd_id) из последнего ответа и вызываете тот же запрос, но с rrdid = maxRrd.
      • Если получили пусто — выходим из rrd-цикла.
    • Обновляете cursorStart = maxDateTo + 1 день и повторяете, пока cursorStart <= end.
  1. Анти-дубликаты Пересечения недель — это нормально (вы сами это заметили). Дедуплируйте по ключу rrd_id (на всякий случай можно по паре (realizationreport_id, rrd_id)). 
  2. Автодробление, если внутри окна >100 000 строк Если первое обращение к окну вернуло ровно 100 000 строк и вы видите, что maxDateTo почти не сдвигается, включайте «двоичный поиск по дате»: временно уменьшаете tempEnd (середина между cursorStart и end) до тех пор, пока очередное окно стабильно не отдаёт <100 000 строк; после выгрузки этого куска сдвигаете cursorStart = maxDateTo + 1 и продолжаете.

Почему это работает

  • Метод возвращает «детализацию к еженедельным отчётам» и разрешает кусочить массив по rrd_id, но не гарантирует, что rrd_id монотонно растёт вместе с календарной датой на длинных периодах — из-за чего возможен «обрыв» при простом наращивании rrd_id. Документация формально описывает только поведение rrdid как механизма дозагрузки и отсутствие записей как сигнал завершения; строгого SLA по хронологии нет. 

Частые мелочи, которые помогают

  • dateTo передавайте как дату (2025-08-31), а не ...T23:59:59. Так ближе к спецификации (для dateFrom допускается дата-время, для dateTo — дата). 
  • Учитывайте, что всё считается в UTC+3 (Мск) — это важно, если вы строите «+1 день» 
  • Дедуп по rrd_id снимет «пересечение недель» (это ожидаемо).
0

Ответы на комментарий

Понял, неправильно интерпретировал документацию, будут пробовать ваш метод, спасибо за ответ.

0

Добрый день

прочитав пункт N2 про автодробление, я правильно понимаю, что если я знаю, что у меня в отчете > 300k строк, то мне не надо идти неделями, а идти надо днями ? а если у меня в дне будет больше 100к строк, что делать ?

0

Добрый день, так как в среднем в 100 секундный тайаут у нас вписывается получение 2-10к строк (100к крайняя редкость ), то несколько вопросов 1 - гарантируется ли монотонность rrd_id внутри отчета или хотя бы дня 2 - правильно ли я понимаю что по rr_dt можно использовать для отбора строк внутри одного дня и что для продолжения загрузки я могу использовать max(rrd_id) в start_date ?

С Уважением ish

0

а этот текст вообще человек писал ? а то "почему это работает" + "дата почти не сдвигается", навевает на мысль, что нет, не человек. Почти это сколько ? вот у меня отчеты 250-300к строк, забираю пакетами, влезающими в 100 сек , бывает 100к строк , а чаще 2-10к строк. при таком окне дата _совсем_ не сдвигается. получается тупик. :)

что такое не гарантирует что мононтонно растет с календарной датой на длинных периодах ? а в каких пределах гарантирует ? ведь если гарантии монотонности нет , то можно найти такой период, в котором в двух соседних строках монотонного роста не будет.

что имеется ввиду

  1. Итерация по “недельным окнам”
  • Старт: cursorStart = 2024-01-29, end = 2025-08-31.

    я себе представляю недельное окно как понедельник-воскресенье например, но если внутри него не гарантируется монотонность роста rrd_id , то опять тупик.

    решаю такую же задачу как автор, только в пределах квартала. никак не могу понять, как убедиться, что отчет загружен весь, как его загрузить гарантированно весь, при том, что он большой. пусть день будет заведомо больше 100к строк. (чтобы дихотомия по дате не работала :)) на часы разбить нелья, так как конечная дата это дата, а не datetime

    пока идея только одна, залить как зальется, а дальше сравнить со списком отчетов, выгруженных с сайта. но хочется верить, что есть и другой путь. как точно определить, что конкретный отчет залит весь ?

    С Уважением ish

0

думал писать или не писать, решил что может это кому то поможет

наши данные. 8.5 млн строк с января 24 года по сегодня отчет за 2 ноября 345 тыс строк.

текущий алгоритм. автоматически подбирает limit так чтобы "посылка" уложилась в 0.85 от установленного таймаута. который сейчас используем 180 секунд, начинает с 1000 строк. после 10 таймаутов подряд ждет 10 минут, мало ли что с API .

идея начинать со 100к строк при текущей производительности API приведет лишь к лишним таймаутам.

начинали с окна от сегодня и до конца, пришли к загрузке строго по отчетам. берем первые 1000 строк, из него min date_from , dateto = min date_from + 6 дней дедупликация при таком подходе не требуется. единственный drawback это n лишних запросов по минуте, которые приводят к получению пустого массива. на больших отчетах это ерунда. на маленьких - гарантированная задержка

по поводу дедупликации.. 100к строк это +-200 MB , при каком то тесте плавающего окна мы получили десяток дублированных отчетов с количеством дублей от 1-3 идея с дедупликацией подразумевает получение сотен мегабайт (или гигабайты ) информации, которая будет дропнута. эффективная дедупликация миллионов строк отдельная задача. алгоритм идти ровно по отчету не дал ни одного дубля на 8.5 млн строк на периоде в 92 недели (184 отчета )

2 WB team : Вы вроде написали, что слушаете предложения. накидаю

по данному методу 1. сделать возможность выбирать варианта отчета. имхо, все поля имеют ценность для какого то ограниченного применения. для бухгалтерии, надо 15-20 полей (сейчас лень точно считать ) , это радикально сократит объем передаваемых данных. я бы вообще думал про передачу списка нужных полей. сгенерировать набор полей в запросе стоит копейки, а объем передаваемых данных существенно упадет 2. сделать метод получить список отчетов за период, и метод получить отчет с понятной разбивкой на страницы. это радикально упростит работу с апи и уберет необходимость разбираться с особенностями rrd_id . в идеале, чтобы список отчетов содержал количеств строк в отчете, это позволит оптимизировать limit . 3. не считать запрос, вернувший пустой массив за запрос ( с точки зрения лимитов). это техническое действие :) 4. дать возможность не получать строки в которых тип документа != продажа или возврат. это существенно сократит объем передаваемой информации, а ценность их, например для бухгалтерии нулевая. 5. еще бы описание улучшить. узнавать опытным путем что 0 это не целое число, а yyyy-MM-dd не дата, а datetime , занимает время

С Уважением ish

0
Комментарий

Здравствуйте!

Если вы не можете выгрузить данные после 2024-12-15, значит ранее вам в колокольчик было отправлено уведомление (в декабре 2024), о том что для выгрузки недельных отчетов после 2024-12-15 по техническим причинам нужно указывать dateFrom = 2024-12-16.

Соответственно если вы хотите выгрузить все данные, вам нужно сделать 2 вида запросов, одни с dateFrom 2024-01-29, пока не получите все данные, и второй вид с dateFrom = 2024-12-16

+2

Ответы на комментарий

Добрый день. Если вы говорите про уведомление в личном кабинете продавца, то у меня туда нет доступа. Или вы что-то другое имели в виду?

0

Да, уведомление было отправлено в колокольчик личного кабинета продавца

+1