125 lines
5.1 KiB
Python
125 lines
5.1 KiB
Python
# backend/modules/task_management/services.py
|
|
|
|
from django.db import transaction
|
|
from rest_framework.exceptions import ValidationError
|
|
from django.core.exceptions import ValidationError as DjangoValidationError
|
|
import logging
|
|
|
|
from .models import Task, TaskTemplate, TaskWorkEntry
|
|
from modules.fleet.models import VehicleServiceRecord
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class TaskService:
|
|
@staticmethod
|
|
def create_task_entry(data: dict, user=None) -> Task:
|
|
"""
|
|
Univerzalna metoda: prihvaća podatke i opcionalnog korisnika.
|
|
"""
|
|
payload = dict(data)
|
|
template_id = payload.pop('template_id', None)
|
|
|
|
if payload.get('status') == 'DONE' and (user and not user.is_staff):
|
|
raise ValidationError({"status": "Samo admini mogu odmah označiti zadatak kao gotov."})
|
|
|
|
template = None
|
|
if template_id:
|
|
template = TaskTemplate.objects.filter(id=template_id, is_active=True).prefetch_related('entries').first()
|
|
if not template:
|
|
raise ValidationError({"template_id": "Odabrani template nije pronađen."})
|
|
|
|
payload['title'] = template.title
|
|
payload['description'] = template.description
|
|
payload['status'] = 'aktivan'
|
|
payload.setdefault('work_order', None)
|
|
|
|
title = (payload.get('title') or '').strip()
|
|
if title and len(title) < 3:
|
|
raise ValidationError({"title": "Naslov zadatka mora imati barem 3 znaka."})
|
|
if not title:
|
|
raise ValidationError({"title": "Naslov zadatka je obavezan."})
|
|
|
|
if user and 'assigned_to' not in payload:
|
|
payload['assigned_to'] = user
|
|
|
|
entry = Task(**payload)
|
|
try:
|
|
entry.full_clean()
|
|
except DjangoValidationError as exc:
|
|
logger.error(f"Neuspješna validacija zadatka: {exc}")
|
|
raise ValidationError(exc.message_dict if hasattr(exc, 'message_dict') else exc.messages)
|
|
|
|
with transaction.atomic():
|
|
entry.save()
|
|
if template:
|
|
TaskService._create_work_entries_from_template(task=entry, template=template)
|
|
TaskService._create_service_records_from_template(task=entry, template=template, user=user)
|
|
|
|
logger.info(f"Zadatak uspješno kreiran: {entry.id}")
|
|
return entry
|
|
|
|
@staticmethod
|
|
def _create_work_entries_from_template(*, task: Task, template: TaskTemplate):
|
|
template_entries = list(template.entries.filter(is_active=True).order_by('sort_order', 'created_at')[:10])
|
|
for idx, source in enumerate(template_entries, start=1):
|
|
TaskWorkEntry.objects.create(
|
|
task=task,
|
|
template_entry=source,
|
|
sort_order=idx,
|
|
title=source.title,
|
|
work_description=source.work_description,
|
|
active_faults=source.active_faults,
|
|
explanation_hr=source.explanation_hr,
|
|
)
|
|
|
|
@staticmethod
|
|
def _create_service_records_from_template(*, task: Task, template: TaskTemplate, user):
|
|
if not user:
|
|
raise ValidationError({
|
|
"template_id": "Kreiranje taska iz templatea zahtijeva prijavljenog korisnika za servisne zapise."
|
|
})
|
|
if not task.vehicle_id:
|
|
raise ValidationError({
|
|
"vehicle": "Task iz templatea mora imati dodijeljenu dizalicu za generiranje servisnih zapisa."
|
|
})
|
|
|
|
template_entries = list(template.entries.filter(is_active=True).order_by('sort_order', 'created_at')[:10])
|
|
for source in template_entries:
|
|
description_parts = []
|
|
if source.work_description:
|
|
description_parts.append(source.work_description.strip())
|
|
if source.explanation_hr:
|
|
description_parts.append(f"Obrazloženje (HR): {source.explanation_hr.strip()}")
|
|
if source.active_faults:
|
|
description_parts.append(f"Aktivne greške: {source.active_faults.strip()}")
|
|
description = "\n\n".join([part for part in description_parts if part]).strip() or source.title
|
|
|
|
VehicleServiceRecord.objects.create(
|
|
vehicle=task.vehicle,
|
|
task=task,
|
|
performed_by=user,
|
|
service_title=source.title,
|
|
description=description,
|
|
parts=(source.active_faults or '').strip(),
|
|
cost=0,
|
|
)
|
|
|
|
@staticmethod
|
|
def update_task_entry(instance, data, user):
|
|
if not user.is_staff and instance.assigned_to != user:
|
|
raise ValidationError("Nemate dozvolu za izmjenu ovog zadatka.")
|
|
|
|
for attr, value in data.items():
|
|
if attr == 'template_id':
|
|
continue
|
|
setattr(instance, attr, value)
|
|
if 'title' in data and len(str(data.get('title') or '').strip()) < 3:
|
|
raise ValidationError({"title": "Naslov zadatka mora imati barem 3 znaka."})
|
|
try:
|
|
instance.full_clean()
|
|
except DjangoValidationError as exc:
|
|
raise ValidationError(exc.message_dict if hasattr(exc, 'message_dict') else exc.messages)
|
|
instance.save()
|
|
return instance
|