Making scope filter by product id
This commit is contained in:
1 parent
6d7c5c5604
commit
2318a6daeb
4 files changed
+36
-5
No files matched your search
@@ -1,4 +1,4 @@
|
|||||||
from sqlalchemy import distinct, select
|
from sqlalchemy import distinct, or_, select
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
from app.models.associations import augmented_part_imported_parts
|
from app.models.associations import augmented_part_imported_parts
|
||||||
@@ -89,10 +89,19 @@ async def list_filtered(
|
|||||||
direction: str = "asc",
|
direction: str = "asc",
|
||||||
skip: int = 0,
|
skip: int = 0,
|
||||||
limit: int = 100,
|
limit: int = 100,
|
||||||
|
match_sku: bool = False,
|
||||||
) -> list[AugmentedPart]:
|
) -> list[AugmentedPart]:
|
||||||
q = select(AugmentedPart)
|
q = select(AugmentedPart)
|
||||||
if description.strip():
|
if description.strip():
|
||||||
q = q.where(AugmentedPart.description.ilike(f"%{description.strip()}%"))
|
term = f"%{description.strip()}%"
|
||||||
|
if match_sku:
|
||||||
|
q = q.where(
|
||||||
|
or_(
|
||||||
|
AugmentedPart.description.ilike(term), AugmentedPart.sku.ilike(term)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
q = q.where(AugmentedPart.description.ilike(term))
|
||||||
if colour_id is not None:
|
if colour_id is not None:
|
||||||
q = q.where(AugmentedPart.colour_id == colour_id)
|
q = q.where(AugmentedPart.colour_id == colour_id)
|
||||||
if manufacturer_id is not None:
|
if manufacturer_id is not None:
|
||||||
|
|||||||
@@ -33,8 +33,9 @@ async def build(
|
|||||||
"""Return the context for ``scopes.html``.
|
"""Return the context for ``scopes.html``.
|
||||||
|
|
||||||
The scope rows are narrowed by the scope-attribute filters (``description``
|
The scope rows are narrowed by the scope-attribute filters (``description``
|
||||||
matches the scope's description; the ``*_id`` filters match exactly).
|
matches either the scope's description or its SKU/product ID; the ``*_id``
|
||||||
``fits_part_type_id`` keeps only scopes that have at least one (non-``none``)
|
filters match exactly). ``fits_part_type_id`` keeps only scopes that have
|
||||||
|
at least one (non-``none``)
|
||||||
fit for that part type. Callers that paginate should slice ``rows``
|
fit for that part type. Callers that paginate should slice ``rows``
|
||||||
themselves — this always returns the full filtered set, since
|
themselves — this always returns the full filtered set, since
|
||||||
``fits_part_type_id`` is a post-filter that can't be pushed into the DB query.
|
``fits_part_type_id`` is a post-filter that can't be pushed into the DB query.
|
||||||
@@ -71,6 +72,7 @@ async def build(
|
|||||||
sub_part_type_id=sub_part_type_id,
|
sub_part_type_id=sub_part_type_id,
|
||||||
part_type_id=scope_type.id,
|
part_type_id=scope_type.id,
|
||||||
limit=1000,
|
limit=1000,
|
||||||
|
match_sku=True,
|
||||||
)
|
)
|
||||||
scope_ids = {s.id for s in scopes}
|
scope_ids = {s.id for s in scopes}
|
||||||
if not scope_ids:
|
if not scope_ids:
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
hx-target="#scopes-table-card"
|
hx-target="#scopes-table-card"
|
||||||
hx-trigger="input delay:300ms, change"
|
hx-trigger="input delay:300ms, change"
|
||||||
hx-swap="outerHTML">
|
hx-swap="outerHTML">
|
||||||
<input type="text" name="description" placeholder="Search scopes…"
|
<input type="text" name="description" placeholder="Search by description or product ID…"
|
||||||
value="{{ filters.description or '' }}">
|
value="{{ filters.description or '' }}">
|
||||||
<select name="manufacturer_id">
|
<select name="manufacturer_id">
|
||||||
<option value="">All manufacturers</option>
|
<option value="">All manufacturers</option>
|
||||||
|
|||||||
@@ -147,6 +147,26 @@ async def test_build_filters_by_description(db_sessionmaker):
|
|||||||
assert _descriptions(guide) == ["Alpha 3-18x50"]
|
assert _descriptions(guide) == ["Alpha 3-18x50"]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_build_filters_by_sku(db_sessionmaker):
|
||||||
|
async with db_sessionmaker() as db:
|
||||||
|
ids = await _seed_guide_data(db)
|
||||||
|
ids["s1"].sku = "ARM-12345"
|
||||||
|
await db.commit()
|
||||||
|
guide = await scope_guide.build(db, description="ARM-12345")
|
||||||
|
assert _descriptions(guide) == ["Alpha 3-18x50"]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_build_filters_by_partial_sku(db_sessionmaker):
|
||||||
|
async with db_sessionmaker() as db:
|
||||||
|
ids = await _seed_guide_data(db)
|
||||||
|
ids["s1"].sku = "ARM-12345"
|
||||||
|
await db.commit()
|
||||||
|
guide = await scope_guide.build(db, description="12345")
|
||||||
|
assert _descriptions(guide) == ["Alpha 3-18x50"]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_build_filters_by_manufacturer(db_sessionmaker):
|
async def test_build_filters_by_manufacturer(db_sessionmaker):
|
||||||
async with db_sessionmaker() as db:
|
async with db_sessionmaker() as db:
|
||||||
|
|||||||
Reference in new issue
Block a user