| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566 |
- """Reservations no print can use any more are released at start.
- Before b2ed37b6c, billing a print without a user (authentication off, or a
- user deleted while it printed) stopped before releasing the print's budget
- reservation, so it held that much of the cost centre's budget for good. A
- reservation whose queue entry has finished or is gone can never be charged.
- """
- from __future__ import annotations
- import pytest
- from sqlalchemy import select
- from backend.app.core.database import _release_stuck_budget_reservations
- from backend.app.models.finance import BudgetReservation, CostCenter
- from backend.app.models.print_queue import PrintQueueItem
- pytestmark = [pytest.mark.asyncio, pytest.mark.integration]
- CASES = {
- # queue entry status (None: entry deleted) -> reservation released?
- "completed": True,
- "failed": True,
- "cancelled": True,
- None: True,
- "printing": False,
- "pending": False,
- "skipped": False, # can go back to pending
- }
- async def test_reservations_of_finished_or_deleted_entries_are_released(db_session, printer_factory, archive_factory):
- printer = await printer_factory()
- archive = await archive_factory(printer.id)
- center = CostCenter(name="Lab", total_budget=100)
- db_session.add(center)
- await db_session.flush()
- reservation_ids = {}
- for status in CASES:
- if status is None:
- source_id = 999_999
- else:
- item = PrintQueueItem(printer_id=printer.id, archive_id=archive.id, status=status)
- db_session.add(item)
- await db_session.flush()
- source_id = item.id
- reservation = BudgetReservation(
- cost_center_id=center.id, amount=5, status="active", source_type="print_queue", source_id=source_id
- )
- db_session.add(reservation)
- await db_session.flush()
- reservation_ids[status] = reservation.id
- other = BudgetReservation(cost_center_id=center.id, amount=5, status="active", source_type="manual", source_id=1)
- db_session.add(other)
- await db_session.commit()
- other_id = other.id
- await _release_stuck_budget_reservations(await db_session.connection())
- await _release_stuck_budget_reservations(await db_session.connection()) # a restart changes nothing
- await db_session.commit()
- db_session.expire_all()
- rows = dict((await db_session.execute(select(BudgetReservation.id, BudgetReservation.status))).all())
- released = {status: rows[rid] == "released" for status, rid in reservation_ids.items()}
- assert released == CASES
- assert rows[other_id] == "active"
|