defmodule Plaid.AssetReport do
@moduledoc """
[Plaid Asset Reports API](https://plaid.com/docs/api/products/#assets) calls and schema.
"""
alias Plaid.AssetReport.User
alias Plaid.Castable
defmodule AsyncResponse do
@moduledoc """
Plaid Asset Report schema used when generating asset reports.
Async because it only returns a token, the actual asset-report needs to
be fetched after the proper webhook is received. [See docs.](https://plaid.com/docs/api/products/#asset_reportcreate)
"""
@behaviour Castable
@type t :: %__MODULE__{
asset_report_token: String.t(),
asset_report_id: String.t(),
request_id: String.t()
}
defstruct [
:asset_report_token,
:asset_report_id,
:request_id
]
@impl true
def cast(generic_map) do
%__MODULE__{
asset_report_token: generic_map["asset_report_token"],
asset_report_id: generic_map["asset_report_id"],
request_id: generic_map["request_id"]
}
end
end
@doc """
Create an Asset Report.
Does a `POST /asset_report/create` call to initiate the process of
creating an asset report.
Params:
* `access_tokens` - List of tokens coresponding to the items that will be included in the report.
* `days_requested` - The days of history to include in the asset report.
Options:
* `:client_report_id` - Client-generated identifier, which can be used by lenders to track loan applications.
* `:webhook` - URL Plaid will use to send webhooks for when the asset report is ready.
* `:user` - Information about the user to be appended to the asset report. See `Plaid.AssetReport.User` for available fields.
## Examples
AssetReport.create(["access-sandbox-123xxx"], 3, client_id: "123", secret: "abc")
{:ok, %AssetReport.AsyncResponse{}}
"""
@spec create([String.t()], non_neg_integer(), options, Plaid.config()) ::
{:ok, AsyncResponse.t()} | {:error, Plaid.Error.t()}
when options: %{
optional(:client_report_id) => String.t(),
optional(:webhook) => String.t(),
optional(:user) => User.t()
}
def create(access_tokens, days_requested, options \\ %{}, config) do
options_payload = Map.take(options, [:client_report_id, :webhook, :user])
payload =
%{}
|> Map.put(:access_tokens, access_tokens)
|> Map.put(:days_requested, days_requested)
|> Map.put(:options, options_payload)
Plaid.Client.call("/asset_report/create", payload, AsyncResponse, config)
end
defmodule GetResponse do
@moduledoc """
[Plaid API /asset_report/get response schema](https://plaid.com/docs/api/products/#asset_reportget)
"""
@behaviour Castable
alias Plaid.AssetReport.{Report, Warning}
@type t :: %__MODULE__{
report: Report.t(),
warnings: [Warning.t()],
request_id: String.t()
}
defstruct [
:report,
:warnings,
:request_id
]
@impl true
def cast(generic_map) do
%__MODULE__{
report: Castable.cast(Report, generic_map["report"]),
warnings: Castable.cast_list(Warning, generic_map["warnings"]),
request_id: generic_map["request_id"]
}
end
end
@doc """
Get an asset report.
Does a `POST /asset_report/get` call to fetch an asset report.
Params:
* `asset_report_token` - The asset report token from the `create_report` response.
Options:
* `:include_insights` - Whether we should retrieve the report as an "Assets + Insights" report.
## Examples
AssetReport.get("asset-prod-123xxx", client_id: "123", secret: "abc")
{:ok, %AssetReport.GetResponse{}}
"""
@spec get(String.t(), options, Plaid.config()) ::
{:ok, GetResponse.t()} | {:error, Plaid.Error.t()}
when options: %{optional(:include_insights) => boolean()}
def get(asset_report_token, options \\ %{}, config) do
payload =
options
|> Map.take([:include_insights])
|> Map.put(:asset_report_token, asset_report_token)
Plaid.Client.call("/asset_report/get", payload, GetResponse, config)
end
@doc """
Get an asset report as a PDF.
Does a `POST /asset_report/pdf/get` call to fetch an asset report as a PDF.
Params:
* `asset_report_token` - The asset report token from the `create_report` response.
## Examples
AssetReport.get_pdf("asset-prod-123xxx", client_id: "123", secret: "abc")
{:ok, <<0, 1, 2, 3>>}
"""
@spec get_pdf(String.t(), Plaid.config()) :: {:ok, bitstring()} | {:error, Plaid.Error.t()}
def get_pdf(asset_report_token, config) do
Plaid.Client.call(
"/asset_report/pdf/get",
%{asset_report_token: asset_report_token},
:raw,
config
)
end
@doc """
Create a new, refreshed Asset Report.
Does a `POST /asset_report/refresh` call to initiate the process of
creating a new asset report with refreshed data, based off of a previous one.
Params:
* `asset_report_token` - The token for the asset report you want to refresh.
Options:
* `:client_report_id` - Client-generated identifier, which can be used by lenders to track loan applications.
* `:days_requested` - The days of history to include in the asset report.
* `:webhook` - URL Plaid will use to send webhooks for when the asset report is ready.
* `:user` - Information about the user to be appended to the asset report. See `Plaid.AssetReport.User` for available fields.
Each option above acts as an "override" of the original values passed to `create/4`.
Meaning when not specified, values from the original `create/4` request will be used.
## Examples
AssetReport.refresh("assets-sandbox-123xxx", client_id: "123", secret: "abc")
{:ok, %AssetReport.AsyncResponse{}}
"""
@spec refresh(String.t(), options, Plaid.config()) ::
{:ok, AsyncResponse.t()} | {:error, Plaid.Error.t()}
when options: %{
optional(:client_report_id) => String.t(),
optional(:days_requested) => non_neg_integer(),
optional(:webhook) => String.t(),
optional(:user) => User.t()
}
def refresh(asset_report_token, options \\ %{}, config) do
options_payload = Map.take(options, [:client_report_id, :webhook, :user])
payload =
%{}
|> Plaid.Util.maybe_put(:days_requested, options)
|> Map.put(:asset_report_token, asset_report_token)
|> Map.put(:options, options_payload)
Plaid.Client.call("/asset_report/refresh", payload, AsyncResponse, config)
end
@doc """
Create a new, filtered Asset Report.
Does a `POST /asset_report/filter` call to initiate the process of
creating a new asset report with filtered accounts, based off of a previous one.
Params:
* `asset_report_token` - The token for the asset report you want to refresh.
* `account_ids_to_exclude` - The accounts to exclude from the original Asset Report.
## Examples
AssetReport.filter("assets-sandbox-123xxx", ["123xxx"], client_id: "123", secret: "abc")
{:ok, %AssetReport.AsyncResponse{}}
"""
@spec filter(String.t(), [String.t()], Plaid.config()) ::
{:ok, AsyncResponse.t()} | {:error, Plaid.Error.t()}
def filter(asset_report_token, account_ids_to_exclude, config) do
Plaid.Client.call(
"/asset_report/filter",
%{
asset_report_token: asset_report_token,
account_ids_to_exclude: account_ids_to_exclude
},
AsyncResponse,
config
)
end
defmodule RemoveResponse do
@moduledoc """
[Plaid /asset_report/remove response schema.](https://plaid.com/docs/api/products/#asset_reportremove)
"""
@behaviour Castable
@type t :: %__MODULE__{
removed: boolean(),
request_id: String.t()
}
defstruct [
:removed,
:request_id
]
@impl true
def cast(generic_map) do
%__MODULE__{
removed: generic_map["removed"],
request_id: generic_map["request_id"]
}
end
end
@doc """
Remove an Asset Report.
Does a `POST /asset_report/remove` call to remove an asset report and
invalidate its `asset_report_token`.
Params:
* `asset_report_token` - The token for the asset report you want to remove.
## Examples
AssetReport.remove("assets-sandbox-123xxx", client_id: "123", secret: "abc")
{:ok, %AssetReport.RemoveResponse{}}
"""
@spec remove(String.t(), Plaid.config()) ::
{:ok, RemoveResponse.t()} | {:error, Plaid.Error.t()}
def remove(asset_report_token, config) do
Plaid.Client.call(
"/asset_report/remove",
%{asset_report_token: asset_report_token},
RemoveResponse,
config
)
end
defmodule CreateAuditCopyResponse do
@moduledoc """
[Plaid /asset_report/audit_copy/create response schema](https://plaid.com/docs/api/products/#asset_reportaudit_copycreate)
"""
@behaviour Castable
@type t :: %__MODULE__{
audit_copy_token: String.t(),
request_id: String.t()
}
defstruct [
:audit_copy_token,
:request_id
]
@impl true
def cast(generic_map) do
%__MODULE__{
audit_copy_token: generic_map["audit_copy_token"],
request_id: generic_map["request_id"]
}
end
end
@doc """
Create an audit copy token.
Does a `POST /asset_report/audit_copy/create` call to create an audit copy token
which can be sent to participating auditors.
Params:
* `asset_report_token` - The token for which you want to create an audit copy.
* `auditor_id` - The auditor_id of the third party with whom you would like to share the Asset Report.
## Examples
AssetReport.create_audit_copy("assets-sandbox-123xxx", "fannie_mae", client_id: "123", secret: "abc")
{:ok, %AssetReport.CreateAuditCopyResponse{}}
"""
@spec create_audit_copy(String.t(), String.t(), Plaid.config()) ::
{:ok, CreateAuditCopyResponse.t()} | {:error, Plaid.Error.t()}
def create_audit_copy(asset_report_token, auditor_id, config) do
Plaid.Client.call(
"/asset_report/audit_copy/create",
%{asset_report_token: asset_report_token, auditor_id: auditor_id},
CreateAuditCopyResponse,
config
)
end
defmodule RemoveAuditCopyResponse do
@moduledoc """
[Plaid /asset_report/audit_copy/remove response schema.](https://plaid.com/docs/api/products/#asset_reportaudit_copyremove)
"""
@behaviour Castable
@type t :: %__MODULE__{
removed: boolean(),
request_id: String.t()
}
defstruct [
:removed,
:request_id
]
@impl true
def cast(generic_map) do
%__MODULE__{
removed: generic_map["removed"],
request_id: generic_map["request_id"]
}
end
end
@doc """
Remove an Asset Report Audit Copy.
Does a `POST /asset_report/audit_copy/remove` call to remove an audit copy and
invalidate its `audit_copy_token`.
Params:
* `audit_copy_token` - The token for the asset report audit copy you want to remove.
## Examples
AssetReport.remove_audit_copy("a-sandbox-123xxx", client_id: "123", secret: "abc")
{:ok, %AssetReport.RemoveAuditCopyResponse{}}
"""
@spec remove_audit_copy(String.t(), Plaid.config()) ::
{:ok, RemoveAuditCopyResponse.t()} | {:error, Plaid.Error.t()}
def remove_audit_copy(audit_copy_token, config) do
Plaid.Client.call(
"/asset_report/audit_copy/remove",
%{audit_copy_token: audit_copy_token},
RemoveAuditCopyResponse,
config
)
end
end