from datetime import datetime from typing import Optional import pytest from freezegun import freeze_time from httpx import AsyncClient, Response from sqlalchemy import select, func from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.sql.functions import count from models import WorkShift, PaymentRecord from tests.conftest import db_session @pytest.mark.asyncio async def test_start_shift(admin_client: AsyncClient, db_session: AsyncSession): now = datetime.now() user_id = 2 response: Response = await admin_client.post(f"/work-shifts/start-shift/{user_id}") # Assert response assert response.status_code == 200 assert response.json().get("ok") is True get_workshift = select(WorkShift).where(WorkShift.user_id == user_id, func.date(WorkShift.started_at) == now.date()) work_shift: Optional[WorkShift] = (await db_session.execute(get_workshift)).scalars().one_or_none() # Assert database assert work_shift is not None assert work_shift.finished_at is None assert work_shift.started_at.hour == now.hour assert work_shift.started_at.minute == now.minute @pytest.mark.asyncio async def test_forbidden_starting_second_shift_per_day(admin_client: AsyncClient, db_session: AsyncSession): now = datetime.now() user_id = 2 response: Response = await admin_client.post(f"/work-shifts/start-shift/{user_id}") # Assert first response assert response.status_code == 200 assert response.json().get("ok") is True response: Response = await admin_client.post(f"/work-shifts/start-shift/{user_id}") # Assert second response assert response.status_code == 200 assert response.json().get("ok") is False get_count = ( select(count(WorkShift.id)) .where(WorkShift.user_id == user_id, func.date(WorkShift.started_at) == now.date()) ) work_shift_count: int = (await db_session.execute(get_count)).scalar() # Assert database assert work_shift_count == 1 @pytest.mark.asyncio @freeze_time("2024-11-21 22:25:00") async def test_finish_one_day_shift(admin_client: AsyncClient, db_session: AsyncSession): fixed_now = datetime(2024, 11, 21, 22, 25, 0) user_id = 2 response: Response = await admin_client.post(f"/work-shifts/finish-shift/{user_id}") # Assert response assert response.status_code == 200 assert response.json().get("ok") is True # Assert database get_workshift = select(WorkShift).where(WorkShift.id == 100) work_shift: Optional[WorkShift] = (await db_session.execute(get_workshift)).scalars().one_or_none() assert work_shift is not None assert work_shift.finished_at == fixed_now assert work_shift.user_id == user_id get_payments = select(PaymentRecord).where(PaymentRecord.user_id == user_id, PaymentRecord.start_date == fixed_now.date()) payment: Optional[PaymentRecord] = (await db_session.execute(get_payments)).scalars().one_or_none() assert payment is not None assert payment.created_by_user_id == 1 # работа: 8 * 350; # переработка: 2.5 * 450; # из них был перерыв: 0.5 * 450; assert abs(payment.amount - 3700) < 0.01 @pytest.mark.asyncio @freeze_time("2024-11-13 10:00:00") async def test_finish_three_days_shift(admin_client: AsyncClient, db_session: AsyncSession): fixed_now = datetime(2024, 11, 13, 10, 00, 0) user_id = 1 response: Response = await admin_client.post(f"/work-shifts/finish-shift/{user_id}") # Assert response assert response.status_code == 200 assert response.json().get("ok") is True # Assert database get_workshift = select(WorkShift).where(WorkShift.id == 101) work_shift: Optional[WorkShift] = (await db_session.execute(get_workshift)).scalars().one_or_none() assert work_shift is not None assert work_shift.finished_at == fixed_now get_payments = select(PaymentRecord).where( PaymentRecord.user_id == user_id, PaymentRecord.start_date.between( datetime(2024, 11, 11, 00, 00), datetime(2024, 11, 14, 00, 00, 00) ) ) payments = (await db_session.execute(get_payments)).scalars().all() assert len(payments) == 3 # работа: 8 * 450; # переработка: 4 * 550; # из них был перерыв: 0.5 * 550; assert abs(payments[0].amount - 5525) < 0.01 # работа: 8 * 450; # переработка: 16 * 550; # из них был перерыв: 0.5 * 550; assert abs(payments[1].amount - 12125) < 0.01 # работа: 8 * 450; # переработка: 2 * 550; # из них был перерыв: 0.5 * 550; assert abs(payments[2].amount - 4425) < 0.01