diff --git a/lib/simpleshop_theme/clients/printful.ex b/lib/simpleshop_theme/clients/printful.ex index 94f3849..f8626c6 100644 --- a/lib/simpleshop_theme/clients/printful.ex +++ b/lib/simpleshop_theme/clients/printful.ex @@ -187,7 +187,7 @@ defmodule SimpleshopTheme.Clients.Printful do ) """ def calculate_shipping(recipient, items) do - post("/v2/shipping-rates", %{recipient: recipient, items: items}) + post("/v2/shipping-rates", %{recipient: recipient, order_items: items}) end # ============================================================================= diff --git a/lib/simpleshop_theme/providers/printful.ex b/lib/simpleshop_theme/providers/printful.ex index 98a900b..432c1ac 100644 --- a/lib/simpleshop_theme/providers/printful.ex +++ b/lib/simpleshop_theme/providers/printful.ex @@ -168,19 +168,22 @@ defmodule SimpleshopTheme.Providers.Printful do with api_key when is_binary(api_key) <- ProviderConnection.get_api_key(conn), :ok <- set_credentials(api_key, store_id) do - variant_ids = extract_catalog_variant_ids(products) + # Build per-product items: one representative variant per product + product_items = extract_per_product_items(products) Logger.info( - "Fetching Printful shipping rates for #{length(variant_ids)} catalogue variants" + "Fetching Printful shipping rates for #{length(product_items)} product(s), " <> + "#{length(target_countries())} countries" ) rates = - target_countries() - |> Enum.with_index() - |> Enum.flat_map(fn {country_code, index} -> - if index > 0, do: Process.sleep(100) - fetch_rates_for_country(variant_ids, country_code, products) - end) + for {catalog_product_id, variant_id} <- product_items, + {country_code, _index} <- Enum.with_index(target_countries()), + reduce: [] do + acc -> + if acc != [], do: Process.sleep(100) + acc ++ fetch_rate_for_product(catalog_product_id, variant_id, country_code) + end {:ok, rates} else @@ -193,30 +196,23 @@ defmodule SimpleshopTheme.Providers.Printful do ["GB", "US", "DE", "FR", "CA", "AU", "IE", "NL", "AT", "BE"] end - defp fetch_rates_for_country(variant_ids, country_code, products) do - items = - Enum.map(variant_ids, fn vid -> - %{source: "catalog", catalog_variant_id: vid, quantity: 1} - end) + defp fetch_rate_for_product(catalog_product_id, variant_id, country_code) do + items = [%{source: "catalog", catalog_variant_id: variant_id, quantity: 1}] case Client.calculate_shipping(%{country_code: country_code}, items) do {:ok, rates} when is_list(rates) -> - # Take the STANDARD rate (cheapest) - standard = Enum.find(rates, &(&1["id"] == "STANDARD")) || List.first(rates) + standard = Enum.find(rates, &(&1["shipping"] == "STANDARD")) || List.first(rates) if standard do - catalog_product_id = extract_first_catalog_product_id(products) - rate_cents = parse_price(standard["rate"]) - [ %{ blueprint_id: catalog_product_id, print_provider_id: 0, country_code: country_code, - first_item_cost: rate_cents, + first_item_cost: parse_price(standard["rate"]), additional_item_cost: 0, currency: String.upcase(standard["currency"] || "USD"), - handling_time_days: standard["maxDeliveryDays"] + handling_time_days: standard["max_delivery_days"] } ] else @@ -232,33 +228,24 @@ defmodule SimpleshopTheme.Providers.Printful do end end - defp extract_catalog_variant_ids(products) do + # Returns {catalog_product_id, first_catalog_variant_id} per product + defp extract_per_product_items(products) do products |> Enum.flat_map(fn product -> provider_data = product[:provider_data] || %{} + catalog_product_id = + provider_data[:catalog_product_id] || provider_data["catalog_product_id"] + catalog_variant_ids = provider_data[:catalog_variant_ids] || provider_data["catalog_variant_ids"] || [] - if catalog_variant_ids == [] do - # Fall back to extracting from raw data - raw = provider_data[:raw] || provider_data["raw"] || %{} - sync_variants = raw["sync_variants"] || raw[:sync_variants] || [] - Enum.map(sync_variants, fn sv -> sv["variant_id"] || sv[:variant_id] end) - else - catalog_variant_ids + case {catalog_product_id, catalog_variant_ids} do + {nil, _} -> [] + {_, []} -> [] + {cpid, [vid | _]} -> [{cpid, vid}] end end) - |> Enum.reject(&is_nil/1) - |> Enum.uniq() - end - - defp extract_first_catalog_product_id(products) do - products - |> Enum.find_value(fn product -> - provider_data = product[:provider_data] || %{} - provider_data[:catalog_product_id] || provider_data["catalog_product_id"] - end) || 0 end # ============================================================================= @@ -310,6 +297,9 @@ defmodule SimpleshopTheme.Providers.Printful do provider_data: %{ catalog_product_id: catalog_product_id, catalog_variant_ids: catalog_variant_ids, + # Shipping calc uses these generic keys (shared with Printify) + blueprint_id: catalog_product_id, + print_provider_id: 0, thumbnail_url: sync_product["thumbnail_url"], options: build_option_types(sync_variants), raw: %{sync_product: sync_product} diff --git a/test/simpleshop_theme/providers/printful_test.exs b/test/simpleshop_theme/providers/printful_test.exs index 6791f9e..276fcb5 100644 --- a/test/simpleshop_theme/providers/printful_test.exs +++ b/test/simpleshop_theme/providers/printful_test.exs @@ -178,6 +178,8 @@ defmodule SimpleshopTheme.Providers.PrintfulTest do # Provider data assert normalized.provider_data.catalog_product_id == 71 + assert normalized.provider_data.blueprint_id == 71 + assert normalized.provider_data.print_provider_id == 0 assert is_list(normalized.provider_data.options) assert length(normalized.provider_data.catalog_variant_ids) == 4 end @@ -357,6 +359,8 @@ defmodule SimpleshopTheme.Providers.PrintfulTest do provider_data: %{ catalog_product_id: catalog_product_id, catalog_variant_ids: catalog_variant_ids, + blueprint_id: catalog_product_id, + print_provider_id: 0, thumbnail_url: sync_product["thumbnail_url"], options: build_option_types(sync_variants), raw: %{sync_product: sync_product}