Техническая реализация — сбор данных¶
Таблица: «Калькулятор маржинальности Brodeks» (1yTZW_8iWFMMsk3JzgIK2CzvawHS2kr-Wov_vxMCrIqs; переименована 06.07.2026, ранее называлась «AGT планирование продаж V1» — id и содержимое не менялись, только название файла в Google Drive), сервис-аккаунт claude-sheets@my-project-93453-01-04-26.iam.gserviceaccount.com.
Статус документа: восстановлен 03.07.2026 задним числом по ответам пользователя и прямому осмотру листов через gspread — исходные скрипты, которыми собирались данные, не сохранены (выполнялись как разовый ad-hoc код другим ИИ-инстансом, файлы не найдены ни в проекте, ни на Google Drive, ни на «Gemini Home VM»). Дальше — правило: каждый шаг реализации документируется сразу после выполнения, чтобы не терять историю повторно.
1. Лист prodazhi_po_kanalam_only_1c_mt — история продаж по каналам¶
- Источник: SQL-запрос через
pgapi(https://pg.dimavp.ru) к таблицеprodazhi_po_kanalam_only_1c_mt— обновляется ежедневно по cron на офисном сервере. - Технология загрузки: та же база
pgapi, что используется в проектах FBO Маркетплейсы и Отчет по сравнению остатков склада и организации (см.scripts/pgapi_config.jsтам —PGAPI_URL/PGAPI_KEY, эндпоинт/files/downloadдля файлов; для SQL-таблиц используется отдельный SQL-эндпоint pgapi, конкретный запрос текущей выгрузки не сохранён). - Объём: 208 166 строк, период июль 2025 – июль 2026.
- Каналы (
podrazdelenie): В2В, Дилеры Brodeks, Розница, Интернет-магазин, Маркетплейс Озон, Маркетплейс Wildberries. В файл включены только 3 группы (В2В, Дилеры, Розница+ИМ) — Ozon/Wildberries сознательно исключены (см. 02_Решения, 03.07.2026). - ⚠️ Открыто: точный SQL-запрос (фильтры, агрегация по месяцам) не восстановлен — при пересборке нужно реконструировать по итоговой структуре листа.
2. Лист API_прайс_лист — прайс-лист¶
- Источник: файл
Прайс-лист XLSX.xlsxна офисном сервере (ВДС офис), листAPI_прайс_листвнутри него — Артикул / Номенклатура / Базовая цена / Цена продажи (4 810 позиций). - Технология загрузки:
pgapiDownloadFile_(fileName)— тот же паттерн, что вscripts/pgapi_config.jsпроекта «Отчет по сравнению остатков склада и организации» (скачивание xlsx черезpg.dimavp.ru/files/download, конвертация в Google Sheets черезDrive.Files.copy, парсинг, удаление временных файлов). - ⚠️ Открыто: это плоский прайс-лист без формул скидок по каналам — справочник 0.5 («цены/скидки по каналам», 07) в полном виде (с параметрами каналов) пока не построен поверх него.
3. Листы _RAW_себестоимость → API_себестоимость — себестоимость¶
- Источник: файл
Себестоимость товаров организаций по брендам - июль 25-дек 25 (XLSX).xlsxна офисном сервере — тот же файл, что использует проект «Отчет по сравнению остатков склада и организации». - Технология загрузки (эталон):
scripts/load_sebestoimost.jsв том проекте, функцииloadSebestoimost()+aggregateSebestoimost(): - Скачать xlsx через
pgapiDownloadFile_, сконвертировать в Google Sheet. - Найти строку шапки по ключевым словам («Марка (бренд)» / «Артикул»), построить плоские имена колонок (
buildColNames_). - Записать сырые данные в
_RAW_себестоимость(Бренд, Артикул, Номенклатура, 4 пары Кол-во/Сумма, дата файла) — лист скрыт. - Агрегация в
API_себестоимость: себестоимость единицы = Сумма / Кол-во, приоритет самой свежей ненулевой пары (J/K → H/I → F/G → D/E), округление до целого. - Кастомизация для AGT планирования (03.07.2026): добавлена колонка «с НДС 22%» — фиксированная ставка, копейки отбрасываются (
floor, не округление) — этого нет в эталонном скрипте, добавлено отдельно. Итог: 2 898 артикулов, 5 колонок (без НДС / с НДС). - ⚠️ Открыто: точный скрипт, добавивший колонку «с НДС», не сохранён — логика (
floor, ставка 22%) известна из02_Решения.md, но код нужно восстанавливать заново при следующей пересборке.
4. Лист ABC_анализ — ABC-классификация¶
- Метод восстановлен 03.07.2026 обратным анализом данных (лист содержит статические значения, не формулы — расчёт делался внешним скриптом, результат вставлен как значения).
- Структура: Бренд | Артикул | Сумма продаж, руб (июль 2025 – июль 2026) | Признак ABC (внутри бренда).
- Методология (подтверждена расчётом по всем 87 брендам в файле):
- Артикулы группируются отдельно по каждому бренду (не по компании в целом).
- Внутри бренда — сортировка по убыванию суммы продаж за весь период (13 мес, июль 2025 – июль 2026, все доступные периоды).
- Строится накопительный % от суммы продаж бренда.
- Классика Парето: A — куммулятивно до ~80% выручки бренда, B — от ~80% до ~95%, C — свыше ~95%. Границы подтверждены статистически: у всех крупных брендов первое появление B стабильно на 80.2–80.7% кумулятивной выручки, C — на 95.0–95.6%.
- Не покрыто: обновление листа по расписанию — источник (история продаж) обновляется ежедневно, но
ABC_анализ— статический снимок, требует пересчёта вручную/по кнопке (кнопки пока нет).
5. Лист «Дилеры Brodeks» — встроенный расчёт прибыли (задача 3.8)¶
Реализовано 03.07.2026 напрямую через gspread/Sheets API (эта сессия) — единственный шаг с полностью сохранённой историей.
- Колонки «Категория», «ABC» — из справочника модель-цвет / листа
ABC_анализ(способ проставления в существующих строках не проверялся отдельно — колонки уже были заполнены на момент осмотра). - Строка чекбоксов (TRUE/FALSE, ряд 2) — включение месяца ПЛАН в «Итого план».
CA= «Цена продажи, руб (с НДС)» —=IFERROR(VLOOKUP($B{row}, 'API_прайс_лист'!$A:$D, 4, FALSE), 0).CB= «Цена продажи со скидкой, руб (с НДС)» — НОВАЯ колонка, добавлена 03.07.2026 19:5x:CB2— коэффициент скидки канала, редактируемый вручную. Установлен 0.67 (Дилеры = скидка 33% от РРЦ, см. 07).CB{row}==CA{row}*$CB$2.- Причина: до правки «Сумма выручки» в блоке ПЛАН считалась от полной цены (
CA) без скидки дилера — прибыль и выручка были завышены на канале «Дилеры». Проверено на первом месяце плана: сумма выручки до правки 28 921 730 ₽ → после 19 377 559 ₽ (≈ ×0.67, совпадает с ожидаемым). CC= «Себестоимость, руб (с НДС)» (былаCBдо вставки колонки, сдвинута автоматически).- Блок ПЛАН (24 месяца, авг.2026 – июл.2028): каждый месяц — Шт | Сумма выручки | Прибыль.
- «Сумма выручки» переключена с
CA(полная цена) наCB(цена со скидкой) — правка применена ко всем 24 месяцам, строки 6–6005 (буфер под будущие артикулы). - «Прибыль» = Сумма выручки − Шт × Себестоимость — формула не менялась, автоматически стала корректной после правки выручки.
- Область применения: правка сделана только на листе «Дилеры Brodeks» — по прямому указанию пользователя. Листы «В2В» и «Розница+ИМ» ещё старой структуры (без Категории/ABC/чекбоксов/скидки/маржи) — не трогались.
- Отложено на потом (по решению пользователя 03.07.2026): форматирование новой колонки (числовой формат — сейчас
CB2отображается как «1» из-за унаследованного целочисленного формата ячейки, хотя значение0.67) и цветовая раскраска листа.
6. Раскраска листа «Дилеры Brodeks» (первый проход, 03.07.2026 20:14)¶
- Шапка (строки 1–4) — по смысловым блокам:
A1:F4(Бренд/Артикул/Наименование/Категория/ABC/Ключ) — тёмно-серый фон, белый жирный текст.G1:BY4(блок ФАКТ, история 36 мес) — светло-синий.CA1:CC4(Цена продажи / Цена со скидкой / Себестоимость) — светло-оранжевый.CD1:EY4(блок ПЛАН, 24 мес + Итого) — светло-зелёный; заголовки колонок «Прибыль» (24 шт.) — более тёмный зелёный, чтобы визуально выделялся денежный итог месяца.- Строка 2 от
CB2доEY2(коэффициенты и чекбоксы месяцев) — жёлтый фон: маркер «это редактируется руками». - Первые 10 строк данных (6–15) — условное форматирование (динамическое, не статичная заливка):
A6:C15(имя товара) — фон по значению ABC в колонке E: A — зелёный, B — жёлтый, C — серый. Сейчас все 10 строк класса A (сортировка по выручке), так и должно быть.D6:D15(Категория) — фон по значению текста категории: Куртки/Кофты — синий, Брюки/Полукомбезы/Шорты/Вейдерсы — бежевый, Костюмы/Комбезы — сиреневый, Обувь — розовый, Перчатки — жёлтый, Аксессуары — светло-серый.- Правила динамические (Google Sheets Conditional Formatting, не разовая заливка) — при изменении ABC/категории строки цвет пересчитается автоматически. Область пока жёстко ограничена строками 6–15 (по прямому запросу «первые 10 строк») — при расширении на весь лист нужно расширить диапазоны правил.
- Не сделано (открыт вопрос): формат чисел «сумма» — сейчас разделитель тысяч запятая (
19,377,559), т.к. локаль файлаen_US. Per-cell локаль-оверрайд ([$-ru-RU]/[$-419]) в число-форматах Sheets не меняет разделитель группировки — он жёстко завязан на локаль всего файла. Единственный способ получить пробел — сменить локаль всего файла наru_RU, что также поменяет: разделитель формул в UI (запятая → точка с запятой) и десятичный разделитель (точка → запятая) — влияет на все листы и всех соавторов. Решение отложено, нужно подтверждение пользователя.
6.1. Раскраска — расширение на весь лист + бренды (03.07.2026 20:17)¶
- Обнаружен дубль правил: при повторном осмотре листа найдено 19 правил Conditional Formatting вместо ожидаемых 9 (включая незапрошенные правила подсветки знака «Прибыль» и вариант ABC-правил с диапазоном A:F вместо A:C) — похоже, лист параллельно редактировала ещё одна сессия/ИИ. Все 19 старых правил удалены, набор пересобран с нуля.
- Новый чистый набор — 13 правил, диапазон строк везде 6:6005 (весь буфер листа, не только первые 10 строк):
- ABC по имени товара (
A:C) — 3 правила (A/B/C). - Категория (
D) — 6 правил (см. раздел 6). - Знак прибыли (все 24 колонки «Прибыль» блока ПЛАН) — 2 правила: отрицательная — красный фон/тёмно-красный текст, положительная — зелёный фон.
- Бренд (
A:F, весь ID-блок) — 2 правила, добавлено по запросу «чтобы бросалось в глаза»:Brodeks(216 из 221 артикулов) — без заливки (нейтральный фон),Portwest(4 шт.) — яркий синий,BASE(1 шт.) — яркий красный/розовый. Смысл: на канале «Дилеры Brodeks» подавляющее большинство — сам бренд Brodeks, но есть единичные посторонние бренды (Portwest, BASE) — теперь они визуально выделяются в общей массе. - Все правила — Conditional Formatting (динамические), не разовая заливка; применены только на листе «Дилеры Brodeks».
6.2. Доработка раскраски + колонка рентабельности (03.07.2026 20:21–20:27)¶
- Уточнение по цвету (пользователь): типы данных нужно различать явно — «Шт» оставить белым, суммовые типы («Сумма», «Цена/Скидка/Себестоимость», «Сумма выручки», «Прибыль») — в цвете своего блока. Единый фон блока — оставлен, «сразу видно, в каком блоке находишься».
- Сброшены на белый все 60 колонок «Шт» (строки 5–6005) — 36 в ФАКТ + 24 в ПЛАН.
- Шапка ID-блока (
A1:F4) сделана светлее: было тёмно-серый/белый текст → стало светло-серо-голубой фон (#E6EDF2-подобный) с тёмным текстом. - Добавлен фон для баннеров строки 1 (ФАКТ/ПЛАН/коэффициент-подсказка) — раньше текст висел без подложки.
- Данные всего блока ФАКТ/Цена/ПЛАН (строки 5–6005) получили лёгкую тонировку под цвет заголовка блока (бледно-синий/бледно-оранжевый/бледно-зелёный).
- Разделители между месяцами (правые границы колонок) — предложены, но пользователь отменил выполнение (
updateBordersне применён) — отложено, ждём отдельного решения. - Новая колонка
EZ— «Рентабельность, % (по отмеченным месяцам)»: - Формула по строке:
=IF(EY{row}=0,0,ROUND((Σ IF(<чекбокс месяца>$2,<Прибыль месяца>{row},0))/EY{row}*100,1))— сумма прибыли только по отмеченным чекбоксом месяцам (тот же фильтр, что уже используетEX/EYдля Итого план шт/выручки), делённая на итоговую выручку, ×100. - Строка ИТОГО (
EZ5) — аналогичная формула на уровне колоночных сумм (CF5,CI5, …), не пересум по строкам (проценты не суммируются). - Формат числа — не нативный Sheets PERCENT (тот делит на 100 сам, было бы двойное умножение), а кастомный
0.0"%"(уже готовое значение ×100 из формулы, просто дописывается знак). - Оформление — бирюзовый акцент в шапке (
#99CCC7-подобный) и лёгкая бирюзовая тонировка данных — отдельный визуальный класс «KPI-показатель», не сумма и не количество. - Проверено:
EZ5(весь ассортимент) = 51%, отдельные строки — 24.2–50.7% в выборке.
6.3. Сжатие шапки: удаление строки 2, локаль ru_RU, чекбоксы (03.07.2026 20:27–20:37)¶
- Формат сумм — пробел вместо запятой: сменена локаль всей таблицы на
ru_RU(updateSpreadsheetProperties). Побочный эффект подтверждён и принят: разделитель аргументов формул в UI —;вместо,(значения не изменились, Sheets хранит формулы независимо от локали и просто по-другому их показывает), десятичный разделитель —,вместо.. Формулы, записанные ранее через API при локалиen_US, продолжили работать корректно после смены локали (проверено). A5(«свод. строка») →A5:F5кратко, единообразно—во всех 6 колонках ID-блока — чтобы не засорять выпадающий список фильтра по этим колонкам смешанными служебными текстами.- Экономия строки в шапке (запрос пользователя):
- Месячный коэффициент прогноза перенесён из
<Шт-колонка>$2в<колонка Сумма выручки>$3(пример:CD2→CE3), галочка учёта месяца — из<Сумма выручки>$2в<Прибыль>$3(пример:CE2→CF3). Коэффициент скидки каналаCB2(0.67) — аналогично вCB3. - Формулы блока ПЛАН (
Шт,EX/EY/EZ,CBсо скидкой) — переписаны под новые адреса, для всех 24 месяцев × 6000 строк. - Найден и исправлен побочный баг: перенос значения галочки через
values.updateскопировал только логическое значение (TRUE/FALSE), но не саму проверку данных (Data Validation, тип BOOLEAN) — визуально чекбоксы превратились в обычный текст «TRUE»/«FALSE» без виджета («везде TRUE» на вид). Восстановлено черезsetDataValidation(BOOLEAN,showCustomUi: true) на новых 24 ячейках. - Старая строка 2 (уже не используется формулами) — удалена целиком через
deleteDimension(ROWS). Google Sheets автоматически сдвинул все формулы, диапазоны SUM, правила условного форматирования и data validation на строку вверх — проверено:EY4(былоEY5) =SUM(EY5:EY6004), итог не изменился (1 362 273 018 ₽), 13 правил форматирования не потеряны, чекбокс-виджет пережил сдвиг. - Итог структуры шапки: было 5 строк до данных (1 баннер + 2 служебные + 1 заголовки колонок + 1 ИТОГО), стало 4 (баннер + месяц/коэфф/чекбокс совмещены + заголовки колонок + ИТОГО). Данные теперь с строки 5 (было — с 6).
CB1(комментарий «Коэфф. скидки канала…») — удалён по просьбе пользователя, лишний текст.- Строку 1 (баннер ФАКТ/ПЛАН) решили не трогать — вынести баннер больше некуда без потери контекста.
7. Проверка полноты списка артикулов (03.07.2026 20:14)¶
По сигналу пользователя («всегда 226 строк, должно быть больше») сверил список артикулов листа с сырыми данными prodazhi_po_kanalam_only_1c_mt, отфильтрованными по podrazdelenie = "Дилеры Brodeks" (без фильтра по бренду — канал изредка продаёт не только Brodeks) за весь период (13 мес, июль 2025 – июль 2026): 221 артикул в сырых данных = 221 артикул на листе, 0 пропущенных, 0 лишних. Лист полный и корректный, расхождения нет. ssylka_na_document (первый столбец сырой таблицы) для этого подразделения всегда заполнен — пустым он бывает только у Ozon/Wildberries/«Нет продаж», что не влияет на этот лист, но важно учесть при будущей сборке МП-каналов (эти подразделения сейчас не включены, см. раздел 1).
6.4. Индекс ABC для сортировки + исправление буфера «Прибыль» (03.07.2026 20:40–20:45)¶
- Найден и исправлен пропуск: формулы «Прибыль» (все 24 месяца ПЛАН) были протянуты только до строки 225 (реальные данные), а не до конца буфера (6004), в отличие от всех остальных формул листа. Дозаполнено
={Сумма выручки}{row}-{Шт}{row}*CC{row}до строки 6004 во всех 24 колонках. - Новая колонка «Индекс ABC» — ранг товара внутри группы (бренд + класс ABC) по убыванию выручки, слитный формат
A001,A002, …C133и т.д. Цель — сортировка основного листа по этому индексу (самый продаваемый товар класса — первый). - Источник расчёта — лист
ABC_анализ(не сам «Дилеры Brodeks»): добавлена колонкаE—=D{row}&TEXT(SUMPRODUCT(($A$2:$A$2756=A{row})*($D$2:$D$2756=D{row})*($C$2:$C$2756>C{row}))+1;"000")— считает, сколько товаров того же бренда и того же класса ABC имеют выручку больше текущего, +1 = ранг. Посчитано один раз на компактной таблице (2755 строк), а не на большом листе плана (~6000×24) — так быстрее и не нагружает лист планировщика тяжёлым SUMPRODUCT по 6000 строкам. - В «Дилеры Brodeks» — новая колонка
F(вставлена после ABC, до Ключа — вся таблица сдвинулась на 1 колонку вправо, автосдвиг Sheets прошёл чисто, проверено) — простойVLOOKUPпо артикулу вABC_анализ!B:E, колонка 4. - Важный урок по локали: после смены локали файла на
ru_RU(см. 6.3) формулы, записанные через API с,как разделителем аргументов, дают#ERROR!— нужно использовать;. Отловлено сразу на первой попытке записи формулы ранга, исправлено.
6.5. Инцидент с сортировкой, восстановление, полное удаление буфера (03.07.2026 20:45–21:03)¶
Что произошло¶
- Пользователь отсортировал лист по колонке «Индекс ABC» через встроенную сортировку по столбцу (UI). Буфер формул был протянут на 6000 строк вперёд (реальных артикулов — 221, остальные ~5780 строк — формулы, дающие пустую строку
""черезIFERROR(...,"")). - Причина поломки:
""(результат формулы) — это не то же самое, что физически пустая ячейка. При сортировке по возрастанию такие ячейки трактуются как «меньше» любого текста и улетают наверх, перемешиваясь с реальными данными. При по убыванию — данные в основном уходят вниз, но сама операция сортировки (черезsortSpecsзаложенный вbasicFilter) зацепила и служебную строку «Итого» (была в строке 4, эту же строку отсортировало вместе со всеми — уехала на строку 5783), а 221 реальный товар оказался сдвинут единым блоком в конец диапазона (строки 5784–6004). - Дополнительно: до этого была попытка настроить
basicFilterсо скрытием пустых строк по столбцу B (Артикул) черезsetDataValidation-подобныйFilterCriteria.condition. Первая попытка (type: BLANK) не сработала (ничего не скрывала), вторая (type: NOT_BLANK) неожиданно скрыла все строки, включая реальные. Фильтр был немедленно снят (clearBasicFilter) — семантика условияBLANK/NOT_BLANKв Sheets API в связке с уже существующимsortSpecsот пользователя вела себя непредсказуемо, для дальнейшей работы отказались от этого пути.
Восстановление¶
- Найдены точные позиции: строка «Итого» — 5783 (со сбитым диапазоном
SUM(EY5784:EY11783)— сдвинулся вместе со строкой, поэтому диапазон «уехал» далеко за пределы реальных данных, но численно считал верно, т.к. лишние строки пустые), 221 товар — строки 5784–6004 (без пропусков). - Оба блока возвращены на место через
cutPaste(аналог вырезать→вставить, Sheets автоматически поддерlive относительные ссылки формул — так же надёжно сработало ранее при удалении строки 2): «Итого» → строка 4, товары → строки 5–225. - Обнаружена и исправлена вторая, независимая проблема: при вставке колонки «Индекс ABC» (см. 6.4) весь блок «Итого план шт / Итого план выручки / Рентабельность» физически сдвинулся с
EX/EY/EZнаEY/EZ/FA— а более поздняя точечная работа (перекраска блока «Итого» по типам данных, см. 6.3–6.4) ссылалась на старые буквыEX/EY/EZпо памяти, не сверяясь заново с шапкой. Формулы в реальныхEY/EZ/FAпри этом тоже оказались перепутаны местами (Шт↔Выручка↔Прибыль) — источник путаницы: тройной сдвиг (удаление строки 2 → вставка колонки Индекс ABC → сортировка/cutPaste) без промежуточной пере-проверки жёстко прописанных буквенных ссылок в скриптах. - Правило на будущее: после любой структурной операции (вставка/удаление строки или колонки) — заново вычислять буквы колонок через сканирование заголовков (
row_values+ фильтр по тексту), а не переиспользовать буквы из предыдущего шага скрипта. EY/EZ/FAполностью пересобраны с нуля по свежесканированным колонкам Шт/Сумма выручки/Прибыль (24 месяца), проверено:EZ4(Итого выручка) = 1 362 273 018 ₽,FA4(Рентабельность) = 51,0% — совпадает с ранее известными верными значениями.
Решение: буфер удалён полностью¶
- Пользователь: «Пустые строки не нужны, только ты будешь добавлять новые строки в лист».
- Все строки после 225 (реальные данные) — удалены физически (
deleteDimension, было 6009 строк → стало 225). Буфера больше нет вообще. - Новый рабочий процесс: при появлении новых артикулов строки добавляет ИИ (Claude) с полным набором формул по образцу существующих — не заводится заранее «про запас».
- Следствие: сортировка любым способом (по возрастанию/убыванию, через UI) теперь безопасна — скрывать/сортировать нечего, все 225 строк содержательны (4 шапки + 221 товар).
6.6. Лист «Инструкция» и финальная полировка — первая версия завершена (03.07.2026 21:03–21:31)¶
- Создан лист «Инструкция» (первая вкладка книги) — пользовательская документация по листу «Дилеры Brodeks»: структура блоков, что означают цвета, как работают коэффициент прогноза и галочка «учитывать в Итого», что такое Индекс ABC, как безопасно сортировать/фильтровать, как добавлять новые товары (только через Claude, буфера строк больше нет), где искать техническую документацию.
- Оформление: объединённые ячейки (заголовки и абзацы — на всю ширину, двухколоночные строки — метка + описание на всю оставшуюся ширину), перенос текста (
WRAP), высота строк пересчитана под контент. - Раскраска — содержательная, не декоративная: строки, описывающие блоки листа (A–G/ФАКТ/Цена/ПЛАН/Итого) и легенда цветов (п.3) — покрашены в те же цвета, которые описывают. Легенда буквально показывает свой цвет.
- Исправлен формат ячейки
CC2(коэффициент скидки канала) — показывал «1» вместо «0,67» из-за унаследованного целочисленного формата (pattern: "0"). Установлен0.00. Остальные коэффициенты (CF2,CI2и т.д., по месяцам) — были в порядке, проверены отдельно. - Различены цветом колонки цены/скидки/себестоимости (раньше — единый оранжевый, сливались): «Цена продажи» — светло-персиковый, «Цена продажи со скидкой» — насыщенный оранжевый, «Себестоимость» — коричнево-бежевый.
Итог: первая версия листа «Дилеры Brodeks» завершена¶
Работа 03.07.2026 (с учётом всех сессий дня) закрывает пилотную реализацию задачи 3.8 (встроенный расчёт прибыли поверх задачи 2.3, планировщик продаж) для канала «Дилеры Brodeks»: - Полная структура: карточка товара + Индекс ABC → история продаж (36 мес) → цена/скидка/себестоимость → план (24 мес, Шт/Выручка/Прибыль) → Итого (шт/выручка/рентабельность). - Данные проверены на полноту (221 = 221 артикулов за весь период). - Формулы восстановлены и проверены после инцидента с сортировкой (см. 6.5), буфер убран — риск повторной поломки исключён. - Раскраска по смыслу (тип данных, ABC, категория, бренд, знак прибыли) на весь лист. - Документация для пользователя (лист «Инструкция») и для разработчика (этот файл) готовы.
Следующий шаг (по решению пользователя 03.07.2026 21:31): переходим от подготовки к получению обратной связи от Глеба — показ пилотного канала «Дилеры Brodeks», сбор замечаний, далее — решение о репликации структуры на «В2В»/«Розница+ИМ» и/или доработке по замечаниям. Листы «В2В» и «Розница+ИМ» пока не трогали — ждут результата обратной связи.
6.7. Скрипты оформлены задним числом (04.07.2026)¶
По запросу пользователя весь код, которым сегодня (03.07.2026) правился лист «Дилеры Brodeks» через терминал (gspread, ad-hoc), оформлен в виде файлов в scripts/ — закрывает пробел, отмеченный в разделах 6.1–6.5 («скрипты не найдены/не зафиксированы»). Список файлов и порядок применения — scripts/README.md.
Важная оговорка: эти файлы — не «код, который был буквально выполнен один в один», а реконструкция подхода в переиспользуемом виде (функции с параметрами, без хардкода букв колонок там, где это возможно). Каждый файл содержит предупреждения о рисках (пересканировать заголовки после структурных правок, проверить локаль перед записью формул и т.д.), извлечённые из реальных ошибок сегодняшнего дня (см. разделы 6.5–6.6).
8. Лист «Дилеры Brodeks v2» — ручная РРЦ, план с июля, ручное Шт (06.07.2026)¶
По прямому запросу пользователя, не дожидаясь обратной связи от Глеба (см. итог раздела 6.6/задача 3.9 — она остаётся в статусе «ожидает показа», обратная связь ещё не поступала). Оригинальный лист «Дилеры Brodeks» не тронут — все правки на копии «Дилеры Brodeks v2» (Дилеры Brodeks.duplicate()). Генератор — scripts/18_dealers_v2_price_override.py.
8.1. Структурные изменения¶
- Новая колонка «РРЦ канала вручную, руб.» между «Цена продажи со скидкой» (была
CC) и «Себестоимость» (былаCD, теперь сдвинута наCE). Пусто по умолчанию. Если человек вписывает число — это значение используется ВЕЗДЕ вместо расчётной цены со скидкой, во всех формулах выручки/прибыли по всем месяцам сразу (цена в этой колонке одна на строку/SKU, не помесячная — важно понимать: правка одной ячейки меняет весь план по этому товару, не один месяц). - Горизонт плана расширен на 1 месяц в прошлое: было авг.26–июл.28 (24 мес), стало июл.26–июл.28 (25 мес). Чекбокс «учитывать в Итого» (строка 2) включён по умолчанию для первых 12 месяцев нового горизонта (июл.26–июн.27), выключен для оставшихся 13 (июл.27–июл.28) — тот же принцип «скользящий год вперёд», что был в оригинале, просто стартовая точка на месяц раньше.
- В каждом месяце плана — новая колонка «Шт вручную» (после расчётного «Шт», перед «Сумма выручки»). Пусто по умолчанию. Если заполнена человеком — используется вместо расчётного количества в формулах Сумма выручки/Прибыль этого месяца И в Итого-блоке (Итого-Шт теперь считает «эффективное» количество:
IF(ручное<>"";ручное;расчётное)по каждому отмеченному месяцу). - Блок Итого расширен с (Шт/Выручка/Рентабельность) до (Шт/Выручка/Себестоимость/Прибыль/Рентабельность). Итого-Себестоимость = Итого-Шт(эффективный) × Себестоимость строки. Итого-Прибыль = Итого-Выручка − Итого-Себестоимость.
- Сравнительный блок (через 2 пустые колонки после Рентабельности): «Итого выручка (РРЦ канала до ручной правки)» — тот же эффективный Шт, но по БАЗОВОЙ цене со скидкой (колонка «Цена продажи со скидкой», игнорируя ручную РРЦ) и «Дельта прибыли» = Итого-Прибыль(факт., с ручной РРЦ) − (baseline-выручка − Итого-Себестоимость). Изолирует именно эффект ручной правки цены, при тех же количестве и себестоимости.
8.2. Инцидент и исправление: строка 4 («ИТОГО») — не реальный SKU¶
Себестоимость/Цена-со-скидкой на строке 4 (там B4="—", не настоящий артикул) — VLOOKUP не находит ничего, IFERROR(...,0) даёт 0. Формулы «Итого-Себестоимость = Итого-Шт × Себестоимость-строки» и «baseline-выручка = Итого-Шт × Цена-строки», написанные по единому шаблону для всех строк, на строке 4 считали 0 (себестоимость всей строки «Итого» = 0 → прибыль = вся выручка → рентабельность 100% → бессмысленные числа). Обнаружено сразу при проверке (GD4/GI4 = 0, GF4 = 100%, GJ4 ≈ выручка целиком). Исправлено точечно: только на строке 4 GD4/GI4 переопределены как SUM(GD5:GD225)/SUM(GI5:GI225) — сумма по реальным строкам, а не Шт×цена-строки-4. После исправления: GD4 = 175 877 082 ₽, GE4 (прибыль) = 185 944 874 ₽, GF4 (рентаб.) = 51,4% — согласуется с исходным пилотом (51,6% на 03.07, отличие ожидаемо из-за сдвига чек-бокс-окна на 1 месяц раньше).
Правило на будущее: если границы данных (сейчас строки 5–225) изменятся, формулы GD4/GI4 нужно поправить вручную на новый диапазон SUM — это единственные две ячейки листа, которые НЕ следуют общему построчному шаблону.
8.3. Проверка на реальных данных (строка 5, KW204BLACK)¶
Временно внесены значения CD5=20000 (ручная РРЦ) и CG5=50 (ручное Шт на июл.26), затем удалены после проверки. Результат пересчёта совпал с ручным расчётом на бумаге по всем цепочкам (Сумма выручки июл.26 = 50×20000 = 1 000 000; Итого-Шт вырос на 38 (50−12); Итого-Выручка/Себестоимость/Прибыль/Рентабельность/baseline/дельта — все пересчитались корректно, включая дельту прибыли = 10 009 215 ₽, изолирующую эффект именно ценовой правки). Тестовые значения очищены (batch_clear), лист возвращён к чистому состоянию без ручных вводов.
8.4. ABC_анализ v2 — новая методология ранжирования¶
По запросу пользователя логика ABC полностью пересобрана (не патч старой, а параллельная система — старый лист ABC_анализ не тронут). Генератор — scripts/17_abc_analysis_v2.py, результат — лист ABC_анализ v2 (2887 строк = все бренды/артикулы, встречавшиеся хоть в одном из 4 каналов).
- Источник: тот же лист
prodazhi_po_kanalam_only_1c_mt(208 156 строк), уже загруженный в эту книгу — не понадобилось новых выгрузок через pgapi. - 4 канала: Дил = «Дилеры Brodeks»; B2B = «В2В»; Роз = «Розница» + «Интернет магазин»; МП = «Маркетплейс Озон» + «Маркетплейс Wildberries» — по решению пользователя 06.07.2026: эти данные ЕСТЬ в сыром источнике (34 751 и 8 795 строк соответственно), их разделение из общего проекта, отмеченное в разделе 1 и в 03_Задачи.md, касалось только уже built-планировщиков каналов, не сырых данных. «Нет продаж» (33 542 строки) исключены как не-канал.
- 5 параллельных ранжирований на каждый SKU:
- 4 колонки «в бренде» (
Дил-ABC (в бренде)и т.д.) — ранг товара среди товаров ТОГО ЖЕ бренда по продажам ОДНОГО канала. Используется в листах-планировщиках (колонка «ABC»). - 4 колонки «в канале» — ранг среди ВСЕХ брендов, тоже по одному каналу (кросс-брендовая важность для канала).
- 1 колонка
AGT-ABC— глобальный ранг по сумме продаж по ВСЕМ каналам и брендам сразу. Используется в планировщиках как «Индекс ABC». - Методология классов — та же восстановленная логика Парето (раздел 1): A ≤ 80%, B 80–95%, C > 95% накопительной выручки в своей популяции; SKU без продаж в данном разрезе — пустой код (не притягивается к C).
- Ключ строки — составной
Ключ (Бренд+Артикул)(первая колонка, форматBrodeks__KW204BLACK, тот же паттерн, что и в планировщиках), а не голый Артикул: найдено 9 коллизий одинаковых артикулов у разных брендов в общем справочнике всех 87+ брендов (включая 2 реальных для Brodeks —KW101GREY,KW603COBALTсовпадают с артикулами других брендов/«!Нет бренда»). VLOOKUP по одному артикулу подтягивал бы случайный бренд. - Инцидент при первой сборке: индексы pandas-таблицы после
groupby/sort_valuesвнутри классификации не были переиндексированы перед присвоением результата колонкой (pivot[col] = [список]— присвоение по ПОЗИЦИИ, а не по индексу), из-за чего колонки «в канале» иAGT-ABCизначально были рассинхронизированы (лидер по выручке получал код ранга ~470 вместо ~1–5). Обнаружено сразу проверкой (KW204BLACK должен быть в топ-3 по общей выручке, но показывалAGT-B467), исправлено через.reindex(pivot.index)перед сборкой строк, пересчитано и перепроверено (KS302BLACK →AGT-A001, KS209BLACK →AGT-A002, KW204BLACK →AGT-A003, порядок теперь совпадает с сортировкой по итоговой выручке).
8.5. Подключение ABC v2 к «Дилеры Brodeks v2»¶
- Колонка
E(«ABC») — было статическое значение (буква), сталоVLOOKUPна «Дил-ABC (в бренде)» изABC_анализ v2по ключу Бренд+Артикул. - Колонка
F(«Индекс ABC») — былоVLOOKUPна старый листABC_анализ, сталоVLOOKUPнаAGT-ABCизABC_анализ v2. - Побочный эффект, исправлен: 3 правила условного форматирования (закраска строки по классу — зелёный/оранжевый/серый для A/B/C) были завязаны на точное совпадение
$E4="A"— сломались бы, т.к. вEтеперь строка видаДил-A007, а не голая буква. Формулы правил переписаны наMID($E4;5;1)="A"(и аналогично для B/C) — класс всегда 5-й символ строки (после 3-буквенного префикса канала и дефиса).
8.6. Лист «Все каналы_Глеб» — полная копия структуры «Дилеры Brodeks v2» на всех SKU¶
Первая версия была урезанным статическим срезом (идентификация + суммы), но пользователь уточнил: «Все каналы_Глеб» должен полностью повторять «Дилеры Brodeks v2» (весь ФАКТ-блок на 36 месяцев, цена/себестоимость/ручная РРЦ, ПЛАН на 25 месяцев с ручным Шт, расширенный блок Итого, сравнение с базовой РРЦ) — просто с суммой продаж по ВСЕМ 4 каналам вместо одного, и на всём универсуме 2887 SKU (не только 221 артикул канала Дилеры). Пересобрано начисто, генератор — scripts/19_vse_kanaly_gleb.py.
- Приём реализации: не пересборка формул с нуля, а (1) дублирование «Дилеры Brodeks v2» (все формулы/раскраска уже верные), (2) расширение до 2891 строк (
add_rows), (3)copyPasteстроки 5 на весь диапазон 5:2891 — Sheets сам тиражирует формулы с адаптацией относительных ссылок построчно (ровно как протяжка маркером заполнения), статические данные при этом копируются как есть — переписываются следующим шагом, (4) перезапись статических колонок (Бренд/Артикул/Наименование/Категория/Ключ/ФАКТ-блок) реальными данными по всем каналам сразу, отсортированными по итоговой выручке. - ФАКТ-блок — не продажи одного канала, а сумма kolichestvo/summa по всем 4 каналам (Дил+B2B+Роз+МП) на каждый месяц, из тех же сырых продаж
prodazhi_po_kanalam_only_1c_mt, группировка по (brend1c, article1c, god_mesyac). - Коэффициент скидки канала (
CC2) переопределён на 1.0 (полная РРЦ без скидки) — у смешанного «все каналы сразу» разреза нет единого канального дисконта (Дилеры −33%, у остальных каналов другие условия). Пользователь может поставить нужный коэффициент вручную или использовать «РРЦ канала вручную» на конкретных SKU. - ABC-колонки — по прямому указанию пользователя: столбец «ABC» (E) всегда пуст (очищен
batch_clearна весь диапазон данных) — нет единого канала-контекста для ранга «в бренде»; столбец «Индекс ABC» (F) = общийAGT-Axxx(та же формула VLOOKUP наABC_анализ v2по ключу Бренд+Артикул, унаследована через copyPaste и адаптировалась сама). Следствие: 3 правила подсветки строк по классу A/B/C (MID($E4;5;1)="A"и т.п.) на этом листе никогда не сработают — E пуст всегда, это ожидаемо, не баг. - Особые ячейки (не по общему построчному шаблону, как и в разделе 8.2):
GD4/GI4(Итого-Себестоимость/baseline-выручка на строке «ИТОГО») переопределены наSUM(...5:...2891)— диапазон новых границ данных. - Инцидент при сборке (ложная тревога): пользователь на середине процесса увидел «много дублей строк» — это был промежуточный
copyPaste-этап (строка 5 тиражирована на все 2891 строки ДО перезаписи реальными данными, поэтому всё временно выглядело как повтор Brodeks/KS302BLACK). После завершения перезаписи проверено: 2887 уникальных пар Бренд+Артикул, дублей нет (проверено 3 способами: точное совпадение, без учёта регистра/пробелов, и напрямую на живом листе). - Проверено на выборке: строка 5 (лидер по общей выручке, KS302BLACK) —
E5пусто,F5="AGT-A001",CC5=CB5(коэффициент 1.0, без скидки), Итого-Шт/Выручка/Рентабельность посчитаны. Строка 4 (ИТОГО, все каналы, все 2887 SKU): 350 887 план-штук, ≈1,97 млрд ₽ план-выручки, рентабельность 61,3% (выше, чем в «Дилеры Brodeks v2», ожидаемо — там коэффициент 0.67, здесь 1.0).
9. Переименование файла Google Sheets (06.07.2026)¶
Файл переименован пользователем в Google Drive: было «AGT планирование продаж V1», стало «Калькулятор маржинальности Brodeks». ID файла и всё содержимое (листы, формулы, данные) не изменились — 1yTZW_8iWFMMsk3JzgIK2CzvawHS2kr-Wov_vxMCrIqs, доступ через тот же сервис-аккаунт. Обновлены упоминания названия в активно сопровождаемых файлах проекта (этот файл, 03_Задачи.md, 02_Решения.md, docs/index.md). Не тронуты: датированные записи в 51_Claude.md/56_OpenCode_*.md/70_Kimi.md (исторические логи сессий) и видения других моделей в docs/ (DeepSeek/GLM/Qwen/Kimi/MiniMax) — там название отражает состояние на момент написания, задним числом не меняем.
10. Лист «В2В» пересобран по аналогии с «Дилеры Brodeks v2» (06.07.2026)¶
По прямому запросу пользователя («заполняем лист В2В по аналогии с дилерами и учти особенности сортировки по ABC»). Старый лист (4 идентификационные колонки, без Категории/ABC/Индекс ABC/ручных override, буфер на 6010 строк) сохранён как «В2В (архив, старая структура)» — переименован, не удалён. Генератор — scripts/20_b2b_v2.py, приём реализации тот же, что и в 8.6/19 (дублирование «Дилеры Brodeks v2» → copyPaste строки-образца на весь диапазон → перезапись статических колонок данными канала).
- Состав: 1234 уникальных Бренд+Артикул (все SKU, когда-либо проданные через канал «В2В» за весь период), ФАКТ-блок — продажи только этого канала.
- Колонка «ABC» (E) — не «Дил-Axxx», а
B2B-ABC (в бренде)изABC_анализ v2(колонкаJ, индекс 10 относительно$A:$Q). Колонка «Индекс ABC» (F) — как и на всех листах, общийAGT-Axxx. - Коэффициент скидки (
CC2) = 0.96 — эмпирическая оценка, не согласованное решение. Рассчитан как факт.выручка / выручка-по-РРЦ на 56 831 сопоставленных строках канала В2В за весь период (≈3,9% фактической скидки). Частично отвечает на открытый вопрос В2 (см. 06_Открытые_вопросы) — цифра расчётная, требует подтверждения Глебом/Аркадьевым; при другом согласованном значении — просто заменитьCC2. - Особенности сортировки по ABC (учтено по прямому указанию пользователя):
- Буфера строк больше нет — ровно 1234 + 4 строки, без запаса «на будущее». Именно буфер стал причиной инцидента при сортировке на самом первом пилоте «Дилеры Brodeks» (раздел 6.5) — без буфера сортировка через UI безопасна.
- Физический порядок строк = по убыванию выручки канала В2В за весь период — это НЕ то же самое, что порядок по колонке E (ранг внутри бренда) и не то же самое, что колонка F (общий ранг AGT) — три разные сортировки одновременно, это нормально (так же устроено в «Дилеры Brodeks v2»/«Все каналы_Глеб»).
- Грабли при записи: коэффициент
0.96, записанный как СТРОКА черезUSER_ENTERED, на локалиru_RUинтерпретируется как текст (точка — не разделитель дробной части в этой локали) → все зависимые формулы дали#VALUE!. Исправлено записью черезvalue_input_option='RAW'с питоновскимfloat. Обнаружено и исправлено сразу же при проверке (GC5/GF5/строка ИТОГО). - Проверено: строка 5 (лидер по выручке В2В — KW204BLACK) —
E5="B2B-A001",F5="AGT-A003" (общий рейтинг ниже, т.к. AGT считает по сумме всех каналов, а не только В2В). Строка 4 (ИТОГО): 140 395 план-штук, 778,2 млн ₽ выручки, рентабельность 62%.
11. Лист «Розница+ИМ» пересобран (06.07.2026)¶
По тому же образцу, что «В2В» (раздел 10). Старый лист сохранён как «Розница+ИМ (архив, старая структура)». Генератор — scripts/21_roznica_v2.py.
- Важное уточнение пользователя: несмотря на название листа, ФАКТ-блок строится только по подразделению «Розница» («данные по подразделению Розница» — прямая цитата), БЕЗ «Интернет магазин». Это отличается от того, как считался «Роз» в
ABC_анализ v2/«Все каналы_Глеб» (там Роз = Розница + Интернет магазин суммарно) — там отдельного ранжирования только по «Розница» без ИМ не строили. Колонка E на этом листе всё равно ссылается на комбинированныйРоз-ABC (в бренде)изABC_анализ v2(столбецK, индекс 11) — небольшая осознанная несогласованность, зафиксирована здесь на случай вопросов. - 1234 → 2281 SKU (подразделение «Розница», весь период) — не путать с 1234 у В2В, разные каналы разного объёма.
- Коэффициент скидки (
CC2) = 1.0 — согласовано (не черновая оценка, в отличие от В2В): по справочнику, Розница = «Полная РРЦ», скидка 0% (решение 29.06.2026, 07_Справочники_классификаторы). - Проверено: строка 5 (лидер по выручке Розницы — KS305BLACK) —
E5="Роз-A001",F5="AGT-A004". Строка 4 (ИТОГО): 24 777 план-штук, 127,2 млн ₽ выручки, рентабельность 41,1%.
12. Лист «Маркетплейсы» создан (06.07.2026)¶
Новый лист (старой версии не было, в отличие от Дилеры/В2В/Розница+ИМ) — по прямому запросу пользователя. Тот же приём (дублирование «Дилеры Brodeks v2»). Генератор — scripts/22_marketpleisy_v2.py.
- ФАКТ-блок — сумма 2 подразделений: «Маркетплейс Озон» + «Маркетплейс Wildberries» (МП = Ozon+WB, тот же принцип объединения, что в
ABC_анализ v2/«Все каналы_Глеб» — в отличие от «Розница+ИМ», где по прямому уточнению пользователя берётся только «Розница» без ИМ). 1583 SKU. - Коэффициент (
CC2) = 0.5 — по справочнику (07_Справочники_классификаторы: «MP — доля от выручки — 50%»). Механически та же формула (Цена со скидкой = РРЦ × коэффициент), но смысл другой: не «цена для покупателя», а «доля выручки, которая реально достаётся компании» после комиссии площадки. - Открытый вопрос НЕ решён этим листом (см. В3, 06_Открытые_вопросы): методика Ozon «выручка + баллы» — как баллы включаются в 50%. Сырое
summaвзято как есть изprodazhi_po_kanalam_only_1c_mt, без корректировок на баллы. - Проверено: строка 5 (лидер — KS302BLACK) —
E5="МП-A001",F5="AGT-A001" (топ и по МП, и по всем каналам сразу). Строка 4 (ИТОГО): 86 139 план-штук, 225,5 млн ₽ выручки, рентабельность 15,4% — заметно ниже остальных каналов, ожидаемо из-за модели «50% выручки» (та же полная себестоимость, но вдвое меньшая цена реализации).
Итог: все 4 канала Глеба (Дилеры/В2В/Розница+ИМ/Маркетплейсы) теперь на структуре v2 как отдельные планировщики.
13. Разбивка «Маркетплейсы» на «Ozon» и «Wildberries» (06.07.2026)¶
По прямому запросу пользователя, с явным условием — не сломать сортировку/ранги ни на одном из существующих листов. Старый лист «Маркетплейсы» переименован в «Маркетплейсы (не используется, архив Ozon+WB)» — не удалён.
Как решена задача «не сломать сортировку»¶
Все листы-планировщики читают ABC_анализ v2 через VLOOKUP(...;'ABC_анализ v2'!$A:$Q;<номер колонки>;FALSE) с жёстко зашитым номером колонки (9/10/11/17 и т.д.), а не именем. Если бы новые колонки для Ozon/WB были вставлены В СЕРЕДИНУ существующего диапазона (например, рядом со старыми колонками «МП»), это сдвинуло бы номера ВСЕХ колонок правее точки вставки — и VLOOKUP на «Дилеры Brodeks v2»/«В2В»/«Розница+ИМ»/«Все каналы_Глеб» стали бы указывать не туда одновременно на всех листах.
Решение: новые колонки добавлены ТОЛЬКО В КОНЕЦ (R:W, после существующей Q), без единой вставки/удаления в диапазоне A:Q. Старые колонки (включая комбинированные «МП-ABC» — они больше не используются ни одним листом, но и не мешают) не тронуты. Генератор — scripts/23_abc_v2_append_ozon_wb.py, порядок строк перед записью проверен assert на точное совпадение Ключа (Бренд+Артикул) построчно с уже существующим листом.
- Новые колонки
ABC_анализ v2:R=Сумма Ozon,S=Сумма Wildberries,T=Ozon-ABC (в бренде),U=WB-ABC (в бренде),V=Ozon-ABC (в канале),W=WB-ABC (в канале). AGT-ABC(столбецQ, общий ранг) пересчитывать не потребовалось — Ozon+Wildberries суммарно математически равны прежней «Сумме МП», общий итог по SKU от разделения канала не меняется.
Листы «Ozon» и «Wildberries»¶
Тот же приём, что в 19–22 (дублирование «Дилеры Brodeks v2» → copyPaste строки-образца → перезапись статических колонок). Генератор — scripts/24_ozon_wb_channels.py.
- Ozon: 1534 SKU. Колонка E → VLOOKUP на
Ozon-ABC (в бренде)(диапазон расширен до$A:$W— только на ЭТИХ двух новых листах, старые остаются на$A:$Q). Строка 4 (ИТОГО): 70 941 план-штук, 185,1 млн ₽ выручки, рентабельность 11,4%. - Wildberries: 359 SKU. Колонка E → VLOOKUP на
WB-ABC (в бренде). Строка 4: 15 200 план-штук, 40,5 млн ₽ выручки, рентабельность 33,7% — заметно выше Ozon (более узкий, но маржинальный ассортимент). - Коэффициент (
CC2) = 0.5 для ОБОИХ — унаследован от прежнего объединённого «МП», отдельного коэффициента по площадкам не согласовано. Открытый вопрос В3 (баллы Ozon) по-прежнему не решён. - Проверено: оба листа — 0 дублей по (Бренд+Артикул); листы «Дилеры Brodeks v2»/«В2В» перепроверены ПОСЛЕ добавления колонок в ABC_анализ v2 — их E/F не изменились (Дил-A001/AGT-A002 и B2B-A001/AGT-A003 соответственно) — подтверждает, что append-стратегия ничего не сломала.
- Побочный баг найден и исправлен (по замечанию пользователя): ячейка
A1на листе «В2В» ошибочно показывала «Дилеры Brodeks» — унаследовано от шаблона «Дилеры Brodeks v2» и не было перезаписано при сборке 20-м скриптом (в отличие от остальных статических колонок A:D/G:CA, ячейкаA1— это отдельная надпись-заголовок листа вне зоны данных, про неё генератор не знал). Исправлено точечно на «В2В»; заодно проверено, что на «Ozon»/«Wildberries»/«Розница+ИМ»/«Все каналы_Глеб» эта ячейка уже верна. Урок: при следующей репликации структуры v2 на новый канал — явно проверять и переписыватьA1(название канала), это не входит в диапазон, который перезаписывают скрипты 19–24.