Packages

phoenix_kit

1.7.28
1.7.208 1.7.207 1.7.206 1.7.205 1.7.204 1.7.203 1.7.202 1.7.201 1.7.200 1.7.199 1.7.198 1.7.197 1.7.196 1.7.194 1.7.193 1.7.192 1.7.191 1.7.190 1.7.189 1.7.187 1.7.186 1.7.185 1.7.184 1.7.183 1.7.182 1.7.181 1.7.180 1.7.179 1.7.178 1.7.177 1.7.176 1.7.175 1.7.174 1.7.173 1.7.172 1.7.171 1.7.170 1.7.169 1.7.168 1.7.167 1.7.166 1.7.165 1.7.164 1.7.162 1.7.161 1.7.160 1.7.159 1.7.157 1.7.156 1.7.155 1.7.154 1.7.153 1.7.152 1.7.151 1.7.150 1.7.149 1.7.146 1.7.145 1.7.144 1.7.143 1.7.138 1.7.133 1.7.132 1.7.131 1.7.130 1.7.128 1.7.126 1.7.125 1.7.121 1.7.120 1.7.119 1.7.118 1.7.117 1.7.116 1.7.115 1.7.114 1.7.113 1.7.112 1.7.111 1.7.110 1.7.109 1.7.108 1.7.107 1.7.106 1.7.105 1.7.104 1.7.103 1.7.102 1.7.101 1.7.100 1.7.99 1.7.98 1.7.97 1.7.96 1.7.95 1.7.94 1.7.93 1.7.92 1.7.91 1.7.90 1.7.89 1.7.88 1.7.87 1.7.86 1.7.85 1.7.84 1.7.83 1.7.82 1.7.81 1.7.80 1.7.79 1.7.78 1.7.77 1.7.76 1.7.75 1.7.74 1.7.71 1.7.70 1.7.69 1.7.66 1.7.65 1.7.64 1.7.63 1.7.62 1.7.61 1.7.59 1.7.58 1.7.57 1.7.56 1.7.55 1.7.54 1.7.53 1.7.52 1.7.51 1.7.49 1.7.44 1.7.43 1.7.42 1.7.41 1.7.39 1.7.38 1.7.37 1.7.36 1.7.34 1.7.33 1.7.31 1.7.30 1.7.29 1.7.28 1.7.27 1.7.26 1.7.25 1.7.24 1.7.23 1.7.22 1.7.21 1.7.20 1.7.19 1.7.18 1.7.17 1.7.16 1.7.15 1.7.14 1.7.13 1.7.12 1.7.11 1.7.10 1.7.9 1.7.8 1.7.7 1.7.6 1.7.5 1.7.4 1.7.3 1.7.2 1.7.1 1.7.0 1.6.20 1.6.19 1.6.18 1.6.17 1.6.16 1.6.15 1.6.14 1.6.13 1.6.12 1.6.11 1.6.10 1.6.9 1.6.8 1.6.7 1.6.6 1.6.5 1.6.4 1.6.3 1.5.2 1.5.1 1.5.0 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.2 1.3.1 1.3.0 1.2.10 1.2.9 1.2.8 1.2.7 1.2.5 1.2.4 1.2.2 1.2.1 1.2.0 1.1.0 1.0.0

A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more

Current section

Files

Jump to
phoenix_kit lib modules shop import option_builder.ex
Raw

lib/modules/shop/import/option_builder.ex

defmodule PhoenixKit.Modules.Shop.Import.OptionBuilder do
@moduledoc """
Build option values and price modifiers from Shopify variant rows.
Extracts Option1/Option2 names and values from CSV rows,
calculates base price (minimum) and price modifiers (deltas from base).
"""
@doc """
Build options data from variant rows.
Returns a map with:
- base_price: minimum variant price (Decimal)
- option1_name: name of first option (e.g., "Size")
- option1_values: list of unique values for option1
- option1_modifiers: map of value => price delta from base
- option2_name: name of second option (e.g., "Color")
- option2_values: list of unique values for option2
## Examples
OptionBuilder.build_from_variants(rows)
# => %{
# base_price: Decimal.new("22.80"),
# option1_name: "Size",
# option1_values: ["4 inches (10 cm)", "5 inches (13 cm)", ...],
# option1_modifiers: %{"4 inches (10 cm)" => "0", "5 inches (13 cm)" => "5.00", ...},
# option2_name: "Color",
# option2_values: ["Black", "White", ...]
# }
"""
def build_from_variants(rows) when is_list(rows) do
# Get option names from first row
first_row = List.first(rows)
option1_name = get_non_empty(first_row, "Option1 Name")
option2_name = get_non_empty(first_row, "Option2 Name")
# Extract variants with prices
variants =
rows
|> Enum.map(fn row ->
%{
option1_value: get_non_empty(row, "Option1 Value"),
option2_value: get_non_empty(row, "Option2 Value"),
price: parse_price(row["Variant Price"])
}
end)
|> Enum.filter(& &1.price)
# Calculate base price (minimum)
base_price =
variants
|> Enum.map(& &1.price)
|> Enum.min(fn -> Decimal.new("0") end)
# Build option1 data (typically Size - affects price)
{option1_values, option1_modifiers} = build_option_data(variants, :option1_value, base_price)
# Build option2 values (typically Color - no price impact, just values)
option2_values = get_unique_values(variants, :option2_value)
%{
base_price: base_price,
option1_name: option1_name,
option1_values: option1_values,
option1_modifiers: option1_modifiers,
option2_name: option2_name,
option2_values: option2_values
}
end
# Private helpers
defp get_non_empty(row, key) do
case row[key] do
nil -> nil
"" -> nil
value -> String.trim(value)
end
end
defp parse_price(nil), do: nil
defp parse_price(""), do: nil
defp parse_price(str) when is_binary(str) do
str = String.trim(str)
case Decimal.parse(str) do
{decimal, _} -> decimal
:error -> nil
end
end
defp build_option_data(variants, field, base_price) do
# Get unique values preserving order of first appearance
values =
variants
|> Enum.map(&Map.get(&1, field))
|> Enum.reject(&is_nil/1)
|> Enum.uniq()
# Build price modifiers for each value
# Group by value and take the first price for each
price_by_value =
variants
|> Enum.reduce(%{}, fn v, acc ->
value = Map.get(v, field)
if value && !Map.has_key?(acc, value) do
Map.put(acc, value, v.price)
else
acc
end
end)
# Calculate modifiers as delta from base price
modifiers =
price_by_value
|> Enum.reduce(%{}, fn {value, price}, acc ->
modifier = Decimal.sub(price, base_price)
Map.put(acc, value, Decimal.to_string(modifier))
end)
{values, modifiers}
end
defp get_unique_values(variants, field) do
variants
|> Enum.map(&Map.get(&1, field))
|> Enum.reject(&is_nil/1)
|> Enum.uniq()
end
end