fix(eias-heat): суффикс « (N)» дублям имён систем — не терять резерв при UPSERT
Живой кейс ЕЭ: две зоны «Локальные зоны … МУП "Екатеринбургэнерго"» в соседних колонках листа (62.198 и 0 Гкал/ч) — UPSERT по (org, sphere, system_name, period) схлопывал их, ноль перезаписывал 62.198.
This commit is contained in:
parent
3b9dfdb44e
commit
11bc503fef
2 changed files with 57 additions and 0 deletions
|
|
@ -317,10 +317,18 @@ def parse_heat_sheet(xlsx_bytes: bytes) -> tuple[list[dict], list[list[object]]]
|
|||
return [], all_cells
|
||||
|
||||
systems: list[dict] = []
|
||||
name_counts: dict[str, int] = {}
|
||||
for j, name in _system_columns(header_cells):
|
||||
reserve = parse_reserve_number(reserve_cells[j] if j < len(reserve_cells) else None)
|
||||
if reserve is None:
|
||||
continue # непарсибельная ячейка резерва (текст/пусто) → систему скипаем
|
||||
# Разные системы могут носить БАЙТ-В-БАЙТ одинаковое имя в соседних колонках
|
||||
# (живой пример ЕЭ: две «Локальные зоны … МУП "Екатеринбургэнерго"» с 62.198
|
||||
# и 0). UPSERT по (org, sphere, system_name, period) схлопнул бы их с потерей
|
||||
# данных — вторым и далее вхождениям добавляем порядковый суффикс « (N)».
|
||||
name_counts[name] = name_counts.get(name, 0) + 1
|
||||
if name_counts[name] > 1:
|
||||
name = f"{name} ({name_counts[name]})"
|
||||
systems.append({"system_name": name, "reserve_gcal_h": reserve})
|
||||
|
||||
return systems, all_cells
|
||||
|
|
|
|||
|
|
@ -327,6 +327,55 @@ def test_parse_heat_sheet_ignores_anketa_rubrics_flag_row_size() -> None:
|
|||
assert 52.0 not in reserves
|
||||
|
||||
|
||||
def test_parse_heat_sheet_suffixes_duplicate_system_names() -> None:
|
||||
"""Разные системы с БАЙТ-В-БАЙТ одинаковым именем не схлопываются.
|
||||
|
||||
Живой прод-кейс (Екатеринбургэнерго, guid fe0c8c57): col7 и col8 обе называются
|
||||
«Локальные зоны теплоснабжения МУП "Екатеринбургэнерго"» с резервами 62.198 и 0 —
|
||||
UPSERT по (org, sphere, system_name, period) перезаписывал 62.198 нулём. Вторым
|
||||
и далее вхождениям добавляется суффикс « (N)».
|
||||
"""
|
||||
wb = openpyxl.Workbook()
|
||||
ws = wb.active
|
||||
ws.title = "ТП"
|
||||
dup = 'Локальные зоны теплоснабжения МУП "Екатеринбургэнерго"'
|
||||
ws.append(
|
||||
_pad(
|
||||
{
|
||||
4: "Централизованная система",
|
||||
7: dup,
|
||||
8: dup,
|
||||
9: 'Локальные зоны теплоснабжения ПАО "Т Плюс"',
|
||||
_ROW_SIZE_COL: 15,
|
||||
}
|
||||
)
|
||||
)
|
||||
ws.append(
|
||||
_pad(
|
||||
{
|
||||
3: 5,
|
||||
4: "Резерв мощности источников тепловой энергии, в т.ч.:",
|
||||
5: "Гкал/час",
|
||||
7: 62.198,
|
||||
8: 0,
|
||||
9: 0,
|
||||
_ROW_SIZE_COL: 57,
|
||||
}
|
||||
)
|
||||
)
|
||||
buf = io.BytesIO()
|
||||
wb.save(buf)
|
||||
|
||||
systems, _ = eh.parse_heat_sheet(buf.getvalue())
|
||||
|
||||
pairs = [(s["system_name"], s["reserve_gcal_h"]) for s in systems]
|
||||
assert pairs == [
|
||||
(dup, 62.198), # первое вхождение — без суффикса, 62.198 НЕ теряется
|
||||
(f"{dup} (2)", 0.0),
|
||||
('Локальные зоны теплоснабжения ПАО "Т Плюс"', 0.0),
|
||||
]
|
||||
|
||||
|
||||
def test_parse_heat_sheet_no_systems_header_returns_empty() -> None:
|
||||
"""Нет строки «Централизованная система» → ([], all_cells) (graceful, не падаем)."""
|
||||
wb = openpyxl.Workbook()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue