53 lines
1.7 KiB
Elixir
53 lines
1.7 KiB
Elixir
defmodule Bid do
|
|
use Ecto.Schema
|
|
import Ecto.Changeset
|
|
alias NeonVertigoService.Repo
|
|
import Ecto.Query, only: [from: 2]
|
|
|
|
@primary_key false
|
|
schema "bids" do
|
|
belongs_to :auction, Auction, foreign_key: :auction_gid, references: :gid, type: :string, primary_key: true
|
|
field :bid_timestamp, :utc_datetime_usec, primary_key: true
|
|
field :bidder_gid, :string, primary_key: true
|
|
field :bid, :decimal
|
|
end
|
|
|
|
def changeset(bid, params \\ %{}) do
|
|
bid
|
|
|> cast(params, [:auction_gid, :bidder_gid, :bid])
|
|
|> validate_required([:auction_gid, :bidder_gid, :bid])
|
|
|> validate_number(:bid, greater_than_or_equal_to: 0)
|
|
|> validate_bid_value_max
|
|
|> validate_bid_value_more_than_auction_starting_price
|
|
|> put_change(:bid_timestamp, DateTime.utc_now)
|
|
|> foreign_key_constraint(:auction_gid)
|
|
end
|
|
|
|
defp validate_bid_value_max(changeset) do
|
|
auction_gid = get_field(changeset, :auction_gid)
|
|
new_bid = get_field(changeset, :bid)
|
|
existing_bid = Repo.one(
|
|
from b in Bid, where: b.auction_gid == ^auction_gid,
|
|
order_by: [desc: :bid_timestamp],
|
|
limit: 1,
|
|
select: b.bid
|
|
)
|
|
|
|
if is_nil(existing_bid) or Decimal.compare(existing_bid, new_bid) == :lt do
|
|
changeset
|
|
else
|
|
add_error(changeset, :bid, "smaller than last bid")
|
|
end
|
|
end
|
|
|
|
defp validate_bid_value_more_than_auction_starting_price(changeset) do
|
|
auction_gid = get_field(changeset, :auction_gid)
|
|
auction = Repo.one!(from a in Auction, where: a.gid == ^auction_gid, select: a)
|
|
if Decimal.compare(auction.starting_price, get_field(changeset, :bid)) == :lt do
|
|
changeset
|
|
else
|
|
add_error(changeset, :bid, "smaller than auction's starting price")
|
|
end
|
|
end
|
|
end
|