fix: add editable work order travel expenses
Introduce a dedicated travel-expenses table for work orders so Broj sati, Količina dnevnica, and Iznos dnevnice can be reviewed and edited before PDF generation. The PDF now uses the stored travel-expenses values, with default HR rate and cache invalidation on updates.
This commit is contained in:
@@ -274,6 +274,30 @@ class WorkOrderImagesEndpointTests(TestCase):
|
||||
self.assertFalse(cached.is_active)
|
||||
self.assertEqual(cached.status, 'failed')
|
||||
|
||||
def test_travel_expenses_update_invalidates_work_order_pdf_cache(self):
|
||||
cached = GeneratedWorkOrderPdf.objects.create(
|
||||
work_order=self.work_order,
|
||||
requested_by=self.user,
|
||||
pdf_type='work_order',
|
||||
status='ready',
|
||||
filename='MT150726.work-order.pdf',
|
||||
expires_at=timezone.now() + timedelta(hours=1),
|
||||
)
|
||||
response = self.client.put(
|
||||
f"/api/fleet/work-orders/{self.work_order.pk}/travel-expenses-table/",
|
||||
data={
|
||||
'broj_sati': '9.5',
|
||||
'kolicina_dnevnica': '0.5',
|
||||
'iznos_dnevnica': '30',
|
||||
'daily_rate_country': 'HR',
|
||||
},
|
||||
format='json',
|
||||
)
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
cached.refresh_from_db()
|
||||
self.assertFalse(cached.is_active)
|
||||
self.assertEqual(cached.status, 'failed')
|
||||
|
||||
def test_service_records_docx_contains_embedded_service_photos(self):
|
||||
VehicleServicePhoto.objects.create(
|
||||
service_record=self.service_record,
|
||||
@@ -491,6 +515,19 @@ class WorkOrderImagesEndpointTests(TestCase):
|
||||
},
|
||||
)
|
||||
|
||||
save_response = self.client.put(
|
||||
f'/api/fleet/work-orders/{self.work_order.pk}/travel-expenses-table/',
|
||||
data={
|
||||
'broj_sati': '9.5',
|
||||
'kolicina_dnevnica': '0.5',
|
||||
'iznos_dnevnica': '80',
|
||||
'daily_rate_country': 'SI',
|
||||
},
|
||||
format='json',
|
||||
)
|
||||
self.assertEqual(save_response.status_code, 200, save_response.content)
|
||||
self.assertEqual(save_response.data['total_for_payout'], '40.00')
|
||||
|
||||
response = self.client.get(f'/api/fleet/work-orders/{self.work_order.pk}/pdf/')
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
self.assertEqual(response['Content-Type'], 'application/pdf')
|
||||
@@ -501,6 +538,39 @@ class WorkOrderImagesEndpointTests(TestCase):
|
||||
self.assertIn('25.12.2033.', text)
|
||||
self.assertIn('9,5', text)
|
||||
self.assertIn('0,5', text)
|
||||
self.assertIn('80.00 €', text)
|
||||
self.assertIn('40.00 €', text)
|
||||
|
||||
def test_work_order_travel_expenses_table_defaults_to_hr_rate_and_calculates_total(self):
|
||||
TaskWorkHoursTable.objects.create(
|
||||
task=self.task,
|
||||
data={
|
||||
'rows': [
|
||||
{
|
||||
'date': '24.12.2033',
|
||||
'work_time_from': '08:00',
|
||||
'work_time_to': '16:00',
|
||||
'travel_hours': '1',
|
||||
'work_hours': '6',
|
||||
},
|
||||
{
|
||||
'date': '25.12.2033',
|
||||
'work_time_from': '09:00',
|
||||
'work_time_to': '15:00',
|
||||
'travel_hours': '0,5',
|
||||
'work_hours': '2',
|
||||
},
|
||||
]
|
||||
},
|
||||
)
|
||||
|
||||
response = self.client.get(f'/api/fleet/work-orders/{self.work_order.pk}/travel-expenses-table/')
|
||||
self.assertEqual(response.status_code, 200, response.content)
|
||||
self.assertEqual(response.data['broj_sati'], '9.50')
|
||||
self.assertEqual(response.data['kolicina_dnevnica'], '0.50')
|
||||
self.assertEqual(response.data['daily_rate_country'], 'HR')
|
||||
self.assertEqual(response.data['iznos_dnevnica'], '30.00')
|
||||
self.assertEqual(response.data['total_for_payout'], '15.00')
|
||||
|
||||
def test_calculate_daily_quantity_from_hours_follows_business_rules(self):
|
||||
self.assertEqual(_calculate_daily_quantity_from_hours(0), 0.0)
|
||||
|
||||
Reference in New Issue
Block a user