US01-06: Review Inventory and Duplicates in the Browser (#51)
This commit was merged in pull request #51.
This commit is contained in:
@@ -30,7 +30,7 @@ from enum import Enum
|
||||
from pathlib import Path
|
||||
from typing import Iterable
|
||||
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy import func, select
|
||||
from sqlalchemy.orm import Session, sessionmaker
|
||||
|
||||
from photo_pipeline import path_policy
|
||||
@@ -55,6 +55,21 @@ class ScanResult:
|
||||
asset_ids: dict[str, str] = field(default_factory=dict) # path -> asset id
|
||||
|
||||
|
||||
def _asset_dict(asset: Asset) -> dict:
|
||||
return {
|
||||
"id": asset.id,
|
||||
"current_path": asset.current_path,
|
||||
"availability_state": asset.availability_state,
|
||||
"byte_size": asset.byte_size,
|
||||
"current_sha256": asset.current_sha256,
|
||||
"pixel_sha256": asset.pixel_sha256,
|
||||
"phash": asset.phash,
|
||||
"canonical_asset_id": asset.canonical_asset_id,
|
||||
"missing": asset.missing_at is not None,
|
||||
"state_version": asset.state_version,
|
||||
}
|
||||
|
||||
|
||||
class InventoryService:
|
||||
def __init__(self, session_factory: sessionmaker) -> None:
|
||||
self._session_factory = session_factory
|
||||
@@ -101,6 +116,30 @@ class InventoryService:
|
||||
result.counts = dict(Counter(result.occurrences.values()))
|
||||
return result
|
||||
|
||||
def list_assets(
|
||||
self,
|
||||
*,
|
||||
limit: int = 50,
|
||||
offset: int = 0,
|
||||
availability: str | None = None,
|
||||
query: str | None = None,
|
||||
) -> dict:
|
||||
"""Paged, filterable asset listing for the inventory UI (read-only)."""
|
||||
limit = max(1, min(limit, 200))
|
||||
offset = max(0, offset)
|
||||
with self._session_factory() as session:
|
||||
stmt = select(Asset)
|
||||
if availability:
|
||||
stmt = stmt.where(Asset.availability_state == availability)
|
||||
if query:
|
||||
stmt = stmt.where(Asset.current_path.like(f"%{query}%"))
|
||||
total = session.scalar(select(func.count()).select_from(stmt.subquery()))
|
||||
rows = session.execute(
|
||||
stmt.order_by(Asset.current_path).limit(limit).offset(offset)
|
||||
).scalars()
|
||||
items = [_asset_dict(a) for a in rows]
|
||||
return {"items": items, "total": int(total or 0), "limit": limit, "offset": offset}
|
||||
|
||||
def _reconcile_one(
|
||||
self,
|
||||
session: Session,
|
||||
|
||||
Reference in New Issue
Block a user