defmodule BasicECommerce do
@moduledoc """
Main module for this library.
To use it, it needs to be used on your own application and it should configure an adapter
by specifying the used `otp_app` and correctly configuring the adapter for this OTP app.
## Example
# config/config.exs
config :my_app, MyApp.BasicECommerce,
adapter: BasicECommerce.DataSource.JsonAdapter,
json_file_path: '/data/pricing_data.json`
# my_app/basic_ecommerce.ex
defmodule MyApp.BasicECommerce do
use BasicECommerce, otp_app: :my_app
end
"""
defmacro __using__(opts) do
quote bind_quoted: [opts: opts] do
@otp_app Keyword.fetch!(opts, :otp_app)
@config Application.get_env(@otp_app, __MODULE__, [])
@adapter Keyword.fetch!(@config, :adapter)
@doc """
Returns the list of all products in the data source.
"""
@spec list_products() :: [BasicECommerce.Product.t()]
def list_products do
@adapter.list_products(@config)
end
@doc """
Gets a single product by its SKU.
"""
@spec get_product(sku :: atom()) :: {:ok, BasicECommerce.Product.t()} | {:error, String.t()}
def get_product(sku) do
@adapter.get_product(sku, @config)
end
@doc """
Returns the applicable special offers for a given SKU.
"""
@spec applicable_special_offers(sku :: atom()) :: [BasicECommerce.SpecialOffer.t()]
def applicable_special_offers(sku) do
@adapter.applicable_special_offers(sku, @config)
end
@doc """
Compute and return the total price of an order
"""
@spec compute_total(order :: BasicECommerce.Order.t()) :: integer()
def compute_total(order) do
BasicECommerce.Order.total!(order, &get_product/1, &applicable_special_offers/1)
end
@on_load :validate_config
@doc false
def validate_config do
@adapter.validate_config(@config)
end
end
end
end