# filepath: lib/da_product_app/transactions/transaction.ex defmodule DaProductApp.Transactions.Transaction do use Ecto.Schema import Ecto.Changeset import Ecto.Query, only: [from: 2] @primary_key {:id, :id, autogenerate: true} schema "transactions" do field :patient_name, :string field :uhid, :string field :charge_rate, :decimal field :email, :string field :mobile_no, :string field :processing_id, :string field :uname, :string field :user_id, :string field :pay_mode, :string field :location_id, :string field :transaction_location, :string field :credentials_user, :string field :credentials_key, :string field :version, :string field :return_url, :string field :response_url, :string field :status, :string field :transaction_id, :string field :transaction_amount, :decimal field :transaction_ref_number, :string field :m_ref_num, :string field :name, :string field :provider_id, :integer field :device_id, :string field :merchant_id, :string field :additional_data, :map field :payment_reference_id, :string field :refund_reference_id, :string field :provider_name, :string field :payload, :map field :settlement_date_time, :utc_datetime field :batch_number, :string field :bank_user_id, :string field :merchant_tag, :string field :settlement_id, :string field :settlement_status, :string, default: "unmatched" field :ysp_tid, :string has_many :operations, DaProductApp.Transactions.TransactionOperation timestamps() end @doc false def changeset(transaction, attrs) do transaction |> cast(attrs, [ :patient_name, :uhid, :charge_rate, :email, :mobile_no, :processing_id, :uname, :user_id, :pay_mode, :location_id, :transaction_location, :credentials_user, :credentials_key, :version, :return_url, :response_url, :status, :transaction_id, :transaction_amount, :transaction_ref_number, :m_ref_num, :name, :provider_id, :device_id, :merchant_id, :additional_data, :payment_reference_id, :refund_reference_id, :provider_name, :payload, :settlement_date_time, :batch_number, :bank_user_id, :merchant_tag, :settlement_id, :settlement_status, :ysp_tid ]) |> maybe_set_default_email() |> maybe_set_user_id() |> validate_required([:status]) end # If email is blank, generate a default value. defp maybe_set_default_email(changeset) do if get_field(changeset, :email) in [nil, ""] do default_email = "ch_" <> (:crypto.strong_rand_bytes(6) |> Base.encode16(case: :lower)) <> "@momentpay.in" put_change(changeset, :email, default_email) else changeset end end # Set user_id from uname; if uname is missing then default to "1". defp maybe_set_user_id(changeset) do case get_field(changeset, :uname) do nil -> put_change(changeset, :user_id, "1") "" -> put_change(changeset, :user_id, "1") username -> put_change(changeset, :user_id, username) end end def get_transaction_by_processing_id(nil), do: nil def get_transaction_by_processing_id(processing_id) when is_binary(processing_id) do from(t in __MODULE__, where: t.processing_id == ^processing_id) |> DaProductApp.Repo.one() end def create_transaction(attrs \\ %{}) do result = %__MODULE__{} |> changeset(attrs) |> DaProductApp.Repo.insert() # Trigger risk evaluation for new transactions case result do {:ok, transaction} -> RiskCore.Workers.TransactionRiskEvaluator.enqueue_evaluation(transaction.id, "QR") {:ok, transaction} error -> error end end @doc """ Gets pending transactions for a specific device_id """ def get_pending_transactions_by_device(device_id) when is_binary(device_id) do from(t in __MODULE__, where: t.device_id == ^device_id and t.status in ["pending", "QR_GENERATED"] ) |> DaProductApp.Repo.all() end @doc """ Gets the latest transaction for a specific device_id """ def get_latest_transaction_by_device(device_id) when is_binary(device_id) do from(t in __MODULE__, where: t.device_id == ^device_id, order_by: [desc: t.inserted_at], limit: 1 ) |> DaProductApp.Repo.one() end end