<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="253602" data-post-id="253602">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="docjazither" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/docjazither/120/26058_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  docjazither
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Yep<br>
The task is to find duplicate entries and delete everything and spare the most optimal one</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Mix.Tasks.App.CleanUpDuplicateAccounts do
  use Mix.Task

  import Ecto.Query, only: [where: 3, from: 2]

  alias App.Data.{....
  }

  require Logger

  def run(_args) do
    Logger.info("Starting task to clean up duplicate accounts...")

    {:ok, _} = Application.ensure_all_started(:data)

    query =
      from(u in User,
        where:
          fragment(
            "exists (
                select 1
                from users inner
                where inner.id != ?
                and lower(inner.email) = lower(?)
              )",
            u.id,
            u.email
          ),
        order_by: u.email
      )

    query
    |&gt; Repo.all()
    |&gt; Enum.group_by(&amp;String.downcase(&amp;1.email))
    |&gt; Enum.each(fn {_k, duplicates} -&gt;
      comparing_statuses(duplicates)
    end)
  end

  defp get_tasks_for_users(id) do
        # Logic return tasks
  end

  defp check_and_remove_account(user) do
    if !user.is_email_verified ||
         is_nil(user.encrypted_password) do
      tasks = get_tasks_for_user(user.id)

      case tasks do
        [] -&gt;
          Logger.info("Deleting user: id #{user.id} with email #{user.email}")
          Users.delete(user)

        _ -&gt;
          Logger.info("Unable to delete - user: id #{user.id} has active tasks")
      end
    end
  end

  defp mass_deletion_check(duplicates) do
    are_all_duplicates_not_verified =
      Enum.all?(duplicates, &amp;(!&amp;1.is_email_verified || is_nil(&amp;1.encrypted_password)))

    if are_all_duplicates_not_verified do
      [_ | duplicates_to_delete] = duplicates

      Enum.each(
        duplicates_to_delete,
        fn index -&gt;
          check_and_remove_account(index)
        end
      )
    else
      Enum.each(duplicates, fn index -&gt;
        if !index.is_email_verified or is_nil(index.encrypted_password) do
          check_and_remove_account(index)
        else
          Logger.info(
            "Not deleting - user: id #{index.id} has email is verified or password is set"
          )
        end
      end)
    end
  end

  defp get_handle_for_user(id) do
        # logic to return handles
  end

  # If handles are the same then start mass_deletion_check for the duplicates
  # If handles are different then delete email from accounts except one
  defp handle_or_email_deletion_check(duplicates) do
    duplicates_with_handle =
      duplicates
      |&gt; Enum.reduce([], fn user, acc -&gt;
        acc ++ [Map.put(user, :handle, get_handle_for_user(user.id))]
      end)

    handle_group = Enum.group_by(duplicates_with_handle, &amp; &amp;1.handle)

    if Enum.count(handle_group) &lt; 2 do
      mass_deletion_check(duplicates)
    else
      [_ | handle_group_to_delete_email] = Enum.to_list(handle_group)

      Enum.each(handle_group_to_delete_email, fn {_k, duplicates} -&gt;
        remove_email_except_one(duplicates)
      end)
    end
  end

  defp remove_email_except_one(duplicates) do
    Enum.each(duplicates, fn user -&gt;
      Users.update(user, %{email: nil})
    end)
  end

  defp count_with_status(duplicates, status) when not is_list(status) do
    count_with_status(duplicates, [status])
  end

  defp count_with_status(duplicates, status) do
    Enum.count(
      duplicates,
      &amp;(&amp;1.user_status_id in UserStatuses.get_id_by_code(status))
    )
  end

  defp accumulating(duplicates, status) do
    duplicates
    |&gt; Enum.reduce([], fn user, acc -&gt;
      if user.user_status_id in UserStatuses.get_id_by_code(status) do
        acc ++ [user]
      else
        check_and_remove_account(user)
        acc
      end
    end)
  end

  defp accumulating_accounts_with_required_status(duplicates, status)
       when status == "approval_requested" do
    duplicates_account_with_approval_requested = accumulating(duplicates, [status])

    delete_all_and_update_first_one(duplicates_account_with_approval_requested)
  end

  defp accumulating_accounts_with_required_status(duplicates, status) when not is_list(status) do
    duplicates_to_delete = accumulating(duplicates, [status])

    mass_deletion_check(duplicates_to_delete)
  end

  defp accumulating_accounts_with_required_status(duplicates, status) do
    duplicates_to_delete = accumulating(duplicates, status)

    mass_deletion_check(duplicates_to_delete)
  end

  defp iterate_and_remove(duplicates, status)
       when not is_list(status) do
    iterate_and_remove(duplicates, [status])
  end

  defp iterate_and_remove(duplicates, status) do
    Enum.each(duplicates, fn user -&gt;
      if user.user_status_id not in UserStatuses.get_id_by_code(status) do
        check_and_remove_account(user)
      end
    end)
  end

  defp iterate_and_update(duplicates, status) do
    Enum.each(duplicates, fn user -&gt;
      if user.user_status_id ==
           UserStatuses.get_id_by_code(status) do
        Users.update(user, %{email: nil})
      end
    end)
  end

  defp iterate_and_update(duplicates, status_one, status_two) do
    Enum.each(duplicates, fn user -&gt;
      if user.user_status_id !==
           UserStatuses.get_id_by_code(status_one) do
        check_and_remove_account(user)
      else
        Users.update(user, %{
          user_status_id: UserStatuses.get_id_by_code(status_two)
        })
      end
    end)
  end

  defp deleting_with_approached_and_approved_case(duplicates) do
    duplicates_approved_and_approached =
      Enum.reduce(duplicates, [], fn user, acc -&gt;
        if user.user_status_id !== UserStatuses.get_id_by_code("approved") and
             user.user_status_id !==
               UserStatuses.get_id_by_code("approached") do
          check_and_remove_account(user)
          acc
        else
          acc ++ [user]
        end
      end)

    handle_from_approved =
      get_handle_for_user(Enum.at(duplicates_approved_and_approached, 0).id)

    handle_from_approached =
      get_handle_for_user(Enum.at(duplicates_approved_and_approached, 1).id)

    case {handle_from_approved, handle_from_approached} do
      {handle_from_approved, handle_from_approached}
      when handle_from_approved == handle_from_approached and not is_nil(handle_from_approved) and
             not is_nil(handle_from_approached) -&gt;
        iterate_and_remove(
          duplicates_approved_and_approached,
          "approached"
        )

      _ -&gt;
        iterate_and_update(
          duplicates_approved_and_approached,
          "approached"
        )
    end
  end

  defp delete_all_and_update_first_one(duplicates) do
    [user_to_update | duplicates_to_delete] = duplicates
    Enum.each(duplicates_to_delete, fn user -&gt; check_and_remove_account(user) end)

    Users.update(user_to_update, %{
      user_status_id: UserStatuses.get_id_by_code("approved")
    })
  end

  defp count_duplicates_statuses(duplicates) do
    approved_count = count_with_status(duplicates, "approved")

    invalid_count =
      count_with_status(duplicates, [
        "invalid",
        "under_investigation",
        "suspended"
      ])

    approached_count = count_with_status(duplicates, "approached")

    rejected_count = count_with_status(duplicates, "rejected")

    external_count = count_with_status(duplicates, "external")

    approval_requested_count = count_with_status(duplicates, "approval_requested")

    {approved_count, invalid_count, approached_count, rejected_count, external_count,
     approval_requested_count}
  end

  defp comparing_statuses(duplicates) do
    statuses = count_duplicates_statuses(duplicates)
    handle_statuses(statuses, duplicates)
  end

  defp handle_statuses({1, _, 0, _, _, _}, duplicates) do
    iterate_and_remove(duplicates, "approved")
  end

  defp handle_statuses({1, _, 1, _, _, _}, duplicates) do
    deleting_with_approached_and_approved_case(duplicates)
  end

  defp handle_statuses(
         {approved_count, _, 0, _, _, _},
         duplicates
       )
       when approved_count &gt;= 2 do
    accumulating_accounts_with_required_status(duplicates, "approved")
  end

  defp handle_statuses({0, 1, _, _, _, _}, duplicates) do
    iterate_and_remove(duplicates, [
      "invalid",
      "under_investigation",
      "suspended"
    ])
  end

  defp handle_statuses({0, invalid_count, _, _, _, _}, duplicates) when invalid_count &gt;= 2 do
    accumulating_accounts_with_required_status(duplicates, [
      "invalid",
      "under_investigation",
      "suspended"
    ])
  end

  defp handle_statuses({0, 0, 1, _, _, 0}, duplicates) do
    iterate_and_remove(duplicates, "approached")
  end

  defp handle_statuses({0, 0, 1, _, _, 1}, duplicates) do
    iterate_and_update(
      duplicates,
      "approval_requested",
      "approved"
    )
  end

  defp handle_statuses({0, 0, approached_count, _, _, approval_requested_count}, duplicates)
       when approached_count &gt;= 2 and approval_requested_count &gt;= 2 do
    accumulating_accounts_with_required_status(duplicates, "approval_requested")
  end

  defp handle_statuses({0, 0, approached_count, _, _, 0}, duplicates)
       when approached_count &gt;= 2 do
    iterate_and_remove(duplicates, "approached")

    handle_or_email_deletion_check(duplicates)
  end

  defp handle_statuses({0, 0, 0, 1, _, _}, duplicates) do
    iterate_and_remove(duplicates, "rejected")
  end

  defp handle_statuses({0, 0, 0, rejected_count, _, _}, duplicates) when rejected_count &gt;= 2 do
    accumulating_accounts_with_required_status(duplicates, "rejected")
  end

  defp handle_statuses({0, 0, 0, 0, 1, _}, duplicates) do
    iterate_and_remove(duplicates, "external")
  end

  defp handle_statuses({0, 0, 0, 0, external_count, _}, duplicates) when external_count &gt;= 2 do
    accumulating_accounts_with_required_status(duplicates, "external")
  end

  defp handle_statuses({0, 0, 0, 0, 0, approval_requested_count}, duplicates)
       when approval_requested_count &gt;= 2 do
    mass_deletion_check(duplicates)
  end
end
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="253602" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/delete-the-1st-pair-in-a-map/48389/62">Post #61</a>
	                </div>
	            </div>
              <div id="likers-container-253602" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="253602"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-last-post cat-last-post" title="Last post!"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <span class="all-loaded">— All posts loaded —</span>
</div></template></turbo-stream>