fix: 8 багов — город, IS поля, ПО, авторасчёт, скролл, прогресc, комиссия, замены

This commit is contained in:
2026-07-30 14:38:47 +04:00
parent 7eb736bcbf
commit 30cb3f66bf
5 changed files with 210 additions and 38 deletions
+56 -8
View File
@@ -57,16 +57,19 @@ def process_template(
buf.seek(0)
doc = Document(buf)
# 5. Плоская замена переменных (2 прохода)
for _ in range(2):
# 5. Плоская замена переменных (3 прохода)
for _ in range(3):
_replace_in_paragraphs(doc.paragraphs, replacements)
_replace_in_tables(doc.tables, replacements)
_replace_in_headers_footers(doc, replacements)
# 6. Подсветка незаполненных
# 6. Логирование незаменённых переменных
_log_unmatched(doc, replacements, log_func if log_func else lambda x: None)
# 7. Подсветка незаполненных
_highlight_unmatched(doc)
# 7. Сохранение
# 8. Сохранение
doc.save(output_path)
if log_func:
@@ -338,12 +341,57 @@ def _find_element_bounds(xml_str: str, pos: int):
return None, None
# ==================== ЛОГИРОВАНИЕ НЕЗАМЕНЁННЫХ ====================
UNMATCHED_PATTERN = re.compile(r'\{\{[^}]+\}\}|<[A-Za-z0-9_]+>')
def _log_unmatched(doc, replacements: Dict[str, str], log_func):
"""Логирует оставшиеся незаменённые переменные."""
unmatched = set()
def _scan_text(text):
for m in UNMATCHED_PATTERN.finditer(text):
var = m.group(0)
# Проверяем, не является ли это уже обработанной переменной
if var.startswith('{{'):
if var not in replacements:
unmatched.add(var)
elif var.startswith('<'):
if var not in replacements:
unmatched.add(var)
for para in doc.paragraphs:
_scan_text(para.text)
for table in doc.tables:
for row in table.rows:
for cell in row.cells:
for para in cell.paragraphs:
_scan_text(para.text)
for section in doc.sections:
for hf in [section.header, section.footer,
section.first_page_header, section.first_page_footer]:
if hf:
for para in hf.paragraphs:
_scan_text(para.text)
if unmatched:
log_func(f"⚠️ Незаменённые переменные ({len(unmatched)}): {', '.join(sorted(unmatched)[:20])}")
if len(unmatched) > 20:
log_func(f" ... и ещё {len(unmatched) - 20}")
else:
log_func("✅ Все переменные успешно заменены")
# ==================== ПОДСВЕТКА НЕЗАПОЛНЕННЫХ ====================
def _highlight_unmatched(doc):
"""Подсвечивает незаполненные переменные красным."""
"""Подсвечивает незаполненные переменные красным ({{...}} и старые <...>)."""
ns = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'
def _has_unmatched(text):
return bool(UNMATCHED_PATTERN.search(text))
def _highlight_run(run):
rpr = run._element.find(f'{{{ns}}}rPr')
if rpr is None:
@@ -358,7 +406,7 @@ def _highlight_unmatched(doc):
for para in doc.paragraphs:
for run in para.runs:
if '{{' in run.text and '}}' in run.text:
if _has_unmatched(run.text):
_highlight_run(run)
for table in doc.tables:
@@ -366,7 +414,7 @@ def _highlight_unmatched(doc):
for cell in row.cells:
for para in cell.paragraphs:
for run in para.runs:
if '{{' in run.text and '}}' in run.text:
if _has_unmatched(run.text):
_highlight_run(run)
for section in doc.sections:
@@ -374,5 +422,5 @@ def _highlight_unmatched(doc):
if hf:
for para in hf.paragraphs:
for run in para.runs:
if '{{' in run.text and '}}' in run.text:
if _has_unmatched(run.text):
_highlight_run(run)