0da9c13192
Иерархия рамочных/дочерних договоров и платежей, интернет-биллинг, месячные IT-отчёты (импорт, DOCX/PDF, шаблоны выводов). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
180 lines
7.0 KiB
Python
180 lines
7.0 KiB
Python
"""Текст классического IT-шаблона (seed)."""
|
||
|
||
CLASSIC_HTML = r"""<!DOCTYPE html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<title>{{ labels.main_title }} — {{ month_title }}</title>
|
||
<style>
|
||
body { font-family: "DejaVu Sans", Arial, sans-serif; color: #1a2332; background: #e8edf4; margin: 0; padding: 1.5rem; }
|
||
.sheet { max-width: 820px; margin: 0 auto; background: #fff; padding: 2rem 2.25rem; box-shadow: 0 8px 24px rgba(0,0,0,.08); }
|
||
.brand { text-align: center; font-size: 0.95rem; font-weight: 600; }
|
||
.dept { text-align: center; font-size: 0.85rem; color: #5a6577; font-style: italic; margin-bottom: 1rem; }
|
||
h1 { text-align: center; font-size: 1.15rem; letter-spacing: 0.04em; margin: 0.5rem 0; }
|
||
.period { text-align: center; margin-bottom: 1.25rem; color: #334; }
|
||
h2 { font-size: 1rem; margin: 1.25rem 0 0.5rem; border-bottom: 1px solid #d8dee8; padding-bottom: 0.25rem; }
|
||
table { width: 100%; border-collapse: collapse; font-size: 0.85rem; margin: 0.5rem 0 1rem; }
|
||
th, td { border: 1px solid #cfd8e6; padding: 0.4rem 0.55rem; text-align: left; vertical-align: top; }
|
||
th { background: #f0f4fa; }
|
||
ul { margin: 0.25rem 0 0.75rem; padding-left: 1.2rem; }
|
||
.emp { margin-bottom: 1rem; }
|
||
.role { color: #5a6577; font-size: 0.8rem; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="sheet">
|
||
<div class="brand">{{ company.company }}</div>
|
||
<div class="dept">{{ company.department }}</div>
|
||
<h1>{{ labels.main_title }}</h1>
|
||
<div class="period">{{ month_title }}</div>
|
||
|
||
<table>
|
||
<tr><th>Показатель</th><th>Значение</th></tr>
|
||
<tr><td>{{ labels.period_label }}</td><td>{{ stats.period }}</td></tr>
|
||
<tr><td>{{ labels.staff_label }}</td><td>{{ stats.staff_count }} сотрудника</td></tr>
|
||
<tr><td>{{ labels.objects_label }}</td><td>{{ stats.objects_count }}</td></tr>
|
||
<tr><td>{{ labels.work_mode_label }}</td><td>{{ month.work_mode }}</td></tr>
|
||
<tr><td>{{ labels.tasks_label }}</td><td>{{ stats.total_tasks }}</td></tr>
|
||
</table>
|
||
|
||
<h2>1. {{ labels.staff_heading }}</h2>
|
||
<ul>
|
||
{% for emp in employees %}
|
||
<li>{{ emp.name }}{% if emp.role %} — {{ emp.role }}{% endif %}</li>
|
||
{% empty %}
|
||
<li>Нет данных</li>
|
||
{% endfor %}
|
||
</ul>
|
||
|
||
<h2>2. {{ labels.summary_heading }}</h2>
|
||
{% if report.summary %}
|
||
<ul>
|
||
{% for row in report.summary %}
|
||
<li><strong>{{ row.name }}</strong> — {{ row.count }}{% if row.people %} ({{ row.people }}){% endif %}</li>
|
||
{% endfor %}
|
||
</ul>
|
||
{% else %}
|
||
<p>Нет записей за месяц.</p>
|
||
{% endif %}
|
||
|
||
<h2>3. {{ labels.objects_heading }}</h2>
|
||
{% if report.pharmacies %}<p>{{ labels.pharmacies_label }}: {{ report.pharmacies|join:", " }}.</p>{% endif %}
|
||
{% if report.other_points %}<p>{{ labels.other_label }}: {{ report.other_points|join:", " }}.</p>{% endif %}
|
||
{% if not report.pharmacies and not report.other_points %}
|
||
<p>Объекты не указаны.</p>
|
||
{% endif %}
|
||
|
||
<h2>4. Выполненные работы по сотрудникам</h2>
|
||
{% for emp in employees %}
|
||
{% if emp.tasks or emp.systems %}
|
||
<div class="emp">
|
||
<strong>{{ emp.name }}</strong>
|
||
{% if emp.role %}<div class="role">{{ emp.role }}</div>{% endif %}
|
||
{% for sys in emp.systems %}
|
||
<p><strong>{{ sys.name }}</strong> — {{ sys.work }}</p>
|
||
{% endfor %}
|
||
{% if emp.tasks %}
|
||
<table>
|
||
<thead><tr><th>Дата</th><th>Объект</th><th>Работы</th></tr></thead>
|
||
<tbody>
|
||
{% for task in emp.tasks %}
|
||
<tr>
|
||
<td>{{ task.date }}</td>
|
||
<td>{{ task.object|default:"—" }}</td>
|
||
<td>
|
||
{% if task.work_items|length > 1 %}
|
||
<ul>{% for item in task.work_items %}<li>{{ item }}</li>{% endfor %}</ul>
|
||
{% else %}
|
||
{{ task.work }}
|
||
{% endif %}
|
||
</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
{% endif %}
|
||
</div>
|
||
{% endif %}
|
||
{% empty %}
|
||
<p>Нет данных.</p>
|
||
{% endfor %}
|
||
|
||
{% if conclusions %}
|
||
<h2>5. {{ labels.conclusions_heading }}</h2>
|
||
{% for item in conclusions %}
|
||
<p>{{ item.text }}</p>
|
||
{% if item.bullets %}
|
||
<ul>{% for b in item.bullets %}<li>{{ b }}</li>{% endfor %}</ul>
|
||
{% endif %}
|
||
{% endfor %}
|
||
{% endif %}
|
||
|
||
<p style="margin-top:2rem; color:#5a6577; font-size:0.85rem;">Подготовлено: {{ prepared_date }}</p>
|
||
</div>
|
||
</body>
|
||
</html>
|
||
"""
|
||
|
||
CLASSIC_MD = r"""# IT-отчёт — {{ report.title }}
|
||
|
||
**Период:** {{ report.period_from }} – {{ report.period_to }}
|
||
**Всего работ:** {{ report.total_tasks }}
|
||
**Активных сотрудников:** {{ report.people_active }}
|
||
**Объектов:** {{ report.objects_count }}
|
||
|
||
## {{ labels.summary_heading }}
|
||
|
||
{% for row in report.summary %}- **{{ row.name }}** — {{ row.count }}{% if row.people %} ({{ row.people }}){% endif %}
|
||
{% empty %}_Нет записей за месяц._
|
||
{% endfor %}
|
||
{% if report.pharmacies or report.other_points %}
|
||
## {{ labels.objects_heading }}
|
||
|
||
{% if report.pharmacies %}- {{ labels.pharmacies_label }}: {{ report.pharmacies|join:", " }}.
|
||
{% endif %}{% if report.other_points %}- {{ labels.other_label }}: {{ report.other_points|join:", " }}.
|
||
{% endif %}{% endif %}
|
||
{% for emp in employees %}{% if emp.tasks or emp.systems %}
|
||
## {{ emp.name }}
|
||
{% if emp.role %}*{{ emp.role }}*
|
||
{% endif %}{% for sys in emp.systems %}
|
||
### {{ sys.name }}
|
||
{{ sys.work }}
|
||
{% endfor %}{% for task in emp.tasks %}{% if task.work_items|length > 1 %}- {{ task.date }}{% if task.object %} {{ task.object }}{% endif %}:
|
||
{% for item in task.work_items %} - {{ item }}
|
||
{% endfor %}{% else %}- {{ task.date }}{% if task.object %} {{ task.object }}{% endif %} — {{ task.work }}
|
||
{% endif %}{% endfor %}{% endif %}{% endfor %}
|
||
{% if conclusions %}
|
||
## {{ labels.conclusions_heading }}
|
||
|
||
{% for item in conclusions %}{{ item.text }}
|
||
{% for b in item.bullets %} - {{ b }}
|
||
{% endfor %}
|
||
{% endfor %}{% endif %}
|
||
"""
|
||
|
||
CLASSIC_BLOCKS = {
|
||
'labels': {
|
||
'main_title': 'ОТЧЁТ О ВЫПОЛНЕННЫХ РАБОТАХ',
|
||
'summary_heading': 'Сводка по направлениям',
|
||
'objects_heading': 'Объекты',
|
||
'staff_heading': 'Состав IT-отдела',
|
||
'employees_heading': 'Выполненные работы по сотрудникам',
|
||
'conclusions_heading': 'Основные выводы и рекомендации',
|
||
'period_label': 'Отчётный период',
|
||
'staff_label': 'Состав отдела',
|
||
'objects_label': 'Охвачено объектов',
|
||
'work_mode_label': 'Режим работы',
|
||
'tasks_label': 'Всего задач',
|
||
'pharmacies_label': 'Аптеки',
|
||
'other_label': 'Другие объекты',
|
||
'extra_label': 'Прочее',
|
||
},
|
||
'sections': [
|
||
'stats', 'staff', 'summary', 'objects', 'employees', 'conclusions', 'signature',
|
||
],
|
||
}
|
||
|
||
# Системный классический шаблон работает через блочный конструктор
|
||
CLASSIC_ENGINE = 'blocks_v1'
|
||
|