from datetime import timedelta import pytest from django.urls import reverse from django.utils import timezone from rest_framework.test import APIClient from apps.accounts.models import User, UserRole from apps.bookings.models import Booking, BookingStatus from apps.notifications.models import Notification, NotificationEvent, NotificationStatus from apps.salons.models import Salon, Service, StaffProfile @pytest.fixture def booking_payload(): owner = User.objects.create_user( email="owner@example.com", password="pass", role=UserRole.MANAGER, phone_number="0500000001", ) customer = User.objects.create_user( email="customer@example.com", password="pass", phone_number="0500000002", ) staff_user = User.objects.create_user( email="staff@example.com", password="pass", role=UserRole.STAFF, phone_number="0500000003", ) salon = Salon.objects.create( owner=owner, name="Main Salon", description="", address="123 King Rd", city="Riyadh", phone_number="0512345678", ) service = Service.objects.create( salon=salon, name="Haircut", description="", duration_minutes=60, price_amount=120, currency="SAR", ) staff = StaffProfile.objects.create(user=staff_user, salon=salon) start_time = timezone.now() + timedelta(days=1) end_time = start_time + timedelta(minutes=60) return { "customer": customer, "staff_user": staff_user, "service": service, "staff": staff, "payload": { "service": service.id, "staff": staff.id, "start_time": start_time.isoformat(), "end_time": end_time.isoformat(), "notes": "", }, } @pytest.mark.django_db def test_booking_create_sends_notifications(booking_payload): client = APIClient() client.force_authenticate(user=booking_payload["customer"]) response = client.post( reverse("booking-list"), booking_payload["payload"], content_type="application/json", ) assert response.status_code == 201 notifications = Notification.objects.filter(event=NotificationEvent.BOOKING_CREATED) assert notifications.count() == 2 assert all(notification.status == NotificationStatus.SENT for notification in notifications) @pytest.mark.django_db def test_booking_status_change_sends_notifications_once(booking_payload): client = APIClient() client.force_authenticate(user=booking_payload["customer"]) response = client.post( reverse("booking-list"), booking_payload["payload"], content_type="application/json", ) assert response.status_code == 201 booking_id = Booking.objects.get(customer=booking_payload["customer"]).id update_payload = {"status": BookingStatus.CONFIRMED} client.force_authenticate(user=booking_payload["staff_user"]) response_update = client.patch( reverse("booking-detail", args=[booking_id]), update_payload, content_type="application/json", ) assert response_update.status_code == 200 notifications = Notification.objects.filter(event=NotificationEvent.BOOKING_CONFIRMED) assert notifications.count() == 2 response_repeat = client.patch( reverse("booking-detail", args=[booking_id]), update_payload, content_type="application/json", ) assert response_repeat.status_code == 200 notifications_repeat = Notification.objects.filter(event=NotificationEvent.BOOKING_CONFIRMED) assert notifications_repeat.count() == 2