defmodule StarkBank.BrcodePayment do alias StarkBank.Utils.Rest alias StarkBank.Utils.Check alias StarkBank.BrcodePayment alias StarkBank.User.Project alias StarkBank.User.Organization alias StarkBank.Error @moduledoc """ Groups BrcodePayment related functions """ @doc """ When you initialize a BrcodePayment, the entity will not be automatically created in the Stark Bank API. The 'create' function sends the structs to the Stark Bank API and returns the list of created structs. ## Parameters (required): - `:brcode` [string]: String loaded directly from the QRCode or copied from the invoice. ex: "00020126580014br.gov.bcb.pix0136a629532e-7693-4846-852d-1bbff817b5a8520400005303986540510.005802BR5908T'Challa6009Sao Paulo62090505123456304B14A" - `:tax_id` [string]: receiver tax ID (CPF or CNPJ) with or without formatting. ex: "01234567890" or "20.018.183/0001-80" - `:description` [string]: Text to be displayed in your statement (min. 10 characters). ex: "payment ABC" ## Parameters (conditionally required): - `:amount` [int, default nil]: If the BR Code does not provide an amount, this parameter is mandatory, else it is optional. ex: 23456 (= R$ 234.56) ## Parameters (optional): - `:scheduled` [Date, DateTime or string, default now]: payment scheduled date or datetime. ex: "2020-12-13T18:36:18.219000+00:00" - `:tags` [list of strings]: list of strings for tagging. ## Attributes (return-only): - `:id` [string, default nil]: unique id returned when payment is created. ex: "5656565656565656" - `:name` [string, default nil]: receiver name. ex: "Jon Snow" - `:status` [string, default nil]: current payment status. ex: "success" or "failed" - `:type` [string, default nil]: brcode type. ex: "static" or "dynamic" - `:fee` [integer, default nil]: fee charged when a brcode payment is created. ex: 200 (= R$ 2.00) - `:created` [DateTime, default nil]: creation datetime for the payment. ex: ~U[2020-03-26 19:32:35.418698Z] - `:updated` [DateTime, default nil]: latest update datetime for the Deposit. ex: ~U[2020-08-20 19:32:35.418698Z] """ @enforce_keys [:brcode, :tax_id, :description] defstruct [ :brcode, :tax_id, :description, :amount, :scheduled, :tags, :id, :name, :status, :type, :fee, :created, :updated ] @type t() :: %__MODULE__{} @doc """ Send a list of BrcodePayment structs for creation in the Stark Bank API ## Parameters (required): - `payments` [list of BrcodePayment structs]: list of BrcodePayment structs to be created in the API ## Options: - `:user` [Organization/Project]: Organization or Project struct returned from StarkBank.project(). Only necessary if default project or organization has not been set in configs. ## Return: - list of BrcodePayment structs with updated attributes """ @spec create([BrcodePayment.t() | map()], user: Project.t() | Organization.t() | nil) :: {:ok, [BrcodePayment.t()]} | {:error, [Error.t()]} def create(payments, options \\ []) do Rest.post( resource(), payments, options ) end @doc """ Same as create(), but it will unwrap the error tuple and raise in case of errors. """ @spec create!([BrcodePayment.t() | map()], user: Project.t() | Organization.t() | nil) :: any def create!(payments, options \\ []) do Rest.post!( resource(), payments, options ) end @doc """ Receive a single BrcodePayment struct previously created by the Stark Bank API by passing its id ## Parameters (required): - `id` [string]: struct unique id. ex: "5656565656565656" ## Options: - `:user` [Organization/Project]: Organization or Project struct returned from StarkBank.project(). Only necessary if default project or organization has not been set in configs. ## Return: - BrcodePayment struct with updated attributes """ @spec get(binary, user: Project.t() | Organization.t() | nil) :: {:ok, BrcodePayment.t()} | {:error, [%Error{}]} def get(id, options \\ []) do Rest.get_id(resource(), id, options) end @doc """ Same as get(), but it will unwrap the error tuple and raise in case of errors. """ @spec get!(binary, user: Project.t() | Organization.t() | nil) :: BrcodePayment.t() def get!(id, options \\ []) do Rest.get_id!(resource(), id, options) end @doc """ Receive a single BrcodePayment pdf file generated in the Stark Bank API by passing its id. ## Parameters (required): - `id` [string]: struct unique id. ex: "5656565656565656" ## Options: - `:user` [Organization/Project]: Organization or Project struct returned from StarkBank.project(). Only necessary if default project or organization has not been set in configs. ## Return: - BrcodePayment pdf file content """ @spec pdf(binary, user: Project.t() | Organization.t() | nil) :: {:ok, binary} | {:error, [%Error{}]} def pdf(id, options \\ []) do Rest.get_pdf(resource(), id, options |> Keyword.delete(:user), options[:user]) end @doc """ Same as pdf(), but it will unwrap the error tuple and raise in case of errors. """ @spec pdf!(binary, user: Project.t() | Organization.t() | nil) :: binary def pdf!(id, options \\ []) do Rest.get_pdf!(resource(), id, options |> Keyword.delete(:user), options[:user]) end @doc """ Receive a stream of BrcodePayment structs previously created in the Stark Bank API ## Options: - `:limit` [integer, default nil]: maximum number of structs to be retrieved. Unlimited if nil. ex: 35 - `:after` [Date or string, default nil]: date filter for structs created only after specified date. ex: ~D[2020-03-25] - `:before` [Date or string, default nil]: date filter for structs created only before specified date. ex: ~D[2020-03-25] - `:tags` [list of strings, default nil]: tags to filter retrieved structs. ex: ["tony", "stark"] - `:ids` [list of strings, default nil]: list of ids to filter retrieved objects. ex: ["5656565656565656", "4545454545454545"] - `:status` [string, default nil]: filter for status of retrieved structs. ex: "paid" - `:user` [Organization/Project]: Organization or Project struct returned from StarkBank.project(). Only necessary if default project or organization has not been set in configs. ## Return: - stream of BrcodePayment structs with updated attributes """ @spec query( limit: integer, after: Date.t() | binary, before: Date.t() | binary, tags: [binary], ids: [binary], status: binary, user: Project.t() | Organization.t() ) :: ({:cont, {:ok, [BrcodePayment.t()]}} | {:error, [Error.t()]} | {:halt, any} | {:suspend, any}, any -> any) def query(options \\ []) do Rest.get_list(resource(), options) end @doc """ Same as query(), but it will unwrap the error tuple and raise in case of errors. """ @spec query!( limit: integer, after: Date.t() | binary, before: Date.t() | binary, tags: [binary], ids: [binary], status: binary, user: Project.t() | Organization.t() ) :: ({:cont, [BrcodePayment.t()]} | {:halt, any} | {:suspend, any}, any -> any) def query!(options \\ []) do Rest.get_list!(resource(), options) end @doc """ Update an BrcodePayment by passing id, if it hasn't been paid yet. ## Parameters (required): - `:id` [string]: BrcodePayment id. ex: '5656565656565656' ## Parameters (optional): - `:status` [string]: You may cancel the BrcodePayment by passing "canceled" in the status - `:user` [Organization/Project]: Organization or Project struct returned from StarkBank.project(). Only necessary if default project or organization has not been set in configs. ## Return: - target BrcodePayment with updated attributes """ @spec update(binary, status: binary, user: Project.t() | Organization.t() | nil) :: {:ok, BrcodePayment.t()} | {:error, [%Error{}]} def update(id, parameters \\ []) do Rest.patch_id(resource(), id, parameters |> Enum.into(%{})) end @doc """ Same as update(), but it will unwrap the error tuple and raise in case of errors. """ @spec update!(binary, status: binary, user: Project.t() | Organization.t() | nil) :: BrcodePayment.t() def update!(id, parameters \\ []) do Rest.patch_id!(resource(), id, parameters |> Enum.into(%{})) end @doc false def resource() do { "BrcodePayment", &resource_maker/1 } end @doc false def resource_maker(json) do %BrcodePayment{ brcode: json[:brcode], tax_id: json[:tax_id], description: json[:description], amount: json[:amount], scheduled: json[:scheduled] |> Check.datetime(), tags: json[:tags], id: json[:id], name: json[:name], status: json[:status], type: json[:type], fee: json[:fee], created: json[:created] |> Check.datetime(), updated: json[:updated] |> Check.datetime() } end end