[SF-v2 #955] 955-A5: Excel-экспортёр (real impl) #991

Closed
opened 2026-06-02 19:25:15 +00:00 by lekss361 · 2 comments
Owner

Часть EPIC #955 (Site Finder v2 / GG-форсайт). Декомпозиция критпути — ground-truth (прод-БД + код) + web-research, 2026-06-02.

Scope: exporters/excel.py = 4-строчный stub; Excel-экспорт для SF не существует.

Файлы: backend/app/services/exporters/excel.py

DoD:

  • openpyxl workbook из SiteFinderReport; табличные секции §13

Зависит от: 955-A2
Effort: M

**Часть EPIC #955 (Site Finder v2 / GG-форсайт).** Декомпозиция критпути — ground-truth (прод-БД + код) + web-research, 2026-06-02. **Scope:** exporters/excel.py = 4-строчный stub; Excel-экспорт для SF не существует. **Файлы:** backend/app/services/exporters/excel.py **DoD:** - openpyxl workbook из SiteFinderReport; табличные секции §13 **Зависит от:** 955-A2 **Effort:** M
lekss361 added this to the Site Finder v2 — Foresight (GG-форсайт) milestone 2026-06-02 19:25:19 +00:00
lekss361 added the
GG-форсайт
scope/backend
site-finder
labels 2026-06-02 19:25:20 +00:00
lekss361 reopened this issue 2026-06-03 17:59:34 +00:00
Author
Owner

🟠 Reopen — MEDIUM: Excel-экспортёр молча теряет те же колонки (тот же контракт-mismatch, что и PDF #989). Валидация #1022.

Баг. backend/app/services/exporters/excel.py:

  • _build_future_market_sheet читает f.get("demand") / f.get("supply") — реальный DemandSupplyForecast.as_dict() (demand_supply_forecast.py:156) эмитит projected_demand_units / projected_supply_units. → колонки всегда .
  • _build_scenarios_sheet читает data.get("overall") — у ScenarioForecast.as_dict() (scenarios.py:107) такого ключа нет. → колонка всегда .

🟡 Доп. (LOW): секции future_supply (FutureSupplyPressure) и future_competitors ассемблер кладёт в future_market, но ни один экспортёр их не рендерит; confidence.factors (структурный rationale из #990) тоже не выгружается (только level+rationale). Данные есть в report — молча не попадают в выгрузку.

Fix: те же имена ключей, что в #989; добавить fixtures по реальному as_dict(); опц. вывести future_supply/future_competitors/confidence.factors.

openpyxl используется корректно (Workbook, wb.save(BytesIO), get_column_letter), _fmt безопасен на None/dict — крэша нет, потеря данных тихая.

🟠 **Reopen — MEDIUM: Excel-экспортёр молча теряет те же колонки (тот же контракт-mismatch, что и PDF #989).** Валидация #1022. **Баг.** `backend/app/services/exporters/excel.py`: - `_build_future_market_sheet` читает `f.get("demand")` / `f.get("supply")` — реальный `DemandSupplyForecast.as_dict()` (`demand_supply_forecast.py:156`) эмитит `projected_demand_units` / `projected_supply_units`. → колонки всегда `—`. - `_build_scenarios_sheet` читает `data.get("overall")` — у `ScenarioForecast.as_dict()` (`scenarios.py:107`) такого ключа нет. → колонка всегда `—`. 🟡 Доп. (LOW): секции `future_supply` (FutureSupplyPressure) и `future_competitors` ассемблер кладёт в `future_market`, но **ни один экспортёр их не рендерит**; `confidence.factors` (структурный rationale из #990) тоже не выгружается (только `level`+`rationale`). Данные есть в report — молча не попадают в выгрузку. **Fix:** те же имена ключей, что в #989; добавить fixtures по реальному `as_dict()`; опц. вывести future_supply/future_competitors/confidence.factors. _openpyxl используется корректно (`Workbook`, `wb.save(BytesIO)`, `get_column_letter`), `_fmt` безопасен на None/dict — крэша нет, потеря данных тихая._
Collaborator

FIXED (PR #1037). Excel: same key fix + added missing future_supply (index+breakdown) and confidence.factors sections. Fixtures rebuilt from real as_dict() (drift-proof). Closing on test-verify; reopen if disagrees.

FIXED (PR #1037). Excel: same key fix + added missing future_supply (index+breakdown) and confidence.factors sections. Fixtures rebuilt from real as_dict() (drift-proof). Closing on test-verify; reopen if disagrees.
Sign in to join this conversation.
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#991
No description provided.