Skip to content

Steven Leighton's engineering exercise #91

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions elixir/lib/homework/companies.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
defmodule Homework.Companies do
@moduledoc """
The Companies context.
"""

import Ecto.Query, warn: false
alias Homework.Repo

alias Homework.Companies.Company

@doc """
Returns the list of companies.

## Examples

iex> list_companies([])
[%Company{}, ...]

"""
def list_companies(_args) do
Repo.all(Company)
end

@doc """
Gets a single company.

Raises `Ecto.NoResultsError` if the Company does not exist.

## Examples

iex> get_company!(123)
%User{}

iex> get_company!(456)
** (Ecto.NoResultsError)

"""
def get_company!(id), do: Repo.get!(Company, id)

@doc """
Fuzzy search for companies by name.

## Examples

iex> find_companies("some company")
[%Company{}, ...]

"""
def find_companies(name) do
query =
from c in Company,
where: like(c.name, ^("%#{name}%")),
select: c
Repo.all(query)
end

@doc """
Creates a company.

## Examples

iex> create_company(%{field: value})
{:ok, %Company{}}

iex> create_company(%{field: bad_value})
{:error, %Ecto.Changeset{}}

"""
def create_company(attrs \\ %{}) do
%Company{}
|> Company.changeset(attrs)
|> Repo.insert()
end

@doc """
Updates a company.

## Examples

iex> update_company(company, %{field: new_value})
{:ok, %Company{}}

iex> update_company(company, %{field: bad_value})
{:error, %Ecto.Changeset{}}

"""
def update_company(%Company{} = company, attrs) do
company
|> Company.changeset(attrs)
|> Repo.update()
end

@doc """
Deletes a company.

## Examples

iex> delete_company(company)
{:ok, %Company{}}

iex> delete_company(company)
{:error, %Ecto.Changeset{}}

"""
def delete_company(%Company{} = company) do
Repo.delete(company)
end

@doc """
Returns an `%Ecto.Changeset{}` for tracking company changes.

## Examples

iex> change_company(company)
%Ecto.Changeset{data: %Company{}}

"""
def change_company(%Company{} = company, attrs \\ %{}) do
Company.changeset(company, attrs)
end
end
20 changes: 20 additions & 0 deletions elixir/lib/homework/companies/company.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
defmodule Homework.Companies.Company do
use Ecto.Schema
import Ecto.Changeset

@primary_key {:id, :binary_id, autogenerate: true}
schema "companies" do
field(:name, :string)
field(:credit_line, :integer)
field(:available_credit, :integer)

timestamps()
end

@doc false
def changeset(company, attrs) do
company
|> cast(attrs, [:name, :credit_line, :available_credit])
|> validate_required([:name, :credit_line, :available_credit])
end
end
17 changes: 17 additions & 0 deletions elixir/lib/homework/merchants.ex
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,23 @@ defmodule Homework.Merchants do
"""
def get_merchant!(id), do: Repo.get!(Merchant, id)

@doc """
Fuzzy search for merchants by name.

## Examples

iex> find_merchants("some name")
[%Merchant{}, ...]

"""
def find_merchants(name) do
query =
from m in Merchant,
where: like(m.name, ^("%#{name}%")),
select: m
Repo.all(query)
end

@doc """
Creates a merchant.

Expand Down
33 changes: 31 additions & 2 deletions elixir/lib/homework/transactions.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ defmodule Homework.Transactions do
alias Homework.Repo

alias Homework.Transactions.Transaction
alias Homework.Users.User
alias Homework.Companies.Company

@doc """
Returns the list of transactions.
Expand Down Expand Up @@ -38,7 +40,25 @@ defmodule Homework.Transactions do
def get_transaction!(id), do: Repo.get!(Transaction, id)

@doc """
Creates a transaction.
Finds all transactions with an amount within a given range.

## Examples

iex> find_transactions(123, 456)
[%Transaction{}, ...]

"""
def find_transactions(min, max) do
query =
from t in Transaction,
where: t.amount >= ^min and t.amount <= ^max,
select: t
Repo.all(query)
end

@doc """
Creates a transaction. Also updates the available credit for the
company associated with the transaction.

## Examples

Expand All @@ -49,7 +69,16 @@ defmodule Homework.Transactions do
{:error, %Ecto.Changeset{}}

"""
def create_transaction(attrs \\ %{}) do
def create_transaction(%{amount: amount, credit: credit, user_id: user_id} = attrs \\ %{}) do
change_amount = (if credit, do: 1, else: -1) * amount

query =
from c in Company,
join: u in User,
on: c.id == u.company_id,
where: u.id == ^user_id
Repo.update_all(query, inc: [available_credit: change_amount])

%Transaction{}
|> Transaction.changeset(attrs)
|> Repo.insert()
Expand Down
4 changes: 2 additions & 2 deletions elixir/lib/homework/transactions/transaction.ex
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ defmodule Homework.Transactions.Transaction do
@doc false
def changeset(transaction, attrs) do
transaction
|> cast(attrs, [:user_id, :amount, :debit, :description, :merchant_id])
|> validate_required([:user_id, :amount, :debit, :description, :merchant_id])
|> cast(attrs, [:user_id, :amount, :credit, :debit, :description, :merchant_id])
|> validate_required([:user_id, :amount, :credit, :debit, :description, :merchant_id])
end
end
21 changes: 21 additions & 0 deletions elixir/lib/homework/users.ex
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,27 @@ defmodule Homework.Users do
"""
def get_user!(id), do: Repo.get!(User, id)

@doc """
Fuzzy search for users by first and last name.

## Examples

iex> find_users("Joe", "S")
[%User{}, ...]

iex> find_users("", "Smith")
[%User{}, ...]

"""
def find_users(first, last) do
query =
from u in User,
where: like(u.first_name, ^("%#{first}%"))
and like(u.last_name, ^("%#{last}%")),
select: u
Repo.all(query)
end

@doc """
Creates a user.

Expand Down
7 changes: 5 additions & 2 deletions elixir/lib/homework/users/user.ex
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
defmodule Homework.Users.User do
use Ecto.Schema
import Ecto.Changeset
alias Homework.Companies.Company

@primary_key {:id, :binary_id, autogenerate: true}
schema "users" do
field(:dob, :string)
field(:first_name, :string)
field(:last_name, :string)

belongs_to(:company, Company, type: :binary_id, foreign_key: :company_id)

timestamps()
end

@doc false
def changeset(user, attrs) do
user
|> cast(attrs, [:first_name, :last_name, :dob])
|> validate_required([:first_name, :last_name, :dob])
|> cast(attrs, [:first_name, :last_name, :dob, :company_id])
|> validate_required([:first_name, :last_name, :dob, :company_id])
end
end
61 changes: 61 additions & 0 deletions elixir/lib/homework_web/resolvers/companies_resolver.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
defmodule HomeworkWeb.Resolvers.CompaniesResolver do
alias Homework.Companies

@doc """
Get a list of companies
"""
def companies(_root, args, _info) do
{:ok, Companies.list_companies(args)}
end

@doc """
Find companies by name
"""
def find_companies(_root, %{name: name}, _info) do
{:ok, Companies.find_companies(name)}
end

@doc """
Create a new company
"""
def create_company(_root, %{credit_line: credit_line} = args, _info) do
new_args = Map.put(args, :available_credit, credit_line)
case Companies.create_company(new_args) do
{:ok, company} ->
{:ok, company}

error ->
{:error, "could not create company: #{inspect(error)}"}
end
end

@doc """
Updates a company for an id with args specified.
"""
def update_company(_root, %{id: id} = args, _info) do
company = Companies.get_company!(id)

case Companies.update_company(company, args) do
{:ok, company} ->
{:ok, company}

error ->
{:error, "could not update company: #{inspect(error)}"}
end
end

@doc """
Deletes a company for an id
"""
def delete_company(_root, %{id: id}, _info) do
company = Companies.get_company!(id)

case Companies.delete_company(company) do
{:ok, company} ->
{:ok, company}

error ->
{:error, "could not update company: #{inspect(error)}"}
end
end
end
7 changes: 7 additions & 0 deletions elixir/lib/homework_web/resolvers/merchants_resolver.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ defmodule HomeworkWeb.Resolvers.MerchantsResolver do
{:ok, Merchants.list_merchants(args)}
end

@doc """
Find merchants by name
"""
def find_merchants(_root, %{name: name}, _info) do
{:ok, Merchants.find_merchants(name)}
end

@doc """
Create a new merchant
"""
Expand Down
7 changes: 7 additions & 0 deletions elixir/lib/homework_web/resolvers/transactions_resolver.ex
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ defmodule HomeworkWeb.Resolvers.TransactionsResolver do
{:ok, Merchants.get_merchant!(merchant_id)}
end

@doc """
Find transactions by amount
"""
def find_transactions(_root, %{min: min, max: max}, _info) do
{:ok, Transactions.find_transactions(min, max)}
end

@doc """
Create a new transaction
"""
Expand Down
7 changes: 7 additions & 0 deletions elixir/lib/homework_web/resolvers/users_resolver.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ defmodule HomeworkWeb.Resolvers.UsersResolver do
{:ok, Users.list_users(args)}
end

@doc """
Find users by first and last name
"""
def find_users(_root, %{first_name: first, last_name: last}, _info) do
{:ok, Users.find_users(first, last)}
end

@doc """
Creates a user
"""
Expand Down
Loading