Using embeds_one as a form helper and deriving persisted fields — what is the correct approach?

I have a schema like this:

embeds_one :product_profile, ProductProfile, on_replace: :delete, load_in_query: false

I use product_profile as a form/helper structure in LiveView (e.g. live_select), not something I want to persist.

However, I also rely on it for more than just selecting a product: it drives a lot of calculations (pricing, discounts, etc.), so keeping it around in the changeset is very convenient.

From it, I derive product_id inside the changeset:

|> cast_embed(:product_profile)
|> sync_product_id()

Before inserting, I manually transform the params:

filtered_items =
  proposal_items_list
  |> Enum.map(fn {_i, item} ->
    product_id = get_in(item, ["product_profile", "product_id"])

    item
    |> Map.put("product_id", product_id)
    |> Map.delete("product_profile")
  end)

This works, but feels a bit manual / hacky.

Is this considered an acceptable pattern in Ecto (using an embedded schema mainly as a transient helper for UI + calculations, while extracting a persisted field from it), or is there a more idiomatic approach to avoid reshaping the params before insert?