diff --git a/spoolman/api/v1/filament.py b/spoolman/api/v1/filament.py index b211cb9..1f1dec6 100644 --- a/spoolman/api/v1/filament.py +++ b/spoolman/api/v1/filament.py @@ -207,6 +207,15 @@ async def find( ), example=20.0, ), + external_id: Optional[str] = Query( + default=None, + description=( + "Find filaments imported by the given external ID. " + "Separate multiple IDs with a comma. " + "Specify empty string to match filaments with no external ID." + ), + example="polymaker_pla_polysonicblack_1000_175", + ), sort: Optional[str] = Query( default=None, title="Sort", @@ -259,6 +268,7 @@ async def find( name=name, material=material, article_number=article_number, + external_id=external_id, sort_by=sort_by, limit=limit, offset=offset, diff --git a/spoolman/api/v1/vendor.py b/spoolman/api/v1/vendor.py index a120b9d..c81eff9 100644 --- a/spoolman/api/v1/vendor.py +++ b/spoolman/api/v1/vendor.py @@ -76,6 +76,15 @@ async def find( title="Vendor Name", description="Partial case-insensitive search term for the vendor name. Separate multiple terms with a comma.", ), + external_id: Optional[str] = Query( + default=None, + title="Vendor External ID", + description=( + "Exact match for the vendor external ID. " + "Separate multiple IDs with a comma. " + "Specify empty string to match filaments with no external ID." + ), + ), sort: Optional[str] = Query( default=None, title="Sort", @@ -104,6 +113,7 @@ async def find( db_items, total_count = await vendor.find( db=db, name=name, + external_id=external_id, sort_by=sort_by, limit=limit, offset=offset, diff --git a/spoolman/database/filament.py b/spoolman/database/filament.py index e854196..21904e8 100644 --- a/spoolman/database/filament.py +++ b/spoolman/database/filament.py @@ -98,6 +98,7 @@ async def find( name: Optional[str] = None, material: Optional[str] = None, article_number: Optional[str] = None, + external_id: Optional[str] = None, sort_by: Optional[dict[str, SortOrder]] = None, limit: Optional[int] = None, offset: int = 0, @@ -121,6 +122,7 @@ async def find( stmt = add_where_clause_str_opt(stmt, models.Filament.name, name) stmt = add_where_clause_str_opt(stmt, models.Filament.material, material) stmt = add_where_clause_str_opt(stmt, models.Filament.article_number, article_number) + stmt = add_where_clause_str_opt(stmt, models.Filament.external_id, external_id) total_count = None diff --git a/spoolman/database/vendor.py b/spoolman/database/vendor.py index ec2a9b8..fd943a5 100644 --- a/spoolman/database/vendor.py +++ b/spoolman/database/vendor.py @@ -9,7 +9,7 @@ from sqlalchemy.ext.asyncio import AsyncSession from spoolman.api.v1.models import EventType, Vendor, VendorEvent from spoolman.database import models -from spoolman.database.utils import SortOrder, add_where_clause_str +from spoolman.database.utils import SortOrder, add_where_clause_str, add_where_clause_str_opt from spoolman.exceptions import ItemNotFoundError from spoolman.ws import websocket_manager @@ -50,6 +50,7 @@ async def find( *, db: AsyncSession, name: Optional[str] = None, + external_id: Optional[str] = None, sort_by: Optional[dict[str, SortOrder]] = None, limit: Optional[int] = None, offset: int = 0, @@ -61,6 +62,7 @@ async def find( stmt = select(models.Vendor) stmt = add_where_clause_str(stmt, models.Vendor.name, name) + stmt = add_where_clause_str_opt(stmt, models.Vendor.external_id, external_id) total_count = None diff --git a/tests_integration/tests/filament/test_add.py b/tests_integration/tests/filament/test_add.py index 991f9a2..57cb1f7 100644 --- a/tests_integration/tests/filament/test_add.py +++ b/tests_integration/tests/filament/test_add.py @@ -23,6 +23,7 @@ def test_add_filament(random_vendor: dict[str, Any]): settings_extruder_temp = 200 settings_bed_temp = 60 color_hex = "FF0000" + external_id = "polymaker_pla_polysonicblack_1000_175" result = httpx.post( f"{URL}/api/v1/filament", json={ @@ -39,6 +40,7 @@ def test_add_filament(random_vendor: dict[str, Any]): "settings_extruder_temp": settings_extruder_temp, "settings_bed_temp": settings_bed_temp, "color_hex": color_hex, + "external_id": external_id, }, ) result.raise_for_status() @@ -63,6 +65,7 @@ def test_add_filament(random_vendor: dict[str, Any]): "settings_extruder_temp": settings_extruder_temp, "settings_bed_temp": settings_bed_temp, "color_hex": color_hex, + "external_id": external_id, }, ) diff --git a/tests_integration/tests/filament/test_find.py b/tests_integration/tests/filament/test_find.py index e864729..d2f477e 100644 --- a/tests_integration/tests/filament/test_find.py +++ b/tests_integration/tests/filament/test_find.py @@ -50,6 +50,7 @@ def filaments(random_vendor_mod: dict[str, Any], random_empty_vendor_mod: dict[s "spool_weight": 250, "article_number": "987654321", "color_hex": "EE0000", + "external_id": "some_external_id", "comment": "abcdefghåäö", }, ) @@ -418,6 +419,35 @@ def test_find_filaments_by_empty_article_number(filaments: Fixture): assert_lists_compatible(filaments_result, filaments.filaments[3:]) +def test_find_filaments_by_external_id(filaments: Fixture): + # Execute + result = httpx.get( + f"{URL}/api/v1/filament", + params={"external_id": "some_external_id"}, + ) + result.raise_for_status() + + # Verify + filaments_result = result.json() + assert filaments_result[0] == filaments.filaments[1] + + +def test_find_filaments_by_empty_external_id(filaments: Fixture): + # Execute + result = httpx.get( + f"{URL}/api/v1/filament", + params={"external_id": ""}, + ) + result.raise_for_status() + + # Verify + filaments_result = result.json() + assert_lists_compatible( + filaments_result, + [filaments.filaments[0], filaments.filaments[2], filaments.filaments[3], filaments.filaments[4]], + ) + + def test_find_filaments_by_similar_color(filaments: Fixture): # Execute result = httpx.get( diff --git a/tests_integration/tests/filament/test_update.py b/tests_integration/tests/filament/test_update.py index 90b2739..c635784 100644 --- a/tests_integration/tests/filament/test_update.py +++ b/tests_integration/tests/filament/test_update.py @@ -26,6 +26,7 @@ def test_update_filament(random_vendor: dict[str, Any]): "settings_extruder_temp": 200, "settings_bed_temp": 60, "color_hex": "FF0000", + "external_id": "external_id1", }, ) result.raise_for_status() @@ -44,6 +45,7 @@ def test_update_filament(random_vendor: dict[str, Any]): new_settings_extruder_temp = 210 new_settings_bed_temp = 70 new_color_hex = "00FF00" + new_external_id = "external_id2" result = httpx.patch( f"{URL}/api/v1/filament/{added_filament['id']}", json={ @@ -60,6 +62,7 @@ def test_update_filament(random_vendor: dict[str, Any]): "settings_extruder_temp": new_settings_extruder_temp, "settings_bed_temp": new_settings_bed_temp, "color_hex": new_color_hex, + "external_id": new_external_id, }, ) result.raise_for_status() @@ -84,6 +87,7 @@ def test_update_filament(random_vendor: dict[str, Any]): "settings_extruder_temp": new_settings_extruder_temp, "settings_bed_temp": new_settings_bed_temp, "color_hex": new_color_hex, + "external_id": new_external_id, }, ) diff --git a/tests_integration/tests/vendor/test_add.py b/tests_integration/tests/vendor/test_add.py index 22cbd8b..17da002 100644 --- a/tests_integration/tests/vendor/test_add.py +++ b/tests_integration/tests/vendor/test_add.py @@ -12,9 +12,14 @@ def test_add_vendor(): # Execute name = "John" comment = "abcdefghåäö" + external_id = "external_id1" result = httpx.post( f"{URL}/api/v1/vendor", - json={"name": name, "comment": comment}, + json={ + "name": name, + "external_id": external_id, + "comment": comment, + }, ) result.raise_for_status() @@ -27,6 +32,7 @@ def test_add_vendor(): "registered": vendor["registered"], "name": name, "comment": comment, + "external_id": external_id, }, ) diff --git a/tests_integration/tests/vendor/test_find.py b/tests_integration/tests/vendor/test_find.py index 2584224..2649a6d 100644 --- a/tests_integration/tests/vendor/test_find.py +++ b/tests_integration/tests/vendor/test_find.py @@ -27,7 +27,7 @@ def vendors() -> Iterable[Fixture]: result = httpx.post( f"{URL}/api/v1/vendor", - json={"name": "Stan", "comment": "gfdadfg"}, + json={"name": "Stan", "comment": "gfdadfg", "external_id": "some_external_id"}, ) result.raise_for_status() vendor_2 = result.json() @@ -185,3 +185,29 @@ def test_find_vendors_by_empty_name(vendors: Fixture): # Verify vendors_result = result.json() assert vendors_result == [vendors.vendors[2]] + + +def test_find_vendors_by_external_id(vendors: Fixture): + # Execute + result = httpx.get( + f"{URL}/api/v1/vendor", + params={"external_id": "some_external_id"}, + ) + result.raise_for_status() + + # Verify + vendors_result = result.json() + assert vendors_result == [vendors.vendors[1]] + + +def test_find_vendors_by_empty_external_id(vendors: Fixture): + # Execute + result = httpx.get( + f"{URL}/api/v1/vendor", + params={"external_id": ""}, + ) + result.raise_for_status() + + # Verify + vendors_result = result.json() + assert_lists_compatible(vendors_result, [vendors.vendors[0], vendors.vendors[2]])