feat(requests): add bulk update, bulk delete and a count endpoint
This commit is contained in:
1 parent
f7f89a3cc7
commit
07c988c443
2 files changed
+70
-1
No files matched your search
@@ -1270,3 +1270,27 @@ def test_connections_hear_about_committed_rows(client, monkeypatch):
|
||||
calls.clear()
|
||||
client.delete(f"/api/requests/{req_id}")
|
||||
assert calls == [("POST", "http://hook/in")] # nothing new on disk, no scan
|
||||
|
||||
|
||||
def test_bulk_move_delete_and_count(client):
|
||||
def lib(name, media_type):
|
||||
return client.post("/api/libraries", json={
|
||||
"name": name, "media_type": media_type,
|
||||
"root_path": str(client.tmp_path / name)}).json()["id"]
|
||||
|
||||
a, b, audio = lib("a", "ebook"), lib("b", "ebook"), lib("audio", "audiobook")
|
||||
ids = [client.post("/api/requests", json={"library_id": a, "title": f"T{i}"}).json()["id"]
|
||||
for i in range(3)]
|
||||
assert client.get("/api/requests/count?status=missing").json() == {"count": 3}
|
||||
|
||||
assert client.put("/api/requests/bulk", json={
|
||||
"ids": ids[:2], "library_id": audio}).status_code == 400
|
||||
assert client.put("/api/requests/bulk", json={
|
||||
"ids": ids[:2], "library_id": b}).json() == {"updated": 2}
|
||||
assert [r["id"] for r in client.get(f"/api/requests?library_id={b}").json()] \
|
||||
== sorted(ids[:2], reverse=True)
|
||||
|
||||
assert client.request("DELETE", "/api/requests/bulk",
|
||||
json={"ids": ids[1:]}).json() == {"deleted": 2}
|
||||
assert client.get("/api/requests/count?status=missing").json() == {"count": 1}
|
||||
assert [r["event"] for r in client.get("/api/history").json()] == ["deleted"] * 2
|
||||
+46
-1
@@ -2,7 +2,7 @@ from pathlib import Path
|
||||
|
||||
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy import func, select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from .. import config, connect
|
||||
@@ -176,6 +176,51 @@ def create_bulk_items(data: BulkItemsIn, session: Session = Depends(get_session)
|
||||
return {"created": [_out(r) for r in created], "skipped": skipped}
|
||||
|
||||
|
||||
@router.get("/count")
|
||||
def count_requests(status: str | None = None, session: Session = Depends(get_session)):
|
||||
stmt = select(func.count()).select_from(BookRequest)
|
||||
if status:
|
||||
stmt = stmt.where(BookRequest.status == status)
|
||||
return {"count": session.scalar(stmt)}
|
||||
|
||||
|
||||
class BulkIdsIn(BaseModel):
|
||||
ids: list[int]
|
||||
|
||||
|
||||
class BulkUpdateIn(BulkIdsIn):
|
||||
library_id: int
|
||||
|
||||
|
||||
# registered before the /{request_id} routes, which would try "bulk" as an id
|
||||
@router.put("/bulk")
|
||||
def update_bulk(data: BulkUpdateIn, session: Session = Depends(get_session)):
|
||||
"""Move requests to another library. Imported files stay where they are
|
||||
until the request is relocated."""
|
||||
lib = session.get(Library, data.library_id)
|
||||
if not lib:
|
||||
raise HTTPException(404, "library not found")
|
||||
reqs = session.scalars(select(BookRequest).where(BookRequest.id.in_(data.ids))).all()
|
||||
if any(r.media_type != lib.media_type for r in reqs):
|
||||
raise HTTPException(400, "library has a different media type")
|
||||
for r in reqs:
|
||||
r.library_id = lib.id
|
||||
session.commit()
|
||||
return {"updated": len(reqs)}
|
||||
|
||||
|
||||
@router.delete("/bulk")
|
||||
def delete_bulk(data: BulkIdsIn, background: BackgroundTasks,
|
||||
session: Session = Depends(get_session)):
|
||||
reqs = session.scalars(select(BookRequest).where(BookRequest.id.in_(data.ids))).all()
|
||||
rows = [record(session, "deleted", r, source=r.imported_path) for r in reqs]
|
||||
for r in reqs:
|
||||
session.delete(r)
|
||||
session.commit()
|
||||
connect.schedule(background, rows)
|
||||
return {"deleted": len(reqs)}
|
||||
|
||||
|
||||
@router.put("/{request_id}", response_model=RequestOut)
|
||||
def update_request(request_id: int, data: RequestIn, session: Session = Depends(get_session)):
|
||||
req = session.get(BookRequest, request_id)
|
||||
|
||||
Reference in new issue
Block a user