defmodule DaProductApp.BatchNumber do use Ecto.Schema import Ecto.Changeset import Ecto.Query @primary_key {:id, :id, autogenerate: true} schema "batch_numbers" do field :merchant_id, :string field :batch_number, :string field :date, :date field :transaction_count, :integer, default: 0 field :last_used_at, :utc_datetime timestamps() end @doc false def changeset(batch_number, attrs) do batch_number |> cast(attrs, [:merchant_id, :batch_number, :date, :transaction_count, :last_used_at]) |> validate_required([:merchant_id, :batch_number, :date]) |> unique_constraint([:merchant_id, :date], name: :unique_merchant_date) end @doc """ Gets or creates a batch number for a merchant on a specific date. Returns a 6-digit zero-padded batch number string. """ def get_or_create_batch_number(merchant_id, date \\ Date.utc_today()) do case DaProductApp.Repo.get_by(__MODULE__, merchant_id: merchant_id, date: date) do nil -> # Create new batch number starting with 000001 batch_number = "000001" attrs = %{ merchant_id: merchant_id, batch_number: batch_number, date: date, transaction_count: 1, last_used_at: DateTime.utc_now() } case DaProductApp.Repo.insert(changeset(%__MODULE__{}, attrs)) do {:ok, batch_record} -> {:ok, batch_record.batch_number} {:error, _changeset} -> # Handle race condition - try to get existing record case DaProductApp.Repo.get_by(__MODULE__, merchant_id: merchant_id, date: date) do nil -> {:error, "Failed to create batch number"} existing -> increment_batch_number(existing) end end existing_batch -> increment_batch_number(existing_batch) end end defp increment_batch_number(batch_record) do new_count = batch_record.transaction_count + 1 new_batch_number = String.pad_leading("#{new_count}", 6, "0") changeset = changeset(batch_record, %{ batch_number: new_batch_number, transaction_count: new_count, last_used_at: DateTime.utc_now() }) case DaProductApp.Repo.update(changeset) do {:ok, updated_batch} -> {:ok, updated_batch.batch_number} {:error, _changeset} -> {:error, "Failed to update batch number"} end end end