fetch catalog color hex codes during Printful sync

Printful sync variants don't include color_code — hex values are only
available from the catalog product endpoint. Fetch catalog colors per
unique product type during sync (cached in process dictionary to avoid
duplicate calls) and store as "colors" array in option values, matching
the Printify format that Product.option_types expects.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jamey 2026-02-16 00:11:18 +00:00
parent daa6d3de71
commit 4e19d4c4a9

View File

@ -76,7 +76,9 @@ defmodule SimpleshopTheme.Providers.Printful do
case Client.get_sync_product(product["id"]) do case Client.get_sync_product(product["id"]) do
{:ok, detail} -> {:ok, detail} ->
normalize_product(detail["sync_product"], detail["sync_variants"] || []) sync_variants = detail["sync_variants"] || []
catalog_colors = fetch_catalog_colors(sync_variants)
normalize_product(detail["sync_product"], sync_variants, catalog_colors)
{:error, reason} -> {:error, reason} ->
Logger.warning( Logger.warning(
@ -106,6 +108,42 @@ defmodule SimpleshopTheme.Providers.Printful do
end end
end end
# Fetch catalog color hex codes for a product's catalog type.
# Caches per catalog_product_id in the process dictionary to avoid duplicate calls.
defp fetch_catalog_colors(sync_variants) do
catalog_product_id = extract_catalog_product_id_from_variants(sync_variants)
cache_key = {:catalog_colors, catalog_product_id}
case Process.get(cache_key) do
nil ->
colors = do_fetch_catalog_colors(catalog_product_id)
Process.put(cache_key, colors)
colors
cached ->
cached
end
end
defp do_fetch_catalog_colors(0), do: %{}
defp do_fetch_catalog_colors(catalog_product_id) do
Process.sleep(100)
case Client.get_catalog_product(catalog_product_id) do
{:ok, catalog} ->
(catalog["colors"] || [])
|> Map.new(fn c -> {c["name"], c["value"]} end)
{:error, reason} ->
Logger.warning(
"Failed to fetch catalog colors for product #{catalog_product_id}: #{inspect(reason)}"
)
%{}
end
end
# ============================================================================= # =============================================================================
# Orders # Orders
# ============================================================================= # =============================================================================
@ -295,7 +333,7 @@ defmodule SimpleshopTheme.Providers.Printful do
# Data Normalization # Data Normalization
# ============================================================================= # =============================================================================
defp normalize_product(sync_product, sync_variants) do defp normalize_product(sync_product, sync_variants, catalog_colors) do
images = extract_preview_images(sync_variants) images = extract_preview_images(sync_variants)
catalog_product_id = extract_catalog_product_id_from_variants(sync_variants) catalog_product_id = extract_catalog_product_id_from_variants(sync_variants)
catalog_variant_ids = Enum.map(sync_variants, & &1["variant_id"]) |> Enum.reject(&is_nil/1) catalog_variant_ids = Enum.map(sync_variants, & &1["variant_id"]) |> Enum.reject(&is_nil/1)
@ -322,7 +360,7 @@ defmodule SimpleshopTheme.Providers.Printful do
print_provider_id: 0, print_provider_id: 0,
thumbnail_url: sync_product["thumbnail_url"], thumbnail_url: sync_product["thumbnail_url"],
artwork_url: extract_artwork_url(sync_variants), artwork_url: extract_artwork_url(sync_variants),
options: build_option_types(sync_variants), options: build_option_types(sync_variants, catalog_colors),
raw: %{sync_product: sync_product} raw: %{sync_product: sync_product}
} }
} }
@ -395,16 +433,18 @@ defmodule SimpleshopTheme.Providers.Printful do
end) || 0 end) || 0
end end
# Build option types from variants for frontend display # Build option types from variants for frontend display.
defp build_option_types(sync_variants) do # catalog_colors is a %{"Black" => "#0b0b0b", ...} map from the catalog API.
# Build colour values with hex codes from sync variant data defp build_option_types(sync_variants, catalog_colors) do
colors = colors =
sync_variants sync_variants
|> Enum.reject(fn sv -> is_nil(sv["color"]) end) |> Enum.reject(fn sv -> is_nil(sv["color"]) end)
|> Enum.uniq_by(fn sv -> sv["color"] end) |> Enum.uniq_by(fn sv -> sv["color"] end)
|> Enum.map(fn sv -> |> Enum.map(fn sv ->
base = %{"title" => normalize_text(sv["color"])} title = normalize_text(sv["color"])
if sv["color_code"], do: Map.put(base, "hex", sv["color_code"]), else: base base = %{"title" => title}
hex = Map.get(catalog_colors, sv["color"])
if hex, do: Map.put(base, "colors", [hex]), else: base
end) end)
sizes = sizes =