defmodule Yousign.API.Documents do
import Yousign.Request
alias Yousign.Document
alias Multipart.Part
alias Yousign.DocumentInput
@doc """
Gets a single document by its id
## Examples
iex> Yousign.API.Documents.get("123")
{:ok, %{"data" => %{"id" => "123", "name" => "test"}}}
iex> Yousign.API.Documents.get("invalid")
{:error, 404}
"""
@spec get(String.t(), String.t()) :: {:error, any()} | {:ok, any()}
def get(signature_request_id, id) do
make_request(:get, "signature_requests/#{signature_request_id}/documents/#{id}")
end
@doc """
List all documents in a signature request
## Examples
iex> Yousign.API.Documents.list("123")
{:ok, %{"data" => [], "meta" => %{"pagination" => %{"total" => 0}}}}
iex> Yousign.API.Documents.list("123")
{:ok, %{"data" => [%{"id" => "123", "name" => "test"}], "meta" => %{"pagination" => %{"total" => 1}}}}
"""
@spec list(String.t()) :: {:error, any()} | {:ok, any()}
def list(signature_request_id) do
make_request(:get, "signature_requests/#{signature_request_id}/documents")
end
@doc """
Creates a new document
"""
@spec create(%DocumentInput{}, String.t() | boolean()) :: {:error, any()} | {:ok, %Document{}}
def create(body, filename \\ true) do
{:ok, path} = base64_to_file(body.file)
body =
Multipart.new()
|> Multipart.add_part(Part.text_field(Atom.to_string(Map.get(body, :nature, nil)), :nature))
|> Multipart.add_part(
Part.text_field(to_string(Map.get(body, :parse_anchors, false)), :parse_anchors)
)
|> Multipart.add_part(Part.file_field(path, :file, filename: filename))
case make_multipart_request(:post, "documents", body, 201) do
{:ok, data} ->
File.rm!(path)
{:ok, data}
{:error, error} ->
File.rm!(path)
{:error, error}
end
end
@doc """
Creates a new document and adds it to the given signature request
"""
@spec add_to_signature_request(String.t(), %DocumentInput{}, String.t() | boolean()) ::
{:error, any()} | {:ok, %Document{}}
def add_to_signature_request(signature_request_id, body, filename \\ true) do
{:ok, path} = base64_to_file(body.file)
body =
Multipart.new()
|> Multipart.add_part(Part.text_field(Atom.to_string(Map.get(body, :nature, nil)), :nature))
|> Multipart.add_part(
Part.text_field(to_string(Map.get(body, :parse_anchors, false)), :parse_anchors)
)
|> Multipart.add_part(Part.file_field(path, :file, filename: filename))
case make_multipart_request(
:post,
"signature_requests/#{signature_request_id}/documents",
body,
201
) do
{:ok, data} ->
File.rm!(path)
{:ok, data}
{:error, error} ->
File.rm!(path)
{:error, error}
end
end
@doc """
Downloads all the documents attached to a signature request
Version Options:
- :completed: downloads the completed version of the documents
- :current: downloads the current version of the documents
Defaults to :current
"""
@spec download(String.t(), atom()) :: {:error, any()} | {:ok, any()}
def download(signature_request_id, version \\ :current)
def download(signature_request_id, :completed) do
make_request(
:get,
"signature_requests/#{signature_request_id}/documents/download?version=completed"
)
end
def download(signature_request_id, :current) do
make_request(
:get,
"signature_requests/#{signature_request_id}/documents/download?version=current"
)
end
@spec base64_to_file(String.t()) :: {:error, any()} | {:ok, String.t()}
defp base64_to_file(encoded_string) do
with {:ok, data} <- Base.decode64(encoded_string),
{:ok, path} <-
Temp.path(prefix: "yousign_ex_temp", suffix: ".pdf"),
{:ok, file} <- File.open(path, [:write, :binary]),
:ok <- IO.binwrite(file, data),
:ok <- File.close(file) do
{:ok, path}
end
end
end