61 lines
1.7 KiB
Python

from dataclasses import dataclass
from commerce.models import Product, ProductBinding, SourceSystem
@dataclass(frozen=True)
class ProductMatch:
product: Product | None
method: str | None
@property
def matched(self) -> bool:
return self.product is not None
def _normalized(value: str | None) -> str:
return (value or "").strip()
def match_product(
*,
source: SourceSystem,
external_id: str | None = None,
external_sku: str | None = None,
barcode: str | None = None,
) -> ProductMatch:
"""Resolve a source product using explicit bindings before safe identifiers."""
external_id = _normalized(external_id)
external_sku = _normalized(external_sku)
barcode = _normalized(barcode)
if external_id:
binding = (
ProductBinding.objects.select_related("product")
.filter(source=source, external_id=external_id)
.first()
)
if binding:
return ProductMatch(binding.product, "external_id")
if external_sku:
bindings = list(
ProductBinding.objects.select_related("product").filter(
source=source, external_sku__iexact=external_sku
)[:2]
)
if len(bindings) == 1:
return ProductMatch(bindings[0].product, "external_sku")
products = list(Product.objects.filter(sku__iexact=external_sku)[:2])
if len(products) == 1:
return ProductMatch(products[0], "canonical_sku")
if barcode:
products = list(Product.objects.filter(barcode=barcode)[:2])
if len(products) == 1:
return ProductMatch(products[0], "barcode")
return ProductMatch(None, None)