93 lines
4.7 KiB
Python
93 lines
4.7 KiB
Python
from datetime import date
|
|
from decimal import Decimal
|
|
|
|
from django.test import TestCase
|
|
from django.urls import reverse
|
|
from django.utils import timezone
|
|
|
|
from apps.accounts.models import User
|
|
from apps.companies.models import Company
|
|
from apps.projects.models import Project, ProjectMember
|
|
|
|
from .models import Task
|
|
|
|
|
|
class TaskAccessTests(TestCase):
|
|
def setUp(self):
|
|
self.worker = User.objects.create_user(username="worker", password="password123", must_change_password=False)
|
|
self.other = User.objects.create_user(username="other", password="password123", must_change_password=False)
|
|
self.admin = User.objects.create_user(username="admin", password="password123", role=User.Role.ADMIN, must_change_password=False)
|
|
self.company = Company.objects.create(name="Клиент")
|
|
self.project = Project.objects.create(company=self.company, name="Проект")
|
|
ProjectMember.objects.create(project=self.project, user=self.worker, hourly_rate=Decimal("1000.00"))
|
|
ProjectMember.objects.create(project=self.project, user=self.other, hourly_rate=Decimal("1200.00"))
|
|
self.task = Task.objects.create(
|
|
project=self.project, assignee=self.other, title="Чужая задача", description="Описание",
|
|
work_date=date(2026, 7, 14), duration_minutes=60, hourly_rate=Decimal("1200.00"),
|
|
amount=Decimal("1200.00"), created_by=self.other,
|
|
)
|
|
|
|
def test_worker_sees_only_own_tasks(self):
|
|
self.client.force_login(self.worker)
|
|
response = self.client.get(reverse("task-list"))
|
|
self.assertNotContains(response, "Чужая задача")
|
|
|
|
def test_worker_cannot_edit_another_users_task(self):
|
|
self.client.force_login(self.worker)
|
|
response = self.client.get(reverse("task-edit", args=(self.task.pk,)))
|
|
self.assertEqual(response.status_code, 403)
|
|
|
|
def test_create_copies_rate_and_calculates_rounded_amount(self):
|
|
self.client.force_login(self.worker)
|
|
response = self.client.post(reverse("task-create"), {
|
|
"project": self.project.pk, "assignee": self.worker.pk, "title": "Работа",
|
|
"description": "Сделано", "work_date": "2026-07-14", "duration_hours": 1,
|
|
"duration_minutes_input": 1,
|
|
"status": Task.Status.COMPLETED,
|
|
})
|
|
self.assertRedirects(response, reverse("task-list"))
|
|
task = Task.objects.get(title="Работа")
|
|
self.assertEqual(task.hourly_rate, Decimal("1000.00"))
|
|
self.assertEqual(task.amount, Decimal("1016.67"))
|
|
|
|
def test_admin_can_see_all_tasks(self):
|
|
self.client.force_login(self.admin)
|
|
response = self.client.get(reverse("task-list"))
|
|
self.assertContains(response, "Чужая задача")
|
|
|
|
def test_new_task_defaults_to_current_date(self):
|
|
self.client.force_login(self.worker)
|
|
response = self.client.get(reverse("task-create"))
|
|
self.assertEqual(response.context["form"].fields["work_date"].initial, timezone.localdate())
|
|
|
|
def test_duration_must_be_greater_than_zero(self):
|
|
self.client.force_login(self.worker)
|
|
response = self.client.post(reverse("task-create"), {
|
|
"project": self.project.pk, "assignee": self.worker.pk, "title": "Работа",
|
|
"description": "Сделано", "work_date": "2026-07-14", "duration_hours": 0,
|
|
"duration_minutes_input": 0, "status": Task.Status.COMPLETED,
|
|
})
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(response, "Укажите продолжительность больше нуля")
|
|
|
|
def test_duration_edit_keeps_rate_snapshot(self):
|
|
own_task = Task.objects.create(
|
|
project=self.project, assignee=self.worker, title="Старая работа", description="Описание",
|
|
work_date=date(2026, 7, 14), duration_minutes=60, hourly_rate=Decimal("1000.00"),
|
|
amount=Decimal("1000.00"), created_by=self.worker,
|
|
)
|
|
membership = ProjectMember.objects.get(project=self.project, user=self.worker)
|
|
membership.hourly_rate = Decimal("2000.00")
|
|
membership.save()
|
|
self.client.force_login(self.worker)
|
|
response = self.client.post(reverse("task-edit", args=(own_task.pk,)), {
|
|
"project": self.project.pk, "assignee": self.worker.pk, "title": own_task.title,
|
|
"description": own_task.description, "work_date": "2026-07-14", "duration_hours": 2,
|
|
"duration_minutes_input": 0,
|
|
"status": Task.Status.COMPLETED,
|
|
})
|
|
self.assertRedirects(response, reverse("task-list"))
|
|
own_task.refresh_from_db()
|
|
self.assertEqual(own_task.hourly_rate, Decimal("1000.00"))
|
|
self.assertEqual(own_task.amount, Decimal("2000.00"))
|