157 lines
5.2 KiB
Python
157 lines
5.2 KiB
Python
"""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
|