feat(mera/pdf): дисклеймер 135-ФЗ в подвале каждой страницы отчёта (блок 4.2) (#2885)
Some checks failed
Deploy Trade-In / build-backend (push) Blocked by required conditions
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 12s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Has been cancelled
Some checks failed
Deploy Trade-In / build-backend (push) Blocked by required conditions
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 12s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Has been cancelled
This commit is contained in:
commit
321cf85e87
1 changed files with 48 additions and 6 deletions
|
|
@ -238,6 +238,11 @@ _FS_MD = "10.5pt" # базовый текст (body), значения в та
|
||||||
_FS_LG = "13pt" # заголовки страниц (h2, PT Serif)
|
_FS_LG = "13pt" # заголовки страниц (h2, PT Serif)
|
||||||
_FS_XL = "16pt" # главный заголовок cover (h1, PT Serif)
|
_FS_XL = "16pt" # главный заголовок cover (h1, PT Serif)
|
||||||
_FS_XXL = "22pt" # крупные ценовые цифры (dual-price блок)
|
_FS_XXL = "22pt" # крупные ценовые цифры (dual-price блок)
|
||||||
|
# Намеренное исключение из 6-шаговой шкалы: running-footer — @page margin-box с
|
||||||
|
# фиксированной высотой (19mm ≈ 53.9pt), делить с mono-мета-строкой/wordmark
|
||||||
|
# практически нечем (см. _page_footer). 135-ФЗ дисклеймер (Блок 4.2) должен
|
||||||
|
# влезать в ~380-450 симв. на каждой странице без пятой пустой страницы.
|
||||||
|
_FS_XXS = "5pt" # ТОЛЬКО 135-ФЗ футер-дисклеймер (_page_footer) — не переиспользовать
|
||||||
|
|
||||||
|
|
||||||
# ── Embedded fonts (PT Sans / PT Serif, ParaType, SIL OFL 1.1) ──────────────
|
# ── Embedded fonts (PT Sans / PT Serif, ParaType, SIL OFL 1.1) ──────────────
|
||||||
|
|
@ -528,6 +533,20 @@ def _page_header(brand, report_num: str, report_date: dt.date) -> str: # type:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Блок 4.2 юр-требований: должен печататься в подвале КАЖДОЙ страницы отчёта
|
||||||
|
# (не только cover). Текст утверждён владельцем продукта дословно — не менять
|
||||||
|
# формулировку без явного запроса. Заведён как модульная константа (не inline
|
||||||
|
# в _page_footer), чтобы не расползалась по нескольким билдерам страниц.
|
||||||
|
_PDF_135FZ_FOOTER_NOTICE = (
|
||||||
|
"Документ содержит индикативный (ориентировочный) расчёт стоимости объекта, "
|
||||||
|
"сформированный автоматически сервисом «МЕРА». Не является отчётом об оценке "
|
||||||
|
"по Федеральному закону № 135-ФЗ и не имеет установленной этим законом "
|
||||||
|
"юридической силы. Не предназначен для использования при ипотечном "
|
||||||
|
"кредитовании, в судебных разбирательствах, нотариальных действиях и иных "
|
||||||
|
"случаях, где законом предусмотрено обязательное проведение независимой оценки."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _page_footer(
|
def _page_footer(
|
||||||
brand, # type: ignore[no-untyped-def]
|
brand, # type: ignore[no-untyped-def]
|
||||||
report_num: str,
|
report_num: str,
|
||||||
|
|
@ -542,7 +561,10 @@ def _page_footer(
|
||||||
|
|
||||||
строка 1 — mono meta (№ отчёта / дата / срок действия); тонкая градиентная
|
строка 1 — mono meta (№ отчёта / дата / срок действия); тонкая градиентная
|
||||||
линия-разделитель; строка 2 — точка акцента + wordmark (brand.name — НЕ
|
линия-разделитель; строка 2 — точка акцента + wordmark (brand.name — НЕ
|
||||||
хардкод «МЕРА», white-label остаётся рабочим). Номер версии продукта здесь
|
хардкод «МЕРА», white-label остаётся рабочим); строка 3 — 135-ФЗ дисклеймер
|
||||||
|
(Блок 4.2, _PDF_135FZ_FOOTER_NOTICE) — печатается на КАЖДОЙ странице, т.к.
|
||||||
|
footer рендерится один раз как running @page margin-box (см. вызов в
|
||||||
|
generate_trade_in_pdf), а не per-page. Номер версии продукта здесь
|
||||||
НЕ дублируется — единственное место вывода версии в PDF — running-header
|
НЕ дублируется — единственное место вывода версии в PDF — running-header
|
||||||
(_page_header → product_version_line()); раньше рядом с wordmark висел
|
(_page_header → product_version_line()); раньше рядом с wordmark висел
|
||||||
decorative "vN.N.N" (_REPORT_ENGINE_VERSION), не связанный с реальной
|
decorative "vN.N.N" (_REPORT_ENGINE_VERSION), не связанный с реальной
|
||||||
|
|
@ -552,6 +574,17 @@ def _page_footer(
|
||||||
на офер-странице), которого нет в веб-референсе (там нет пагинации). Не
|
на офер-странице), которого нет в веб-референсе (там нет пагинации). Не
|
||||||
удалён — вынесен приглушённой строкой НАД HUD-баром, чтобы не терять
|
удалён — вынесен приглушённой строкой НАД HUD-баром, чтобы не терять
|
||||||
полезную для печатного многостраничного отчёта информацию.
|
полезную для печатного многостраничного отчёта информацию.
|
||||||
|
|
||||||
|
#footer-height-budget (2026-08-14, Блок 4.2): @bottom-center margin-box
|
||||||
|
высотой = page margin-bottom (см. _build_css). Добавление 135-ФЗ текста
|
||||||
|
(~440 симв.) потребовало И сжать существующий HUD-хром (margin-top
|
||||||
|
6→4pt, padding-top 8→6pt, line-height мета/wordmark строк 1.35→1.15,
|
||||||
|
градиент-разделитель margin 6pt 0→3pt 0 — экономия ~13pt), И минимально
|
||||||
|
поднять @page margin-bottom (19mm→21mm, +2mm/+5.67pt) — сжатия одного
|
||||||
|
подвала было недостаточно без деградации до нечитаемого. Риск: margin-bottom
|
||||||
|
режет тело КАЖДОЙ из 4 страниц → потенциальный откат к 5-й почти пустой
|
||||||
|
странице (регрессия, чинившаяся в 42a50cf8) — реальным рендером
|
||||||
|
(WeasyPrint/Pango, недоступен на Windows-деве) не подтверждено, см. PR.
|
||||||
"""
|
"""
|
||||||
note_html = ""
|
note_html = ""
|
||||||
if page_note:
|
if page_note:
|
||||||
|
|
@ -583,18 +616,18 @@ def _page_footer(
|
||||||
# тела страницы) и был источником сложности; заменён на простую тонкую
|
# тела страницы) и был источником сложности; заменён на простую тонкую
|
||||||
# градиентную линию-разделитель между строками meta/wordmark.
|
# градиентную линию-разделитель между строками meta/wordmark.
|
||||||
return f"""
|
return f"""
|
||||||
<div style="margin-top:6pt;">
|
<div style="margin-top:4pt;">
|
||||||
{note_html}
|
{note_html}
|
||||||
<div style="border-top:1pt solid {_LINE_SOFT};padding-top:8pt;
|
<div style="border-top:1pt solid {_LINE_SOFT};padding-top:6pt;
|
||||||
font-family:{mono_family};font-size:{_FS_XS};letter-spacing:0.06em;
|
font-family:{mono_family};font-size:{_FS_XS};letter-spacing:0.06em;
|
||||||
color:{_MUTED_2};">
|
color:{_MUTED_2};line-height:1.15;">
|
||||||
<div style="white-space:nowrap;overflow:hidden;">
|
<div style="white-space:nowrap;overflow:hidden;">
|
||||||
ОТЧЁТ <span style="color:{_MUTED};">{_html.escape(report_num)}</span>
|
ОТЧЁТ <span style="color:{_MUTED};">{_html.escape(report_num)}</span>
|
||||||
<span style="margin-left:16pt;">ДАТА
|
<span style="margin-left:16pt;">ДАТА
|
||||||
<span style="color:{_MUTED};">{report_date.strftime("%d.%m.%Y")}</span></span>
|
<span style="color:{_MUTED};">{report_date.strftime("%d.%m.%Y")}</span></span>
|
||||||
{valid_until_html}
|
{valid_until_html}
|
||||||
</div>
|
</div>
|
||||||
<div style="height:1pt;margin:6pt 0;background:linear-gradient(90deg,
|
<div style="height:1pt;margin:3pt 0;background:linear-gradient(90deg,
|
||||||
transparent,{_LINE_DOTTED} 15%,{_ACCENT} 50%,{_LINE_DOTTED} 85%,
|
transparent,{_LINE_DOTTED} 15%,{_ACCENT} 50%,{_LINE_DOTTED} 85%,
|
||||||
transparent);"></div>
|
transparent);"></div>
|
||||||
<div style="display:flex;align-items:center;gap:7pt;min-width:0;">
|
<div style="display:flex;align-items:center;gap:7pt;min-width:0;">
|
||||||
|
|
@ -606,6 +639,11 @@ def _page_footer(
|
||||||
{_html.escape(brand.name).upper()}</span>
|
{_html.escape(brand.name).upper()}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div style="margin-top:3pt;font-family:'PT Sans','DejaVu Sans',sans-serif;
|
||||||
|
font-size:{_FS_XXS};line-height:1.15;color:{_MUTED_2};
|
||||||
|
overflow-wrap:anywhere;">
|
||||||
|
{_html.escape(_PDF_135FZ_FOOTER_NOTICE)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -1962,7 +2000,11 @@ def _build_css(brand=None) -> str: # type: ignore[no-untyped-def]
|
||||||
}}
|
}}
|
||||||
@page {{
|
@page {{
|
||||||
size: A4;
|
size: A4;
|
||||||
margin: 25mm 18mm 19mm 18mm;
|
/* bottom 19mm→21mm (#footer-height-budget, Блок 4.2): +2mm — минимум,
|
||||||
|
которого не хватило внутри @bottom-center margin-box (высота margin-box
|
||||||
|
= margin-bottom) даже после сжатия HUD-хрома _page_footer под 135-ФЗ
|
||||||
|
дисклеймер на каждой странице. См. арифметику в _page_footer(). */
|
||||||
|
margin: 25mm 18mm 21mm 18mm;
|
||||||
@top-center {{ content: element(runningHeader); vertical-align: bottom; }}
|
@top-center {{ content: element(runningHeader); vertical-align: bottom; }}
|
||||||
@bottom-center {{ content: element(runningFooter); vertical-align: top; }}
|
@bottom-center {{ content: element(runningFooter); vertical-align: top; }}
|
||||||
}}
|
}}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue