# 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