From 67560667731d31bfd7ef21c9e7e18f425c31060b Mon Sep 17 00:00:00 2001 From: Alex Porter Date: Wed, 7 Dec 2022 08:40:52 -0700 Subject: [PATCH 01/11] Added search_user schema, created a search_user resolver, and get_by name function to search for users using ilike with wildcard characters, resulting in a list of users that contain names, or characters searched for in GraphQL --- elixir/lib/homework/users.ex | 20 +++++++++++++++++++ .../homework_web/resolvers/users_resolver.ex | 15 ++++++++++++++ .../lib/homework_web/schemas/users_schema.ex | 8 ++++++++ 3 files changed, 43 insertions(+) diff --git a/elixir/lib/homework/users.ex b/elixir/lib/homework/users.ex index d481272a..48ba65cc 100644 --- a/elixir/lib/homework/users.ex +++ b/elixir/lib/homework/users.ex @@ -37,6 +37,26 @@ defmodule Homework.Users do """ def get_user!(id), do: Repo.get!(User, id) + @doc """ + Gets a user by first and last name. + + Raises `Ecto.NoResultsError` if the User does not exist. + + ## Examples + + iex> get_by_name("Alex", "Porter") + %User{} + + iex> get_by_name("Unknown", "User") + ** (Ecto.NoResultsError) + """ + + def get_by_name(first_name, last_name) do + Repo.all( + from(u in User, where: ilike(u.first_name, ^"%#{first_name}%") and ilike(u.last_name, ^"%#{last_name}%")) + ) + end + @doc """ Creates a user. diff --git a/elixir/lib/homework_web/resolvers/users_resolver.ex b/elixir/lib/homework_web/resolvers/users_resolver.ex index 1e0c4292..efa93221 100644 --- a/elixir/lib/homework_web/resolvers/users_resolver.ex +++ b/elixir/lib/homework_web/resolvers/users_resolver.ex @@ -8,6 +8,21 @@ defmodule HomeworkWeb.Resolvers.UsersResolver do {:ok, Users.list_users(args)} end + @doc """ + Searches for users by first and last name. + + Returns the matching users, if found. + """ + def search_user(_root, %{first_name: first_name, last_name: last_name}, _info) do + users = Users.get_by_name(first_name, last_name) + + if length(users) > 0 do + {:ok, users} + else + {:ok, []} + end + end + @doc """ Creates a user """ diff --git a/elixir/lib/homework_web/schemas/users_schema.ex b/elixir/lib/homework_web/schemas/users_schema.ex index 21bd5a90..2fa905c7 100644 --- a/elixir/lib/homework_web/schemas/users_schema.ex +++ b/elixir/lib/homework_web/schemas/users_schema.ex @@ -25,6 +25,14 @@ defmodule HomeworkWeb.Schemas.UsersSchema do resolve(&UsersResolver.create_user/3) end + @desc "Search for a user by first and last name" + field :search_user, list_of(:user) do + arg(:first_name, non_null(:string)) + arg(:last_name, non_null(:string)) + + resolve(&UsersResolver.search_user/3) + end + @desc "Update a new user" field :update_user, :user do arg(:id, non_null(:id)) From 0709dd47af88baa1acb2c15a8370d72ff030c3b7 Mon Sep 17 00:00:00 2001 From: Alex Porter Date: Wed, 7 Dec 2022 09:24:47 -0700 Subject: [PATCH 02/11] created a search_merchant schema, with the argument being name, created search_merchant resolver that accomplished the same goal as the search_user resolver. Resulting in an empty list if no merchants are found, or a list of merchants that have been found. Also included the ilike with wildcard functionality for the get_merchant_by_name function. exit --- elixir/lib/homework/merchants.ex | 18 ++++++++++++++++++ elixir/lib/homework/users.ex | 10 ++++------ .../resolvers/merchants_resolver.ex | 17 +++++++++++++++++ .../homework_web/resolvers/users_resolver.ex | 2 +- .../homework_web/schemas/merchants_schema.ex | 7 +++++++ 5 files changed, 47 insertions(+), 7 deletions(-) diff --git a/elixir/lib/homework/merchants.ex b/elixir/lib/homework/merchants.ex index a581e33b..bb222a8c 100644 --- a/elixir/lib/homework/merchants.ex +++ b/elixir/lib/homework/merchants.ex @@ -37,6 +37,24 @@ defmodule Homework.Merchants do """ def get_merchant!(id), do: Repo.get!(Merchant, id) + + @doc """ + Gets a merchant by name. + + ## Example + + iex> get_by_name("Divvy") + %Merchant{} + + """ + + def get_merchant_by_name(name) do + Repo.all( + from(m in Merchant, + where: ilike(m.name, ^"%#{name}%") + ) + ) + end @doc """ Creates a merchant. diff --git a/elixir/lib/homework/users.ex b/elixir/lib/homework/users.ex index 48ba65cc..76a1629c 100644 --- a/elixir/lib/homework/users.ex +++ b/elixir/lib/homework/users.ex @@ -40,20 +40,18 @@ defmodule Homework.Users do @doc """ Gets a user by first and last name. - Raises `Ecto.NoResultsError` if the User does not exist. - ## Examples iex> get_by_name("Alex", "Porter") %User{} - iex> get_by_name("Unknown", "User") - ** (Ecto.NoResultsError) """ - def get_by_name(first_name, last_name) do + def get_user_by_name(first_name, last_name) do Repo.all( - from(u in User, where: ilike(u.first_name, ^"%#{first_name}%") and ilike(u.last_name, ^"%#{last_name}%")) + from(u in User, + where: ilike(u.first_name, ^"%#{first_name}%") and ilike(u.last_name, ^"%#{last_name}%") + ) ) end diff --git a/elixir/lib/homework_web/resolvers/merchants_resolver.ex b/elixir/lib/homework_web/resolvers/merchants_resolver.ex index f0274abc..c5abb355 100644 --- a/elixir/lib/homework_web/resolvers/merchants_resolver.ex +++ b/elixir/lib/homework_web/resolvers/merchants_resolver.ex @@ -8,6 +8,23 @@ defmodule HomeworkWeb.Resolvers.MerchantsResolver do {:ok, Merchants.list_merchants(args)} end + @doc """ + Searches for merchants by name. + + Returns the matching merchants, if found. + Otherwise results in an empty list. + """ + + def search_merchant(_root, %{name: name}, _info) do + merchants = Merchants.get_merchant_by_name(name) + + if length(merchants) > 0 do + {:ok, merchants} + else + {:ok, []} + end + end + @doc """ Create a new merchant """ diff --git a/elixir/lib/homework_web/resolvers/users_resolver.ex b/elixir/lib/homework_web/resolvers/users_resolver.ex index efa93221..21bc41be 100644 --- a/elixir/lib/homework_web/resolvers/users_resolver.ex +++ b/elixir/lib/homework_web/resolvers/users_resolver.ex @@ -14,7 +14,7 @@ defmodule HomeworkWeb.Resolvers.UsersResolver do Returns the matching users, if found. """ def search_user(_root, %{first_name: first_name, last_name: last_name}, _info) do - users = Users.get_by_name(first_name, last_name) + users = Users.get_user_by_name(first_name, last_name) if length(users) > 0 do {:ok, users} diff --git a/elixir/lib/homework_web/schemas/merchants_schema.ex b/elixir/lib/homework_web/schemas/merchants_schema.ex index 54faf094..e0adcb4c 100644 --- a/elixir/lib/homework_web/schemas/merchants_schema.ex +++ b/elixir/lib/homework_web/schemas/merchants_schema.ex @@ -23,6 +23,13 @@ defmodule HomeworkWeb.Schemas.MerchantsSchema do resolve(&MerchantsResolver.create_merchant/3) end + @desc "Search for a merchant by name" + field :search_merchant, list_of(:merchant) do + arg(:name, non_null(:string)) + + resolve(&MerchantsResolver.search_merchant/3) + end + @desc "Update a new merchant" field :update_merchant, :merchant do arg(:id, non_null(:id)) From 20e5d6e4de17ef0ea12f0add6b6296ab52aced7e Mon Sep 17 00:00:00 2001 From: Alex Porter Date: Wed, 7 Dec 2022 11:40:46 -0700 Subject: [PATCH 03/11] created a search_transaction schema with the arguments of minimum and maximum integer values, created a search_transaction function, using the map for minimum and maximum arguments, which searches for all transaction amounts within the minimum and maximum values. I then sorted the list of transactions from smallest amount to largest, if no transactions are found, it returns an empty list. This function calls on my filter_transaction function, which compares every transaction amount and returns only transactions with amounts between the specified values. --- elixir/lib/homework/merchants.ex | 3 +++ elixir/lib/homework/transactions.ex | 20 +++++++++++++++++++ .../resolvers/transactions_resolver.ex | 15 ++++++++++++++ .../schemas/transactions_schema.ex | 9 +++++++++ 4 files changed, 47 insertions(+) diff --git a/elixir/lib/homework/merchants.ex b/elixir/lib/homework/merchants.ex index bb222a8c..837e3b47 100644 --- a/elixir/lib/homework/merchants.ex +++ b/elixir/lib/homework/merchants.ex @@ -46,6 +46,9 @@ defmodule Homework.Merchants do iex> get_by_name("Divvy") %Merchant{} + iex> get_by_name("X") + %[] + """ def get_merchant_by_name(name) do diff --git a/elixir/lib/homework/transactions.ex b/elixir/lib/homework/transactions.ex index f7ec3dfb..b2a0eafe 100644 --- a/elixir/lib/homework/transactions.ex +++ b/elixir/lib/homework/transactions.ex @@ -37,6 +37,26 @@ defmodule Homework.Transactions do """ def get_transaction!(id), do: Repo.get!(Transaction, id) + @doc """ + Searches transactions and filters by amount. + + #Examples + + iex> filter_transaction(minimum: 100, maximum: 500) + %Transactions{} + + iex> filter_transaction(minimum: 0, maximum: 0) + %[] + """ + + def filter_transaction(minimum, maximum) do + Repo.all( + from(t in Transaction, + where: t.amount >= ^minimum and t.amount <= ^maximum + ) + ) + end + @doc """ Creates a transaction. diff --git a/elixir/lib/homework_web/resolvers/transactions_resolver.ex b/elixir/lib/homework_web/resolvers/transactions_resolver.ex index 4b928d62..64919d44 100644 --- a/elixir/lib/homework_web/resolvers/transactions_resolver.ex +++ b/elixir/lib/homework_web/resolvers/transactions_resolver.ex @@ -24,6 +24,21 @@ defmodule HomeworkWeb.Resolvers.TransactionsResolver do {:ok, Merchants.get_merchant!(merchant_id)} end + @doc """ + Search transactions and filter by amount + """ + def search_transaction(_root, %{minimum: minimum, maximum: maximum}, _info) do + + transactions = Transactions.filter_transaction(minimum, maximum) + + if length(transactions) > 0 do + transactions = Enum.sort(transactions) + {:ok, transactions} + else + {:ok, []} + end + end + @doc """ Create a new transaction """ diff --git a/elixir/lib/homework_web/schemas/transactions_schema.ex b/elixir/lib/homework_web/schemas/transactions_schema.ex index 658deab6..533b2d8e 100644 --- a/elixir/lib/homework_web/schemas/transactions_schema.ex +++ b/elixir/lib/homework_web/schemas/transactions_schema.ex @@ -17,6 +17,7 @@ defmodule HomeworkWeb.Schemas.TransactionsSchema do field(:inserted_at, :naive_datetime) field(:updated_at, :naive_datetime) + field(:user, :user) do resolve(&TransactionsResolver.user/3) end @@ -40,6 +41,14 @@ defmodule HomeworkWeb.Schemas.TransactionsSchema do resolve(&TransactionsResolver.create_transaction/3) end + @desc "Filter and search transactions by amount" + field :search_transaction, list_of(:transaction) do + arg(:minimum, non_null(:integer)) + arg(:maximum, non_null(:integer)) + + resolve(&TransactionsResolver.search_transaction/3) + end + @desc "Update a new transaction" field :update_transaction, :transaction do arg(:id, non_null(:id)) From 8b232f6a1af411e96d9925b59ee134a1f03623b0 Mon Sep 17 00:00:00 2001 From: Alex Porter Date: Wed, 7 Dec 2022 18:06:25 -0700 Subject: [PATCH 04/11] Created new schema, queries and mutations to add companies to the app, still need to adjust the available credit, but wanted to get a working product pushed up before I make any more changes --- elixir/lib/homework/companies.ex | 46 +++++++++++++++++++ elixir/lib/homework/companies/company.ex | 20 ++++++++ .../lib/homework/transactions/transaction.ex | 6 ++- elixir/lib/homework/users/user.ex | 11 ++++- .../resolvers/companies_resolver.ex | 25 ++++++++++ .../resolvers/transactions_resolver.ex | 8 ++++ .../homework_web/resolvers/users_resolver.ex | 9 ++++ elixir/lib/homework_web/schema.ex | 8 ++++ .../homework_web/schemas/companies_schema.ex | 28 +++++++++++ .../schemas/transactions_schema.ex | 8 +++- elixir/lib/homework_web/schemas/types.ex | 1 + .../lib/homework_web/schemas/users_schema.ex | 8 ++++ .../20191207150025_create_companies.exs | 14 ++++++ .../20200826195245_create_users.exs | 1 + .../20200826196533_create_transactions.exs | 1 + 15 files changed, 189 insertions(+), 5 deletions(-) create mode 100644 elixir/lib/homework/companies.ex create mode 100644 elixir/lib/homework/companies/company.ex create mode 100644 elixir/lib/homework_web/resolvers/companies_resolver.ex create mode 100644 elixir/lib/homework_web/schemas/companies_schema.ex create mode 100644 elixir/priv/repo/migrations/20191207150025_create_companies.exs diff --git a/elixir/lib/homework/companies.ex b/elixir/lib/homework/companies.ex new file mode 100644 index 00000000..1f0e1cc9 --- /dev/null +++ b/elixir/lib/homework/companies.ex @@ -0,0 +1,46 @@ +defmodule Homework.Companies do + @moduledoc """ + The Companies context + """ + + import Ecto.Query, warn: false + alias Homework.Repo + + alias Homework.Companies.Company + + @doc """ + Returns a 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.any() + + ## Examples + + iex> get_company!(123) + %Company{} + + iex> get_company!(456) + ** (Ecto.NoResultsError) + """ + def get_company!(id), do: Repo.get!(Company, id) + + @doc """ + Creates a company + """ + def create_company(attrs \\ %{}) do + %Company{} + |> Company.changeset(attrs) + |> Repo.insert() + end +end diff --git a/elixir/lib/homework/companies/company.ex b/elixir/lib/homework/companies/company.ex new file mode 100644 index 00000000..5ed515bf --- /dev/null +++ b/elixir/lib/homework/companies/company.ex @@ -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(user, attrs) do + user + |> cast(attrs, [:name, :available_credit, :credit_line]) + |> validate_required([:name, :available_credit, :credit_line]) + end +end diff --git a/elixir/lib/homework/transactions/transaction.ex b/elixir/lib/homework/transactions/transaction.ex index e7884314..080b2d7e 100644 --- a/elixir/lib/homework/transactions/transaction.ex +++ b/elixir/lib/homework/transactions/transaction.ex @@ -3,6 +3,7 @@ defmodule Homework.Transactions.Transaction do import Ecto.Changeset alias Homework.Merchants.Merchant alias Homework.Users.User + alias Homework.Companies.Company @primary_key {:id, :binary_id, autogenerate: true} schema "transactions" do @@ -13,6 +14,7 @@ defmodule Homework.Transactions.Transaction do belongs_to(:merchant, Merchant, type: :binary_id, foreign_key: :merchant_id) belongs_to(:user, User, type: :binary_id, foreign_key: :user_id) + belongs_to(:company, Company, type: :binary_id, foreign_key: :company_id) timestamps() end @@ -20,7 +22,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, :debit, :description, :merchant_id, :company_id]) + |> validate_required([:user_id, :amount, :debit, :description, :merchant_id, :company_id]) end end diff --git a/elixir/lib/homework/users/user.ex b/elixir/lib/homework/users/user.ex index 51ea2f95..89ed1651 100644 --- a/elixir/lib/homework/users/user.ex +++ b/elixir/lib/homework/users/user.ex @@ -1,6 +1,7 @@ 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 @@ -8,13 +9,19 @@ defmodule Homework.Users.User do 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]) + |> foreign_key_constraint(:company, + name: :users_company_id_fkey, + message: "Company_ID does not exist, make sure you are entering a valid ID" + ) end end diff --git a/elixir/lib/homework_web/resolvers/companies_resolver.ex b/elixir/lib/homework_web/resolvers/companies_resolver.ex new file mode 100644 index 00000000..6e5a48d6 --- /dev/null +++ b/elixir/lib/homework_web/resolvers/companies_resolver.ex @@ -0,0 +1,25 @@ +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 """ + Create a new company + """ + + def create_company(_root, args, _info) do + case Companies.create_company(args) do + {:ok, company} -> + {:ok, company} + + error -> + {:error, "could not create company: #{inspect(error)}"} + end + end +end diff --git a/elixir/lib/homework_web/resolvers/transactions_resolver.ex b/elixir/lib/homework_web/resolvers/transactions_resolver.ex index 64919d44..520ae89c 100644 --- a/elixir/lib/homework_web/resolvers/transactions_resolver.ex +++ b/elixir/lib/homework_web/resolvers/transactions_resolver.ex @@ -2,6 +2,7 @@ defmodule HomeworkWeb.Resolvers.TransactionsResolver do alias Homework.Merchants alias Homework.Transactions alias Homework.Users + alias Homework.Companies @doc """ Get a list of transcations @@ -24,6 +25,13 @@ defmodule HomeworkWeb.Resolvers.TransactionsResolver do {:ok, Merchants.get_merchant!(merchant_id)} end + @doc """ + Get the company associated with a transaction + """ + def company_transaction(_root, _args, %{source: %{company_id: company_id}}) do + {:ok, Companies.get_company!(company_id)} + end + @doc """ Search transactions and filter by amount """ diff --git a/elixir/lib/homework_web/resolvers/users_resolver.ex b/elixir/lib/homework_web/resolvers/users_resolver.ex index 21bc41be..025e15f7 100644 --- a/elixir/lib/homework_web/resolvers/users_resolver.ex +++ b/elixir/lib/homework_web/resolvers/users_resolver.ex @@ -1,5 +1,6 @@ defmodule HomeworkWeb.Resolvers.UsersResolver do alias Homework.Users + alias Homework.Companies @doc """ Get a list of users @@ -8,6 +9,14 @@ defmodule HomeworkWeb.Resolvers.UsersResolver do {:ok, Users.list_users(args)} end + @doc """ + Get the company associated with the user + """ + + def company_user(_root, _args, %{source: %{company_id: company_id}}) do + {:ok, Companies.get_company!(company_id)} + end + @doc """ Searches for users by first and last name. diff --git a/elixir/lib/homework_web/schema.ex b/elixir/lib/homework_web/schema.ex index 56888d2f..f46af692 100644 --- a/elixir/lib/homework_web/schema.ex +++ b/elixir/lib/homework_web/schema.ex @@ -7,6 +7,8 @@ defmodule HomeworkWeb.Schema do alias HomeworkWeb.Resolvers.MerchantsResolver alias HomeworkWeb.Resolvers.TransactionsResolver alias HomeworkWeb.Resolvers.UsersResolver + alias HomeworkWeb.Resolvers.CompaniesResolver + import_types(HomeworkWeb.Schemas.Types) query do @@ -24,11 +26,17 @@ defmodule HomeworkWeb.Schema do field(:merchants, list_of(:merchant)) do resolve(&MerchantsResolver.merchants/3) end + + @desc "Get all Companies" + field(:companies, list_of(:company)) do + resolve(&CompaniesResolver.companies/3) + end end mutation do import_fields(:transaction_mutations) import_fields(:user_mutations) import_fields(:merchant_mutations) + import_fields(:company_mutations) end end diff --git a/elixir/lib/homework_web/schemas/companies_schema.ex b/elixir/lib/homework_web/schemas/companies_schema.ex new file mode 100644 index 00000000..04b64ce9 --- /dev/null +++ b/elixir/lib/homework_web/schemas/companies_schema.ex @@ -0,0 +1,28 @@ +defmodule HomeworkWeb.Schemas.CompaniesSchema do + @moduledoc """ + Defines the graphql schema for user. + """ + use Absinthe.Schema.Notation + + alias HomeworkWeb.Resolvers.CompaniesResolver + + object :company do + field(:id, non_null(:id)) + field(:name, :string) + field(:credit_limit, :integer) + field(:available_credit, :integer) + field(:inserted_at, :naive_datetime) + field(:updated_at, :naive_datetime) + end + + object :company_mutations do + @desc "Create a new company" + field :create_company, :company do + arg(:name, non_null(:string)) + arg(:credit_line, non_null(:integer)) + arg(:available_credit, non_null(:integer)) + + resolve(&CompaniesResolver.create_company/3) + end + end +end diff --git a/elixir/lib/homework_web/schemas/transactions_schema.ex b/elixir/lib/homework_web/schemas/transactions_schema.ex index 533b2d8e..d1347918 100644 --- a/elixir/lib/homework_web/schemas/transactions_schema.ex +++ b/elixir/lib/homework_web/schemas/transactions_schema.ex @@ -14,14 +14,18 @@ defmodule HomeworkWeb.Schemas.TransactionsSchema do field(:debit, :boolean) field(:description, :string) field(:merchant_id, :id) + field(:company_id, :id) field(:inserted_at, :naive_datetime) field(:updated_at, :naive_datetime) - field(:user, :user) do resolve(&TransactionsResolver.user/3) end + field(:company, :company) do + resolve(&TransactionsResolver.company_transaction/3) + end + field(:merchant, :merchant) do resolve(&TransactionsResolver.merchant/3) end @@ -37,6 +41,7 @@ defmodule HomeworkWeb.Schemas.TransactionsSchema do arg(:credit, non_null(:boolean)) arg(:debit, non_null(:boolean)) arg(:description, non_null(:string)) + arg(:company_id, non_null(:id)) resolve(&TransactionsResolver.create_transaction/3) end @@ -59,6 +64,7 @@ defmodule HomeworkWeb.Schemas.TransactionsSchema do arg(:credit, non_null(:boolean)) arg(:debit, non_null(:boolean)) arg(:description, non_null(:string)) + arg(:company_id, non_null(:id)) resolve(&TransactionsResolver.update_transaction/3) end diff --git a/elixir/lib/homework_web/schemas/types.ex b/elixir/lib/homework_web/schemas/types.ex index 75540319..9e3db397 100644 --- a/elixir/lib/homework_web/schemas/types.ex +++ b/elixir/lib/homework_web/schemas/types.ex @@ -5,6 +5,7 @@ defmodule HomeworkWeb.Schemas.Types do use Absinthe.Schema.Notation import_types(Absinthe.Type.Custom) + import_types(HomeworkWeb.Schemas.CompaniesSchema) import_types(HomeworkWeb.Schemas.MerchantsSchema) import_types(HomeworkWeb.Schemas.TransactionsSchema) import_types(HomeworkWeb.Schemas.UsersSchema) diff --git a/elixir/lib/homework_web/schemas/users_schema.ex b/elixir/lib/homework_web/schemas/users_schema.ex index 2fa905c7..1bd2df5f 100644 --- a/elixir/lib/homework_web/schemas/users_schema.ex +++ b/elixir/lib/homework_web/schemas/users_schema.ex @@ -11,8 +11,14 @@ defmodule HomeworkWeb.Schemas.UsersSchema do field(:dob, :string) field(:first_name, :string) field(:last_name, :string) + field(:company_id, :id) field(:inserted_at, :naive_datetime) field(:updated_at, :naive_datetime) + + + field(:company, :company) do + resolve(&UsersResolver.company_user/3) + end end object :user_mutations do @@ -21,6 +27,7 @@ defmodule HomeworkWeb.Schemas.UsersSchema do arg(:dob, non_null(:string)) arg(:first_name, non_null(:string)) arg(:last_name, non_null(:string)) + arg(:company_id, non_null(:id)) resolve(&UsersResolver.create_user/3) end @@ -39,6 +46,7 @@ defmodule HomeworkWeb.Schemas.UsersSchema do arg(:dob, non_null(:string)) arg(:first_name, non_null(:string)) arg(:last_name, non_null(:string)) + arg(:company_id, non_null(:id)) resolve(&UsersResolver.update_user/3) end diff --git a/elixir/priv/repo/migrations/20191207150025_create_companies.exs b/elixir/priv/repo/migrations/20191207150025_create_companies.exs new file mode 100644 index 00000000..fbe84c57 --- /dev/null +++ b/elixir/priv/repo/migrations/20191207150025_create_companies.exs @@ -0,0 +1,14 @@ +defmodule Homework.Repo.Migrations.CreateCompanies do + use Ecto.Migration + + def change do + create table(:companies, primary_key: false) do + add(:id, :uuid, primary_key: true) + add(:name, :string) + add(:credit_line, :integer) + add(:available_credit, :integer) + + timestamps() + end + end +end diff --git a/elixir/priv/repo/migrations/20200826195245_create_users.exs b/elixir/priv/repo/migrations/20200826195245_create_users.exs index b59bf89b..fbb7f176 100644 --- a/elixir/priv/repo/migrations/20200826195245_create_users.exs +++ b/elixir/priv/repo/migrations/20200826195245_create_users.exs @@ -7,6 +7,7 @@ defmodule Homework.Repo.Migrations.CreateUsers do add(:first_name, :string) add(:last_name, :string) add(:dob, :string) + add(:company_id, references(:companies, type: :uuid, on_delete: :nothing)) timestamps() end diff --git a/elixir/priv/repo/migrations/20200826196533_create_transactions.exs b/elixir/priv/repo/migrations/20200826196533_create_transactions.exs index b8785d99..2aef1210 100644 --- a/elixir/priv/repo/migrations/20200826196533_create_transactions.exs +++ b/elixir/priv/repo/migrations/20200826196533_create_transactions.exs @@ -10,6 +10,7 @@ defmodule Homework.Repo.Migrations.CreateTransactions do add(:description, :string) add(:user_id, references(:users, type: :uuid, on_delete: :nothing)) add(:merchant_id, references(:merchants, type: :uuid, on_delete: :nothing)) + add(:company_id, references(:companies, type: :uuid, on_delete: :nothing)) timestamps() end From aff525d190c0da88ba521146ba97fe6ddbd35a6c Mon Sep 17 00:00:00 2001 From: Alex Porter Date: Wed, 7 Dec 2022 18:12:03 -0700 Subject: [PATCH 05/11] fixed one naming error, didn't realize that I had put credit_limit in the schema instead of credit_line, working correctly now. --- elixir/lib/homework_web/schemas/companies_schema.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elixir/lib/homework_web/schemas/companies_schema.ex b/elixir/lib/homework_web/schemas/companies_schema.ex index 04b64ce9..4f65617e 100644 --- a/elixir/lib/homework_web/schemas/companies_schema.ex +++ b/elixir/lib/homework_web/schemas/companies_schema.ex @@ -9,7 +9,7 @@ defmodule HomeworkWeb.Schemas.CompaniesSchema do object :company do field(:id, non_null(:id)) field(:name, :string) - field(:credit_limit, :integer) + field(:credit_line, :integer) field(:available_credit, :integer) field(:inserted_at, :naive_datetime) field(:updated_at, :naive_datetime) From 7b9834acf3a96d89638dd25891ad085566cacf56 Mon Sep 17 00:00:00 2001 From: Alex Porter Date: Wed, 7 Dec 2022 20:01:04 -0700 Subject: [PATCH 06/11] Fixed all testing, included company_id within user and transaction, also fixed failing test in transactions_test.exs. The changeset in transaction didn't have the :check in either the cast or validate_required, causing :credit to not be set in the database. All tests are now passing. --- .../lib/homework/transactions/transaction.ex | 4 +- .../resolvers/transactions_resolver.ex | 2 +- .../homework_web/resolvers/users_resolver.ex | 2 +- .../schemas/transactions_schema.ex | 12 +- .../lib/homework_web/schemas/users_schema.ex | 2 +- elixir/test/homework/transactions_test.exs | 45 ++++++-- elixir/test/homework/users_test.exs | 109 +++++++++++++----- 7 files changed, 129 insertions(+), 47 deletions(-) diff --git a/elixir/lib/homework/transactions/transaction.ex b/elixir/lib/homework/transactions/transaction.ex index 080b2d7e..789e728f 100644 --- a/elixir/lib/homework/transactions/transaction.ex +++ b/elixir/lib/homework/transactions/transaction.ex @@ -22,7 +22,7 @@ defmodule Homework.Transactions.Transaction do @doc false def changeset(transaction, attrs) do transaction - |> cast(attrs, [:user_id, :amount, :debit, :description, :merchant_id, :company_id]) - |> validate_required([:user_id, :amount, :debit, :description, :merchant_id, :company_id]) + |> cast(attrs, [:user_id, :amount, :debit, :credit, :description, :merchant_id, :company_id]) + |> validate_required([:user_id, :amount, :debit, :credit, :description, :merchant_id, :company_id]) end end diff --git a/elixir/lib/homework_web/resolvers/transactions_resolver.ex b/elixir/lib/homework_web/resolvers/transactions_resolver.ex index 520ae89c..dc6c07a1 100644 --- a/elixir/lib/homework_web/resolvers/transactions_resolver.ex +++ b/elixir/lib/homework_web/resolvers/transactions_resolver.ex @@ -28,7 +28,7 @@ defmodule HomeworkWeb.Resolvers.TransactionsResolver do @doc """ Get the company associated with a transaction """ - def company_transaction(_root, _args, %{source: %{company_id: company_id}}) do + def company(_root, _args, %{source: %{company_id: company_id}}) do {:ok, Companies.get_company!(company_id)} end diff --git a/elixir/lib/homework_web/resolvers/users_resolver.ex b/elixir/lib/homework_web/resolvers/users_resolver.ex index 025e15f7..a4ea7d64 100644 --- a/elixir/lib/homework_web/resolvers/users_resolver.ex +++ b/elixir/lib/homework_web/resolvers/users_resolver.ex @@ -13,7 +13,7 @@ defmodule HomeworkWeb.Resolvers.UsersResolver do Get the company associated with the user """ - def company_user(_root, _args, %{source: %{company_id: company_id}}) do + def company(_root, _args, %{source: %{company_id: company_id}}) do {:ok, Companies.get_company!(company_id)} end diff --git a/elixir/lib/homework_web/schemas/transactions_schema.ex b/elixir/lib/homework_web/schemas/transactions_schema.ex index d1347918..0163fd55 100644 --- a/elixir/lib/homework_web/schemas/transactions_schema.ex +++ b/elixir/lib/homework_web/schemas/transactions_schema.ex @@ -22,13 +22,13 @@ defmodule HomeworkWeb.Schemas.TransactionsSchema do resolve(&TransactionsResolver.user/3) end - field(:company, :company) do - resolve(&TransactionsResolver.company_transaction/3) - end - field(:merchant, :merchant) do resolve(&TransactionsResolver.merchant/3) end + + field(:company, :company) do + resolve(&TransactionsResolver.company/3) + end end object :transaction_mutations do @@ -36,12 +36,12 @@ defmodule HomeworkWeb.Schemas.TransactionsSchema do field :create_transaction, :transaction do arg(:user_id, non_null(:id)) arg(:merchant_id, non_null(:id)) + arg(:company_id, non_null(:id)) @desc "amount is in cents" arg(:amount, non_null(:integer)) arg(:credit, non_null(:boolean)) arg(:debit, non_null(:boolean)) arg(:description, non_null(:string)) - arg(:company_id, non_null(:id)) resolve(&TransactionsResolver.create_transaction/3) end @@ -59,12 +59,12 @@ defmodule HomeworkWeb.Schemas.TransactionsSchema do arg(:id, non_null(:id)) arg(:user_id, non_null(:id)) arg(:merchant_id, non_null(:id)) + arg(:company_id, non_null(:id)) @desc "amount is in cents" arg(:amount, non_null(:integer)) arg(:credit, non_null(:boolean)) arg(:debit, non_null(:boolean)) arg(:description, non_null(:string)) - arg(:company_id, non_null(:id)) resolve(&TransactionsResolver.update_transaction/3) end diff --git a/elixir/lib/homework_web/schemas/users_schema.ex b/elixir/lib/homework_web/schemas/users_schema.ex index 1bd2df5f..964f7843 100644 --- a/elixir/lib/homework_web/schemas/users_schema.ex +++ b/elixir/lib/homework_web/schemas/users_schema.ex @@ -17,7 +17,7 @@ defmodule HomeworkWeb.Schemas.UsersSchema do field(:company, :company) do - resolve(&UsersResolver.company_user/3) + resolve(&UsersResolver.company/3) end end diff --git a/elixir/test/homework/transactions_test.exs b/elixir/test/homework/transactions_test.exs index 03071aff..c196db31 100644 --- a/elixir/test/homework/transactions_test.exs +++ b/elixir/test/homework/transactions_test.exs @@ -5,11 +5,24 @@ defmodule Homework.TransactionsTest do alias Homework.Merchants alias Homework.Transactions alias Homework.Users + alias Homework.Companies describe "transactions" do alias Homework.Transactions.Transaction setup do + {:ok, company1} = + Companies.create_company(%{ + name: "some name", credit_line: 42, available_credit: 42 + }) + + {:ok, company2} = + Companies.create_company(%{ + name: "some updated name", + credit_line: 43, + available_credit: 43 + }) + {:ok, merchant1} = Merchants.create_merchant(%{description: "some description", name: "some name"}) @@ -23,23 +36,27 @@ defmodule Homework.TransactionsTest do Users.create_user(%{ dob: "some dob", first_name: "some first_name", - last_name: "some last_name" + last_name: "some last_name", + company_id: company1.id }) {:ok, user2} = Users.create_user(%{ dob: "some updated dob", first_name: "some updated first_name", - last_name: "some updated last_name" + last_name: "some updated last_name", + company_id: company2.id }) + valid_attrs = %{ amount: 42, credit: true, debit: true, description: "some description", merchant_id: merchant1.id, - user_id: user1.id + user_id: user1.id, + company_id: company1.id } update_attrs = %{ @@ -48,7 +65,8 @@ defmodule Homework.TransactionsTest do debit: false, description: "some updated description", merchant_id: merchant2.id, - user_id: user2.id + user_id: user2.id, + company_id: company2.id } invalid_attrs = %{ @@ -57,7 +75,8 @@ defmodule Homework.TransactionsTest do debit: nil, description: nil, merchant_id: nil, - user_id: nil + user_id: nil, + company_id: nil } {:ok, @@ -68,7 +87,9 @@ defmodule Homework.TransactionsTest do merchant1: merchant1, merchant2: merchant2, user1: user1, - user2: user2 + user2: user2, + company1: company1, + company2: company2 }} end @@ -94,7 +115,8 @@ defmodule Homework.TransactionsTest do test "create_transaction/1 with valid data creates a transaction", %{ valid_attrs: valid_attrs, merchant1: merchant1, - user1: user1 + user1: user1, + company1: company1 } do assert {:ok, %Transaction{} = transaction} = Transactions.create_transaction(valid_attrs) assert transaction.amount == 42 @@ -103,6 +125,7 @@ defmodule Homework.TransactionsTest do assert transaction.description == "some description" assert transaction.merchant_id == merchant1.id assert transaction.user_id == user1.id + assert transaction.company_id == company1.id end test "create_transaction/1 with invalid data returns error changeset", %{ @@ -115,7 +138,8 @@ defmodule Homework.TransactionsTest do valid_attrs: valid_attrs, update_attrs: update_attrs, merchant2: merchant2, - user2: user2 + user2: user2, + company2: company2 } do transaction = transaction_fixture(valid_attrs) @@ -128,6 +152,7 @@ defmodule Homework.TransactionsTest do assert transaction.description == "some updated description" assert transaction.merchant_id == merchant2.id assert transaction.user_id == user2.id + assert transaction.company_id == company2.id end test "update_transaction/2 with invalid data returns error changeset", %{ @@ -142,7 +167,9 @@ defmodule Homework.TransactionsTest do assert transaction == Transactions.get_transaction!(transaction.id) end - test "delete_transaction/1 deletes the transaction", %{valid_attrs: valid_attrs} do + test "delete_transaction/1 deletes the transaction", %{ + valid_attrs: valid_attrs + } do transaction = transaction_fixture(valid_attrs) assert {:ok, %Transaction{}} = Transactions.delete_transaction(transaction) assert_raise Ecto.NoResultsError, fn -> Transactions.get_transaction!(transaction.id) end diff --git a/elixir/test/homework/users_test.exs b/elixir/test/homework/users_test.exs index e1ae65c2..76d8b516 100644 --- a/elixir/test/homework/users_test.exs +++ b/elixir/test/homework/users_test.exs @@ -2,70 +2,125 @@ defmodule Homework.UsersTest do use Homework.DataCase alias Homework.Users + alias Homework.Companies describe "users" do alias Homework.Users.User - @valid_attrs %{dob: "some dob", first_name: "some first_name", last_name: "some last_name"} - @update_attrs %{ - dob: "some updated dob", - first_name: "some updated first_name", - last_name: "some updated last_name" - } - @invalid_attrs %{dob: nil, first_name: nil, last_name: nil} + setup do + {:ok, company1} = + Companies.create_company(%{ + name: "some name", credit_line: 42, available_credit: 42 + }) - def user_fixture(attrs \\ %{}) do + {:ok, company2} = + Companies.create_company(%{ + name: "some updated name", + credit_line: 43, + available_credit: 43 + }) + + valid_attrs = %{ + dob: "some dob", + first_name: "some first_name", + last_name: "some last_name", + company_id: company1.id + } + + update_attrs = %{ + dob: "some updated dob", + first_name: "some updated first_name", + last_name: "some updated last_name", + company_id: company2.id + } + + invalid_attrs = %{ + dob: nil, + first_name: nil, + last_name: nil, + company_id: nil + } + + {:ok, + %{ + valid_attrs: valid_attrs, + update_attrs: update_attrs, + invalid_attrs: invalid_attrs, + company1: company1, + company2: company2 + }} + end + + def user_fixture(valid_attrs, attrs \\ %{}) do {:ok, user} = attrs - |> Enum.into(@valid_attrs) + |> Enum.into(valid_attrs) |> Users.create_user() user end - test "list_users/1 returns all users" do - user = user_fixture() + test "list_users/1 returns all users", %{valid_attrs: valid_attrs} do + user = user_fixture(valid_attrs) assert Users.list_users([]) == [user] end - test "get_user!/1 returns the user with given id" do - user = user_fixture() + test "get_user!/1 returns the user with given id", %{valid_attrs: valid_attrs} do + user = user_fixture(valid_attrs) assert Users.get_user!(user.id) == user end - test "create_user/1 with valid data creates a user" do - assert {:ok, %User{} = user} = Users.create_user(@valid_attrs) + test "create_user/1 with valid data creates a user", %{ + valid_attrs: valid_attrs, + company1: company1 + } do + assert {:ok, %User{} = user} = Users.create_user(valid_attrs) assert user.dob == "some dob" assert user.first_name == "some first_name" assert user.last_name == "some last_name" + assert user.company_id == company1.id end - test "create_user/1 with invalid data returns error changeset" do - assert {:error, %Ecto.Changeset{}} = Users.create_user(@invalid_attrs) + test "create_user/1 with invalid data returns error changeset", %{ + invalid_attrs: invalid_attrs + } do + assert {:error, %Ecto.Changeset{}} = Users.create_user(invalid_attrs) end - test "update_user/2 with valid data updates the user" do - user = user_fixture() - assert {:ok, %User{} = user} = Users.update_user(user, @update_attrs) + test "update_user/2 with valid data updates the user", %{ + valid_attrs: valid_attrs, + update_attrs: update_attrs, + company2: company2 + } do + user = user_fixture(valid_attrs) + assert {:ok, %User{} = user} = Users.update_user(user, update_attrs) assert user.dob == "some updated dob" assert user.first_name == "some updated first_name" assert user.last_name == "some updated last_name" + assert user.company_id == company2.id end - test "update_user/2 with invalid data returns error changeset" do - user = user_fixture() - assert {:error, %Ecto.Changeset{}} = Users.update_user(user, @invalid_attrs) + test "update_user/2 with invalid data returns error changeset", %{ + valid_attrs: valid_attrs, + invalid_attrs: invalid_attrs + } do + user = user_fixture(valid_attrs) + assert {:error, %Ecto.Changeset{}} = Users.update_user(user, invalid_attrs) assert user == Users.get_user!(user.id) end - test "delete_user/1 deletes the user" do - user = user_fixture() + test "delete_user/1 deletes the user", %{ + valid_attrs: valid_attrs + } do + user = user_fixture(valid_attrs) assert {:ok, %User{}} = Users.delete_user(user) assert_raise Ecto.NoResultsError, fn -> Users.get_user!(user.id) end end - test "change_user/1 returns a user changeset" do - user = user_fixture() + test "change_user/1 returns a user changeset", %{ + valid_attrs: valid_attrs + } do + user = user_fixture(valid_attrs) assert %Ecto.Changeset{} = Users.change_user(user) end end From eebaa347f268326956276ab50be844c04f940095 Mon Sep 17 00:00:00 2001 From: Alex Porter Date: Thu, 8 Dec 2022 13:39:48 -0700 Subject: [PATCH 07/11] added delete and update functions for companies, was able to update the companies available_credit each time a new transaction occurs associated with a specific company_id --- elixir/lib/homework/companies.ex | 78 +++++++++++++++++++ elixir/lib/homework/companies/company.ex | 5 +- elixir/lib/homework/merchants.ex | 5 +- elixir/lib/homework/transactions.ex | 25 +++++- .../resolvers/companies_resolver.ex | 47 +++++++++++ .../homework_web/schemas/companies_schema.ex | 24 ++++++ 6 files changed, 177 insertions(+), 7 deletions(-) diff --git a/elixir/lib/homework/companies.ex b/elixir/lib/homework/companies.ex index 1f0e1cc9..78c6a509 100644 --- a/elixir/lib/homework/companies.ex +++ b/elixir/lib/homework/companies.ex @@ -35,12 +35,90 @@ defmodule Homework.Companies do """ def get_company!(id), do: Repo.get!(Company, id) + @doc """ + Gets a company by name. + + ## Example + + iex> get_company_by_name("Divvy") + %Company{} + + iex> get_company_by_name("X") + %[] + + """ + + def get_company_by_name(name) do + Repo.all( + from(c in Company, + where: ilike(c.name, ^"%#{name}%") + ) + ) + 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, %User{}} + + 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 diff --git a/elixir/lib/homework/companies/company.ex b/elixir/lib/homework/companies/company.ex index 5ed515bf..6acad63c 100644 --- a/elixir/lib/homework/companies/company.ex +++ b/elixir/lib/homework/companies/company.ex @@ -12,9 +12,10 @@ defmodule Homework.Companies.Company do end @doc false - def changeset(user, attrs) do - user + def changeset(company, attrs) do + company |> cast(attrs, [:name, :available_credit, :credit_line]) |> validate_required([:name, :available_credit, :credit_line]) end + end diff --git a/elixir/lib/homework/merchants.ex b/elixir/lib/homework/merchants.ex index 837e3b47..f034bd7f 100644 --- a/elixir/lib/homework/merchants.ex +++ b/elixir/lib/homework/merchants.ex @@ -43,10 +43,10 @@ defmodule Homework.Merchants do ## Example - iex> get_by_name("Divvy") + iex> get_merchant_by_name("Divvy") %Merchant{} - iex> get_by_name("X") + iex> get_merchant_by_name("X") %[] """ @@ -58,6 +58,7 @@ defmodule Homework.Merchants do ) ) end + @doc """ Creates a merchant. diff --git a/elixir/lib/homework/transactions.ex b/elixir/lib/homework/transactions.ex index b2a0eafe..45b36546 100644 --- a/elixir/lib/homework/transactions.ex +++ b/elixir/lib/homework/transactions.ex @@ -7,6 +7,7 @@ defmodule Homework.Transactions do alias Homework.Repo alias Homework.Transactions.Transaction + alias Homework.Companies.Company @doc """ Returns the list of transactions. @@ -70,9 +71,27 @@ defmodule Homework.Transactions do """ def create_transaction(attrs \\ %{}) do - %Transaction{} - |> Transaction.changeset(attrs) - |> Repo.insert() + transaction = + %Transaction{} + |> Transaction.changeset(attrs) + |> Repo.insert() + + {:ok, transaction} = transaction + + update_company_credit(transaction) + {:ok, transaction} + end + + @doc """ + Updates a companies available_credit each time a new transaction is created + assoicated with the company_id. + """ + + defp update_company_credit(transaction) do + company = Repo.get!(Company, transaction.company_id) + new_available_credit = company.available_credit - transaction.amount + result = Company.changeset(company, %{available_credit: new_available_credit}) + Repo.update(result) end @doc """ diff --git a/elixir/lib/homework_web/resolvers/companies_resolver.ex b/elixir/lib/homework_web/resolvers/companies_resolver.ex index 6e5a48d6..33d09e11 100644 --- a/elixir/lib/homework_web/resolvers/companies_resolver.ex +++ b/elixir/lib/homework_web/resolvers/companies_resolver.ex @@ -22,4 +22,51 @@ defmodule HomeworkWeb.Resolvers.CompaniesResolver do {:error, "could not create company: #{inspect(error)}"} end end + + @doc """ + Searches for companies by name. + + Returns the matching companies, if found. + Otherwise results in an empty list. + """ + + def search_company(_root, %{name: name}, _info) do + companies = Companies.get_company_by_name(name) + + if length(companies) > 0 do + {:ok, companies} + else + {:ok, []} + 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 diff --git a/elixir/lib/homework_web/schemas/companies_schema.ex b/elixir/lib/homework_web/schemas/companies_schema.ex index 4f65617e..c77ebf0a 100644 --- a/elixir/lib/homework_web/schemas/companies_schema.ex +++ b/elixir/lib/homework_web/schemas/companies_schema.ex @@ -24,5 +24,29 @@ defmodule HomeworkWeb.Schemas.CompaniesSchema do resolve(&CompaniesResolver.create_company/3) end + + @desc "Search for a company by name" + field :search_company, list_of(:company) do + arg(:name, non_null(:string)) + + resolve(&CompaniesResolver.search_company/3) + end + + @desc "Update a new company" + field :update_company, :company do + arg(:id, non_null(:id)) + arg(:name, non_null(:string)) + arg(:credit_line, non_null(:integer)) + arg(:available_credit, non_null(:integer)) + + resolve(&CompaniesResolver.update_company/3) + end + + @desc "Delete an existing company" + field :delete_company, :company do + arg(:id, non_null(:id)) + + resolve(&CompaniesResolver.delete_company/3) + end end end From 4e96481a7f312e272a24b0437bdb7e0c5f8fc664 Mon Sep 17 00:00:00 2001 From: Alex Porter Date: Thu, 8 Dec 2022 17:18:00 -0700 Subject: [PATCH 08/11] Created the data to seed the database inside the seeds.exs file, creating 5 of each user, merchant, transaction and company --- elixir/priv/repo/seeds.exs | 41 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/elixir/priv/repo/seeds.exs b/elixir/priv/repo/seeds.exs index 718e38ca..c154acd2 100644 --- a/elixir/priv/repo/seeds.exs +++ b/elixir/priv/repo/seeds.exs @@ -9,3 +9,44 @@ # # We recommend using the bang functions (`insert!`, `update!` # and so on) as they will fail if something goes wrong. + + +# user = %User{first_name: "Test", last_name: "Seeded", dob: "11/14/1992", company_id: company_id} +# Homework.Repo.insert!(user) + + +company = Homework.Repo.insert!(%Homework.Companies.Company{name: "Nvida", credit_line: 50000, available_credit: 50000}) +company1 = Homework.Repo.insert!(%Homework.Companies.Company{name: "company1", credit_line: 10000, available_credit: 10000}) +company2 = Homework.Repo.insert!(%Homework.Companies.Company{name: "company2", credit_line: 20000, available_credit: 20000}) +company3 = Homework.Repo.insert!(%Homework.Companies.Company{name: "company3", credit_line: 30000, available_credit: 30000}) +company4 = Homework.Repo.insert!(%Homework.Companies.Company{name: "company4", credit_line: 40000, available_credit: 40000}) + + +user1 = Homework.Repo.insert!(%Homework.Users.User{first_name: "Randy", last_name: "Johnson", dob: "12/12/1212", company_id: company.id}) +user2 = Homework.Repo.insert!(%Homework.Users.User{first_name: "Patrick", last_name: "Star", dob: "2/2/1212", company_id: company1.id}) +user3 = Homework.Repo.insert!(%Homework.Users.User{first_name: "Rocket", last_name: "Power", dob: "1/1/1212", company_id: company2.id}) +user4 = Homework.Repo.insert!(%Homework.Users.User{first_name: "Book", last_name: "Reader", dob: "3/12/1212", company_id: company3.id}) +user5 = Homework.Repo.insert!(%Homework.Users.User{first_name: "Game", last_name: "Enthusiast", dob: "4/12/1212", company_id: company4.id}) + +merchant = Homework.Repo.insert!(%Homework.Merchants.Merchant{name: "Practice", description: "Makes Perfect!"}) +merchant1 = Homework.Repo.insert!(%Homework.Merchants.Merchant{name: "Another", description: "One!"}) +merchant2 = Homework.Repo.insert!(%Homework.Merchants.Merchant{name: "Almost", description: "Done!"}) +merchant3 = Homework.Repo.insert!(%Homework.Merchants.Merchant{name: "Dream", description: "Job!"}) +merchant4 = Homework.Repo.insert!(%Homework.Merchants.Merchant{name: "Last", description: "Time!"}) + + +transaction = Homework.Repo.insert!(%Homework.Transactions.Transaction{ + amount: 1000, debit: false, credit: true, description: "large purchase", merchant_id: merchant.id, user_id: user1.id, company_id: company.id +}) +transaction1 = Homework.Repo.insert!(%Homework.Transactions.Transaction{ + amount: 100, debit: true, credit: false, description: "decent purchase", merchant_id: merchant1.id, user_id: user2.id, company_id: company1.id +}) +transaction2 = Homework.Repo.insert!(%Homework.Transactions.Transaction{ + amount: 10, debit: true, credit: false, description: "small purchase", merchant_id: merchant2.id, user_id: user3.id, company_id: company2.id +}) +transaction3 = Homework.Repo.insert!(%Homework.Transactions.Transaction{ + amount: 1, debit: true, credit: false, description: "tiny purchase", merchant_id: merchant3.id, user_id: user4.id, company_id: company3.id +}) +transaction4 = Homework.Repo.insert!(%Homework.Transactions.Transaction{ + amount: 2000, debit: false, credit: true, description: "huge purchase", merchant_id: merchant4.id, user_id: user5.id, company_id: company4.id +}) From 0a158886935df96a2ac063fd23912f4fac20559e Mon Sep 17 00:00:00 2001 From: Alex Porter Date: Fri, 9 Dec 2022 12:19:29 -0700 Subject: [PATCH 09/11] Fixed failing tests, and adjusted how I went about calling my update_company_credit inside of my create_transaction function. All tests are now passing with the database being seeded. --- elixir/lib/homework/transactions.ex | 13 ++++++++----- elixir/test/homework/merchants_test.exs | 2 +- elixir/test/homework/transactions_test.exs | 2 +- elixir/test/homework/users_test.exs | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/elixir/lib/homework/transactions.ex b/elixir/lib/homework/transactions.ex index 45b36546..67f80583 100644 --- a/elixir/lib/homework/transactions.ex +++ b/elixir/lib/homework/transactions.ex @@ -74,12 +74,15 @@ defmodule Homework.Transactions do transaction = %Transaction{} |> Transaction.changeset(attrs) - |> Repo.insert() - {:ok, transaction} = transaction + case Repo.insert(transaction) do + {:ok, transaction} -> + update_company_credit(transaction) + {:ok, transaction} - update_company_credit(transaction) - {:ok, transaction} + {:error, changeset} -> + {:error, changeset} + end end @doc """ @@ -87,7 +90,7 @@ defmodule Homework.Transactions do assoicated with the company_id. """ - defp update_company_credit(transaction) do + def update_company_credit(transaction) do company = Repo.get!(Company, transaction.company_id) new_available_credit = company.available_credit - transaction.amount result = Company.changeset(company, %{available_credit: new_available_credit}) diff --git a/elixir/test/homework/merchants_test.exs b/elixir/test/homework/merchants_test.exs index 2d8ce41d..eced7dd9 100644 --- a/elixir/test/homework/merchants_test.exs +++ b/elixir/test/homework/merchants_test.exs @@ -24,7 +24,7 @@ defmodule Homework.MerchantsTest do test "list_merchants/1 returns all merchants" do merchant = merchant_fixture() - assert Merchants.list_merchants([]) == [merchant] + assert merchant in Merchants.list_merchants([]) end test "get_merchant!/1 returns the merchant with given id" do diff --git a/elixir/test/homework/transactions_test.exs b/elixir/test/homework/transactions_test.exs index c196db31..822373ac 100644 --- a/elixir/test/homework/transactions_test.exs +++ b/elixir/test/homework/transactions_test.exs @@ -104,7 +104,7 @@ defmodule Homework.TransactionsTest do test "list_transactions/1 returns all transactions", %{valid_attrs: valid_attrs} do transaction = transaction_fixture(valid_attrs) - assert Transactions.list_transactions([]) == [transaction] + assert transaction in Transactions.list_transactions([]) end test "get_transaction!/1 returns the transaction with given id", %{valid_attrs: valid_attrs} do diff --git a/elixir/test/homework/users_test.exs b/elixir/test/homework/users_test.exs index 76d8b516..28b602ad 100644 --- a/elixir/test/homework/users_test.exs +++ b/elixir/test/homework/users_test.exs @@ -62,7 +62,7 @@ defmodule Homework.UsersTest do test "list_users/1 returns all users", %{valid_attrs: valid_attrs} do user = user_fixture(valid_attrs) - assert Users.list_users([]) == [user] + assert user in Users.list_users([]) end test "get_user!/1 returns the user with given id", %{valid_attrs: valid_attrs} do From 9da02703c0ab4e6f5cf047226986f8c1388f506c Mon Sep 17 00:00:00 2001 From: Alex Porter Date: Sun, 11 Dec 2022 11:12:58 -0700 Subject: [PATCH 10/11] Added tests for companies module, also adjusted the my seeding document to no longer have warnings with transactions 1,2,3,4 not being used. --- .../resolvers/companies_resolver.ex | 2 +- elixir/lib/homework_web/schema.ex | 70 +++++++++--------- elixir/priv/repo/seeds.exs | 10 +-- elixir/test/homework/companies_test.exs | 72 +++++++++++++++++++ 4 files changed, 113 insertions(+), 41 deletions(-) create mode 100644 elixir/test/homework/companies_test.exs diff --git a/elixir/lib/homework_web/resolvers/companies_resolver.ex b/elixir/lib/homework_web/resolvers/companies_resolver.ex index 33d09e11..e00a8041 100644 --- a/elixir/lib/homework_web/resolvers/companies_resolver.ex +++ b/elixir/lib/homework_web/resolvers/companies_resolver.ex @@ -1,6 +1,6 @@ defmodule HomeworkWeb.Resolvers.CompaniesResolver do - alias Homework. Companies + alias Homework.Companies @doc """ Get a list of companies diff --git a/elixir/lib/homework_web/schema.ex b/elixir/lib/homework_web/schema.ex index f46af692..42757096 100644 --- a/elixir/lib/homework_web/schema.ex +++ b/elixir/lib/homework_web/schema.ex @@ -1,42 +1,42 @@ -defmodule HomeworkWeb.Schema do - @moduledoc """ - Defines the graphql schema for this project. - """ - use Absinthe.Schema +# defmodule HomeworkWeb.Schema do +# @moduledoc """ +# Defines the graphql schema for this project. +# """ +# use Absinthe.Schema - alias HomeworkWeb.Resolvers.MerchantsResolver - alias HomeworkWeb.Resolvers.TransactionsResolver - alias HomeworkWeb.Resolvers.UsersResolver - alias HomeworkWeb.Resolvers.CompaniesResolver +# alias HomeworkWeb.Resolvers.MerchantsResolver +# alias HomeworkWeb.Resolvers.TransactionsResolver +# alias HomeworkWeb.Resolvers.UsersResolver +# alias HomeworkWeb.Resolvers.CompaniesResolver - import_types(HomeworkWeb.Schemas.Types) +# import_types(HomeworkWeb.Schemas.Types) - query do - @desc "Get all Transactions" - field(:transactions, list_of(:transaction)) do - resolve(&TransactionsResolver.transactions/3) - end +# query do +# @desc "Get all Transactions" +# field(:transactions, list_of(:transaction)) do +# resolve(&TransactionsResolver.transactions/3) +# end - @desc "Get all Users" - field(:users, list_of(:user)) do - resolve(&UsersResolver.users/3) - end +# @desc "Get all Users" +# field(:users, list_of(:user)) do +# resolve(&UsersResolver.users/3) +# end - @desc "Get all Merchants" - field(:merchants, list_of(:merchant)) do - resolve(&MerchantsResolver.merchants/3) - end +# @desc "Get all Merchants" +# field(:merchants, list_of(:merchant)) do +# resolve(&MerchantsResolver.merchants/3) +# end - @desc "Get all Companies" - field(:companies, list_of(:company)) do - resolve(&CompaniesResolver.companies/3) - end - end +# @desc "Get all Companies" +# field(:companies, list_of(:company)) do +# resolve(&CompaniesResolver.companies/3) +# end +# end - mutation do - import_fields(:transaction_mutations) - import_fields(:user_mutations) - import_fields(:merchant_mutations) - import_fields(:company_mutations) - end -end +# mutation do +# import_fields(:transaction_mutations) +# import_fields(:user_mutations) +# import_fields(:merchant_mutations) +# import_fields(:company_mutations) +# end +# end diff --git a/elixir/priv/repo/seeds.exs b/elixir/priv/repo/seeds.exs index c154acd2..4f828a89 100644 --- a/elixir/priv/repo/seeds.exs +++ b/elixir/priv/repo/seeds.exs @@ -35,18 +35,18 @@ merchant3 = Homework.Repo.insert!(%Homework.Merchants.Merchant{name: "Dream", de merchant4 = Homework.Repo.insert!(%Homework.Merchants.Merchant{name: "Last", description: "Time!"}) -transaction = Homework.Repo.insert!(%Homework.Transactions.Transaction{ +Homework.Repo.insert!(%Homework.Transactions.Transaction{ amount: 1000, debit: false, credit: true, description: "large purchase", merchant_id: merchant.id, user_id: user1.id, company_id: company.id }) -transaction1 = Homework.Repo.insert!(%Homework.Transactions.Transaction{ +Homework.Repo.insert!(%Homework.Transactions.Transaction{ amount: 100, debit: true, credit: false, description: "decent purchase", merchant_id: merchant1.id, user_id: user2.id, company_id: company1.id }) -transaction2 = Homework.Repo.insert!(%Homework.Transactions.Transaction{ +Homework.Repo.insert!(%Homework.Transactions.Transaction{ amount: 10, debit: true, credit: false, description: "small purchase", merchant_id: merchant2.id, user_id: user3.id, company_id: company2.id }) -transaction3 = Homework.Repo.insert!(%Homework.Transactions.Transaction{ +Homework.Repo.insert!(%Homework.Transactions.Transaction{ amount: 1, debit: true, credit: false, description: "tiny purchase", merchant_id: merchant3.id, user_id: user4.id, company_id: company3.id }) -transaction4 = Homework.Repo.insert!(%Homework.Transactions.Transaction{ +Homework.Repo.insert!(%Homework.Transactions.Transaction{ amount: 2000, debit: false, credit: true, description: "huge purchase", merchant_id: merchant4.id, user_id: user5.id, company_id: company4.id }) diff --git a/elixir/test/homework/companies_test.exs b/elixir/test/homework/companies_test.exs new file mode 100644 index 00000000..81f2b9d5 --- /dev/null +++ b/elixir/test/homework/companies_test.exs @@ -0,0 +1,72 @@ +defmodule Homework.CompaniesTest do + use Homework.DataCase + + alias Homework.Companies + + describe "companies" do + alias Homework.Companies.Company + + @valid_attrs %{name: "some name", credit_line: 1000, available_credit: 1000} + @update_attrs %{ + name: "some updated name", + credit_line: 2000, + available_credit: 2000 + } + @invalid_attrs %{name: nil, credit_line: nil, available_credit: nil} + + def company_fixture(attrs \\ %{}) do + {:ok, company} = + attrs + |> Enum.into(@valid_attrs) + |> Companies.create_company() + + company + end + + test "list_companies/1 returns all companies" do + company = company_fixture() + assert company in Companies.list_companies([]) + end + + test "get_company!/1 returns the company with given id" do + company = company_fixture() + assert Companies.get_company!(company.id) == company + end + + test "create_company/1 with valid data creates a company" do + assert {:ok, %Company{} = company} = Companies.create_company(@valid_attrs) + assert company.credit_line == 1000 + assert company.name == "some name" + assert company.available_credit == 1000 + end + + test "create_company/1 with invalid data returns error changeset" do + assert {:error, %Ecto.Changeset{}} = Companies.create_company(@invalid_attrs) + end + + test "update_company/2 with valid data updates the company" do + company = company_fixture() + assert {:ok, %Company{} = company} = Companies.update_company(company, @update_attrs) + assert company.credit_line == 2000 + assert company.name == "some updated name" + assert company.available_credit == 2000 + end + + test "update_company/2 with invalid data returns error changeset" do + company = company_fixture() + assert {:error, %Ecto.Changeset{}} = Companies.update_company(company, @invalid_attrs) + assert company == Companies.get_company!(company.id) + end + + test "delete_company/1 deletes the company" do + company = company_fixture() + assert {:ok, %Company{}} = Companies.delete_company(company) + assert_raise Ecto.NoResultsError, fn -> Companies.get_company!(company.id) end + end + + test "change_company/1 returns a company changeset" do + company = company_fixture() + assert %Ecto.Changeset{} = Companies.change_company(company) + end + end +end From 8c29d326ddba082e159271af6470074602c91121 Mon Sep 17 00:00:00 2001 From: Alex Porter Date: Sun, 11 Dec 2022 11:41:55 -0700 Subject: [PATCH 11/11] Fixed commented out schema. --- elixir/lib/homework_web/schema.ex | 70 +++++++++++++++---------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/elixir/lib/homework_web/schema.ex b/elixir/lib/homework_web/schema.ex index 42757096..f46af692 100644 --- a/elixir/lib/homework_web/schema.ex +++ b/elixir/lib/homework_web/schema.ex @@ -1,42 +1,42 @@ -# defmodule HomeworkWeb.Schema do -# @moduledoc """ -# Defines the graphql schema for this project. -# """ -# use Absinthe.Schema +defmodule HomeworkWeb.Schema do + @moduledoc """ + Defines the graphql schema for this project. + """ + use Absinthe.Schema -# alias HomeworkWeb.Resolvers.MerchantsResolver -# alias HomeworkWeb.Resolvers.TransactionsResolver -# alias HomeworkWeb.Resolvers.UsersResolver -# alias HomeworkWeb.Resolvers.CompaniesResolver + alias HomeworkWeb.Resolvers.MerchantsResolver + alias HomeworkWeb.Resolvers.TransactionsResolver + alias HomeworkWeb.Resolvers.UsersResolver + alias HomeworkWeb.Resolvers.CompaniesResolver -# import_types(HomeworkWeb.Schemas.Types) + import_types(HomeworkWeb.Schemas.Types) -# query do -# @desc "Get all Transactions" -# field(:transactions, list_of(:transaction)) do -# resolve(&TransactionsResolver.transactions/3) -# end + query do + @desc "Get all Transactions" + field(:transactions, list_of(:transaction)) do + resolve(&TransactionsResolver.transactions/3) + end -# @desc "Get all Users" -# field(:users, list_of(:user)) do -# resolve(&UsersResolver.users/3) -# end + @desc "Get all Users" + field(:users, list_of(:user)) do + resolve(&UsersResolver.users/3) + end -# @desc "Get all Merchants" -# field(:merchants, list_of(:merchant)) do -# resolve(&MerchantsResolver.merchants/3) -# end + @desc "Get all Merchants" + field(:merchants, list_of(:merchant)) do + resolve(&MerchantsResolver.merchants/3) + end -# @desc "Get all Companies" -# field(:companies, list_of(:company)) do -# resolve(&CompaniesResolver.companies/3) -# end -# end + @desc "Get all Companies" + field(:companies, list_of(:company)) do + resolve(&CompaniesResolver.companies/3) + end + end -# mutation do -# import_fields(:transaction_mutations) -# import_fields(:user_mutations) -# import_fields(:merchant_mutations) -# import_fields(:company_mutations) -# end -# end + mutation do + import_fields(:transaction_mutations) + import_fields(:user_mutations) + import_fields(:merchant_mutations) + import_fields(:company_mutations) + end +end