Skip to content

Commit

Permalink
Removed action from all changesets (7)
Browse files Browse the repository at this point in the history
* Updated `Helper.Query` to work with `create_changeset` and
`update_changeset`.
* Fix credo issues of `User` and correct `update_changeset`.
* Remove `schema/stock/stock.ex` as it only aliased modules. See the
recent Elixir guidelines for library authors.
* Changesets in `schema/stock` got a rewrite as they were overly
complicated.
* Added specs and docs for most (schema) functions.
* Moved `ShipmentUnit` out of `stock/`
* Fixes #23
  • Loading branch information
oyeb authored and pkrawat1 committed Oct 4, 2018
1 parent 51ba344 commit 314e92f
Show file tree
Hide file tree
Showing 41 changed files with 369 additions and 382 deletions.
2 changes: 1 addition & 1 deletion .credo.exs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
# In the latter case `**/*.{ex,exs}` will be used.
#
included: ["lib/", "src/", "web/", "apps/"],
excluded: [~r"/_build/", ~r"/deps/"]
excluded: [~r"/_build/", ~r"/deps/", ~r"/assets/node_modules/"]
},
#
# If you create your own checks, you must specify the source files for
Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ matrix:
- elixir: "1.5.3"
script:
- mix coveralls.json --umbrella
- elixir: "1.6.2"
- elixir: "1.6.4"

notifications:
email:
Expand Down
4 changes: 2 additions & 2 deletions apps/snitch_core/lib/core/data/model/payment/card_payment.ex
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ defmodule Snitch.Data.Model.CardPayment do
slug: slug
}

payment_changeset = Payment.changeset(payment, more_payment_params, :create)
payment_changeset = Payment.create_changeset(payment, more_payment_params)

Multi.new()
|> Multi.insert(:payment, payment_changeset)
Expand All @@ -67,7 +67,7 @@ defmodule Snitch.Data.Model.CardPayment do
{:ok, %{card_payment: CardPayment.t(), payment: Payment.t()}}
| {:error, Ecto.Changeset.t()}
def update(card_payment, card_params, payment_params) do
card_payment_changeset = CardPayment.changeset(card_payment, card_params, :update)
card_payment_changeset = CardPayment.update_changeset(card_payment, card_params)

Multi.new()
|> Multi.update(:card_payment, card_payment_changeset)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
defmodule Snitch.Data.Model.ShipmentUnit do
@moduledoc """
`ShipmentUnit` CRUD API (ironic as there is only `create` :P).
"""

use Snitch.Data.Model
Expand Down
4 changes: 2 additions & 2 deletions apps/snitch_core/lib/core/data/model/shipping_method.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ defmodule Snitch.Data.Model.ShippingMethod do
"""
@spec create(map, [Zone.t()]) :: {:ok, SMSchema.t()} | {:error, Ecto.Changeset.t()}
def create(params, zone_structs) do
cs = SMSchema.changeset(%SMSchema{}, params, zone_structs, :create)
cs = SMSchema.create_changeset(%SMSchema{}, params, zone_structs)
Repo.insert(cs)
end

Expand Down Expand Up @@ -41,7 +41,7 @@ defmodule Snitch.Data.Model.ShippingMethod do
@spec update(SMSchema.t(), map, [Zone.t()]) ::
{:ok, SMSchema.t()} | {:error, Ecto.Changeset.t()}
def update(shipping_method, params, zone_structs) do
cs = SMSchema.changeset(shipping_method, params, zone_structs, :update)
cs = SMSchema.update_changeset(shipping_method, params, zone_structs)
Repo.update(cs)
end

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
defmodule Snitch.Data.Model.StockMovement do
@moduledoc """
`StockMovement` API
"""

use Snitch.Data.Model
Expand Down
2 changes: 1 addition & 1 deletion apps/snitch_core/lib/core/data/model/user.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ defmodule Snitch.Data.Model.User do
end

@spec get_all() :: [UserSchema.t()]
def get_all(), do: Repo.all(UserSchema)
def get_all, do: Repo.all(UserSchema)
end
4 changes: 2 additions & 2 deletions apps/snitch_core/lib/core/data/schema/address.ex
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ defmodule Snitch.Data.Schema.Address do
@required_fields ~w(first_name last_name address_line_1 city zip_code)a
@optional_fields ~w(phone alternate_phone)a

@spec changeset(__MODULE__.t(), map) :: Ecto.Changeset.t()
def changeset(address, params \\ %{}) do
@spec changeset(t, map) :: Ecto.Changeset.t()
def changeset(%__MODULE__{} = address, params) do
address
|> cast(params, @required_fields ++ @optional_fields)
|> validate_required(@required_fields)
Expand Down
20 changes: 19 additions & 1 deletion apps/snitch_core/lib/core/data/schema/card.ex
Original file line number Diff line number Diff line change
@@ -1,11 +1,29 @@
defmodule Snitch.Data.Schema.Card do
@moduledoc """
Models Credit and Debit cards.
A `User` can save cards by setting the `:card_name`, even if the card is not
saved, it is associated with the user.
"""

use Snitch.Data.Schema

alias Snitch.Data.Schema.{CardPayment, User}

@typedoc """
## `:is_disabled` and `:card_name`
These fields together decide if the card is listed as a "saved card" to the user.
| `:is_disabled` | `:card_name` | Listed as a saved card? |
|----------------|---------------------|-------------------------|
| `false` | **not `nil` or `""` | yes |
| `false` | `nil` or `""` | no |
| `true` | `any` | no |
## Note
A `Card` is never deleted, because `CardPayments` are never deleted.
"""
@type t :: %__MODULE__{}

schema "snitch_cards" do
Expand Down Expand Up @@ -37,7 +55,7 @@ defmodule Snitch.Data.Schema.Card do
digits (inclusive), according to [ISO/IEC
7812](https://www.iso.org/obp/ui/#iso:std:iso-iec:7812:-1:ed-5:v1:en)
"""
@spec changeset(__MODULE__.t(), map, :create | :update) :: Ecto.Changeset.t()
@spec changeset(t, map, :create | :update) :: Ecto.Changeset.t()
def changeset(card, params, action)

def changeset(%__MODULE__{} = card, params, :create) do
Expand Down
8 changes: 6 additions & 2 deletions apps/snitch_core/lib/core/data/schema/country.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ defmodule Snitch.Data.Schema.Country do
use Snitch.Data.Schema
alias Snitch.Data.Schema.State

@type t :: %__MODULE__{}

schema "snitch_countries" do
field(:iso_name, :string)
field(:iso, :string)
Expand All @@ -18,9 +20,10 @@ defmodule Snitch.Data.Schema.Country do
timestamps()
end

def changeset(%__MODULE__{} = country, attrs \\ %{}) do
@spec changeset(t, map) :: Ecto.Changeset.t()
def changeset(%__MODULE__{} = country, params) do
country
|> cast(attrs, [:iso, :iso3, :iso_name, :name, :numcode, :states_required])
|> cast(params, [:iso, :iso3, :iso_name, :name, :numcode, :states_required])
|> validate_required([:iso, :iso3, :iso_name, :name, :numcode])
|> validate_length(:iso, is: 2)
|> validate_length(:iso3, is: 3)
Expand All @@ -31,6 +34,7 @@ defmodule Snitch.Data.Schema.Country do
|> build_iso_name
end

@spec build_iso_name(Ecto.Changeset.t()) :: Ecto.Changeset.t()
defp build_iso_name(changeset) do
name = get_change(changeset, :name)

Expand Down
8 changes: 4 additions & 4 deletions apps/snitch_core/lib/core/data/schema/line_item.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ defmodule Snitch.Data.Schema.LineItem do
Do not persist this to DB since price fields and order are not set! To set
prices see `update_totals/1` and `create_changeset/2`.
"""
@spec changeset(__MODULE__.t(), map) :: Ecto.Changeset.t()
def changeset(line_item, params) do
@spec changeset(t, map) :: Ecto.Changeset.t()
def changeset(%__MODULE__{} = line_item, params) do
line_item
|> cast(params, @required_fields ++ @optional_fields)
|> validate_required(@required_fields)
Expand All @@ -40,8 +40,8 @@ defmodule Snitch.Data.Schema.LineItem do
@doc """
Returns a `LineItem` changeset that can be used for `insert`/`update`.
"""
@spec create_changeset(__MODULE__.t(), map) :: Ecto.Changeset.t()
def create_changeset(line_item, params) do
@spec create_changeset(t, map) :: Ecto.Changeset.t()
def create_changeset(%__MODULE__{} = line_item, params) do
line_item
|> changeset(params)
|> validate_required(@optional_fields)
Expand Down
59 changes: 29 additions & 30 deletions apps/snitch_core/lib/core/data/schema/order.ex
Original file line number Diff line number Diff line change
Expand Up @@ -37,50 +37,52 @@ defmodule Snitch.Data.Schema.Order do

@required_fields ~w(slug state user_id)a
@optional_fields ~w(billing_address_id shipping_address_id)a
@create_fields @required_fields
@update_fields ~w(slug state)a ++ @optional_fields

@doc """
Returns a complete changeset with totals.
Returns a Order changeset with totals for a "new" order.
The `action` field can be either `:create` or `:update`.
* `:create`
- A list of `LineItem` params are expected under the `:line_items` key, and
each of those must include price fields, use
`Snitch.Data.Model.LineItem.update_price_and_totals/1` if
needed. Note that `variant_id`s must be unique in each line item.
* `:update`
- `LineItem` params (if any) must include price fields.
## Note
The changeset `action` is not set.
A list of `LineItem` params are expected under the `:line_items` key, and each
of those must include price fields, use
`Snitch.Data.Model.LineItem.update_price_and_totals/1` if needed.
> Note that `variant_id`s must be unique in each line item.
"""
@spec changeset(__MODULE__.t(), map, :create | :update) :: Ecto.Changeset.t()
def changeset(order, params, action) do
@spec create_changeset(t, map) :: Ecto.Changeset.t()
def create_changeset(%__MODULE__{} = order, params) do
order
|> cast(params, @required_fields ++ @optional_fields)
|> cast(params, @create_fields)
|> validate_required(@required_fields)
|> common_changeset()
|> foreign_key_constraint(:user_id)
|> foreign_key_constraint(:billing_address_id)
|> foreign_key_constraint(:shipping_address_id)
|> do_changeset(action)
end

@spec create_changeset(Ecto.Changeset.t()) :: Ecto.Changeset.t()
defp create_changeset(order_changeset) do
order_changeset
|> cast_assoc(:line_items, with: &LineItem.create_changeset/2, required: true)
|> ensure_unique_line_items()
|> compute_totals()
end

@spec update_changeset(Ecto.Changeset.t()) :: Ecto.Changeset.t()
defp update_changeset(order_changeset) do
order_changeset
@doc """
Returns a Order changeset with totals to update `order`.
`LineItem` params (if any) must include price fields.
> Note that `variant_id`s must be unique in each line item.
"""
@spec update_changeset(t, map) :: Ecto.Changeset.t()
def update_changeset(%__MODULE__{} = order, params) do
order
|> cast(params, @update_fields)
|> common_changeset()
|> cast_assoc(:line_items, with: &LineItem.create_changeset/2)
|> ensure_unique_line_items()
|> compute_totals()
end

@spec common_changeset(Ecto.Changeset.t()) :: Ecto.Changeset.t()
defp common_changeset(order_changeset) do
order_changeset
|> foreign_key_constraint(:billing_address_id)
|> foreign_key_constraint(:shipping_address_id)
end

@spec compute_totals(Ecto.Changeset.t()) :: Ecto.Changeset.t()
defp compute_totals(%Ecto.Changeset{valid?: true} = order_changeset) do
item_total =
Expand All @@ -100,9 +102,6 @@ defmodule Snitch.Data.Schema.Order do

defp compute_totals(order_changeset), do: order_changeset

defp do_changeset(changeset, :create), do: create_changeset(changeset)
defp do_changeset(changeset, :update), do: update_changeset(changeset)

@spec ensure_unique_line_items(Ecto.Changeset.t()) :: Ecto.Changeset.t()
defp ensure_unique_line_items(%Ecto.Changeset{valid?: true} = order_changeset) do
line_item_changesets = get_field(order_changeset, :line_items)
Expand Down
27 changes: 15 additions & 12 deletions apps/snitch_core/lib/core/data/schema/payment/card_payment.ex
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,13 @@ defmodule Snitch.Data.Schema.CardPayment do
@create_fields ~w(payment_id card_id)a ++ @update_fields

@doc """
Returns a `CardPayment` changeset.
Returns a `CardPayment` changeset for a new `card_payment`.
`:payment_id` is required when `action` is `:create`. When `action` is
`:update`, the `:payment_id` if provided, is simply ignored.
Consider deleting the payment if you wish to "change" the payment type.
`:payment_id` is required!
"""
@spec changeset(__MODULE__.t(), map, :create | :update) :: Ecto.Changeset.t()
def changeset(payment, params, action)

def changeset(payment, params, :create) do
payment
@spec create_changeset(t, map) :: Ecto.Changeset.t()
def create_changeset(%__MODULE__{} = card_payment, params) do
card_payment
|> cast(params, @create_fields)
|> assoc_card()
|> unique_constraint(:payment_id)
Expand All @@ -54,8 +49,16 @@ defmodule Snitch.Data.Schema.CardPayment do
)
end

def changeset(payment, params, :update) do
cast(payment, params, @update_fields)
@doc """
Returns a `CardPayment` changeset to update a `card_payment`.
Note that `:payment_id` cannot be changed, consider deleting this
`card_payment` instead and creating a new `Snitch.Data.Schema.Payment` as well
as `Snitch.Data.Schema.CardPayment`.
"""
@spec create_changeset(t, map) :: Ecto.Changeset.t()
def update_changeset(%__MODULE__{} = card_payment, params) do
cast(card_payment, params, @update_fields)
end

def assoc_card(payment_changeset) do
Expand Down
37 changes: 22 additions & 15 deletions apps/snitch_core/lib/core/data/schema/payment/payment.ex
Original file line number Diff line number Diff line change
Expand Up @@ -26,39 +26,45 @@ defmodule Snitch.Data.Schema.Payment do
@create_fields @update_fields ++ ~w(amount payment_type payment_method_id)a

@doc """
Returns a `Payment` changeset.
Returns a `Payment` changeset for a new `payment`.
`:payment_type` is required when `action` is `:create`. When `action` is
`:update`, the `:payment_type` and `amount` if provided, are simply ignored.
Consider deleting the payment if you wish to "change" the payment type.
`:payment_type` is required when `action` is `:create`
"""
@spec changeset(__MODULE__.t(), map, :create | :update) :: Ecto.Changeset.t()
def changeset(payment, params, action)

def changeset(payment, params, :create) do
@spec create_changeset(t, map) :: Ecto.Changeset.t()
def create_changeset(%__MODULE__{} = payment, params) do
payment
|> cast(params, @create_fields)
|> validate_required(@create_fields)
|> validate_discriminator(:payment_type, @payment_types)
|> foreign_key_constraint(:payment_method_id)
|> do_changeset()
|> common_changeset()
end

def changeset(payment, params, :update) do
@doc """
Returns a `Payment` changeset to update `payment`.
The `:payment_type` and `amount` if provided, are simply ignored.
Consider deleting the payment, and making a new one if you wish to "change"
the payment type.
"""
@spec create_changeset(t, map) :: Ecto.Changeset.t()
def update_changeset(%__MODULE__{} = payment, params) do
payment
|> cast(params, @update_fields)
|> do_changeset()
|> common_changeset()
end

defp do_changeset(changeset) do
@spec common_changeset(Ecto.Changeset.t()) :: Ecto.Changeset.t()
defp common_changeset(changeset) do
changeset
|> foreign_key_constraint(:order_id)
|> validate_amount(:amount)
|> unique_constraint(:slug)
end

defp validate_discriminator(%{valid?: true} = changeset, key, permitted) do
@spec validate_discriminator(Ecto.Changeset.t(), atom, list) :: Ecto.Changeset.t()
defp validate_discriminator(%Ecto.Changeset{valid?: true} = changeset, key, permitted) do
{_, discriminator} = fetch_field(changeset, key)

if discriminator in permitted do
Expand All @@ -70,7 +76,8 @@ defmodule Snitch.Data.Schema.Payment do

defp validate_discriminator(changeset, _, _), do: changeset

defp validate_amount(%{valid?: true} = changeset, key) do
@spec validate_amount(Ecto.Changeset.t(), atom) :: Ecto.Changeset.t()
defp validate_amount(%Ecto.Changeset{valid?: true} = changeset, key) do
{_, amount} = fetch_field(changeset, key)

if Decimal.cmp(amount.amount, Decimal.new(0)) != :lt do
Expand Down
Loading

0 comments on commit 314e92f

Please sign in to comment.