defmodule BexioApiClient.SalesOrderManagement do
@moduledoc """
Bexio API for the sales order management part of the API.
"""
import BexioApiClient.Helpers
alias BexioApiClient.GlobalArguments
alias BexioApiClient.SearchCriteria
alias BexioApiClient.SalesOrderManagement.{
Comment,
Order,
Quote,
PositionSubposition,
PositionPagebreak,
PositionDiscount,
PositionItem,
PositionDefault,
PositionText,
PositionSubtotal
}
import BexioApiClient.GlobalArguments, only: [opts_to_query: 1]
# Quotes
@doc """
This action fetches a list of all quotes.
"""
@spec fetch_quotes(
client :: Tesla.Client.t(),
opts :: [GlobalArguments.offset_arg()]
) :: {:ok, [Quote.t()]} | {:error, any()}
def fetch_quotes(client, opts \\ []) do
bexio_return_handling(
fn ->
Tesla.get(client, "/2.0/kb_offer", query: opts_to_query(opts))
end,
&map_from_quotes/1
)
end
@doc """
Search quotes via query.
The following search fields are supported:
* id
* kb_item_status
* document_nr
* title
* contact_id
* contact_sub_id
* user_id
* currency_id
* total_gross
* total_net
* total
* is_valid_from
* is_valid_until
* is_valid_to (?)
* updated_at
"""
@spec search_quotes(
client :: Tesla.Client.t(),
criteria :: list(SearchCriteria.t()),
opts :: [GlobalArguments.offset_arg()]
) :: {:ok, [Quote.t()]} | {:error, any()}
def search_quotes(
client,
criteria,
opts \\ []
) do
bexio_return_handling(
fn ->
Tesla.post(client, "/2.0/kb_offer/search", criteria, query: opts_to_query(opts))
end,
&map_from_quotes/1
)
end
@doc """
This action fetches a single quote
"""
@spec fetch_quote(
client :: Tesla.Client.t(),
quote_id :: pos_integer()
) :: {:ok, [Quote.t()]} | {:error, any()}
def fetch_quote(client, quote_id) do
bexio_return_handling(
fn ->
Tesla.get(client, "/2.0/kb_offer/#{quote_id}")
end,
&map_from_quote/1
)
end
defp map_from_quotes(quotes), do: Enum.map(quotes, &map_from_quote/1)
defp map_from_quote(%{
"id" => id,
"document_nr" => document_nr,
"title" => title,
"contact_id" => contact_id,
"contact_sub_id" => contact_sub_id,
"user_id" => user_id,
"project_id" => project_id,
"language_id" => language_id,
"bank_account_id" => bank_account_id,
"currency_id" => currency_id,
"payment_type_id" => payment_type_id,
"header" => header,
"footer" => footer,
"total_gross" => total_gross,
"total_net" => total_net,
"total_taxes" => total_taxes,
"total" => total,
"total_rounding_difference" => total_rounding_difference,
"mwst_type" => mwst_type_id,
"mwst_is_net" => mwst_is_net?,
"show_position_taxes" => show_position_taxes?,
"is_valid_from" => is_valid_from,
"is_valid_until" => is_valid_until,
"contact_address" => contact_address,
"delivery_address_type" => delivery_address_type,
"delivery_address" => delivery_address,
"kb_item_status_id" => kb_item_status_id,
"api_reference" => api_reference,
"viewed_by_client_at" => viewed_by_client_at,
"kb_terms_of_payment_template_id" => kb_terms_of_payment_template_id,
"show_total" => show_total?,
"updated_at" => updated_at,
"template_slug" => template_slug,
"taxs" => taxs,
"network_link" => network_link
}) do
%Quote{
id: id,
document_nr: document_nr,
title: title,
contact_id: contact_id,
contact_sub_id: contact_sub_id,
user_id: user_id,
project_id: project_id,
language_id: language_id,
bank_account_id: bank_account_id,
currency_id: currency_id,
payment_type_id: payment_type_id,
header: header,
footer: footer,
total_gross: to_decimal(total_gross),
total_net: to_decimal(total_net),
total_taxes: to_decimal(total_taxes),
total: to_decimal(total),
total_rounding_difference: total_rounding_difference,
mwst_type: mwst_type(mwst_type_id),
mwst_is_net?: mwst_is_net?,
show_position_taxes?: show_position_taxes?,
is_valid_from: to_date(is_valid_from),
is_valid_until: to_date(is_valid_until),
contact_address: contact_address,
delivery_address_type: delivery_address_type,
delivery_address: delivery_address,
kb_item_status: kb_item_status(kb_item_status_id),
api_reference: api_reference,
viewed_by_client_at: to_datetime(viewed_by_client_at),
kb_terms_of_payment_template_id: kb_terms_of_payment_template_id,
show_total?: show_total?,
updated_at: to_datetime(updated_at),
template_slug: template_slug,
taxs: Enum.map(taxs, &to_tax/1),
network_link: network_link
}
end
defp mwst_type(0), do: :including
defp mwst_type(1), do: :excluding
defp mwst_type(2), do: :exempt
defp kb_item_status(1), do: :draft
defp kb_item_status(2), do: :pending
defp kb_item_status(3), do: :confirmed
defp kb_item_status(4), do: :declined
defp kb_item_status_id(:draft), do: 1
defp kb_item_status_id(:pending), do: 2
defp kb_item_status_id(:confirmed), do: 3
defp kb_item_status_id(:declined), do: 4
defp to_tax(%{"percentage" => percentage, "value" => value}),
do: %{percentage: percentage, value: value}
# Orders
@doc """
This action fetches a list of all orders.
"""
@spec fetch_orders(
client :: Tesla.Client.t(),
opts :: [GlobalArguments.offset_arg()]
) :: {:ok, [Order.t()]} | {:error, any()}
def fetch_orders(client, opts \\ []) do
bexio_return_handling(
fn ->
Tesla.get(client, "/2.0/kb_order", query: opts_to_query(opts))
end,
&map_from_orders/1
)
end
@doc """
Search orders via query.
The following search fields are supported:
* id
* kb_item_status
* document_nr
* title
* contact_id
* contact_sub_id
* user_id
* currency_id
* total_gross
* total_net
* total
* is_valid_from
* updated_at
"""
@spec search_orders(
client :: Tesla.Client.t(),
criteria :: list(SearchCriteria.t()),
opts :: [GlobalArguments.offset_arg()]
) :: {:ok, [Order.t()]} | {:error, any()}
def search_orders(
client,
criteria,
opts \\ []
) do
bexio_return_handling(
fn ->
Tesla.post(client, "/2.0/kb_order/search", criteria, query: opts_to_query(opts))
end,
&map_from_orders/1
)
end
@doc """
This action fetches a single order
"""
@spec fetch_order(
client :: Tesla.Client.t(),
order_id :: pos_integer()
) :: {:ok, [Order.t()]} | {:error, any()}
def fetch_order(client, order_id) do
bexio_return_handling(
fn ->
Tesla.get(client, "/2.0/kb_order/#{order_id}")
end,
&map_from_order/1
)
end
defp map_from_orders(orders), do: Enum.map(orders, &map_from_order/1)
defp map_from_order(%{
"id" => id,
"document_nr" => document_nr,
"title" => title,
"contact_id" => contact_id,
"contact_sub_id" => contact_sub_id,
"user_id" => user_id,
"project_id" => project_id,
"language_id" => language_id,
"bank_account_id" => bank_account_id,
"currency_id" => currency_id,
"payment_type_id" => payment_type_id,
"header" => header,
"footer" => footer,
"total_gross" => total_gross,
"total_net" => total_net,
"total_taxes" => total_taxes,
"total" => total,
"total_rounding_difference" => total_rounding_difference,
"mwst_type" => mwst_type_id,
"mwst_is_net" => mwst_is_net?,
"show_position_taxes" => show_position_taxes?,
"is_valid_from" => is_valid_from,
"contact_address" => contact_address,
"delivery_address_type" => delivery_address_type,
"delivery_address" => delivery_address,
"kb_item_status_id" => kb_item_status_id,
"is_recurring" => is_recurring?,
"api_reference" => api_reference,
"viewed_by_client_at" => viewed_by_client_at,
"updated_at" => updated_at,
"template_slug" => template_slug,
"taxs" => taxs,
"network_link" => network_link
}) do
%Order{
id: id,
document_nr: document_nr,
title: title,
contact_id: contact_id,
contact_sub_id: contact_sub_id,
user_id: user_id,
project_id: project_id,
language_id: language_id,
bank_account_id: bank_account_id,
currency_id: currency_id,
payment_type_id: payment_type_id,
header: header,
footer: footer,
total_gross: to_decimal(total_gross),
total_net: to_decimal(total_net),
total_taxes: to_decimal(total_taxes),
total: to_decimal(total),
total_rounding_difference: total_rounding_difference,
mwst_type: mwst_type(mwst_type_id),
mwst_is_net?: mwst_is_net?,
show_position_taxes?: show_position_taxes?,
is_valid_from: to_date(is_valid_from),
contact_address: contact_address,
delivery_address_type: delivery_address_type,
delivery_address: delivery_address,
kb_item_status: order_kb_item_status(kb_item_status_id),
api_reference: api_reference,
viewed_by_client_at: to_datetime(viewed_by_client_at),
is_recurring?: is_recurring?,
updated_at: to_datetime(updated_at),
template_slug: template_slug,
taxs: Enum.map(taxs, &to_tax/1),
network_link: network_link
}
end
defp order_kb_item_status(5), do: :pending
defp order_kb_item_status(6), do: :done
defp order_kb_item_status(15), do: :partial
defp order_kb_item_status(21), do: :canceled
defp order_kb_item_status_id(:pending), do: 5
defp order_kb_item_status_id(:done), do: 6
defp order_kb_item_status_id(:partial), do: 15
defp order_kb_item_status_id(:canceled), do: 21
# Comments
@doc """
This action fetches a list of comments.
"""
@spec fetch_comments(
client :: Tesla.Client.t(),
document_type :: :offer | :order | :invoice,
document_id :: pos_integer(),
opts :: [GlobalArguments.offset_without_order_by_arg()]
) :: {:ok, [Comment.t()]} | {:error, any()}
def fetch_comments(
client,
document_type,
document_id,
opts \\ []
) do
bexio_return_handling(
fn ->
Tesla.get(client, "/2.0/kb_#{document_type}/#{document_id}/comment",
query: opts_to_query(opts)
)
end,
&map_from_comments/1
)
end
@doc """
This action fetches a single comment.
"""
@spec fetch_comment(
client :: Tesla.Client.t(),
document_type :: :offer | :order | :invoice,
document_id :: pos_integer(),
comment_id :: pos_integer()
) :: {:ok, [Comment.t()]} | {:error, any()}
def fetch_comment(
client,
document_type,
document_id,
comment_id
) do
bexio_return_handling(
fn ->
Tesla.get(
client,
"/2.0/kb_#{document_type}/#{document_id}/comment/#{comment_id}"
)
end,
&map_from_comment/1
)
end
@doc """
Create a comment
"""
@spec create_comment(
client :: Tesla.Client.t(),
document_type :: :offer | :order | :invoice,
document_id :: pos_integer(),
comment :: Comment.t()
) :: {:ok, [Comment.t()]} | {:error, any()}
def create_comment(
client,
document_type,
document_id,
comment
) do
bexio_return_handling(
fn ->
Tesla.post(
client,
"/2.0/kb_#{document_type}/#{document_id}/comment",
mapped_comment(comment)
)
end,
&map_from_comment/1
)
end
defp mapped_comment(%{
text: text,
user_id: user_id,
user_email: user_email,
user_name: user_name,
public?: public?
}) do
%{
text: text,
user_id: user_id,
user_email: user_email,
user_name: user_name,
is_public: public?
}
end
defp map_from_comments(comments), do: Enum.map(comments, &map_from_comment/1)
defp map_from_comment(%{
"id" => id,
"text" => text,
"user_id" => user_id,
"user_email" => user_email,
"user_name" => user_name,
"date" => date,
"is_public" => public?,
"image" => image,
"image_path" => image_path
}) do
%Comment{
id: id,
text: text,
user_id: user_id,
user_email: user_email,
user_name: user_name,
date: to_datetime(date),
public?: public?,
image: image,
image_path: image_path
}
end
# Subtotal Positions
@doc """
This action fetches a list of all subtotal positions for a document.
"""
@spec fetch_subtotal_positions(
client :: Tesla.Client.t(),
document_type :: :offer | :order | :invoice,
document_id :: pos_integer(),
opts :: [GlobalArguments.offset_without_order_by_arg()]
) :: {:ok, [PositionSubtotal.t()]} | {:error, any()}
def fetch_subtotal_positions(
client,
document_type,
document_id,
opts \\ []
) do
bexio_return_handling(
fn ->
Tesla.get(client, "/2.0/kb_#{document_type}/#{document_id}/kb_position_subtotal",
query: opts_to_query(opts)
)
end,
&map_from_subtotal_positions/1
)
end
@doc """
This action fetches a single subtotal position for a document.
"""
@spec fetch_subtotal_position(
client :: Tesla.Client.t(),
document_type :: :offer | :order | :invoice,
document_id :: pos_integer(),
position_id :: pos_integer()
) :: {:ok, [PositionSubtotal.t()]} | {:error, any()}
def fetch_subtotal_position(
client,
document_type,
document_id,
position_id
) do
bexio_return_handling(
fn ->
Tesla.get(
client,
"/2.0/kb_#{document_type}/#{document_id}/kb_position_subtotal/#{position_id}"
)
end,
&map_from_subtotal_position/1
)
end
defp map_from_subtotal_positions(subtotal_positions),
do: Enum.map(subtotal_positions, &map_from_subtotal_position/1)
defp map_from_subtotal_position(%{
"id" => id,
"text" => text,
"value" => value,
"internal_pos" => internal_pos,
"is_optional" => optional?,
"parent_id" => parent_id
}) do
%PositionSubtotal{
id: id,
text: text,
value: Decimal.new(value),
internal_pos: internal_pos,
optional?: optional?,
parent_id: parent_id
}
end
### Text Position
@doc """
This action fetches a list of all text positions for a document.
"""
@spec fetch_text_positions(
client :: Tesla.Client.t(),
document_type :: :offer | :order | :invoice,
document_id :: pos_integer(),
opts :: [GlobalArguments.offset_without_order_by_arg()]
) :: {:ok, [PositionText.t()]} | {:error, any()}
def fetch_text_positions(
client,
document_type,
document_id,
opts \\ []
) do
bexio_return_handling(
fn ->
Tesla.get(client, "/2.0/kb_#{document_type}/#{document_id}/kb_position_text",
query: opts_to_query(opts)
)
end,
&map_from_text_positions/1
)
end
@doc """
This action fetches a single text position for a document.
"""
@spec fetch_text_position(
client :: Tesla.Client.t(),
document_type :: :offer | :order | :invoice,
document_id :: pos_integer(),
position_id :: pos_integer()
) :: {:ok, [BexioApiClient.SalesOrderManagement.PositionText.t()]} | {:error, any()}
def fetch_text_position(
client,
document_type,
document_id,
position_id
) do
bexio_return_handling(
fn ->
Tesla.get(
client,
"/2.0/kb_#{document_type}/#{document_id}/kb_position_text/#{position_id}"
)
end,
&map_from_text_position/1
)
end
defp map_from_text_positions(text_positions),
do: Enum.map(text_positions, &map_from_text_position/1)
defp map_from_text_position(%{
"id" => id,
"text" => text,
"show_pos_nr" => show_pos_nr,
"pos" => pos,
"internal_pos" => internal_pos,
"is_optional" => optional?,
"parent_id" => parent_id
}) do
%PositionText{
id: id,
text: text,
show_pos_nr: show_pos_nr,
pos: pos,
internal_pos: internal_pos,
optional?: optional?,
parent_id: parent_id
}
end
### Default Position
@doc """
This action fetches a list of all default positions for a document.
"""
@spec fetch_default_positions(
client :: Tesla.Client.t(),
document_type :: :offer | :order | :invoice,
document_id :: pos_integer(),
opts :: [GlobalArguments.offset_without_order_by_arg()]
) :: {:ok, [PositionDefault.t()]} | {:error, any()}
def fetch_default_positions(
client,
document_type,
document_id,
opts \\ []
) do
bexio_return_handling(
fn ->
Tesla.get(client, "/2.0/kb_#{document_type}/#{document_id}/kb_position_custom",
query: opts_to_query(opts)
)
end,
&map_from_default_positions/1
)
end
@doc """
This action fetches a single default position for a document.
"""
@spec fetch_default_position(
client :: Tesla.Client.t(),
document_type :: :offer | :order | :invoice,
document_id :: pos_integer(),
position_id :: pos_integer()
) :: {:ok, [PositionDefault.t()]} | {:error, any()}
def fetch_default_position(
client,
document_type,
document_id,
position_id
) do
bexio_return_handling(
fn ->
Tesla.get(
client,
"/2.0/kb_#{document_type}/#{document_id}/kb_position_custom/#{position_id}"
)
end,
&map_from_default_position/1
)
end
defp map_from_default_positions(default_positions),
do: Enum.map(default_positions, &map_from_default_position/1)
defp map_from_default_position(%{
"id" => id,
"amount" => amount,
"unit_id" => unit_id,
"account_id" => account_id,
"unit_name" => unit_name,
"tax_id" => tax_id,
"tax_value" => tax_value,
"text" => text,
"unit_price" => unit_price,
"discount_in_percent" => discount_in_percent,
"position_total" => position_total,
"pos" => pos,
"internal_pos" => internal_pos,
"is_optional" => optional?,
"parent_id" => parent_id
}) do
%PositionDefault{
id: id,
amount: Decimal.new(amount),
unit_id: unit_id,
account_id: account_id,
unit_name: unit_name,
tax_id: tax_id,
tax_value: Decimal.new(tax_value),
text: text,
unit_price: Decimal.new(unit_price),
discount_in_percent: Decimal.new(discount_in_percent),
position_total: Decimal.new(position_total),
pos: pos,
internal_pos: internal_pos,
optional?: optional?,
parent_id: parent_id
}
end
### Item Position
@doc """
This action fetches a list of all item positions for a document.
"""
@spec fetch_item_positions(
client :: Tesla.Client.t(),
document_type :: :offer | :order | :invoice,
document_id :: pos_integer(),
opts :: [GlobalArguments.offset_without_order_by_arg()]
) :: {:ok, [PositionItem.t()]} | {:error, any()}
def fetch_item_positions(
client,
document_type,
document_id,
opts \\ []
) do
bexio_return_handling(
fn ->
Tesla.get(client, "/2.0/kb_#{document_type}/#{document_id}/kb_position_article",
query: opts_to_query(opts)
)
end,
&map_from_item_positions/1
)
end
@doc """
This action fetches a single item position for a document.
"""
@spec fetch_item_position(
client :: Tesla.Client.t(),
document_type :: :offer | :order | :invoice,
document_id :: pos_integer(),
position_id :: pos_integer()
) :: {:ok, [PositionItem.t()]} | {:error, any()}
def fetch_item_position(
client,
document_type,
document_id,
position_id
) do
bexio_return_handling(
fn ->
Tesla.get(
client,
"/2.0/kb_#{document_type}/#{document_id}/kb_position_article/#{position_id}"
)
end,
&map_from_item_position/1
)
end
defp map_from_item_positions(item_positions),
do: Enum.map(item_positions, &map_from_item_position/1)
defp map_from_item_position(%{
"id" => id,
"amount" => amount,
"unit_id" => unit_id,
"account_id" => account_id,
"unit_name" => unit_name,
"tax_id" => tax_id,
"tax_value" => tax_value,
"text" => text,
"unit_price" => unit_price,
"discount_in_percent" => discount_in_percent,
"position_total" => position_total,
"pos" => pos,
"internal_pos" => internal_pos,
"is_optional" => optional?,
"article_id" => article_id,
"parent_id" => parent_id
}) do
%PositionItem{
id: id,
amount: Decimal.new(amount),
unit_id: unit_id,
account_id: account_id,
unit_name: unit_name,
tax_id: tax_id,
tax_value: Decimal.new(tax_value),
text: text,
unit_price: Decimal.new(unit_price),
discount_in_percent: Decimal.new(discount_in_percent),
position_total: Decimal.new(position_total),
pos: pos,
internal_pos: internal_pos,
optional?: optional?,
article_id: article_id,
parent_id: parent_id
}
end
### Discount Position
@doc """
This action fetches a list of all discount positions for a document.
"""
@spec fetch_discount_positions(
client :: Tesla.Client.t(),
document_type :: :offer | :order | :invoice,
document_id :: pos_integer(),
opts :: [GlobalArguments.offset_without_order_by_arg()]
) :: {:ok, [PositionDiscount.t()]} | {:error, any()}
def fetch_discount_positions(
client,
document_type,
document_id,
opts \\ []
) do
bexio_return_handling(
fn ->
Tesla.get(client, "/2.0/kb_#{document_type}/#{document_id}/kb_position_discount",
query: opts_to_query(opts)
)
end,
&map_from_discount_positions/1
)
end
@doc """
This action fetches a single discount position for a document.
"""
@spec fetch_discount_position(
client :: Tesla.Client.t(),
document_type :: :offer | :order | :invoice,
document_id :: pos_integer(),
position_id :: pos_integer()
) :: {:ok, [PositionDiscount.t()]} | {:error, any()}
def fetch_discount_position(
client,
document_type,
document_id,
position_id
) do
bexio_return_handling(
fn ->
Tesla.get(
client,
"/2.0/kb_#{document_type}/#{document_id}/kb_position_discount/#{position_id}"
)
end,
&map_from_discount_position/1
)
end
defp map_from_discount_positions(discount_positions),
do: Enum.map(discount_positions, &map_from_discount_position/1)
defp map_from_discount_position(%{
"id" => id,
"text" => text,
"value" => value,
"discount_total" => discount_total,
"is_percentual" => percentual?
}) do
%PositionDiscount{
id: id,
text: text,
value: Decimal.new(value),
discount_total: Decimal.new(discount_total),
percentual?: percentual?
}
end
### Pagebreak Position
@doc """
This action fetches a list of all pagebreak positions for a document.
"""
@spec fetch_pagebreak_positions(
client :: Tesla.Client.t(),
document_type :: :offer | :order | :invoice,
document_id :: pos_integer(),
opts :: [GlobalArguments.offset_without_order_by_arg()]
) :: {:ok, [PositionPagebreak.t()]} | {:error, any()}
def fetch_pagebreak_positions(
client,
document_type,
document_id,
opts \\ []
) do
bexio_return_handling(
fn ->
Tesla.get(client, "/2.0/kb_#{document_type}/#{document_id}/kb_position_pagebreak",
query: opts_to_query(opts)
)
end,
&map_from_pagebreak_positions/1
)
end
@doc """
This action fetches a single pagebreak position for a document.
"""
@spec fetch_pagebreak_position(
client :: Tesla.Client.t(),
document_type :: :offer | :order | :invoice,
document_id :: pos_integer(),
position_id :: pos_integer()
) :: {:ok, [PositionPagebreak.t()]} | {:error, any()}
def fetch_pagebreak_position(
client,
document_type,
document_id,
position_id
) do
bexio_return_handling(
fn ->
Tesla.get(
client,
"/2.0/kb_#{document_type}/#{document_id}/kb_position_pagebreak/#{position_id}"
)
end,
&map_from_pagebreak_position/1
)
end
defp map_from_pagebreak_positions(pagebreak_positions),
do: Enum.map(pagebreak_positions, &map_from_pagebreak_position/1)
defp map_from_pagebreak_position(%{
"id" => id,
"internal_pos" => internal_pos,
"is_optional" => optional?,
"parent_id" => parent_id
}) do
%PositionPagebreak{
id: id,
internal_pos: internal_pos,
optional?: optional?,
parent_id: parent_id
}
end
### Subposition Position
@doc """
This action fetches a list of all subposition positions for a document.
"""
@spec fetch_subposition_positions(
client :: Tesla.Client.t(),
document_type :: :offer | :order | :invoice,
document_id :: pos_integer(),
opts :: [GlobalArguments.offset_without_order_by_arg()]
) ::
{:ok, [PositionSubposition.t()]} | {:error, any()}
def fetch_subposition_positions(
client,
document_type,
document_id,
opts \\ []
) do
bexio_return_handling(
fn ->
Tesla.get(client, "/2.0/kb_#{document_type}/#{document_id}/kb_position_subposition",
query: opts_to_query(opts)
)
end,
&map_from_subposition_positions/1
)
end
@doc """
This action fetches a single subposition position for a document.
"""
@spec fetch_subposition_position(
client :: Tesla.Client.t(),
document_type :: :offer | :order | :invoice,
document_id :: pos_integer(),
position_id :: pos_integer()
) ::
{:ok, [PositionSubposition.t()]} | {:error, any()}
def fetch_subposition_position(
client,
document_type,
document_id,
position_id
) do
bexio_return_handling(
fn ->
Tesla.get(
client,
"/2.0/kb_#{document_type}/#{document_id}/kb_position_subposition/#{position_id}"
)
end,
&map_from_subposition_position/1
)
end
defp map_from_subposition_positions(subposition_positions),
do: Enum.map(subposition_positions, &map_from_subposition_position/1)
defp map_from_subposition_position(%{
"id" => id,
"text" => text,
"pos" => pos,
"internal_pos" => internal_pos,
"show_pos_nr" => show_pos_nr?,
"is_optional" => optional?,
"total_sum" => total_sum,
"show_pos_prices" => show_pos_prices?,
"parent_id" => parent_id
}) do
%PositionSubposition{
id: id,
text: text,
pos: pos,
internal_pos: internal_pos,
show_pos_prices?: show_pos_prices?,
show_pos_nr?: show_pos_nr?,
total_sum: Decimal.new(total_sum),
optional?: optional?,
parent_id: parent_id
}
end
end