461 lines
25 KiB
Python
461 lines
25 KiB
Python
#!/usr/bin/env python3
|
||
"""Генерация PDF версии инструктажа по безопасности ТС."""
|
||
|
||
from fpdf import FPDF
|
||
from fpdf.enums import XPos, YPos
|
||
|
||
class SafetyBriefingPDF(FPDF):
|
||
def __init__(self):
|
||
super().__init__(orientation="P", unit="mm", format="A4")
|
||
self.set_auto_page_break(True, 20)
|
||
|
||
color_ink = (15, 18, 24)
|
||
color_red = (229, 57, 53)
|
||
color_gray = (91, 101, 115)
|
||
color_gray_100 = (242, 244, 247)
|
||
color_white = (255, 255, 255)
|
||
color_amber = (230, 81, 0)
|
||
color_green = (46, 125, 50)
|
||
color_cyan = (0, 229, 255)
|
||
|
||
# We register DejaVu which supports Cyrillic.
|
||
font_dir = "/usr/share/fonts/truetype/dejavu/"
|
||
self.add_font("DejaVu", "", font_dir + "DejaVuSans.ttf")
|
||
self.add_font("DejaVu", "B", font_dir + "DejaVuSans-Bold.ttf")
|
||
|
||
self.c = {
|
||
"ink": color_ink,
|
||
"red": color_red,
|
||
"gray": color_gray,
|
||
"gray_bg": color_gray_100,
|
||
"white": color_white,
|
||
"amber": color_amber,
|
||
"green": color_green,
|
||
"cyan": color_cyan,
|
||
}
|
||
|
||
# ── helpers ──────────────────────────────────────────────
|
||
|
||
def add_header_page(self):
|
||
"""Первая страница — титульный заголовок."""
|
||
self.add_page()
|
||
m = 15 # боковые поля
|
||
w = self.w - 2 * m
|
||
|
||
# Тёмный заголовок
|
||
self.set_fill_color(*self.c["ink"])
|
||
self.rect(0, 0, self.w, 72, "F")
|
||
|
||
# Красная полоса
|
||
self.set_fill_color(*self.c["red"])
|
||
self.rect(0, 72, self.w, 3, "F")
|
||
|
||
# Плашка «ВНЕПЛАНОВЫЙ ИНСТРУКТАЖ»
|
||
self.set_y(16)
|
||
self.set_font("DejaVu", "B", 9)
|
||
self.set_text_color(*self.c["white"])
|
||
self.set_fill_color(*self.c["red"])
|
||
badge_w = self.get_string_width(" ВНЕПЛАНОВЫЙ ИНСТРУКТАЖ ") + 6
|
||
self.set_x(m)
|
||
self.cell(badge_w, 6, " ВНЕПЛАНОВЫЙ ИНСТРУКТАЖ ", fill=True, new_x=XPos.LMARGIN, new_y=YPos.NEXT)
|
||
|
||
# Заголовок
|
||
self.set_y(28)
|
||
self.set_x(m)
|
||
self.set_font("DejaVu", "B", 18)
|
||
self.set_text_color(*self.c["white"])
|
||
self.multi_cell(w, 8, "Обеспечение безопасности эксплуатации транспортных средств", align="L")
|
||
|
||
# Подзаголовок
|
||
self.set_y(52)
|
||
self.set_x(m)
|
||
self.set_font("DejaVu", "", 9)
|
||
self.set_text_color(154, 163, 178)
|
||
self.multi_cell(w, 5,
|
||
"Недопущение оставления ключей в замке зажигания и свободного доступа\n"
|
||
"посторонних лиц к управлению транспортными средствами")
|
||
|
||
# Мета
|
||
self.set_y(90)
|
||
self.set_x(m)
|
||
self.set_text_color(*self.c["ink"])
|
||
self.set_font("DejaVu", "", 9)
|
||
self.cell(90, 6, "Дата инструктажа: _______________")
|
||
self.cell(0, 6, "Провёл: _______________", new_x=XPos.LMARGIN, new_y=YPos.NEXT)
|
||
|
||
def section_title(self, title):
|
||
"""Заголовок секции с подчёркиванием."""
|
||
self.ln(4)
|
||
self.set_font("DejaVu", "B", 13)
|
||
self.set_text_color(*self.c["ink"])
|
||
self.cell(0, 8, title, new_x="LMARGIN", new_y="NEXT")
|
||
y = self.get_y()
|
||
self.set_draw_color(*self.c["gray_bg"])
|
||
self.set_line_width(0.4)
|
||
self.line(self.l_margin, y + 2, self.w - self.r_margin, y + 2)
|
||
self.ln(5)
|
||
|
||
def body_text(self, text):
|
||
self.set_font("DejaVu", "", 10)
|
||
self.set_text_color(*self.c["ink"])
|
||
self.multi_cell(0, 5.5, text, align="L")
|
||
self.ln(1)
|
||
|
||
def bold_text(self, text):
|
||
self.set_font("DejaVu", "B", 10)
|
||
self.set_text_color(*self.c["ink"])
|
||
self.multi_cell(0, 5.5, text, align="L")
|
||
|
||
def sub_title(self, title):
|
||
self.ln(2)
|
||
self.set_font("DejaVu", "B", 10.5)
|
||
self.set_text_color(*self.c["ink"])
|
||
self.cell(0, 6, title, new_x="LMARGIN", new_y="NEXT")
|
||
self.ln(2)
|
||
|
||
def bullet(self, text, color=None):
|
||
x0 = self.get_x()
|
||
self.set_font("DejaVu", "", 10)
|
||
self.set_text_color(*self.c["ink"])
|
||
bx = self.l_margin + 4
|
||
self.set_x(bx)
|
||
# bullet marker
|
||
self.set_font("DejaVu", "", 10)
|
||
marker_color = color or self.c["ink"]
|
||
self.set_text_color(*marker_color)
|
||
self.set_x(self.l_margin + 1)
|
||
self.cell(5, 5.5, "\u25a0")
|
||
# text
|
||
self.set_text_color(*self.c["ink"])
|
||
self.set_x(bx + 6)
|
||
self.multi_cell(self.w - self.r_margin - bx - 6, 5.5, text)
|
||
self.ln(1)
|
||
|
||
def callout_box(self, text, border_color, bg_color):
|
||
self.set_fill_color(*bg_color)
|
||
self.set_draw_color(*border_color)
|
||
self.set_line_width(0.6)
|
||
m = self.l_margin
|
||
w = self.w - m - self.r_margin
|
||
y0 = self.get_y()
|
||
|
||
lines = text.split("\n")
|
||
n = len(lines)
|
||
h = 10 + n * 5.5 + 4
|
||
self.rect(m, y0, w, h, "DF")
|
||
|
||
self.set_draw_color(*border_color)
|
||
self.set_line_width(0.6)
|
||
self.line(m, y0, m, y0 + h)
|
||
|
||
self.set_xy(m + 5, y0 + 3)
|
||
self.set_font("DejaVu", "", 9.5)
|
||
self.set_text_color(*self.c["ink"])
|
||
for line in lines:
|
||
self.set_x(m + 5)
|
||
self.cell(w - 10, 5.5, line, new_x="LMARGIN", new_y="NEXT")
|
||
self.set_y(y0 + h + 3)
|
||
|
||
def checkbox_line(self, text="", x=None):
|
||
self.set_font("DejaVu", "", 10)
|
||
self.set_text_color(*self.c["ink"])
|
||
self.cell(6, 6, "\u2610")
|
||
self.cell(0, 6, text, new_x="LMARGIN", new_y="NEXT")
|
||
|
||
def centered_text(self, text, font_style="", size=10):
|
||
self.set_font("DejaVu", font_style, size)
|
||
self.set_text_color(*self.c["ink"])
|
||
self.cell(0, 7, text, align="C", new_x="LMARGIN", new_y="NEXT")
|
||
|
||
def _measure_lines(self, w, line_h, text):
|
||
"""Return number of lines multi_cell would produce."""
|
||
return len(self.multi_cell(w, line_h, text, dry_run=True, output="LINES"))
|
||
|
||
|
||
# ══════════════════════════════════════════════════════════
|
||
def build():
|
||
pdf = SafetyBriefingPDF()
|
||
m = 15 # боковое поле
|
||
|
||
# ── Титул ──
|
||
pdf.add_header_page()
|
||
|
||
# ══ 1. ОСНОВАНИЕ И ЦЕЛЬ ══
|
||
pdf.section_title("1. Основание и цель инструктажа")
|
||
pdf.body_text(
|
||
"Настоящий внеплановый инструктаж проводится в связи с необходимостью усиления мер "
|
||
"по обеспечению безопасности дорожного движения и сохранности имущества организации."
|
||
)
|
||
pdf.callout_box(
|
||
"Повод: выявленные случаи / риск оставления ключей в замке зажигания\n"
|
||
"транспортных средств (ТС), что создаёт свободный доступ посторонних лиц\n"
|
||
"к управлению ТС, угон, а также использование ТС не по назначению.",
|
||
pdf.c["red"], (255, 240, 240),
|
||
)
|
||
pdf.body_text(
|
||
"Цель: довести до всех категорий водителей и ответственных лиц категорические "
|
||
"требования по исключению практики оставления ключей в замке зажигания и обеспечению "
|
||
"контроля доступа к транспортным средствам."
|
||
)
|
||
|
||
# ══ 2. НОРМАТИВНАЯ БАЗА ══
|
||
pdf.section_title("2. Нормативная база")
|
||
for item in [
|
||
"Закон Республики Казахстан от 17 апреля 2014 г. № 194-V ЗРК «О дорожном движении»",
|
||
"Приказ Министра внутренних дел РК от 30 июня 2023 г. № 534 «Об утверждении Правил дорожного движения, Основных положений по допуску транспортных средств к эксплуатации»",
|
||
"Приказ и.о. Министра транспорта и коммуникаций РК от 4 марта 2005 г. № 114-I «Об утверждении Правил безопасности и охраны труда на автомобильном транспорте»",
|
||
"Кодекс РК об административных правонарушениях от 5 июля 2014 г. № 235-V ЗРК",
|
||
"Трудовой кодекс РК от 23 ноября 2015 г. № 414-V ЗРК",
|
||
"Правила внутреннего трудового распорядка и должностные инструкции организации",
|
||
"Локальные акты организации по охране труда и безопасности на транспорте",
|
||
]:
|
||
pdf.bullet(item, pdf.c["green"])
|
||
|
||
# ══ 3. КАТЕГОРИИ ЛИЦ ══
|
||
pdf.section_title("3. Категории инструктируемых лиц")
|
||
pdf.sub_title("Водители")
|
||
pdf.body_text("Штатные водители, закреплённые за конкретными ТС, выполняющие рейсы по маршрутам и заданиям организации.")
|
||
pdf.sub_title("Водители-совместители")
|
||
pdf.body_text("Сотрудники, совмещающие обязанности водителя с основной должностью, допущенные к управлению ТС организации.")
|
||
pdf.sub_title("Ответственные лица")
|
||
pdf.body_text("Лица, ответственные за выпуск ТС на линию, техническое состояние, хранение ТС и ведение документации.")
|
||
|
||
# ══ 4. ОПИСАНИЕ ПРОБЛЕМЫ И РИСКОВ ══
|
||
pdf.section_title("4. Описание проблемы и рисков")
|
||
pdf.body_text(
|
||
"Оставление ключей в замке зажигания транспортного средства вне зависимости от места нахождения ТС "
|
||
"(на территории организации, стоянке, в гараже, на линии) создаёт следующие угрозы:"
|
||
)
|
||
|
||
# таблица рисков
|
||
risk_data = [
|
||
("Угон ТС посторонними лицами",
|
||
"Материальный ущерб организации, уголовная ответственность, срыв производственных задач"),
|
||
("Использование ТС не по назначению",
|
||
"Расход ГСМ, износ ТС, нарушение трудовой дисциплины"),
|
||
("ДТП, совершённое лицом без допуска",
|
||
"Ущерб жизни и здоровью третьих лиц, гражданская и уголовная ответственность"),
|
||
("Хищение груза / имущества из ТС",
|
||
"Прямые финансовые потери, утрата доверия контрагентов"),
|
||
("Нарушение требований ОТ и ПДД",
|
||
"Штрафы, дисциплинарные взыскания, предписания контролирующих органов"),
|
||
]
|
||
col1_w = 75
|
||
col2_w = pdf.w - pdf.l_margin - pdf.r_margin - col1_w
|
||
# header
|
||
pdf.set_fill_color(*pdf.c["ink"])
|
||
pdf.set_text_color(*pdf.c["white"])
|
||
pdf.set_font("DejaVu", "B", 9)
|
||
pdf.cell(col1_w, 7, " Риск", border=1, fill=True)
|
||
pdf.cell(col2_w, 7, " Последствия", border=1, fill=True, new_x="LMARGIN", new_y="NEXT")
|
||
# rows
|
||
for i, (risk, consequence) in enumerate(risk_data):
|
||
pdf.set_font("DejaVu", "", 8.5)
|
||
pdf.set_text_color(*pdf.c["ink"])
|
||
if i % 2 == 0:
|
||
pdf.set_fill_color(*pdf.c["gray_bg"])
|
||
else:
|
||
pdf.set_fill_color(*pdf.c["white"])
|
||
y0 = pdf.get_y()
|
||
# measure multi_cell heights
|
||
pdf.set_font("DejaVu", "", 8.5)
|
||
# compute height
|
||
h1 = pdf._measure_lines(col1_w - 2, 4.5, risk) * 4.5
|
||
h2 = pdf._measure_lines(col2_w - 2, 4.5, consequence) * 4.5
|
||
h = max(h1, h2, 13)
|
||
if pdf.get_y() + h > pdf.h - pdf.b_margin:
|
||
pdf.add_page()
|
||
y0 = pdf.get_y()
|
||
# draw
|
||
pdf.set_fill_color(pdf.c["gray_bg"] if i % 2 == 0 else pdf.c["white"])
|
||
pdf.rect(pdf.l_margin, y0, col1_w, h, "DF")
|
||
pdf.rect(pdf.l_margin + col1_w, y0, col2_w, h, "DF")
|
||
pdf.set_xy(pdf.l_margin + 1, y0 + 1)
|
||
pdf.set_text_color(*pdf.c["ink"])
|
||
pdf.set_font("DejaVu", "B", 8.5)
|
||
pdf.multi_cell(col1_w - 2, 4.5, risk)
|
||
pdf.set_xy(pdf.l_margin + col1_w + 1, y0 + 1)
|
||
pdf.set_font("DejaVu", "", 8.5)
|
||
pdf.multi_cell(col2_w - 2, 4.5, consequence)
|
||
pdf.set_y(y0 + h)
|
||
pdf.ln(4)
|
||
|
||
# ══ 5. КАТЕГОРИЧЕСКИЕ ТРЕБОВАНИЯ ══
|
||
pdf.section_title("5. Категорические требования для всех категорий")
|
||
|
||
pdf.callout_box(
|
||
"ЗАПРЕЩЕНО: оставлять ключи в замке зажигания ТС при любых обстоятельствах:\n"
|
||
" \u2022 при кратковременной остановке (заправка, погрузка/разгрузка)\n"
|
||
" \u2022 при стоянке на охраняемой территории организации\n"
|
||
" \u2022 при постановке ТС в гараж / бокс\n"
|
||
" \u2022 при прогреве двигателя без присутствия водителя в кабине\n"
|
||
" \u2022 при передаче ТС другому лицу без оформления путевой документации",
|
||
pdf.c["red"], (255, 240, 240),
|
||
)
|
||
|
||
pdf.callout_box(
|
||
"ОБЯЗАНОСТЬ: при покидании транспортного средства водитель обязан:\n"
|
||
" \u2022 заглушить двигатель\n"
|
||
" \u2022 извлечь ключ из замка зажигания\n"
|
||
" \u2022 убрать ключ в надёжное место (карман одежды, сумку)\n"
|
||
" \u2022 убедиться, что ТС обездвижено (стояночный тормоз, передача)\n"
|
||
" \u2022 закрыть двери кабины/салона на замок",
|
||
pdf.c["amber"], (255, 248, 225),
|
||
)
|
||
|
||
# ══ 6. ТРЕБОВАНИЯ ПО КАТЕГОРИЯМ ══
|
||
pdf.section_title("6. Требования по категориям")
|
||
|
||
pdf.sub_title("6.1 Водители (штатные)")
|
||
for item in [
|
||
"Ключи от закреплённого ТС хранятся только у водителя, которому выданы под подпись.",
|
||
"При возвращении на базу — сдать ключи диспетчеру / ответственному лицу под роспись в журнале.",
|
||
"Запрещена передача ключей третьим лицам (включая коллег) без разрешения ответственного лица.",
|
||
"При обнаружении ключей, оставленных в замке зажигания другого ТС — немедленно сообщить диспетчеру и изъять ключи.",
|
||
]:
|
||
pdf.bullet(item)
|
||
|
||
pdf.sub_title("6.2 Водители-совместители")
|
||
for item in [
|
||
"Ключи от ТС получать у ответственного лица на конкретный рейс/задание под роспись.",
|
||
"По возвращении сдать ключи немедленно, не оставляя их в кабине.",
|
||
"Запрещено брать ТС без оформленного путевого листа и отметки механика о допуске.",
|
||
"Запрещено хранить дубликаты ключей от ТС в личных вещах без согласования с ответственным лицом.",
|
||
]:
|
||
pdf.bullet(item)
|
||
|
||
pdf.sub_title("6.3 Ответственные лица (диспетчеры, механики, начальники колонн)")
|
||
for item in [
|
||
"Вести журнал выдачи-возврата ключей от ТС с подписями водителей и отметками времени.",
|
||
"Ежедневно проверять наличие ключей в месте хранения (запираемый ящик / сейф).",
|
||
"Контролировать, что выпуск ТС осуществляется только при наличии путевого листа и отметки о медосмотре.",
|
||
"Незамедлительно докладывать руководству о фактах оставления ключей в замке зажигания.",
|
||
"Обеспечить хранение резервных (дублирующих) ключей в опечатанном виде с записью в журнале.",
|
||
"Проводить внезапные проверки стоянки ТС на предмет наличия ключей в замке зажигания.",
|
||
]:
|
||
pdf.bullet(item)
|
||
|
||
# ══ 7. ПОРЯДОК ХРАНЕНИЯ И УЧЁТА КЛЮЧЕЙ ══
|
||
pdf.section_title("7. Порядок хранения и учёта ключей от ТС")
|
||
|
||
table_data = [
|
||
("Операция", "Действие", "Документ", "Ответственный"),
|
||
("Выдача ключей перед рейсом", "Выдать водителю лично под роспись", "Журнал выдачи ключей", "Диспетчер"),
|
||
("Возврат ключей после рейса", "Принять, проверить, сделать запись", "Журнал выдачи ключей", "Диспетчер"),
|
||
("Хранение в нерабочее время", "Запираемый шкаф / сейф в диспетчерской", "—", "Диспетчер / охрана"),
|
||
("Дубликаты ключей", "Опечатанный пенал с биркой (номер ТС)", "Опечатанный пенал", "Руководитель транспортного отдела"),
|
||
("Утеря / поломка ключа", "Акт + выдача дубликата + замена замка", "Акт об утере", "Комиссия (не менее 2 чел.)"),
|
||
]
|
||
cols = [45, 55, 42, 52]
|
||
col_total = sum(cols)
|
||
cw = []
|
||
avail = pdf.w - pdf.l_margin - pdf.r_margin
|
||
for c in cols:
|
||
cw.append(avail * c / col_total)
|
||
|
||
for ri, row in enumerate(table_data):
|
||
if pdf.get_y() > pdf.h - 20:
|
||
pdf.add_page()
|
||
for ci, cell in enumerate(row):
|
||
if ri == 0:
|
||
pdf.set_fill_color(*pdf.c["ink"])
|
||
pdf.set_text_color(*pdf.c["white"])
|
||
pdf.set_font("DejaVu", "B", 7.5)
|
||
else:
|
||
pdf.set_fill_color(pdf.c["gray_bg"] if ri % 2 == 0 else pdf.c["white"])
|
||
pdf.set_text_color(*pdf.c["ink"])
|
||
pdf.set_font("DejaVu", "", 7.5)
|
||
pdf.cell(cw[ci], 7, " " + cell, border=1, fill=True)
|
||
pdf.ln()
|
||
|
||
pdf.ln(4)
|
||
|
||
# ══ 8. ОТВЕТСТВЕННОСТЬ ══
|
||
pdf.section_title("8. Ответственность за нарушения")
|
||
|
||
resp_data = [
|
||
("Первичное оставление ключей (без последствий)",
|
||
"Дисциплинарное взыскание (замечание / выговор) + внеочередной инструктаж"),
|
||
("Повторное оставление ключей",
|
||
"Строгий выговор + лишение премии"),
|
||
("Систематические нарушения (3 и более)",
|
||
"Отстранение от управления ТС, расторжение трудового договора"),
|
||
("Оставление ключей, повлёкшее угон / ДТП",
|
||
"Материальная ответственность в полном объёме ущерба + передача материалов в правоохранительные органы"),
|
||
("Сокрытие факта оставления ключей",
|
||
"Увольнение + материальная ответственность"),
|
||
]
|
||
col1_w_r = 80
|
||
col2_w_r = pdf.w - pdf.l_margin - pdf.r_margin - col1_w_r
|
||
# header
|
||
pdf.set_fill_color(*pdf.c["ink"])
|
||
pdf.set_text_color(*pdf.c["white"])
|
||
pdf.set_font("DejaVu", "B", 9)
|
||
pdf.cell(col1_w_r, 7, " Нарушение", border=1, fill=True)
|
||
pdf.cell(col2_w_r, 7, " Мера ответственности", border=1, fill=True, new_x="LMARGIN", new_y="NEXT")
|
||
for i, (violation, measure) in enumerate(resp_data):
|
||
if pdf.get_y() > pdf.h - 20:
|
||
pdf.add_page()
|
||
# compute height
|
||
pdf.set_font("DejaVu", "", 8.5)
|
||
h1 = pdf._measure_lines(col1_w_r - 2, 4.5, violation) * 4.5
|
||
h2 = pdf._measure_lines(col2_w_r - 2, 4.5, measure) * 4.5
|
||
h = max(h1, h2, 13)
|
||
y0 = pdf.get_y()
|
||
if y0 + h > pdf.h - pdf.b_margin:
|
||
pdf.add_page()
|
||
y0 = pdf.get_y()
|
||
pdf.set_fill_color(pdf.c["gray_bg"] if i % 2 == 0 else pdf.c["white"])
|
||
pdf.rect(pdf.l_margin, y0, col1_w_r, h, "DF")
|
||
pdf.rect(pdf.l_margin + col1_w_r, y0, col2_w_r, h, "DF")
|
||
pdf.set_xy(pdf.l_margin + 1, y0 + 1)
|
||
pdf.set_font("DejaVu", "B", 8.5)
|
||
pdf.set_text_color(*pdf.c["ink"])
|
||
pdf.multi_cell(col1_w_r - 2, 4.5, violation)
|
||
pdf.set_xy(pdf.l_margin + col1_w_r + 1, y0 + 1)
|
||
pdf.set_font("DejaVu", "", 8.5)
|
||
pdf.multi_cell(col2_w_r - 2, 4.5, measure)
|
||
pdf.set_y(y0 + h)
|
||
pdf.ln(4)
|
||
|
||
# ══ 9. ЛИСТ ОЗНАКОМЛЕНИЯ ══
|
||
pdf.section_title("9. Лист ознакомления с инструктажом")
|
||
pdf.body_text(
|
||
"Своей подписью подтверждаю, что с содержанием внепланового инструктажа ознакомлен(а), "
|
||
"требования и меру ответственности осознаю, обязуюсь выполнять."
|
||
)
|
||
|
||
pdf.ln(4)
|
||
# Таблица подписей
|
||
sig_header = ["Фамилия И.О.", "Должность / Категория", "Подпись и дата"]
|
||
sig_w = [55, 75, (pdf.w - pdf.l_margin - pdf.r_margin - 130)] # dynamic
|
||
|
||
# header
|
||
pdf.set_fill_color(*pdf.c["ink"])
|
||
pdf.set_text_color(*pdf.c["white"])
|
||
pdf.set_font("DejaVu", "B", 9)
|
||
pdf.cell(sig_w[0], 7, " " + sig_header[0], border=1, fill=True)
|
||
pdf.cell(sig_w[1], 7, " " + sig_header[1], border=1, fill=True)
|
||
pdf.cell(sig_w[2], 7, " " + sig_header[2], border=1, fill=True, new_x="LMARGIN", new_y="NEXT")
|
||
|
||
for i in range(12):
|
||
if pdf.get_y() > pdf.h - 20:
|
||
pdf.add_page()
|
||
pdf.set_fill_color(pdf.c["gray_bg"] if i % 2 == 0 else pdf.c["white"])
|
||
pdf.set_text_color(*pdf.c["ink"])
|
||
pdf.set_font("DejaVu", "", 9)
|
||
pdf.cell(sig_w[0], 9, "", border=1, fill=True)
|
||
pdf.cell(sig_w[1], 9, "", border=1, fill=True)
|
||
pdf.cell(sig_w[2], 9, "", border=1, fill=True, new_x="LMARGIN", new_y="NEXT")
|
||
|
||
pdf.ln(6)
|
||
pdf.body_text("Инструктаж провёл: _______________________________________ (должность, Ф.И.О., подпись, дата)")
|
||
|
||
# ── SAVE ──
|
||
out = "Инструктаж_Безопасность_ТС_Ключи_зажигания.pdf"
|
||
pdf.output(out)
|
||
print(f"PDF сохранён: {out}")
|
||
|
||
if __name__ == "__main__":
|
||
build()
|