Is there a simple way to make child changeset which will be history?

I’m newbie to DB and Ecto.
I’d like to make history data for user_properties which will be changed by real user, like below.

screenshot

For user_properties, I’d like to allow only “INSERT” as history.

User INSERT with property is simple.

  def create_user_with_property(attrs) do
    %User{}
    |> User.changeset(attrs)
    |> Ecto.Changeset.cast_assoc(:property)
    |> Repo.insert()
  end

User UPDATE with property is also simple when it allows “UPDATE”.

  def update_user_with_property(user, attrs) do
    user
    |> User.changeset(attrs)
    |> Ecto.Changeset.cast_assoc(:property)
    |> Repo.update()
  end

I read the blog which explains a solution, https://medium.com/webdevs/entity-status-history-using-ecto-b5df6ec1da52 .

This solution is nice, but the blog points out its complexity.

This part is mostly so complex because I wanted to keep the return value of {:ok, entity} | {:error, changeset} .

I expect like on_replace: :insert, Ecto.Changeset — Ecto v3.11.1 .

Is there any way to solve this more simple?