it_manager: справочник типовых работ в журнале WorkLog.

Категория/работа/required_details вместо свободного work_type; seed Directory, отчёт и тесты.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-07 13:38:07 +03:00
parent be7e5853cb
commit 31bd4c8fa7
11 changed files with 822 additions and 112 deletions
+21 -6
View File
@@ -11,6 +11,7 @@ from django.utils import timezone
from apps.it_manager.models import WorkLog
from apps.it_manager.report_import import default_report_tool_root, load_company, normalize_name
from apps.it_manager.work_directory import detail_labels_from_db, worklog_display_title
from apps.locations.models.base import pharmacy_object_code
from apps.reports.it_monthly.conclusions import build_conclusions
@@ -272,9 +273,13 @@ def build_monthly_report(year: int, month: int, *, company: dict | None = None)
start = date(year, month, 1)
end = date(year, month, calendar.monthrange(year, month)[1])
detail_labels = detail_labels_from_db()
logs = list(
WorkLog.objects.filter(date__gte=start, date__lte=end)
.select_related('technician', 'location', 'work_type', 'ticket')
.select_related(
'technician', 'location', 'work_type', 'ticket',
'catalog_work', 'catalog_work__parent',
)
.prefetch_related('location__pharmacy__organization')
.order_by('date', 'id')
)
@@ -322,16 +327,20 @@ def build_monthly_report(year: int, month: int, *, company: dict | None = None)
systems = []
for log in tech_logs:
obj = location_object_code(log.location)
if not obj:
if log.catalog_work_id:
work = worklog_display_title(log, detail_labels)
if log.description:
work = f'{work}. {log.description}'.strip()
elif not obj:
# префикс «А12 — …» из импорта без локации
m = re.match(r'^([АAПPТTГGЛL]\d+|ОФИС|Склад)\s*[—\-]\s*(.+)$', log.description, re.I | re.S)
m = re.match(r'^([АAПPТTГGЛL]\d+|ОФИС|Склад)\s*[—\-]\s*(.+)$', log.description or '', re.I | re.S)
if m:
obj = m.group(1).upper().replace('A', 'А')
work = m.group(2).strip()
else:
work = log.description
work = log.description or ''
else:
work = log.description
work = log.description or ''
sys_m = SYSTEM_DESC_RE.match(work)
if sys_m and (log.result or '').startswith('import:report-tool:'):
@@ -339,12 +348,18 @@ def build_monthly_report(year: int, month: int, *, company: dict | None = None)
direction_counts[INFRA_DIRECTION] += 1
direction_people[INFRA_DIRECTION].add(short)
else:
work_type_label = ''
if log.catalog_work_id:
parent = log.catalog_work.parent
work_type_label = parent.name if parent else log.catalog_work.name
elif log.work_type_id:
work_type_label = log.work_type.name
tasks.append({
'date': log.date.strftime('%d.%m.%Y'),
'object': obj,
'work': work,
'work_items': split_work_items(work),
'work_type': log.work_type.name if log.work_type_id else '',
'work_type': work_type_label,
'ticket': log.ticket.number if log.ticket_id else '',
'hours': float(log.hours_spent) if log.hours_spent is not None else None,
})