Widget Bilješke sada omogućuje odabir više članova tima (ne samo servisera), a backend validacija i testovi su usklađeni. Dodatno, nakon realtime service_note notifikacije sada se osvježava service-notes store, te create flow više ne briše lokalne bilješke kada odgovor vrati praznu listu. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
170 lines
6.6 KiB
Python
170 lines
6.6 KiB
Python
import uuid
|
|
|
|
from django.contrib.auth import get_user_model
|
|
from django.test import TestCase
|
|
from django.urls import reverse
|
|
from rest_framework.test import APIClient
|
|
|
|
from modules.fleet.models import ServiceContextNote, Vehicle, WorkOrder
|
|
from modules.task_management.models import Task
|
|
|
|
|
|
class ServiceContextNotesApiTests(TestCase):
|
|
def setUp(self):
|
|
user_model = get_user_model()
|
|
suffix = uuid.uuid4().hex[:8]
|
|
self.supervisor = user_model.objects.create_user(
|
|
username=f'supervisor-{suffix}',
|
|
email=f'supervisor-{suffix}@example.test',
|
|
password='test1234',
|
|
is_team_member=True,
|
|
is_serviser=False,
|
|
)
|
|
self.servicer = user_model.objects.create_user(
|
|
username=f'servicer-{suffix}',
|
|
email=f'servicer-{suffix}@example.test',
|
|
password='test1234',
|
|
is_team_member=True,
|
|
is_serviser=True,
|
|
)
|
|
self.other = user_model.objects.create_user(
|
|
username=f'other-{suffix}',
|
|
email=f'other-{suffix}@example.test',
|
|
password='test1234',
|
|
is_team_member=False,
|
|
is_serviser=False,
|
|
)
|
|
self.second_servicer = user_model.objects.create_user(
|
|
username=f'servicer2-{suffix}',
|
|
email=f'servicer2-{suffix}@example.test',
|
|
password='test1234',
|
|
is_team_member=True,
|
|
is_serviser=True,
|
|
)
|
|
self.team_member_non_servicer = user_model.objects.create_user(
|
|
username=f'team-{suffix}',
|
|
email=f'team-{suffix}@example.test',
|
|
password='test1234',
|
|
is_team_member=True,
|
|
is_serviser=False,
|
|
)
|
|
|
|
self.vehicle = Vehicle.objects.create(
|
|
asset_type='crane',
|
|
registration_number=f'SN-{suffix[:6].upper()}',
|
|
crane_serial_number='654321',
|
|
assigned_servicer=self.servicer,
|
|
)
|
|
self.work_order = WorkOrder.objects.create(
|
|
vehicle=self.vehicle,
|
|
creator=self.supervisor,
|
|
purpose='kontrola',
|
|
status='open',
|
|
)
|
|
self.task = Task.objects.create(
|
|
title='Aktivni servis',
|
|
assigned_to=self.servicer,
|
|
vehicle=self.vehicle,
|
|
work_order=self.work_order,
|
|
status='aktivan',
|
|
)
|
|
|
|
self.client = APIClient()
|
|
|
|
def test_supervisor_can_create_team_note_for_active_context(self):
|
|
self.client.force_authenticate(user=self.supervisor)
|
|
response = self.client.post(
|
|
reverse('service-context-note-list'),
|
|
data={
|
|
'note': 'Provjeriti opremu prije izlaska na teren.',
|
|
'note_date': '2026-07-21',
|
|
'audience': 'team',
|
|
'work_order': str(self.work_order.id),
|
|
'task': str(self.task.id),
|
|
},
|
|
format='json',
|
|
)
|
|
self.assertEqual(response.status_code, 201, response.content)
|
|
self.assertGreaterEqual(int(response.data.get('created_count', 0)), 2)
|
|
|
|
self.client.force_authenticate(user=self.servicer)
|
|
list_response = self.client.get(reverse('service-context-note-list'))
|
|
self.assertEqual(list_response.status_code, 200, list_response.content)
|
|
self.assertEqual(len(list_response.data), 1)
|
|
self.assertEqual(list_response.data[0]['audience_source'], 'team')
|
|
self.assertEqual(str(list_response.data[0]['task']), str(self.task.id))
|
|
|
|
def test_servicer_can_create_member_note_for_other_servicer(self):
|
|
self.client.force_authenticate(user=self.servicer)
|
|
response = self.client.post(
|
|
reverse('service-context-note-list'),
|
|
data={
|
|
'note': 'Serviser šalje bilješku drugom serviseru.',
|
|
'audience': 'member',
|
|
'target_user': str(self.second_servicer.id),
|
|
},
|
|
format='json',
|
|
)
|
|
self.assertEqual(response.status_code, 201, response.content)
|
|
self.assertEqual(int(response.data.get('created_count', 0)), 1)
|
|
|
|
def test_recipient_can_close_personal_note(self):
|
|
note = ServiceContextNote.objects.create(
|
|
created_by=self.supervisor,
|
|
recipient=self.servicer,
|
|
audience_source='member',
|
|
note='Osobna bilješka',
|
|
)
|
|
self.client.force_authenticate(user=self.servicer)
|
|
close_url = reverse('service-context-note-close', kwargs={'pk': note.id})
|
|
close_response = self.client.post(close_url, data={}, format='json')
|
|
self.assertEqual(close_response.status_code, 200, close_response.content)
|
|
note.refresh_from_db()
|
|
self.assertTrue(note.is_closed)
|
|
|
|
list_response = self.client.get(reverse('service-context-note-list'))
|
|
self.assertEqual(list_response.status_code, 200)
|
|
self.assertEqual(len(list_response.data), 0)
|
|
|
|
def test_supervisor_can_target_multiple_servicers(self):
|
|
self.client.force_authenticate(user=self.supervisor)
|
|
response = self.client.post(
|
|
reverse('service-context-note-list'),
|
|
data={
|
|
'note': 'Zajednička bilješka za dva servisera.',
|
|
'audience': 'member',
|
|
'target_users': [str(self.servicer.id), str(self.second_servicer.id)],
|
|
},
|
|
format='json',
|
|
)
|
|
self.assertEqual(response.status_code, 201, response.content)
|
|
self.assertEqual(int(response.data.get('created_count', 0)), 2)
|
|
|
|
def test_supervisor_can_create_member_note_for_non_servicer_team_member(self):
|
|
self.client.force_authenticate(user=self.supervisor)
|
|
response = self.client.post(
|
|
reverse('service-context-note-list'),
|
|
data={
|
|
'note': 'Bilješka za team člana koji nije serviser.',
|
|
'audience': 'member',
|
|
'target_users': [str(self.team_member_non_servicer.id)],
|
|
},
|
|
format='json',
|
|
)
|
|
self.assertEqual(response.status_code, 201, response.content)
|
|
self.assertEqual(int(response.data.get('created_count', 0)), 1)
|
|
|
|
def test_member_note_rejects_non_team_member_target(self):
|
|
self.client.force_authenticate(user=self.supervisor)
|
|
response = self.client.post(
|
|
reverse('service-context-note-list'),
|
|
data={
|
|
'note': 'Bilješka ne-smije ići van tima.',
|
|
'audience': 'member',
|
|
'target_users': [str(self.other.id)],
|
|
},
|
|
format='json',
|
|
)
|
|
self.assertEqual(response.status_code, 400, response.content)
|
|
self.assertIn('target_users', response.data)
|