fix: keep default pdf assets outside runtime media
This commit is contained in:
286
backend/workflows/pdf_assets/offboarding_template.html
Normal file
286
backend/workflows/pdf_assets/offboarding_template.html
Normal file
@@ -0,0 +1,286 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ PDF_LANG or T.lang or 'de' }}">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ T.offboarding_title }}</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
color: #0f172a;
|
||||
font-size: 10.2px;
|
||||
line-height: 1.4;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.hero {
|
||||
background: #fff3f3;
|
||||
border: 1px solid #f0dddd;
|
||||
border-left: 4px solid #a32b2b;
|
||||
padding: 8px 10px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin: 0;
|
||||
font-size: 17px;
|
||||
color: #7a1e1e;
|
||||
font-weight: bold;
|
||||
letter-spacing: 0.2px;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-top: 9px;
|
||||
font-size: 11px;
|
||||
color: #7a1e1e;
|
||||
font-weight: bold;
|
||||
border-bottom: 1px solid #efd8d8;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 6px 0;
|
||||
}
|
||||
|
||||
th, td {
|
||||
border: 1px solid #f0e1e1;
|
||||
padding: 4px 6px;
|
||||
vertical-align: top;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
th {
|
||||
background: #fff8f8;
|
||||
color: #651818;
|
||||
font-weight: bold;
|
||||
width: 31%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.mono {
|
||||
font-weight: bold;
|
||||
color: #111827;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.opt-card {
|
||||
border: 1px solid #f0e1e1;
|
||||
margin-top: 6px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.opt-title {
|
||||
background: #7a1e1e;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
padding: 5px 6px;
|
||||
font-size: 9.5px;
|
||||
}
|
||||
|
||||
.opt-grid {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.opt-grid td {
|
||||
border: 1px solid #f0e1e1;
|
||||
padding: 3px 5px;
|
||||
width: 33.33%;
|
||||
font-size: 9.5px;
|
||||
}
|
||||
|
||||
.sigbox {
|
||||
border: 1px solid #e5e7eb;
|
||||
padding: 7px;
|
||||
margin-top: 8px;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.sigline {
|
||||
margin-top: 9px;
|
||||
}
|
||||
|
||||
.line {
|
||||
display: inline-block;
|
||||
border-bottom: 1px solid #334155;
|
||||
min-width: 165px;
|
||||
height: 12px;
|
||||
vertical-align: bottom;
|
||||
margin: 0 6px;
|
||||
}
|
||||
|
||||
.small {
|
||||
color: #64748b;
|
||||
font-size: 9px;
|
||||
}
|
||||
|
||||
.cb {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin-right: 10px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
min-width: 12px;
|
||||
font-size: 12px;
|
||||
line-height: 12px;
|
||||
color: #b8b8b8;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.manual-note {
|
||||
margin: 6px 0 8px;
|
||||
color: #5b6472;
|
||||
font-size: 9.4px;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="hero">
|
||||
<h1 class="title">{{ T.offboarding_title }}</h1>
|
||||
</div>
|
||||
|
||||
{% for section in PDF_SECTIONS %}
|
||||
{% if section.has_content %}
|
||||
<div class="section">{{ section.title }}</div>
|
||||
|
||||
{% if section.scalar_rows %}
|
||||
<table>
|
||||
{% for row in section.scalar_rows %}
|
||||
<tr>
|
||||
<th>{{ row[0].label }}</th>
|
||||
<td{% if not row[1] %} colspan="3"{% endif %}{% if row[0].name in ['full_name', 'work_email'] %} class="mono"{% endif %}>{{ row[0].display_value }}</td>
|
||||
{% if row[1] %}
|
||||
<th>{{ row[1].label }}</th>
|
||||
<td>{{ row[1].display_value }}</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
<div class="section">{{ T.offboarding_requester }}</div>
|
||||
<table>
|
||||
<tr>
|
||||
<th>{{ T.requested_by_name }}</th>
|
||||
<td>{{ REQUESTED_BY_NAME }}</td>
|
||||
<th>{{ T.requested_by_email }}</th>
|
||||
<td>{{ REQUESTED_BY }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
{% if HAS_ONBOARDING_DATA %}
|
||||
<div class="section">{{ T.it_hardware_status }}</div>
|
||||
<div class="opt-card">
|
||||
<div class="opt-title">{{ T.hardware_check }}</div>
|
||||
<table class="opt-grid">
|
||||
{% if HARDWARE_CHECKLIST %}
|
||||
{% for item in HARDWARE_CHECKLIST %}
|
||||
{% if loop.index0 % 3 == 0 %}<tr>{% endif %}
|
||||
<td><span class="cb">□</span> {{ item.label }}</td>
|
||||
{% if loop.index0 % 3 == 2 or loop.last %}</tr>{% endif %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<tr><td colspan="3">{{ T.no_onboarding_hardware }}</td></tr>
|
||||
{% endif %}
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="section">{{ T.manual_return_overview }}</div>
|
||||
<p class="manual-note">{{ T.manual_return_note }}</p>
|
||||
|
||||
<div class="opt-card">
|
||||
<div class="opt-title">{{ T.returned_devices }}</div>
|
||||
<table class="opt-grid">
|
||||
{% for row in MANUAL_DEVICES %}
|
||||
<tr>
|
||||
{% for cell in row %}<td><span class="cb">□</span> {{ cell }}</td>{% endfor %}
|
||||
{% if row|length < 3 %}
|
||||
{% for _ in range(3 - row|length) %}<td></td>{% endfor %}
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="opt-card">
|
||||
<div class="opt-title">{{ T.returned_software }}</div>
|
||||
<table class="opt-grid">
|
||||
{% for row in MANUAL_SOFTWARE %}
|
||||
<tr>
|
||||
{% for cell in row %}<td><span class="cb">□</span> {{ cell }}</td>{% endfor %}
|
||||
{% if row|length < 3 %}
|
||||
{% for _ in range(3 - row|length) %}<td></td>{% endfor %}
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="opt-card">
|
||||
<div class="opt-title">{{ T.removed_workspace_groups }}</div>
|
||||
<table class="opt-grid">
|
||||
{% for row in MANUAL_WORKSPACE_GROUPS %}
|
||||
<tr>
|
||||
{% for cell in row %}<td><span class="cb">□</span> {{ cell }}</td>{% endfor %}
|
||||
{% if row|length < 3 %}
|
||||
{% for _ in range(3 - row|length) %}<td></td>{% endfor %}
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="opt-card">
|
||||
<div class="opt-title">{{ T.removed_accesses }}</div>
|
||||
<table class="opt-grid">
|
||||
{% for row in MANUAL_ACCESSES %}
|
||||
<tr>
|
||||
{% for cell in row %}<td><span class="cb">□</span> {{ cell }}</td>{% endfor %}
|
||||
{% if row|length < 3 %}
|
||||
{% for _ in range(3 - row|length) %}<td></td>{% endfor %}
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="opt-card">
|
||||
<div class="opt-title">{{ T.returned_extra_it }}</div>
|
||||
<table class="opt-grid">
|
||||
{% for row in MANUAL_EXTRA_HARDWARE %}
|
||||
<tr>
|
||||
{% for cell in row %}<td><span class="cb">□</span> {{ cell }}</td>{% endfor %}
|
||||
{% if row|length < 3 %}
|
||||
{% for _ in range(3 - row|length) %}<td></td>{% endfor %}
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% for row in MANUAL_EXTRA_SOFTWARE %}
|
||||
<tr>
|
||||
{% for cell in row %}<td><span class="cb">□</span> {{ cell }}</td>{% endfor %}
|
||||
{% if row|length < 3 %}
|
||||
{% for _ in range(3 - row|length) %}<td></td>{% endfor %}
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="section">{{ T.it_signatures }}</div>
|
||||
<div class="sigbox">
|
||||
<div class="sigline">{{ T.it_checked_by }} <span class="line"></span></div>
|
||||
<div class="sigline">{{ T.it_signature }} <span class="line"></span></div>
|
||||
<div class="sigline">{{ T.return_complete }} <span class="cb">□</span> {{ T.yes }}     <span class="cb">□</span> {{ T.no }}</div>
|
||||
</div>
|
||||
|
||||
<p class="small">{{ T.offboarding_note }}</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,72 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ T.lang or 'de' }}">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ T.live_intro_title }}</title>
|
||||
<style>
|
||||
body { font-family: Helvetica, Arial, sans-serif; color: #0f172a; font-size: 10.2px; line-height: 1.4; margin: 0; }
|
||||
.hero { background: #eef4ff; border: 1px solid #cbd9f6; border-left: 4px solid #3056a3; padding: 8px 10px; margin-bottom: 8px; }
|
||||
.title { margin: 0; font-size: 17px; color: #233f7a; font-weight: bold; }
|
||||
.sub { margin: 2px 0 0 0; color: #475569; font-size: 9.4px; }
|
||||
.section { margin-top: 9px; font-size: 11px; color: #233f7a; font-weight: bold; border-bottom: 1px solid #cbd9f6; padding-bottom: 2px; }
|
||||
table { width: 100%; border-collapse: collapse; margin: 6px 0; }
|
||||
th, td { border: 1px solid #d5e2f9; padding: 4px 6px; vertical-align: top; overflow-wrap: anywhere; word-break: break-word; }
|
||||
th { background: #eaf1ff; color: #1f376b; font-weight: bold; text-align: left; width: 26%; }
|
||||
.opt-card { border: 1px solid #d5e2f9; margin-top: 6px; margin-bottom: 6px; }
|
||||
.opt-title { background: #3056a3; color: #fff; font-weight: bold; padding: 5px 6px; font-size: 9.5px; }
|
||||
.opt-grid { width: 100%; border-collapse: collapse; margin: 0; }
|
||||
.opt-grid td { border: 1px solid #d5e2f9; padding: 5px 6px; font-size: 9.4px; width: 50%; }
|
||||
.selected-mark { font-weight: bold; margin-right: 8px; color: #111827; }
|
||||
.note-box { border: 1px solid #d5e2f9; background: #fcfdff; padding: 8px 10px; margin-top: 8px; min-height: 44px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="hero">
|
||||
<h1 class="title">{{ T.live_intro_title }}</h1>
|
||||
<p class="sub">{{ T.live_intro_sub }}</p>
|
||||
</div>
|
||||
|
||||
<div class="section">{{ T.base_data }}</div>
|
||||
<table>
|
||||
<tr>
|
||||
<th>{{ T.name }}</th>
|
||||
<td>{{ DISPLAY_NAME }}</td>
|
||||
<th>{{ T.department }}</th>
|
||||
<td>{{ ABTEILUNG }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ T.job_title }}</th>
|
||||
<td>{{ BERUFSBEZEICHNUNG }}</td>
|
||||
<th>{{ T.employment_start }}</th>
|
||||
<td>{{ VERTRAGSBEGINN }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ T.work_email }}</th>
|
||||
<td>{{ EMAIL }}</td>
|
||||
<th>{{ T.introduced_by }}</th>
|
||||
<td>{{ REQUESTED_BY_NAME }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
{% for section in INTRO_SECTIONS %}
|
||||
<div class="opt-card">
|
||||
<div class="opt-title">{{ section.title }}</div>
|
||||
<table class="opt-grid">
|
||||
{% for row in section.rows %}
|
||||
<tr>
|
||||
{% for cell in row %}<td><span class="selected-mark">✓</span>{{ cell.label }}</td>{% endfor %}
|
||||
{% if row|length < 2 %}<td></td>{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<div class="section">{{ T.notes }}</div>
|
||||
<div class="note-box">{{ SESSION_NOTES }}</div>
|
||||
|
||||
<div class="section">{{ T.employee_signature_block }}</div>
|
||||
<div class="note-box" style="height: 70px; margin-top: 10px;"></div>
|
||||
</body>
|
||||
</html>
|
||||
194
backend/workflows/pdf_assets/onboarding_intro_template.html
Normal file
194
backend/workflows/pdf_assets/onboarding_intro_template.html
Normal file
@@ -0,0 +1,194 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ T.lang or 'de' }}">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ T.intro_title }}</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
color: #0f172a;
|
||||
font-size: 10.2px;
|
||||
line-height: 1.4;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.hero {
|
||||
background: #eef4ff;
|
||||
border: 1px solid #cbd9f6;
|
||||
border-left: 4px solid #3056a3;
|
||||
padding: 8px 10px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin: 0;
|
||||
font-size: 17px;
|
||||
color: #233f7a;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.sub {
|
||||
margin: 2px 0 0 0;
|
||||
color: #475569;
|
||||
font-size: 9.4px;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-top: 9px;
|
||||
font-size: 11px;
|
||||
color: #233f7a;
|
||||
font-weight: bold;
|
||||
border-bottom: 1px solid #cbd9f6;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 6px 0;
|
||||
}
|
||||
|
||||
th, td {
|
||||
border: 1px solid #d5e2f9;
|
||||
padding: 4px 6px;
|
||||
vertical-align: top;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
th {
|
||||
background: #eaf1ff;
|
||||
color: #1f376b;
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
width: 26%;
|
||||
}
|
||||
|
||||
.mono {
|
||||
font-weight: bold;
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
.note {
|
||||
margin: 6px 0 8px;
|
||||
color: #536174;
|
||||
font-size: 9.3px;
|
||||
}
|
||||
|
||||
.opt-card {
|
||||
border: 1px solid #d5e2f9;
|
||||
margin-top: 6px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.opt-title {
|
||||
background: #3056a3;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
padding: 5px 6px;
|
||||
font-size: 9.5px;
|
||||
}
|
||||
|
||||
.opt-grid {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.opt-grid td {
|
||||
border: 1px solid #d5e2f9;
|
||||
padding: 5px 6px;
|
||||
font-size: 9.4px;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.cb {
|
||||
display: inline-block;
|
||||
min-width: 12px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin-right: 8px;
|
||||
vertical-align: middle;
|
||||
color: #b8b8b8;
|
||||
font-size: 12px;
|
||||
line-height: 12px;
|
||||
}
|
||||
|
||||
.sigbox {
|
||||
border: 1px solid #d5e2f9;
|
||||
padding: 10px;
|
||||
margin-top: 8px;
|
||||
background: #fcfdff;
|
||||
}
|
||||
|
||||
.sigline {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.line {
|
||||
display: inline-block;
|
||||
border-bottom: 1px solid #334155;
|
||||
min-width: 190px;
|
||||
height: 12px;
|
||||
vertical-align: bottom;
|
||||
margin: 0 6px;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="hero">
|
||||
<h1 class="title">{{ T.intro_title }}</h1>
|
||||
<p class="sub">{{ T.intro_sub }}</p>
|
||||
</div>
|
||||
|
||||
<div class="section">{{ T.base_data }}</div>
|
||||
<table>
|
||||
<tr>
|
||||
<th>{{ T.name }}</th>
|
||||
<td class="mono">{{ DISPLAY_NAME }}</td>
|
||||
<th>{{ T.department }}</th>
|
||||
<td>{{ ABTEILUNG }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ T.job_title }}</th>
|
||||
<td>{{ BERUFSBEZEICHNUNG }}</td>
|
||||
<th>{{ T.start_date }}</th>
|
||||
<td>{{ VERTRAGSBEGINN }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ T.work_email }}</th>
|
||||
<td>{{ EMAIL }}</td>
|
||||
<th>{{ T.introduced_by }}</th>
|
||||
<td>{{ REQUESTED_BY_NAME }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p class="note">{{ T.intro_note }}</p>
|
||||
|
||||
{% for section in INTRO_SECTIONS %}
|
||||
<div class="opt-card">
|
||||
<div class="opt-title">{{ section.title }}</div>
|
||||
<table class="opt-grid">
|
||||
{% for row in section.rows %}
|
||||
<tr>
|
||||
{% for cell in row %}<td><span class="cb">□</span> {{ cell }}</td>{% endfor %}
|
||||
{% if row|length < 2 %}
|
||||
{% for _ in range(2 - row|length) %}<td></td>{% endfor %}
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<div class="section">{{ T.confirmation }}</div>
|
||||
<div class="sigbox">
|
||||
<div class="sigline">{{ T.intro_completed_at }} <span class="line"></span></div>
|
||||
<div class="sigline">{{ T.employee_signature }} <span class="line"></span></div>
|
||||
<div class="sigline">{{ T.trainer_signature }} <span class="line"></span></div>
|
||||
<div class="sigline">{{ T.open_questions }} <span class="line" style="min-width: 260px;"></span></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
389
backend/workflows/pdf_assets/onboarding_template.html
Normal file
389
backend/workflows/pdf_assets/onboarding_template.html
Normal file
@@ -0,0 +1,389 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ PDF_LANG or 'de' }}">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ T.onboarding_title }}</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
color: #0f172a;
|
||||
font-size: 10.2px;
|
||||
line-height: 1.4;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.hero {
|
||||
background: #eef4ff;
|
||||
border: 1px solid #cbd9f6;
|
||||
border-left: 4px solid #3056a3;
|
||||
padding: 8px 10px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin: 0;
|
||||
font-size: 17px;
|
||||
color: #233f7a;
|
||||
font-weight: bold;
|
||||
letter-spacing: 0.2px;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-top: 9px;
|
||||
font-size: 11px;
|
||||
color: #233f7a;
|
||||
font-weight: bold;
|
||||
border-bottom: 1px solid #cbd9f6;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 6px 0;
|
||||
}
|
||||
|
||||
th, td {
|
||||
border: 1px solid #d5e2f9;
|
||||
padding: 4px 6px;
|
||||
vertical-align: top;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
th {
|
||||
background: #eaf1ff;
|
||||
color: #1f376b;
|
||||
font-weight: bold;
|
||||
width: 31%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.mono {
|
||||
font-weight: bold;
|
||||
color: #111827;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.opt-card {
|
||||
border: 1px solid #d5e2f9;
|
||||
margin-top: 6px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.opt-title {
|
||||
background: #3056a3;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
padding: 5px 6px;
|
||||
font-size: 9.5px;
|
||||
}
|
||||
|
||||
.opt-grid {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.opt-grid td {
|
||||
border: 1px solid #d5e2f9;
|
||||
padding: 3px 5px;
|
||||
width: 33.33%;
|
||||
font-size: 9.5px;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.signature {
|
||||
width: 150px;
|
||||
height: 70px;
|
||||
max-width: 150px;
|
||||
max-height: 70px;
|
||||
border: 1px solid #c3d3f3;
|
||||
padding: 1px;
|
||||
object-fit: contain;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.small {
|
||||
color: #64748b;
|
||||
font-size: 9px;
|
||||
}
|
||||
|
||||
.muted-cell {
|
||||
color: #64748b;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="hero">
|
||||
<h1 class="title">{{ T.onboarding_title }}</h1>
|
||||
</div>
|
||||
|
||||
<div class="section">{% if PDF_LANG == 'en' %}Master data{% else %}Stammdaten{% endif %}</div>
|
||||
<div class="opt-card">
|
||||
<div class="opt-title">{{ T.onboarding_staff_data }}</div>
|
||||
<table>
|
||||
<tr>
|
||||
<th>{{ T.name }}</th>
|
||||
<td class="mono" colspan="3">{{ DISPLAY_NAME }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ T.department }}</th>
|
||||
<td>{{ ABTEILUNG }}</td>
|
||||
<th>{{ T.job_title }}</th>
|
||||
<td>{{ BERUFSBEZEICHNUNG }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ T.work_email }}</th>
|
||||
<td>{{ EMAIL }}</td>
|
||||
<th>{{ T.employment_type }}</th>
|
||||
<td>{{ BESCHAEFTIGUNG }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ T.contract_start }}</th>
|
||||
<td>{{ VERTRAGSBEGINN }}</td>
|
||||
<th>{{ T.contract_end }}</th>
|
||||
<td>{{ VERTRAGSENDE }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ T.handover_date }}</th>
|
||||
<td colspan="3">{{ UEBERGABEDATUM }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{% if HAS_DEVICES or HAS_GROUPS or HAS_SOFTWARE or HAS_ACCESSES or HAS_RESOURCES or HAS_GROUP_MAILBOXES or HAS_ADDITIONAL_HARDWARE or HAS_ADDITIONAL_SOFTWARE or HAS_ADDITIONAL_ACCESS %}
|
||||
<div class="section">{% if PDF_LANG == 'en' %}IT setup{% else %}IT-Setup{% endif %}</div>
|
||||
|
||||
{% if HAS_DEVICES %}
|
||||
<div class="opt-card">
|
||||
<div class="opt-title">{{ T.devices }}</div>
|
||||
<table class="opt-grid">
|
||||
{% for row in ARBEITSGERÄTE_LIST %}
|
||||
<tr>
|
||||
{% for cell in row %}<td>• {{ cell }}</td>{% endfor %}
|
||||
{% if row|length < 3 %}
|
||||
{% for _ in range(3 - row|length) %}<td></td>{% endfor %}
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if HAS_GROUPS %}
|
||||
<div class="opt-card">
|
||||
<div class="opt-title">{{ T.workspace_groups }}</div>
|
||||
<table class="opt-grid">
|
||||
{% for row in ZUGAENGE_LIST %}
|
||||
<tr>
|
||||
{% for cell in row %}<td>• {{ cell }}</td>{% endfor %}
|
||||
{% if row|length < 3 %}
|
||||
{% for _ in range(3 - row|length) %}<td></td>{% endfor %}
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if HAS_SOFTWARE %}
|
||||
<div class="opt-card">
|
||||
<div class="opt-title">{{ T.software }}</div>
|
||||
<table class="opt-grid">
|
||||
{% for row in SOFTWARE_LIST %}
|
||||
<tr>
|
||||
{% for cell in row %}<td>• {{ cell }}</td>{% endfor %}
|
||||
{% if row|length < 3 %}
|
||||
{% for _ in range(3 - row|length) %}<td></td>{% endfor %}
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if HAS_ACCESSES %}
|
||||
<div class="opt-card">
|
||||
<div class="opt-title">{{ T.accesses }}</div>
|
||||
<table class="opt-grid">
|
||||
{% for row in ACCOUNT_LIST %}
|
||||
<tr>
|
||||
{% for cell in row %}<td>• {{ cell }}</td>{% endfor %}
|
||||
{% if row|length < 3 %}
|
||||
{% for _ in range(3 - row|length) %}<td></td>{% endfor %}
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if HAS_RESOURCES %}
|
||||
<div class="opt-card">
|
||||
<div class="opt-title">{{ T.resources }}</div>
|
||||
<table class="opt-grid">
|
||||
{% for row in STANDARD_RESSOURCEN %}
|
||||
<tr>
|
||||
{% for cell in row %}<td>• {{ cell }}</td>{% endfor %}
|
||||
{% if row|length < 3 %}
|
||||
{% for _ in range(3 - row|length) %}<td></td>{% endfor %}
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if GROUP_MAILBOXES_REQUIRED and HAS_GROUP_MAILBOXES %}
|
||||
<div class="opt-card">
|
||||
<div class="opt-title">{{ T.group_mailboxes_required }}</div>
|
||||
<table class="opt-grid">
|
||||
{% for row in GROUP_MAILBOXES_LIST %}
|
||||
<tr>
|
||||
{% for cell in row %}<td>• {{ cell }}</td>{% endfor %}
|
||||
{% if row|length < 3 %}
|
||||
{% for _ in range(3 - row|length) %}<td></td>{% endfor %}
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if ADDITIONAL_HARDWARE_NEEDED and HAS_ADDITIONAL_HARDWARE %}
|
||||
<div class="opt-card">
|
||||
<div class="opt-title">{{ T.additional_hardware_needed }}</div>
|
||||
<table class="opt-grid">
|
||||
{% for row in ADDITIONAL_HARDWARE_LIST %}
|
||||
<tr>
|
||||
{% for cell in row %}<td>• {{ cell }}</td>{% endfor %}
|
||||
{% if row|length < 3 %}
|
||||
{% for _ in range(3 - row|length) %}<td></td>{% endfor %}
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if ADDITIONAL_SOFTWARE_NEEDED and HAS_ADDITIONAL_SOFTWARE %}
|
||||
<div class="opt-card">
|
||||
<div class="opt-title">{{ T.additional_software_needed }}</div>
|
||||
<table class="opt-grid">
|
||||
{% for row in ADDITIONAL_SOFTWARE_LIST %}
|
||||
<tr>
|
||||
{% for cell in row %}<td>• {{ cell }}</td>{% endfor %}
|
||||
{% if row|length < 3 %}
|
||||
{% for _ in range(3 - row|length) %}<td></td>{% endfor %}
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if ADDITIONAL_ACCESS_NEEDED and HAS_ADDITIONAL_ACCESS %}
|
||||
<div class="opt-card">
|
||||
<div class="opt-title">{{ T.additional_access_needed }}</div>
|
||||
<table class="opt-grid">
|
||||
{% for row in ADDITIONAL_ACCESS_LIST %}
|
||||
<tr>
|
||||
{% for cell in row %}<td>• {{ cell }}</td>{% endfor %}
|
||||
{% if row|length < 3 %}
|
||||
{% for _ in range(3 - row|length) %}<td></td>{% endfor %}
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if (VISITENKARTE_BESTELLT and HAS_VISITENKARTE_DATEN) or HAS_ADDITIONAL_HARDWARE_OTHER or HAS_SUCCESSOR_INFO or HAS_ADDITIONAL_NOTES %}
|
||||
<div class="section">{{ T.additional_details }}</div>
|
||||
{% endif %}
|
||||
|
||||
{% if VISITENKARTE_BESTELLT and HAS_VISITENKARTE_DATEN %}
|
||||
<div class="opt-card">
|
||||
<div class="opt-title">{{ T.business_cards }}</div>
|
||||
<table>
|
||||
<tr>
|
||||
<th>{{ T.name }}</th>
|
||||
<td>{{ VISITENKARTE_NAME }}</td>
|
||||
<th>{{ T.job_title }}</th>
|
||||
<td>{{ VISITENKARTE_TITEL }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ T.email }}</th>
|
||||
<td>{{ VISITENKARTE_EMAIL }}</td>
|
||||
<th>{{ T.phone }}</th>
|
||||
<td>{{ VISITENKARTE_TELEFON }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if HAS_ADDITIONAL_HARDWARE_OTHER %}
|
||||
<div class="opt-card">
|
||||
<div class="opt-title">{{ T.additional_hardware_other }}</div>
|
||||
<table>
|
||||
<tr>
|
||||
<td>{{ ADDITIONAL_HARDWARE_OTHER }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if HAS_SUCCESSOR_INFO %}
|
||||
<div class="opt-card">
|
||||
<div class="opt-title">{{ T.successor_phone }}</div>
|
||||
<table>
|
||||
<tr>
|
||||
<th>{{ T.successor_of }}</th>
|
||||
<td>{{ SUCCESSOR_NAME }}</td>
|
||||
<th>{{ T.inherit_phone_number }}</th>
|
||||
<td>{{ INHERIT_PHONE_NUMBER }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ T.direct_extension }}</th>
|
||||
<td colspan="3">{{ PHONE_NUMBER }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if HAS_ADDITIONAL_NOTES %}
|
||||
<div class="opt-card">
|
||||
<div class="opt-title">{{ T.notes }}</div>
|
||||
<table>
|
||||
<tr>
|
||||
<td>{{ ADDITIONAL_NOTES }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="section">{{ T.confirmation }}</div>
|
||||
<table>
|
||||
<tr>
|
||||
<th>{{ T.requested_by_name }}</th>
|
||||
<td>{{ REQUESTED_BY_NAME }}</td>
|
||||
<th>{{ T.requested_by_email }}</th>
|
||||
<td>{{ REQUESTED_BY_EMAIL }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ T.signature }}</th>
|
||||
{% if UNTERSCHRIFT %}
|
||||
<td colspan="3"><img src="{{ UNTERSCHRIFT }}" alt="{{ T.signature_alt }}" class="signature"></td>
|
||||
{% else %}
|
||||
<td colspan="3" class="muted-cell">{{ UNTERSCHRIFT_HINWEIS }}</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p class="small">{{ T.onboarding_note }}</p>
|
||||
</body>
|
||||
</html>
|
||||
BIN
backend/workflows/pdf_assets/templates.pdf
Normal file
BIN
backend/workflows/pdf_assets/templates.pdf
Normal file
Binary file not shown.
@@ -64,7 +64,7 @@
|
||||
<li><code>/backend/workflows/templates/workflows/base_shell.html</code>: standard page shell for new staff-facing pages</li>
|
||||
<li><code>/backend/workflows/roles.py</code>: centralized role names, capability matrix, and template permission helpers</li>
|
||||
<li>Rule: all interactive app pages should extend <code>base_shell.html</code>; do not rebuild topbar/frame logic in page-local templates.</li>
|
||||
<li><code>/backend/media/templates/</code>: PDF HTML templates and letterhead source files</li>
|
||||
<li><code>/backend/workflows/pdf_assets/</code>: default PDF HTML templates and default letterhead</li>
|
||||
<li><code>/backend/media/pdfs/</code>: generated PDF outputs on host volume</li>
|
||||
<li><code>/backend/locale/</code>: translation catalogs</li>
|
||||
<li><code>/docker-compose.yml</code>: local runtime orchestration</li>
|
||||
|
||||
@@ -119,9 +119,9 @@
|
||||
|
||||
<h2 id="pdfs">7) PDF Engine</h2>
|
||||
<ul>
|
||||
<li>Template source: <code>/backend/media/templates/onboarding_template.html</code> and <code>offboarding_template.html</code>.</li>
|
||||
<li>Additional onboarding intro template: <code>/backend/media/templates/onboarding_intro_template.html</code>.</li>
|
||||
<li>Letterhead defaults to <code>/backend/media/templates/templates.pdf</code>, but can be overridden from Admin Apps → <code>Branding</code>.</li>
|
||||
<li>Template source: <code>/backend/workflows/pdf_assets/onboarding_template.html</code> and <code>offboarding_template.html</code>.</li>
|
||||
<li>Additional onboarding intro template: <code>/backend/workflows/pdf_assets/onboarding_intro_template.html</code>.</li>
|
||||
<li>Letterhead defaults to <code>/backend/workflows/pdf_assets/templates.pdf</code>, but can be overridden from Admin Apps → <code>Branding</code>.</li>
|
||||
<li>Output folder: <code>/backend/media/pdfs/</code>.</li>
|
||||
<li>Fixed PDF labels and notes are rendered through task-level DE/EN text maps and follow the request language with German fallback.</li>
|
||||
<li>Signature images are embedded for compatibility with xhtml2pdf rendering.</li>
|
||||
@@ -190,7 +190,7 @@
|
||||
<li><strong>Einweisungs- und Übergabeprotokoll:</strong> staff-only <code>PDF erzeugen</code>, <code>Neu erzeugen</code>, and <code>PDF öffnen</code> actions directly on onboarding rows in the Requests Dashboard.</li>
|
||||
<li><strong>Einweisung durchführen:</strong> staff-only live checklist page opened from onboarding rows, with draft/completed status, notes, progress tracking, and a separate live-status PDF export.</li>
|
||||
<li><strong>Project Wiki:</strong> this documentation page.</li>
|
||||
<li><strong>UI Shell Standard:</strong> interactive app pages should extend <code>base_shell.html</code>; PDF templates under <code>backend/media/templates/</code> must stay separate.</li>
|
||||
<li><strong>UI Shell Standard:</strong> interactive app pages should extend <code>base_shell.html</code>; default PDF templates under <code>backend/workflows/pdf_assets/</code> must stay separate from runtime media.</li>
|
||||
<li><strong>Release Checklist:</strong> dedicated staff-only release runbook for validation, rollout evidence, and rollback basics.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user