feat(estimates): integrate inventory items

This commit is contained in:
Schubert Ferenc 2026-07-05 11:54:23 +02:00
parent fb5c2cc26a
commit 663bdc41b1
15 changed files with 629 additions and 28 deletions

View file

@ -69,6 +69,32 @@ class InventoryRepository:
)
return items, total
@staticmethod
def search_items(
db: Session,
*,
q: str | None = None,
category_id: int | None = None,
manufacturer: str | None = None,
limit: int = 20,
) -> list[InventoryItem]:
query = InventoryRepository.item_query().where(InventoryItem.is_active.is_(True))
if q:
pattern = f"%{q.strip()}%"
query = query.where(or_(
InventoryItem.sku.ilike(pattern),
InventoryItem.name.ilike(pattern),
InventoryItem.manufacturer.ilike(pattern),
InventoryItem.manufacturer_part_number.ilike(pattern),
InventoryItem.supplier_part_number.ilike(pattern),
InventoryItem.compatible_devices.ilike(pattern),
))
if category_id is not None:
query = query.where(InventoryItem.category_id == category_id)
if manufacturer:
query = query.where(InventoryItem.manufacturer.ilike(f"%{manufacturer.strip()}%"))
return list(db.scalars(query.order_by(InventoryItem.name.asc(), InventoryItem.id.asc()).limit(limit)))
@staticmethod
def get_item(db: Session, item_id: int) -> InventoryItem | None:
return db.scalar(InventoryRepository.item_query().where(InventoryItem.id == item_id))
@ -176,6 +202,22 @@ class InventoryRepository:
.where(InventoryItem.purchase_price_cents.is_not(None))
) or 0
@staticmethod
def count_reserved_items(db: Session) -> int:
return db.scalar(
select(func.count(InventoryItem.id))
.where(InventoryItem.is_active.is_(True))
.where(InventoryItem.quantity_reserved > 0)
) or 0
@staticmethod
def reserved_stock_value_cents(db: Session) -> int:
return db.scalar(
select(func.coalesce(func.sum(InventoryItem.quantity_reserved * InventoryItem.selling_price_cents), 0))
.where(InventoryItem.is_active.is_(True))
.where(InventoryItem.selling_price_cents.is_not(None))
) or 0
@staticmethod
def latest_movements(db: Session, limit: int = 5) -> list[InventoryStockMovement]:
return list(