Каждый месяц планер сравнивает прогноз с фактом. Обычно это полдня в Excel. В этом практикуме мы пройдём настоящий путь: две выгрузки → скрипт → сверка с эталоном → дашборд в одном HTML-файле → кнопка, которая пересобирает всё заново. Главное, чему учит урок: сначала сходятся цифры, потом рисуем красоту.
Every month a planner compares the forecast with actuals. Usually that is half a day in Excel. In this workshop we walk the real path: two exports → a script → reconciliation with the reference → a dashboard in one HTML file → a button that rebuilds everything. The main lesson: first the numbers reconcile, then we make it pretty.
Продавец вечером сначала пересчитывает кассу и сверяет с чеками. Только когда сошлось, он пишет красивый отчёт хозяину. Если начать с отчёта, ошибка в кассе уедет в красивую таблицу — и её никто не заметит.
In the evening a shop assistant first counts the till and checks it against receipts. Only when it reconciles do they write a neat report for the owner. Start with the report, and a till error ends up in a neat table — where nobody notices it.
Задача: каждый месяц сравнивать прогноз с фактом по городам и SKU «Долины напитков» и показывать коллегам итог, отклонение и точность.
Task: every month compare forecast with actuals by city and SKU at "Valley Beverages" and show colleagues the total, deviation and accuracy.
| Признак задачиTask trait | Что это значитWhat it means |
|---|---|
| Повторяется каждый месяцRepeats every month | Нужен скрипт, который запускается одной кнопкой, а не разговор зановоYou need a script run with one click, not a new conversation each time |
| Несколько файлов и справочникSeveral files and a lookup | Склейку и соответствия кодов удобно держать в папке рядом со скриптомThe join and code mappings are best kept in the folder next to the script |
| Смотрят коллегиColleagues view it | Один HTML-файл в общей папке открывается двойным щелчком, без установкиOne HTML file in a shared folder opens with a double click, nothing to install |
Поэтому инструмент — Claude Code (уроки 15-24…15-27). Путь, по которому мы пройдём:
So the tool is Claude Code (lessons 15-24…15-27). The path we will walk:
Октябрь, 4 города × 5 SKU, тысячи литров. Файл продаж выгружен из учётной системы, файл прогноза — из файла планера. Эталон: в отчёте продаж на листе «Итого» стоит 1 287 тыс. л. В файлах спрятаны две ловушки — как в настоящих выгрузках.
October, 4 cities × 5 SKUs, thousand litres. The sales file is exported from the accounting system, the forecast file from the planner's workbook. Reference: the "Total" sheet of the sales report says 1,287 k L. Two traps are hidden in the files — as in real exports.
Выше — первые строки обоих файлов рядом. Присмотритесь к колонке «Город» и к коду сока.
Above are the first rows of both files side by side. Look closely at the "City" column and the juice code.
Создайте папку Plan_Fact, внутри — input с двумя файлами. Откройте Claude Code в папке Plan_Fact, режим — план (урок 15-25). Отправляйте запросы по одному и читайте ответ, прежде чем идти дальше.
Create a Plan_Fact folder with an input folder holding both files. Open Claude Code in Plan_Fact, plan mode (lesson 15-25). Send the requests one at a time and read each answer before moving on.
В папке input два файла: продажи и прогноз за октябрь. Опиши каждый: колонки, единицы, период, сколько городов и SKU. Найди значения города и кода SKU, которые есть только в одном из файлов. Ничего не считай и не меняй. Если что-то непонятно — спроси меня.
The input folder has two files: October sales and forecast. Describe each: columns, units, period, how many cities and SKUs. Find city and SKU code values that appear in only one of the files. Don't calculate or change anything. If anything is unclear, ask me.
Посчитай итог факта и итог прогноза. Факт сверь с эталоном: 1 287 тыс. л. Затем склей файлы по городу и коду SKU и покажи: сколько строк склеилось, сколько осталось без пары и итог факта после склейки. Если он не равен 1 287 — остановись и покажи строки без пары.
Calculate the actuals total and the forecast total. Check actuals against the reference: 1,287 k L. Then join the files on city and SKU code and show: how many rows matched, how many have no pair, and the actuals total after the join. If it isn't 1,287, stop and show the unmatched rows.
Создай справочник mapping.csv: код города → название (VTR → Ветровск) и старый код SKU → новый (3001 → 3101). Напиши скрипт extract.py: читает файлы из input (исходники не меняет), применяет справочник, склеивает, считает отклонение и точность, пишет data.json и печатает в консоль итог факта, прогноза и число строк без пары. Пути — относительно папки скрипта.
Create a lookup mapping.csv: city code → name (VTR → Vetrovsk) and old SKU code → new (3001 → 3101). Write extract.py: reads files from input (never changes the sources), applies the lookup, joins, calculates deviation and accuracy, writes data.json and prints the actuals total, forecast total and number of unmatched rows. Paths relative to the script folder.
Напиши build_dashboard.py: берёт data.json и собирает один файл Dashboard_plan_fakt_2026-10.html. Вверху три плитки: факт, прогноз, точность. Ниже — таблица город × SKU: прогноз, факт, отклонение в %, большие отклонения выделить. Фильтр по городу. Всё внутри одного файла, без интернета. Единицы — тысячи литров.
Write build_dashboard.py: takes data.json and builds one file Dashboard_plan_actual_2026-10.html. At the top three tiles: actuals, forecast, accuracy. Below — a city × SKU table: forecast, actuals, deviation in %, large deviations highlighted. A city filter. Everything inside one file, no internet. Units — thousand litres.
Сделай RUN_dashboard.bat: только латиница, переходит в свою папку (cd /d "%~dp0"), запускает extract.py, потом build_dashboard.py, в конце pause. Запусти его и покажи, что напечаталось. С этого момента после любой правки скриптов запускай .bat заново и проверяй HTML, а не только data.json.
Make RUN_dashboard.bat: Latin characters only, changes to its own folder (cd /d "%~dp0"), runs extract.py then build_dashboard.py, ends with pause. Run it and show the output. From now on, after any script change, run the .bat again and check the HTML, not just data.json.
Напиши README.md: что делает отчёт, куда класть выгрузки, как запустить, что проверить после запуска (итог факта = эталону). Добавь DATA_DICTIONARY.md: колонки, единицы, справочник кодов. И CHANGELOG.md с сегодняшней записью. Простым языком, для коллеги, который видит папку впервые.
Write README.md: what the report does, where to put exports, how to run it, what to check afterwards (actuals total = reference). Add DATA_DICTIONARY.md: columns, units, the code lookup. And CHANGELOG.md with today's entry. Plain language, for a colleague seeing the folder for the first time.
Как считать. Отклонение = (факт − прогноз) ÷ прогноз. Точность = 1 − (сумма |факт − прогноз| по всем строкам город × SKU) ÷ (сумма факта). Это одно из распространённых определений: ошибки в разные стороны не гасят друг друга, а крупные строки весят больше мелких.
How to calculate. Deviation = (actual − forecast) ÷ forecast. Accuracy = 1 − (sum of |actual − forecast| over all city × SKU rows) ÷ (sum of actuals). This is one common definition: errors in opposite directions don't cancel out, and large rows weigh more than small ones.
Пример на одной строке: прогноз 120, факт 132 → ошибка 12. Если бы это была вся компания, точность = 1 − 12 ÷ 132 = 90,9 %.
One-row example: forecast 120, actual 132 → error 12. If that were the whole company, accuracy = 1 − 12 ÷ 132 = 90.9%.
| ГородCity | ПрогнозForecast | ФактActual | Откл.Dev. | ТочностьAccuracy |
|---|---|---|---|---|
| ВетровскVetrovsk | 520 | 515 | −1,0 % | 91,7 % |
| БереговойBeregovoy | 340 | 352 | +3,5 % | 91,5 % |
| КаменскKamensk | 250 | 245 | −2,0 % | 89,8 % |
| ГорныйGorny | 170 | 175 | +2,9 % | 91,4 % |
| ИтогоTotal | 1 280 | 1 287 | +0,5 % | 91,2 % |
| SKU | ПрогнозForecast | ФактActual | Откл.Dev. |
|---|---|---|---|
| Вода 0,5Water 0.5 | 300 | 309 | +3,0 % |
| Вода 1,5Water 1.5 | 440 | 439 | −0,2 % |
| Лимонад 0,5Lemonade 0.5 | 220 | 218 | −0,9 % |
| Кола 1,0Cola 1.0 | 170 | 177 | +4,1 % |
| Сок яблочный 1,0 (3001 → 3101)Apple juice 1.0 (3001 → 3101) | 150 | 144 | −4,0 % |
Ловушка 1 — код города. В продажах Ветровск записан как «VTR», в прогнозе — «Ветровск». Склейка по городу его не находит.
Trap 1 — city code. Sales list Vetrovsk as "VTR", the forecast as "Vetrovsk". A join on city doesn't find it.
Ловушка 2 — смена кода SKU. Сок в прогнозе под старым кодом 3001, в продажах — под новым 3101. Товар тот же, код другой.
Trap 2 — SKU code switch. Juice is under the old code 3001 in the forecast and the new code 3101 in sales. Same product, different code.
Что будет, если не поймать: склеятся только 12 строк из 20, итог факта после склейки — 682 вместо 1 287 (сверка на шаге 2 это ловит). А если оставить строки без пары с нулями, точность выйдет 1,1 % вместо 91,2 % — «прогноз ужасный», хотя ошибка в кодах.
What happens if you miss them: only 12 of 20 rows match, the actuals total after the join is 682 instead of 1,287 (the step-2 check catches this). And if you keep unmatched rows with zeros, accuracy comes out at 1.1% instead of 91.2% — "the forecast is terrible", although the error is in the codes.
Для каждого симптома выберите вероятную причину.
For each symptom choose the likely cause.
| ФайлFile | Для чегоPurpose |
|---|---|
input/ | сюда каждый месяц кладут новые выгрузкиnew exports go here every month |
mapping.csv | справочник кодов; новую смену кода дописывают сюда, а не в скриптthe code lookup; a new code switch is added here, not in the script |
RUN_dashboard.bat | двойной щелчок — данные и дашборд пересобраныdouble click — data and dashboard rebuilt |
Dashboard_…html | открывается в браузере у любого коллеги из общей папкиopens in any colleague's browser from the shared folder |
README.md | как запустить и что проверить — чтобы отчёт жил без автораhow to run and what to check — so the report lives without its author |
Когда отчёт стабилен, его можно пересобирать ночью и получать короткое сообщение утром. Схема:
Once the report is stable, it can rebuild overnight and send you a short message in the morning. The pattern:
RUN_dashboard.bat ночью (компьютер должен быть включён).RUN_dashboard.bat at night (the computer must be on).Добавь в конец пересборки уведомление: при успехе — итог факта, прогноза и точность; при ошибке — номер шага и текст ошибки. Настройки (токен, адрес) читай из файла в моей личной папке, путь не зашивай в скрипт. Покажи, как поставить .bat в Планировщик заданий на 06:00.
Add a notification at the end of the rebuild: on success — actuals, forecast and accuracy; on failure — the step number and error text. Read settings (token, address) from a file in my personal folder, don't hard-code the path. Show how to schedule the .bat in Task Scheduler at 06:00.
| ОшибкаMistake | Как правильноDo this instead |
|---|---|
| Сразу просить «сделай дашборд»Asking "make a dashboard" straight away | Сначала шаги 1–2: файлы поняты, итог сошёлся с эталономSteps 1–2 first: files understood, total matches the reference |
| Верить низкой точности без проверкиTrusting low accuracy without checking | Посмотреть строки без пары — часто это коды, а не прогнозLook at unmatched rows — often it's codes, not the forecast |
| Зашить соответствие кодов в скриптHard-coding code mappings in the script | Держать в mapping.csv — его поправит любой коллегаKeep them in mapping.csv — any colleague can edit it |
| Проверять data.json вместо дашбордаChecking data.json instead of the dashboard | После правки — весь .bat и открыть HTMLAfter a fix — run the whole .bat and open the HTML |
| Путь вида C:\Users\Имя\… в скриптеA path like C:\Users\Name\… in the script | Пути от папки скрипта — тогда работает с любого ноутбукаPaths relative to the script folder — then it works on any laptop |