Adding autovivify aps

This commit is contained in:
Ian Roddis committed 2026-08-18 16:33:23 -03:00
1 parent 34d538f9a0
commit 7e246be39c
2 files changed
+84 -8

No files matched your search

+35 -8
View File
@@ -25,8 +25,11 @@ and colour defaults to an "Unknown" PartColour, since the sheet carries neither.
Fits are created with label POSSIBLE. The referenced part is looked up by
``product_number`` and linked to its first attachment point (chosen answer:
"sole/first AP"). Both directions are resolved in a second pass so a fit between
two scopes in the same spreadsheet resolves regardless of row order.
"sole/first AP"). If the referenced part has no attachment points at all, one
is created for it that mirrors the scope's attachment point's connection, so
the fit has something valid to attach to. Both directions are resolved in a
second pass so a fit between two scopes in the same spreadsheet resolves
regardless of row order.
Bad rows (missing key, unknown fit target, unparseable thread) are skipped and
reported per-row; good rows are committed as they go.
@@ -186,6 +189,24 @@ async def _thread_ap(db: AsyncSession, *, augmented_part_id: int, label: str, sp
)
async def _mirrored_ap(db: AsyncSession, *, augmented_part_id: int, scope_ap):
"""Create an attachment point mirroring ``scope_ap``'s connection.
Used when the referenced part has no attachment point that already fits
the scope, so the explicit ocular_fit/objective_fit link has something
valid to attach to.
"""
return await attachment_point_crud.create(
db,
augmented_part_id=augmented_part_id,
attachment_point_name_id=scope_ap.attachment_point_name_id,
iso_thread_id=scope_ap.iso_thread_id,
unc_thread_id=scope_ap.unc_thread_id,
clamp_connection_id=scope_ap.clamp_connection_id,
static_connection_id=scope_ap.static_connection_id,
)
async def _link_fit(
db: AsyncSession,
*,
@@ -195,7 +216,11 @@ async def _link_fit(
scope_part_id: int,
messages: list[str],
) -> None:
"""Create a POSSIBLE fit from the scope's AP to the referenced part's first AP."""
"""Create a POSSIBLE fit from the scope's AP to the referenced part's first AP.
If the referenced part has no attachment points at all, one is created
mirroring the scope's attachment point's connection.
"""
if scope_ap is None:
messages.append(
f"{scope_role}_fit '{target_sku}' skipped: scope has no {scope_role} attachment point"
@@ -209,12 +234,14 @@ async def _link_fit(
messages.append(f"{scope_role}_fit '{target_sku}' skipped: self-reference")
return
target_aps = await attachment_point_crud.list_for_augmented_part(db, target.id)
if not target_aps:
if target_aps:
target_ap = target_aps[0]
else:
target_ap = await _mirrored_ap(db, augmented_part_id=target.id, scope_ap=scope_ap)
messages.append(
f"{scope_role}_fit '{target_sku}' skipped: referenced part has no attachment points"
f"{scope_role}_fit '{target_sku}': referenced part had no attachment points, "
"created one matching the scope's attachment point"
)
return
target_ap = target_aps[0]
existing = await fit_crud.get_by_attachment_points(db, scope_ap, target_ap)
if existing is None:
await fit_crud.create(db, ap_a=scope_ap, ap_b=target_ap, label=FitLabel.POSSIBLE)
@@ -253,7 +280,7 @@ async def import_scopes(db: AsyncSession, rows: list[dict]) -> ScopeImportResult
if objective_lens_diameter_mm:
default_product_number += f"x{objective_lens_diameter_mm}"
if model_suffix:
default_product_number += " {model_suffix}"
default_product_number += f" {model_suffix}"
product_number = _text(row.get("product_number")) or default_product_number
result = ScopeImportRowResult(
row=row_num, product_number=product_number, status="skipped", messages=[]