cover/Elixir.DaProductApp.Partners.Partner.html

1 defmodule DaProductApp.Partners.Partner do
2 @moduledoc """
3 Partner schema representing merchant acquirers/aggregators.
4
5 Partners are entities that:
6 - Enroll merchants under them
7 - Generate QR codes for merchants
8 - Handle merchant settlements
9 - Provide merchant services
10 """
11 use Ecto.Schema
12 import Ecto.Changeset
13
14 @primary_key {:id, :binary_id, autogenerate: true}
15 @foreign_key_type :binary_id
16
17
:-(
schema "partners" do
18 field :partner_code, :string # Unique partner identifier (e.g., "RAZORPAY", "PAYU")
19 field :partner_name, :string # Display name (e.g., "Razorpay Business")
20 field :partner_type, :string # "AGGREGATOR", "ACQUIRER", "PROCESSOR"
21 field :api_endpoint, :string # Partner's API base URL
22 field :api_key, :string # Partner API key for PSP authentication (new)
23 field :api_secret, :string # Partner API secret (encrypted)
24 field :webhook_url, :string # Partner's webhook for callbacks
25 field :webhook_secret, :string # Webhook signature verification
26 field :settlement_account, :string # Partner's settlement account details
27 field :commission_rate, :decimal # Commission % charged by partner
28 field :status, :string, default: "ACTIVE" # "ACTIVE", "SUSPENDED", "INACTIVE"
29 field :contact_email, :string
30 field :contact_phone, :string
31 field :corridor, :string # International corridor: "SINGAPORE", "UAE", "USA", "DOMESTIC"
32 field :base_currency, :string # Partner's base currency: "SGD", "AED", "USD", "INR"
33 field :ip_whitelist, :string # JSON array of allowed IPs
34 field :rate_limit_per_minute, :integer, default: 100
35 field :last_used_at, :utc_datetime
36 field :api_key_expires_at, :utc_datetime
37 field :onboarded_at, :utc_datetime
38 field :last_reconciled_at, :utc_datetime
39
40 has_many :merchants, DaProductApp.Partners.Merchant
41 has_many :transactions, DaProductApp.Transactions.Transaction
42
43 timestamps(type: :utc_datetime)
44 end
45
46 def changeset(partner, attrs) do
47 partner
48 |> cast(attrs, [
49 :partner_code, :partner_name, :partner_type, :api_endpoint,
50 :api_key, :api_secret, :webhook_url, :webhook_secret, :settlement_account,
51 :commission_rate, :status, :contact_email, :contact_phone,
52 :corridor, :base_currency, :ip_whitelist, :rate_limit_per_minute,
53 :last_used_at, :api_key_expires_at, :onboarded_at, :last_reconciled_at
54 ])
55 |> validate_required([:partner_code, :partner_name, :partner_type])
56 |> validate_inclusion(:partner_type, ["AGGREGATOR", "ACQUIRER", "PROCESSOR"])
57 |> validate_inclusion(:status, ["ACTIVE", "SUSPENDED", "INACTIVE"])
58 |> validate_inclusion(:corridor, ["SINGAPORE", "UAE", "USA", "DOMESTIC"])
59 |> validate_inclusion(:base_currency, ["SGD", "AED", "USD", "INR"])
60 |> validate_format(:contact_email, ~r/@/)
61 |> validate_number(:rate_limit_per_minute, greater_than: 0, less_than: 10000)
62 |> unique_constraint(:partner_code)
63
:-(
|> unique_constraint(:api_key)
64 end
65
66 @doc """
67 Changeset for API key generation/rotation
68 """
69 def api_key_changeset(partner, attrs) do
70 partner
71 |> cast(attrs, [:api_key, :api_secret, :api_key_expires_at, :status])
72 |> validate_required([:api_key, :api_secret])
73
:-(
|> unique_constraint(:api_key)
74 end
75 end
Line Hits Source