| 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 |