"""UACDiameterRangemm handling in the AugmentedPart sync service: the reformatted range field on AugmentedPart, and the "Objective" clamp attachment point it should produce.""" import pytest from sqlalchemy import select from app.crud import attachment_point as attachment_point_crud from app.crud import clamp_connection as clamp_connection_crud from app.models.augmented_part import AugmentedPart from app.models.imported_part import ImportedPart from app.models.manufacturer import Manufacturer from app.models.part_colour import PartColour from app.models.part_type import PartType from app.services import augmented_part_sync from app.services.augmented_part_sync import _parse_uac_diameter_range def test_parse_uac_diameter_range_valid_8_digits(): assert _parse_uac_diameter_range("03505500") == ("03.50-55.00", 3.5, 55.0) @pytest.mark.parametrize("value", [None, "", "1234567", "123456789", "abcdefgh"]) def test_parse_uac_diameter_range_rejects_non_8_digit(value): assert _parse_uac_diameter_range(value) is None def test_parse_uac_diameter_range_strips_non_digit_separators(): # Defensive: pull digits out even if the feed adds punctuation. assert _parse_uac_diameter_range("0350-5500") == ("03.50-55.00", 3.5, 55.0) async def _seed_reference_data(db): manufacturer = Manufacturer(name="Acme", url="https://acme.test") colour = PartColour(name="Black") part_type = PartType(name="Scope") db.add_all([manufacturer, colour, part_type]) await db.flush() return manufacturer, colour, part_type @pytest.mark.asyncio async def test_sync_populates_range_and_creates_objective_clamp_point( db_sessionmaker, ): async with db_sessionmaker() as db: await _seed_reference_data(db) db.add( ImportedPart( InventoryID="INV-UAC-1", Description="Scope widget", UACDiameterRangemm="03505500", ) ) await db.commit() result = await augmented_part_sync.sync(db) assert result.created == 1 ap = ( await db.execute( select(AugmentedPart).where(AugmentedPart.sku == "INV-UAC-1") ) ).scalar_one() assert ap.uac_diameter_range_mm == "03.50-55.00" points = await attachment_point_crud.list_for_augmented_part(db, ap.id) objective_points = [ p for p in points if p.attachment_point_name.name == "Objective" ] assert len(objective_points) == 1 clamp = await clamp_connection_crud.get( db, objective_points[0].clamp_connection_id ) assert clamp.min_mm == 3.5 assert clamp.max_mm == 55.0 assert clamp.min_in == pytest.approx(3.5 / 25.4) assert clamp.max_in == pytest.approx(55.0 / 25.4) @pytest.mark.asyncio async def test_sync_leaves_range_and_objective_point_unset_when_field_blank( db_sessionmaker, ): async with db_sessionmaker() as db: await _seed_reference_data(db) db.add(ImportedPart(InventoryID="INV-NO-UAC", Description="Scope widget")) await db.commit() result = await augmented_part_sync.sync(db) assert result.created == 1 ap = ( await db.execute( select(AugmentedPart).where(AugmentedPart.sku == "INV-NO-UAC") ) ).scalar_one() assert ap.uac_diameter_range_mm is None points = await attachment_point_crud.list_for_augmented_part(db, ap.id) assert all(p.attachment_point_name.name != "Objective" for p in points) @pytest.mark.asyncio async def test_sync_reuses_existing_clamp_connection_for_same_range(db_sessionmaker): async with db_sessionmaker() as db: await _seed_reference_data(db) db.add_all( [ ImportedPart( InventoryID="INV-UAC-A", Description="Scope widget A", UACDiameterRangemm="03505500", ), ImportedPart( InventoryID="INV-UAC-B", Description="Scope widget B", UACDiameterRangemm="03505500", ), ] ) await db.commit() result = await augmented_part_sync.sync(db) assert result.created == 2 clamps = await clamp_connection_crud.list_all(db) assert len(clamps) == 1 @pytest.mark.asyncio async def test_sync_one_populates_range_and_objective_point(db_sessionmaker): async with db_sessionmaker() as db: manufacturer, colour, part_type = await _seed_reference_data(db) db.add( ImportedPart( InventoryID="INV-UAC-MANUAL", Description="Odd widget", UACDiameterRangemm="10002000", ) ) await db.commit() ap = await augmented_part_sync.sync_one( db, inventory_id="INV-UAC-MANUAL", part_type_id=part_type.id, sub_part_type_id=None, ) assert ap.uac_diameter_range_mm == "10.00-20.00" points = await attachment_point_crud.list_for_augmented_part(db, ap.id) objective_points = [ p for p in points if p.attachment_point_name.name == "Objective" ] assert len(objective_points) == 1