From acb056210f42e57c40413ddceb905e20615a064c Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Tue, 21 Sep 2021 20:30:15 -0500 Subject: [PATCH 01/32] First commit going to branch to make changes. --- elixir/config/dev.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elixir/config/dev.exs b/elixir/config/dev.exs index f2d078f5..4a8fea95 100644 --- a/elixir/config/dev.exs +++ b/elixir/config/dev.exs @@ -2,7 +2,7 @@ use Mix.Config # Configure your database config :homework, Homework.Repo, - username: System.get_env("POSTGRES_USER") || "postgres", + username: System.get_env("POSTGRES_USER") || "cjem", password: System.get_env("POSTGRES_PASSWORD") || "postgres", hostname: System.get_env("POSTGRES_HOST") || "localhost", database: System.get_env("POSTGRES_DATABASE") || "homework_dev", From 5d684de75dc5e37ddb2819eff707dec15b441b88 Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Fri, 26 Nov 2021 16:38:53 -0600 Subject: [PATCH 02/32] Added the company and the association with user. But have not added a company user relation in DB --- elixir/lib/homework/companies.ex | 104 ++++++++++++++++++ elixir/lib/homework/companies/company.ex | 21 ++++ elixir/lib/homework/users/user.ex | 6 +- .../20211126221536_create_company.exs | 14 +++ ...20211126222138_add_company_id_to_users.exs | 11 ++ elixir/test/homework/companies_test.exs | 68 ++++++++++++ 6 files changed, 222 insertions(+), 2 deletions(-) create mode 100644 elixir/lib/homework/companies.ex create mode 100644 elixir/lib/homework/companies/company.ex create mode 100644 elixir/priv/repo/migrations/20211126221536_create_company.exs create mode 100644 elixir/priv/repo/migrations/20211126222138_add_company_id_to_users.exs create mode 100644 elixir/test/homework/companies_test.exs diff --git a/elixir/lib/homework/companies.ex b/elixir/lib/homework/companies.ex new file mode 100644 index 00000000..95cc3629 --- /dev/null +++ b/elixir/lib/homework/companies.ex @@ -0,0 +1,104 @@ +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 company. + + ## Examples + + iex> list_company() + [%Company{}, ...] + + """ + def list_company do + Repo.all(Company) + end + + @doc """ + Gets a single company. + + Raises `Ecto.NoResultsError` if the Company does not exist. + + ## 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. + + ## 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 diff --git a/elixir/lib/homework/companies/company.ex b/elixir/lib/homework/companies/company.ex new file mode 100644 index 00000000..315816f6 --- /dev/null +++ b/elixir/lib/homework/companies/company.ex @@ -0,0 +1,21 @@ +defmodule Homework.Companies.Company do + use Ecto.Schema + import Ecto.Changeset + alias Homework.Companies.Company + + schema "company" do + field :available_credit, :integer + field :credit_line, :integer + field :name, :string + has_many :users, Company + + 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 diff --git a/elixir/lib/homework/users/user.ex b/elixir/lib/homework/users/user.ex index 51ea2f95..f93e24a3 100644 --- a/elixir/lib/homework/users/user.ex +++ b/elixir/lib/homework/users/user.ex @@ -1,12 +1,14 @@ 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 @@ -14,7 +16,7 @@ defmodule Homework.Users.User do @doc false def changeset(user, attrs) do user - |> cast(attrs, [:first_name, :last_name, :dob]) - |> validate_required([:first_name, :last_name, :dob]) + |> cast(attrs, [:company_id, :first_name, :last_name, :dob]) + |> validate_required([:company_id, :first_name, :last_name, :dob]) end end diff --git a/elixir/priv/repo/migrations/20211126221536_create_company.exs b/elixir/priv/repo/migrations/20211126221536_create_company.exs new file mode 100644 index 00000000..ca22855f --- /dev/null +++ b/elixir/priv/repo/migrations/20211126221536_create_company.exs @@ -0,0 +1,14 @@ +defmodule Homework.Repo.Migrations.CreateCompany do + use Ecto.Migration + + def change do + create table(:company) do + add :name, :string + add :credit_line, :integer + add :available_credit, :integer + + timestamps() + end + + end +end diff --git a/elixir/priv/repo/migrations/20211126222138_add_company_id_to_users.exs b/elixir/priv/repo/migrations/20211126222138_add_company_id_to_users.exs new file mode 100644 index 00000000..f8ce8006 --- /dev/null +++ b/elixir/priv/repo/migrations/20211126222138_add_company_id_to_users.exs @@ -0,0 +1,11 @@ +defmodule Homework.Repo.Migrations.AddCompanyIdToUsers do + use Ecto.Migration + + def change do + alter table(:users) do + add :company_id, references(:company) + end + + create index(:users, [:company_id]) + end +end diff --git a/elixir/test/homework/companies_test.exs b/elixir/test/homework/companies_test.exs new file mode 100644 index 00000000..49a9b2b4 --- /dev/null +++ b/elixir/test/homework/companies_test.exs @@ -0,0 +1,68 @@ +defmodule Homework.CompaniesTest do + use Homework.DataCase + + alias Homework.Companies + + describe "company" do + alias Homework.Companies.Company + + @valid_attrs %{available_credit: 42, credit_line: 42, name: "some name"} + @update_attrs %{available_credit: 43, credit_line: 43, name: "some updated name"} + @invalid_attrs %{available_credit: nil, credit_line: nil, name: nil} + + def company_fixture(attrs \\ %{}) do + {:ok, company} = + attrs + |> Enum.into(@valid_attrs) + |> Companies.create_company() + + company + end + + test "list_company/0 returns all company" do + company = company_fixture() + assert Companies.list_company() == [company] + 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.available_credit == 42 + assert company.credit_line == 42 + assert company.name == "some name" + 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.available_credit == 43 + assert company.credit_line == 43 + assert company.name == "some updated name" + 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 002d82ac55239ae964d8087c741aaf1931cbaec6 Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Sat, 27 Nov 2021 11:55:30 -0600 Subject: [PATCH 03/32] removed some migrations --- .../migrations/20211126221536_create_company.exs | 14 -------------- .../20211126222138_add_company_id_to_users.exs | 11 ----------- 2 files changed, 25 deletions(-) delete mode 100644 elixir/priv/repo/migrations/20211126221536_create_company.exs delete mode 100644 elixir/priv/repo/migrations/20211126222138_add_company_id_to_users.exs diff --git a/elixir/priv/repo/migrations/20211126221536_create_company.exs b/elixir/priv/repo/migrations/20211126221536_create_company.exs deleted file mode 100644 index ca22855f..00000000 --- a/elixir/priv/repo/migrations/20211126221536_create_company.exs +++ /dev/null @@ -1,14 +0,0 @@ -defmodule Homework.Repo.Migrations.CreateCompany do - use Ecto.Migration - - def change do - create table(:company) do - add :name, :string - add :credit_line, :integer - add :available_credit, :integer - - timestamps() - end - - end -end diff --git a/elixir/priv/repo/migrations/20211126222138_add_company_id_to_users.exs b/elixir/priv/repo/migrations/20211126222138_add_company_id_to_users.exs deleted file mode 100644 index f8ce8006..00000000 --- a/elixir/priv/repo/migrations/20211126222138_add_company_id_to_users.exs +++ /dev/null @@ -1,11 +0,0 @@ -defmodule Homework.Repo.Migrations.AddCompanyIdToUsers do - use Ecto.Migration - - def change do - alter table(:users) do - add :company_id, references(:company) - end - - create index(:users, [:company_id]) - end -end From e5c12aa4ad647e9ecece618ecfaf5c3245eb7d6b Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Sat, 27 Nov 2021 13:18:15 -0600 Subject: [PATCH 04/32] Have company model --- .../migrations/20211127183521_company_model.exs | 13 +++++++++++++ .../20211127184041_associate_users_company.exs | 9 +++++++++ 2 files changed, 22 insertions(+) create mode 100644 elixir/priv/repo/migrations/20211127183521_company_model.exs create mode 100644 elixir/priv/repo/migrations/20211127184041_associate_users_company.exs diff --git a/elixir/priv/repo/migrations/20211127183521_company_model.exs b/elixir/priv/repo/migrations/20211127183521_company_model.exs new file mode 100644 index 00000000..4c66ccbc --- /dev/null +++ b/elixir/priv/repo/migrations/20211127183521_company_model.exs @@ -0,0 +1,13 @@ +defmodule Homework.Repo.Migrations.CompanyModel do + use Ecto.Migration + + def change do + create table(:company, primary_key: false) do + add(:id, :uuid, primary_key: true) + add(:credit_line, :integer) + add(:available_credit, :integer) + add(:name, :string) + end + + end +end diff --git a/elixir/priv/repo/migrations/20211127184041_associate_users_company.exs b/elixir/priv/repo/migrations/20211127184041_associate_users_company.exs new file mode 100644 index 00000000..ab1ea54f --- /dev/null +++ b/elixir/priv/repo/migrations/20211127184041_associate_users_company.exs @@ -0,0 +1,9 @@ +defmodule Homework.Repo.Migrations.AssociateUsersCompany do + use Ecto.Migration + + def change do + alter table(:users) do + add :company_id, references(:company, type: :uuid, on_delete: :nothing) + end + end +end From e6fdf5e110a69a9871f82b072f838bd678ecb494 Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Sat, 4 Dec 2021 19:01:17 -0600 Subject: [PATCH 05/32] Fixed companies. Related company to transaction. seeded db --- elixir/lib/homework/transactions/transaction.ex | 6 ++++-- .../repo/migrations/20211127183521_company_model.exs | 1 + ...20211205005058_add-transaction-relation-company.exs | 10 ++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 elixir/priv/repo/migrations/20211205005058_add-transaction-relation-company.exs 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/priv/repo/migrations/20211127183521_company_model.exs b/elixir/priv/repo/migrations/20211127183521_company_model.exs index 4c66ccbc..8fa72df0 100644 --- a/elixir/priv/repo/migrations/20211127183521_company_model.exs +++ b/elixir/priv/repo/migrations/20211127183521_company_model.exs @@ -7,6 +7,7 @@ defmodule Homework.Repo.Migrations.CompanyModel do add(:credit_line, :integer) add(:available_credit, :integer) add(:name, :string) + timestamps() end end diff --git a/elixir/priv/repo/migrations/20211205005058_add-transaction-relation-company.exs b/elixir/priv/repo/migrations/20211205005058_add-transaction-relation-company.exs new file mode 100644 index 00000000..1f3b2186 --- /dev/null +++ b/elixir/priv/repo/migrations/20211205005058_add-transaction-relation-company.exs @@ -0,0 +1,10 @@ +defmodule :"Elixir.Homework.Repo.Migrations.Add-transaction-relation-company" do + use Ecto.Migration + + + def change do + alter table(:transactions) do + add(:company_id, references(:company, type: :uuid, on_delete: :nothing)) + end + end +end From d7ad38c6d5635f4cedefb655c52c9630c85e4143 Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Sun, 5 Dec 2021 15:58:52 -0600 Subject: [PATCH 06/32] Some change to tests --- elixir/config/test.exs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/elixir/config/test.exs b/elixir/config/test.exs index 37314737..ef21afd3 100644 --- a/elixir/config/test.exs +++ b/elixir/config/test.exs @@ -6,8 +6,8 @@ use Mix.Config # to provide built-in test partitioning in CI environment. # Run `mix help test` for more information. config :homework, Homework.Repo, - username: System.get_env("POSTGRES_USER") || "postgres", - password: System.get_env("POSTGRES_PASSWORD") || "postgres", + username: System.get_env("POSTGRES_USER") || "cjem", + password: System.get_env("POSTGRES_PASSWORD") || "", hostname: System.get_env("POSTGRES_HOST") || "localhost", database: System.get_env("POSTGRES_DATABASE") || "homework_dev", pool: Ecto.Adapters.SQL.Sandbox From f8ba1d89b267ad93e5068c934d5f4e3caa0605bc Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Sun, 5 Dec 2021 16:36:47 -0600 Subject: [PATCH 07/32] Closer to adding a company --- .../resolvers/companies_resolvers.ex | 54 +++++++++++++++++++ elixir/lib/homework_web/schema.ex | 8 +++ .../homework_web/schemas/companies_schema.ex | 45 ++++++++++++++++ elixir/lib/homework_web/schemas/types.ex | 1 + 4 files changed, 108 insertions(+) create mode 100644 elixir/lib/homework_web/resolvers/companies_resolvers.ex create mode 100644 elixir/lib/homework_web/schemas/companies_schema.ex diff --git a/elixir/lib/homework_web/resolvers/companies_resolvers.ex b/elixir/lib/homework_web/resolvers/companies_resolvers.ex new file mode 100644 index 00000000..765a82d6 --- /dev/null +++ b/elixir/lib/homework_web/resolvers/companies_resolvers.ex @@ -0,0 +1,54 @@ +defmodule HomeworkWeb.Resolvers.CompaniesResolver do + alias Homework.Companies + + @doc """ + Get a list of companies + """ + def companies(_root, _args, _info) do + {:ok, Companies.list_company()} + end + + @doc """ + Creates a companies + """ + 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 + + @doc """ + Updates a company for an id with args specified. + """ + def update_company(_root, %{id: id} = args, _info) do + company = Companies.get_company!(id) + !(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 user 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/schema.ex b/elixir/lib/homework_web/schema.ex index 56888d2f..d23c0a19 100644 --- a/elixir/lib/homework_web/schema.ex +++ b/elixir/lib/homework_web/schema.ex @@ -7,6 +7,7 @@ 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 +25,18 @@ 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.company/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..dffd11e1 --- /dev/null +++ b/elixir/lib/homework_web/schemas/companies_schema.ex @@ -0,0 +1,45 @@ +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_line, :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 + + @desc "Update a new user" + field :update_company, :user do + arg(:name, non_null(:string)) + arg(:credit_line, non_null(:integer)) + arg(:available_credit, non_null(:integer)) + arg(:id, non_null(:id)) + + 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 diff --git a/elixir/lib/homework_web/schemas/types.ex b/elixir/lib/homework_web/schemas/types.ex index 75540319..cb9a1c56 100644 --- a/elixir/lib/homework_web/schemas/types.ex +++ b/elixir/lib/homework_web/schemas/types.ex @@ -8,4 +8,5 @@ defmodule HomeworkWeb.Schemas.Types do import_types(HomeworkWeb.Schemas.MerchantsSchema) import_types(HomeworkWeb.Schemas.TransactionsSchema) import_types(HomeworkWeb.Schemas.UsersSchema) + import_types(HomeworkWeb.Schemas.CompaniesSchema) end From d9168d6dd45cdfb7bbf12e4dba131e53a869d06b Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Sun, 5 Dec 2021 17:10:00 -0600 Subject: [PATCH 08/32] Working on making companies work in the graphiql --- elixir/lib/homework_web/schema.ex | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/elixir/lib/homework_web/schema.ex b/elixir/lib/homework_web/schema.ex index d23c0a19..d5834f73 100644 --- a/elixir/lib/homework_web/schema.ex +++ b/elixir/lib/homework_web/schema.ex @@ -28,7 +28,7 @@ defmodule HomeworkWeb.Schema do @desc "Get all Companies" field(:companies, list_of(:company)) do - resolve(&CompaniesResolver.company/3) + resolve(&CompanyResolver.companies/3) end end @@ -37,6 +37,5 @@ defmodule HomeworkWeb.Schema do import_fields(:user_mutations) import_fields(:merchant_mutations) import_fields(:company_mutations) - end end From 8da541b3b48baebcb4e2a834700056b56d19d249 Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Sun, 5 Dec 2021 17:43:59 -0600 Subject: [PATCH 09/32] Can see all the models in tdhe graphql thingy --- elixir/lib/homework_web/resolvers/companies_resolvers.ex | 4 ++-- elixir/lib/homework_web/schema.ex | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/elixir/lib/homework_web/resolvers/companies_resolvers.ex b/elixir/lib/homework_web/resolvers/companies_resolvers.ex index 765a82d6..4eb153ee 100644 --- a/elixir/lib/homework_web/resolvers/companies_resolvers.ex +++ b/elixir/lib/homework_web/resolvers/companies_resolvers.ex @@ -4,8 +4,8 @@ defmodule HomeworkWeb.Resolvers.CompaniesResolver do @doc """ Get a list of companies """ - def companies(_root, _args, _info) do - {:ok, Companies.list_company()} + def companies(_root, args, _info) do + {:ok, Companies.list_company(args)} end @doc """ diff --git a/elixir/lib/homework_web/schema.ex b/elixir/lib/homework_web/schema.ex index d5834f73..23bdff48 100644 --- a/elixir/lib/homework_web/schema.ex +++ b/elixir/lib/homework_web/schema.ex @@ -28,7 +28,7 @@ defmodule HomeworkWeb.Schema do @desc "Get all Companies" field(:companies, list_of(:company)) do - resolve(&CompanyResolver.companies/3) + resolve(&CompaniesResolver.companies/3) end end From d5264dd52415be2ab9b1e88f2c502f82b85f820e Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Sun, 5 Dec 2021 17:44:12 -0600 Subject: [PATCH 10/32] Working on making companies work in the graphiql --- elixir/lib/homework/companies.ex | 2 +- elixir/lib/homework/companies/company.ex | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/elixir/lib/homework/companies.ex b/elixir/lib/homework/companies.ex index 95cc3629..e96f0495 100644 --- a/elixir/lib/homework/companies.ex +++ b/elixir/lib/homework/companies.ex @@ -17,7 +17,7 @@ defmodule Homework.Companies do [%Company{}, ...] """ - def list_company do + def list_company(_args) do Repo.all(Company) end diff --git a/elixir/lib/homework/companies/company.ex b/elixir/lib/homework/companies/company.ex index 315816f6..b15fe1b4 100644 --- a/elixir/lib/homework/companies/company.ex +++ b/elixir/lib/homework/companies/company.ex @@ -3,6 +3,7 @@ defmodule Homework.Companies.Company do import Ecto.Changeset alias Homework.Companies.Company + @primary_key {:id, :binary_id, autogenerate: true} schema "company" do field :available_credit, :integer field :credit_line, :integer From 7595bd3df38332975f49d48f61d296e69af5bc13 Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Sun, 5 Dec 2021 19:43:50 -0600 Subject: [PATCH 11/32] Added the seed file --- seed.py | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 seed.py diff --git a/seed.py b/seed.py new file mode 100644 index 00000000..dcd4eea9 --- /dev/null +++ b/seed.py @@ -0,0 +1,156 @@ +import uuid +import random +from datetime import datetime +import pytz +from sqlalchemy import create_engine, Column, Integer, String, DateTime, Boolean, ForeignKey, select +from sqlalchemy.orm import declarative_base, sessionmaker, relationship, backref +from sqlalchemy.dialects.postgresql import UUID +from faker import Faker + + +faker = Faker() +DATABASE_URI = 'postgresql+psycopg2://cjem:password@localhost/homework_dev' +Base = declarative_base() + +engine = create_engine(DATABASE_URI, echo=True) +Session = sessionmaker(bind=engine) +session = Session() + +################################# + +# creates the table +# Base.metadata.create_all(engine) + +################################# + +class Company(Base): + __tablename__='company' + id = Column(UUID(as_uuid=True), primary_key=True) + name = Column(String) + available_credit = Column(Integer) + credit_line = Column(Integer) + inserted_at=Column(DateTime, nullable=False) + updated_at=Column(DateTime, nullable=False) + user = relationship("Users", back_populates="company", uselist=False) + transaction = relationship("Transactions", back_populates="company", uselist=False) + +class Users(Base): + __tablename__ = 'users' + id = Column(UUID(as_uuid=True), primary_key=True) + first_name = Column(String) + last_name = Column(String) + dob = Column(String) + inserted_at=Column(DateTime, nullable=False) + updated_at=Column(DateTime, nullable=False) + transaction = relationship("Transactions", back_populates="users", uselist=False) + company_id = Column(UUID(as_uuid=True), ForeignKey('company.id')) + company = relationship("Company", back_populates="user") + + + +class Merchants(Base): + __tablename__ = 'merchants' + id = Column(UUID(as_uuid=True), primary_key=True) + name = Column(String) + description = Column(String) + inserted_at=Column(DateTime, nullable=False) + updated_at=Column(DateTime, nullable=False) + transaction = relationship("Transactions", back_populates="merchants", uselist=False) + +class Transactions(Base): + __tablename__ = 'transactions' + id = Column(UUID(as_uuid=True), primary_key=True) + amount = Column(Integer) + credit = Column(Boolean) + debit = Column(Boolean) + description = Column(String) + user_id = Column(UUID(as_uuid=True), ForeignKey('users.id')) + users = relationship("Users", back_populates="transaction") + merchant_id = Column(UUID(as_uuid=True), ForeignKey('merchants.id')) + merchants = relationship("Merchants", back_populates="transaction") + inserted_at=Column(DateTime, nullable=False) + updated_at=Column(DateTime, nullable=False) + company_id = Column(UUID(as_uuid=True), ForeignKey('company.id')) + company = relationship("Company", back_populates="transaction") + + +# c = Company( +# id=uuid.uuid1(), +# name="Hello", +# available_credit=1000, +# credit_line=1000, +# inserted_at=datetime.utcnow().strftime('%Y-%m-%d %H:%m:%S'), +# updated_at=datetime.utcnow().strftime('%Y-%m-%d %H:%m:%S') +# ) +for entry in range (1, 10): + + c = Company( + id=uuid.uuid1(), + name=faker.company(), + credit_line=100000, + inserted_at=datetime.utcnow().strftime('%Y-%m-%d %H:%m:%S'), + updated_at=datetime.utcnow().strftime('%Y-%m-%d %H:%m:%S') + ) + session.add(c) + session.commit() + + for u in range(1, 20): + user = Users( + id=uuid.uuid1(), + first_name=faker.first_name(), + last_name=faker.last_name(), + dob=faker.date_of_birth(), + inserted_at=datetime.utcnow().strftime('%Y-%m-%d %H:%m:%S'), + updated_at=datetime.utcnow().strftime('%Y-%m-%d %H:%m:%S'), + company_id = c.id + ) + session.add(user) + session.commit() + + merch = Merchants( + id=uuid.uuid1(), + name=faker.company(), + description=faker.catch_phrase(), + inserted_at=datetime.utcnow().strftime('%Y-%m-%d %H:%m:%S'), + updated_at=datetime.utcnow().strftime('%Y-%m-%d %H:%m:%S') + ) + + session.add(merch) + session.commit() + + for purchase in range(1, 5): + purchase = Transactions( + id=uuid.uuid1(), + amount=random.randrange(1, 1000), + credit=False, + debit=True, + description=faker.sentence(nb_words=5), + user_id=user.id, + company_id=c.id, + merchant_id=merch.id, + inserted_at=datetime.utcnow().strftime('%Y-%m-%d %H:%m:%S'), + updated_at=datetime.utcnow().strftime('%Y-%m-%d %H:%m:%S') + + ) + session.add(purchase) + session.commit() + + +######################################### +## QUERIES + +## for row in session.query(User, User.first_name).all(): +## print(row.User, row.first_name) + +######################################### + + + +## for i in range(1, 10): +## print(i) +## user = User(name=fake.name()) +## session.add(user) +## session.commit() +# # Base.metadata.create_all(engine) + + From 2d4c1bad75dcb7cdfd1542673e88c6d9399e8671 Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Sun, 5 Dec 2021 19:50:01 -0600 Subject: [PATCH 12/32] Added req. file for seeding --- requirements.txt | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..e5e0e4b0 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,8 @@ +Faker==9.9.0 +greenlet==1.1.2 +psycopg2==2.9.2 +python-dateutil==2.8.2 +pytz==2021.3 +six==1.16.0 +SQLAlchemy==1.4.27 +text-unidecode==1.3 From 8d4de383d602a4404b6089df4531588ac7b4c6ca Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Sun, 5 Dec 2021 20:17:09 -0600 Subject: [PATCH 13/32] Added some README documentation --- backend.md | 41 +++++++++++++++++++++++++++++++++++++++++ seed.py | 15 +++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/backend.md b/backend.md index d8378128..a6290fa6 100644 --- a/backend.md +++ b/backend.md @@ -1,5 +1,46 @@ # Divvy Backend Homework Instructions +### Chad Jemmett Divvy Homework Project + +Greetings Divvy Devs. +I have completed the homework in the application process to a Backend Developer at Divvy. +This is a strong example of the work you can expect from me when I start at Divvy. You will give me a project, I will +read and understand the documentation. Then I will implement the feature. +I work idependently, but I always know when to ask the right questions about the process. I enjoy collaboration and code +reviews. + +Please review the following two projects. + + +The first is in this repository. It demonstrates my abilities in Elixir, Ecto and Phoenix. +The second is here: [It is a demonstration of my ability to write an api in Python]()https://github.com/ceejaay/transaction_tracker + +Please visit my other repository to review my work as a current backend developer in Python. + +### My work in this project. +I made two accomplishments on this project. + +1. I wrote a python script to seed the database. +2. I created the components of a new `Company` model. + +The python script to seed the database is here: [Seed File](https://github.com/ceejaay/web-homework/blob/master/seed.py) +At first I researched how to seed the database with the existing `seed` file included in the Homework app. I found the +learning curve to be steep, so I accomplished the task with the tools I am most familiar with. So I used python and a +couple of libraries to seed the Postgres database. +You can read instructions to run the seed in the `seed.py` file. + +For the `Company` model. I researched the Ecto documentation on their website. First I generated a context for the +Company model. I then manually created the relation among the `Company`, `User`, and `Transaction` + +During the procject I solved a number of problems. The most complex of which was using the wrong setting for the UUID ID +number on the `Company` model. I solved the problem by setting the UUID to `:binary_id`. Through experimentation and +research I was able to sucessfully use the models and their functions on the command line. + +I did complete several steps. There are a few things I am excited to ask you about in our future interview. + +Please contact me at your earliest convenience so we can talk about my work. + + This repository provides a starting point for a basic React + GraphQL application. All of the configuration boilerplate is complete so you can start by writing the code that you want us to see. diff --git a/seed.py b/seed.py index dcd4eea9..47f41cd5 100644 --- a/seed.py +++ b/seed.py @@ -8,6 +8,21 @@ from faker import Faker +################################# + +# How to use this file +# Before using these steps, use mix ecto.create, mix ecto.migrate to create and migrate the database. +# 1. Use pyenv to create a virtual environment to install the dependencies. +# 2. Type pyenv virtualenv 3.8.4 seed-environment. This will create a python environment with Python v. 3.8.4 +# 3. Activate the environment by typing pyenv activate seed-environment +# 4. Install the dependencies using the requiremnts.txt file. Type: pip install -r requirements.txt +# 5. Update the path to your postgres database. Set the DATABASE_URI url to 'postgresql+psycopg2://:@localhost/homework_dev' +# 5. When that is complete, type python seed.py and it will seed the database. +################################# + + + faker = Faker() DATABASE_URI = 'postgresql+psycopg2://cjem:password@localhost/homework_dev' Base = declarative_base() From 292a1df6c12d5e41c13bfccc0202d023ba1df6b3 Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Sun, 5 Dec 2021 20:18:39 -0600 Subject: [PATCH 14/32] Formatting --- backend.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/backend.md b/backend.md index a6290fa6..31fc8aed 100644 --- a/backend.md +++ b/backend.md @@ -41,6 +41,12 @@ I did complete several steps. There are a few things I am excited to ask you abo Please contact me at your earliest convenience so we can talk about my work. + +************************************************************************************************* + + + + This repository provides a starting point for a basic React + GraphQL application. All of the configuration boilerplate is complete so you can start by writing the code that you want us to see. From d964f3f517a5f9f2c9f7d51d3a7f5a32e445f23b Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Sun, 5 Dec 2021 20:25:30 -0600 Subject: [PATCH 15/32] Update the readme. --- backend.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/backend.md b/backend.md index 31fc8aed..3d944e2b 100644 --- a/backend.md +++ b/backend.md @@ -3,43 +3,43 @@ ### Chad Jemmett Divvy Homework Project Greetings Divvy Devs. -I have completed the homework in the application process to a Backend Developer at Divvy. +I have completed the homework in the application process to a Backend Developer Position at Divvy. This is a strong example of the work you can expect from me when I start at Divvy. You will give me a project, I will read and understand the documentation. Then I will implement the feature. -I work idependently, but I always know when to ask the right questions about the process. I enjoy collaboration and code +I work idependently, but I always know when to ask the right questions about the process and I enjoy collaboration and code reviews. Please review the following two projects. The first is in this repository. It demonstrates my abilities in Elixir, Ecto and Phoenix. -The second is here: [It is a demonstration of my ability to write an api in Python]()https://github.com/ceejaay/transaction_tracker +The second is here: [It is a demonstration of my ability to write an api in +Python.](https://github.com/ceejaay/transaction_tracker) -Please visit my other repository to review my work as a current backend developer in Python. +Please visit my other repository to review the project. It is an example of the kind of work I do at my current job. -### My work in this project. +### My work in this Elixir project. I made two accomplishments on this project. 1. I wrote a python script to seed the database. 2. I created the components of a new `Company` model. -The python script to seed the database is here: [Seed File](https://github.com/ceejaay/web-homework/blob/master/seed.py) +The python script to seed the database is here: [Seed File.](https://github.com/ceejaay/web-homework/blob/master/seed.py) At first I researched how to seed the database with the existing `seed` file included in the Homework app. I found the -learning curve to be steep, so I accomplished the task with the tools I am most familiar with. So I used python and a +learning curve to be steep, so I accomplished the task with the tools I am most familiar with. I used python and a couple of libraries to seed the Postgres database. You can read instructions to run the seed in the `seed.py` file. For the `Company` model. I researched the Ecto documentation on their website. First I generated a context for the -Company model. I then manually created the relation among the `Company`, `User`, and `Transaction` - -During the procject I solved a number of problems. The most complex of which was using the wrong setting for the UUID ID -number on the `Company` model. I solved the problem by setting the UUID to `:binary_id`. Through experimentation and -research I was able to sucessfully use the models and their functions on the command line. - -I did complete several steps. There are a few things I am excited to ask you about in our future interview. +Company model. I then manually created the relation among the `Company`, `User`, and `Transaction`. +I created the shchema and resolvers for the model. +Thank you for your consideration. I look forward to your feedback on my work in our future interview. Please contact me at your earliest convenience so we can talk about my work. +- Chad Jemmett +chad.jemmett@gmail.com +208-305-0359 ************************************************************************************************* From 5f38dce603f3effd610fc2b152ae1d40f6add267 Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Sun, 5 Dec 2021 20:29:26 -0600 Subject: [PATCH 16/32] Updated the readme --- README.md | 43 +++++++++++++++++++++++++++++++++++++++++++ backend.md | 47 ----------------------------------------------- 2 files changed, 43 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 20c97a64..dff6e5b6 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,48 @@ # Divvy Homework Assignment +### Chad Jemmett Divvy Homework Project + +Greetings Divvy Devs. +I have completed the homework in the application process to a Backend Developer Position at Divvy. +This is a strong example of the work you can expect from me when I start at Divvy. You will give me a project, I will +read and understand the documentation. Then I will implement the feature. +I work idependently, but I always know when to ask the right questions about the process and I enjoy collaboration and code +reviews. + +Please review the following two projects. + + +The first is in this repository. It demonstrates my abilities in Elixir, Ecto and Phoenix. +The second is here: [It is a demonstration of my ability to write an api in +Python.](https://github.com/ceejaay/transaction_tracker) + +Please visit my other repository to review the project. It is an example of the kind of work I do at my current job. + +### My work in this Elixir project. +I made two accomplishments on this project. + +1. I wrote a python script to seed the database. +2. I created the components of a new `Company` model. + +The python script to seed the database is here: [Seed File.](https://github.com/ceejaay/web-homework/blob/master/seed.py) +At first I researched how to seed the database with the existing `seed` file included in the Homework app. I found the +learning curve to be steep, so I accomplished the task with the tools I am most familiar with. I used python and a +couple of libraries to seed the Postgres database. +You can read instructions to run the seed in the `seed.py` file. + +For the `Company` model. I researched the Ecto documentation on their website. First I generated a context for the +Company model. I then manually created the relation among the `Company`, `User`, and `Transaction`. +I created the shchema and resolvers for the model. + +Thank you for your consideration. I look forward to your feedback on my work in our future interview. +Please contact me at your earliest convenience so we can talk about my work. + +- Chad Jemmett +chad.jemmett@gmail.com +208-305-0359 + + +************************************************************************************************* This repository provides a starting point for a basic React + GraphQL application. All of the configuration boilerplate is complete so you can start by writing the code that you want us to see. diff --git a/backend.md b/backend.md index 3d944e2b..d8378128 100644 --- a/backend.md +++ b/backend.md @@ -1,52 +1,5 @@ # Divvy Backend Homework Instructions -### Chad Jemmett Divvy Homework Project - -Greetings Divvy Devs. -I have completed the homework in the application process to a Backend Developer Position at Divvy. -This is a strong example of the work you can expect from me when I start at Divvy. You will give me a project, I will -read and understand the documentation. Then I will implement the feature. -I work idependently, but I always know when to ask the right questions about the process and I enjoy collaboration and code -reviews. - -Please review the following two projects. - - -The first is in this repository. It demonstrates my abilities in Elixir, Ecto and Phoenix. -The second is here: [It is a demonstration of my ability to write an api in -Python.](https://github.com/ceejaay/transaction_tracker) - -Please visit my other repository to review the project. It is an example of the kind of work I do at my current job. - -### My work in this Elixir project. -I made two accomplishments on this project. - -1. I wrote a python script to seed the database. -2. I created the components of a new `Company` model. - -The python script to seed the database is here: [Seed File.](https://github.com/ceejaay/web-homework/blob/master/seed.py) -At first I researched how to seed the database with the existing `seed` file included in the Homework app. I found the -learning curve to be steep, so I accomplished the task with the tools I am most familiar with. I used python and a -couple of libraries to seed the Postgres database. -You can read instructions to run the seed in the `seed.py` file. - -For the `Company` model. I researched the Ecto documentation on their website. First I generated a context for the -Company model. I then manually created the relation among the `Company`, `User`, and `Transaction`. -I created the shchema and resolvers for the model. - -Thank you for your consideration. I look forward to your feedback on my work in our future interview. -Please contact me at your earliest convenience so we can talk about my work. - -- Chad Jemmett -chad.jemmett@gmail.com -208-305-0359 - - -************************************************************************************************* - - - - This repository provides a starting point for a basic React + GraphQL application. All of the configuration boilerplate is complete so you can start by writing the code that you want us to see. From 9b2577e3e9810c615e42b912dc2cdb48d2f87e6c Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Sun, 5 Dec 2021 20:37:23 -0600 Subject: [PATCH 17/32] The final commit and merge. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dff6e5b6..805d639e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Divvy Homework Assignment -### Chad Jemmett Divvy Homework Project +### Chad Jemmett's Divvy Homework Project Greetings Divvy Devs. I have completed the homework in the application process to a Backend Developer Position at Divvy. From 74bea554727f3b50d4089a463edd261b16f3c860 Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Tue, 4 Jan 2022 19:20:41 -0600 Subject: [PATCH 18/32] Have the basics of a seed file. Can seed Company with faker name --- elixir/mix.exs | 3 ++- elixir/mix.lock | 1 + elixir/priv/repo/seeds.exs | 25 +++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/elixir/mix.exs b/elixir/mix.exs index 5b7745a8..a77c2f00 100644 --- a/elixir/mix.exs +++ b/elixir/mix.exs @@ -45,7 +45,8 @@ defmodule Homework.MixProject do {:poison, "~> 2.1.0"}, {:postgrex, ">= 0.0.0"}, {:telemetry_metrics, "~> 0.4"}, - {:telemetry_poller, "~> 0.4"} + {:telemetry_poller, "~> 0.4"}, + {:faker, "~> 0.17"} ] end diff --git a/elixir/mix.lock b/elixir/mix.lock index e1906184..05f65a79 100644 --- a/elixir/mix.lock +++ b/elixir/mix.lock @@ -8,6 +8,7 @@ "decimal": {:hex, :decimal, "1.8.1", "a4ef3f5f3428bdbc0d35374029ffcf4ede8533536fa79896dd450168d9acdf3c", [:mix], [], "hexpm", "3cb154b00225ac687f6cbd4acc4b7960027c757a5152b369923ead9ddbca7aec"}, "ecto": {:hex, :ecto, "3.4.6", "08f7afad3257d6eb8613309af31037e16c36808dfda5a3cd0cb4e9738db030e4", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "6f13a9e2a62e75c2dcfc7207bfc65645ab387af8360db4c89fee8b5a4bf3f70b"}, "ecto_sql": {:hex, :ecto_sql, "3.4.5", "30161f81b167d561a9a2df4329c10ae05ff36eca7ccc84628f2c8b9fa1e43323", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.4.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.3.0 or ~> 0.4.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.0", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "31990c6a3579b36a3c0841d34a94c275e727de8b84f58509da5f1b2032c98ac2"}, + "faker": {:hex, :faker, "0.17.0", "671019d0652f63aefd8723b72167ecdb284baf7d47ad3a82a15e9b8a6df5d1fa", [:mix], [], "hexpm", "a7d4ad84a93fd25c5f5303510753789fc2433ff241bf3b4144d3f6f291658a6a"}, "gettext": {:hex, :gettext, "0.18.1", "89e8499b051c7671fa60782faf24409b5d2306aa71feb43d79648a8bc63d0522", [:mix], [], "hexpm", "e70750c10a5f88cb8dc026fc28fa101529835026dec4a06dba3b614f2a99c7a9"}, "jason": {:hex, :jason, "1.2.1", "12b22825e22f468c02eb3e4b9985f3d0cb8dc40b9bd704730efa11abd2708c44", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b659b8571deedf60f79c5a608e15414085fa141344e2716fbd6988a084b5f993"}, "mime": {:hex, :mime, "1.4.0", "5066f14944b470286146047d2f73518cf5cca82f8e4815cf35d196b58cf07c47", [:mix], [], "hexpm", "75fa42c4228ea9a23f70f123c74ba7cece6a03b1fd474fe13f6a7a85c6ea4ff6"}, diff --git a/elixir/priv/repo/seeds.exs b/elixir/priv/repo/seeds.exs index 718e38ca..70f2bb21 100644 --- a/elixir/priv/repo/seeds.exs +++ b/elixir/priv/repo/seeds.exs @@ -2,6 +2,7 @@ # # mix run priv/repo/seeds.exs # +# # Inside the script, you can read and write to any of your # repositories directly: # @@ -9,3 +10,27 @@ # # We recommend using the bang functions (`insert!`, `update!` # and so on) as they will fail if something goes wrong. +# +# + +defmodule Homework.DatabaseSeeder do + alias Homework.Companies.Company + alias Homework.Repo + + + def insert_company do + Repo.insert! %Company{ + available_credit: 99, + credit_line: 1000, + name: Faker.Company.name() + } + end + + def print_the_name(company) do + IO.puts company.name + end + + +end + +(1 .. 5) |> Enum.each(fn _ -> Homework.DatabaseSeeder.insert_company |> Homework.DatabaseSeeder.print_the_name() end) From 0c2649999b71ea6a7f1ad366988a68b9772cbc93 Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Tue, 4 Jan 2022 20:00:49 -0600 Subject: [PATCH 19/32] Can add all the elements. Just need to combine them in a way so they inherit each other --- elixir/priv/repo/seeds.exs | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/elixir/priv/repo/seeds.exs b/elixir/priv/repo/seeds.exs index 70f2bb21..6616ed44 100644 --- a/elixir/priv/repo/seeds.exs +++ b/elixir/priv/repo/seeds.exs @@ -16,6 +16,9 @@ defmodule Homework.DatabaseSeeder do alias Homework.Companies.Company alias Homework.Repo + alias Homework.Users.User + alias Homework.Merchants.Merchant + alias Homework.Transactions.Transaction def insert_company do @@ -26,11 +29,35 @@ defmodule Homework.DatabaseSeeder do } end - def print_the_name(company) do - IO.puts company.name + def insert_user(company) do + + Repo.insert! %User{ + first_name: Faker.Person.first_name(), + last_name: Faker.Person.last_name(), + dob: Date.to_string(Faker.Date.date_of_birth(1970 .. 1990)), + company_id: company.id + } + end + + def insert_merchant do + Repo.insert! %Merchant{ + description: Faker.Lorem.sentence(6 .. 10), + name: Faker.Commerce.En.department() + } + end + + def insert_transaction(merchant, user) do + Repo.insert! %Transaction{ + amount: :rand.uniform(100), + credit: true, + debit: false, + description: Faker.Commerce.En.department(), + merchant_id: merchant.id + user_id: user.id, + } end end -(1 .. 5) |> Enum.each(fn _ -> Homework.DatabaseSeeder.insert_company |> Homework.DatabaseSeeder.print_the_name() end) +(1 .. 5) |> Enum.each(fn _ -> Homework.DatabaseSeeder.insert_company |> Homework.DatabaseSeeder.create_user() |> new_merechant_transaction() end) From 7ebad802c4189d090f7c560016a119726eba2f32 Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Thu, 6 Jan 2022 21:50:53 -0600 Subject: [PATCH 20/32] Can add companies and associate users. --- elixir/priv/repo/seeds.exs | 40 ++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/elixir/priv/repo/seeds.exs b/elixir/priv/repo/seeds.exs index 6616ed44..eb3476de 100644 --- a/elixir/priv/repo/seeds.exs +++ b/elixir/priv/repo/seeds.exs @@ -30,13 +30,12 @@ defmodule Homework.DatabaseSeeder do end def insert_user(company) do - - Repo.insert! %User{ - first_name: Faker.Person.first_name(), - last_name: Faker.Person.last_name(), - dob: Date.to_string(Faker.Date.date_of_birth(1970 .. 1990)), - company_id: company.id - } + Repo.insert! %User{ + first_name: Faker.Person.first_name(), + last_name: Faker.Person.last_name(), + dob: Date.to_string(Faker.Date.date_of_birth(1970 .. 1990)), + company_id: Map.get(company, :id) + } end def insert_merchant do @@ -46,18 +45,39 @@ defmodule Homework.DatabaseSeeder do } end - def insert_transaction(merchant, user) do + def insert_transaction(user, company, merchant) do Repo.insert! %Transaction{ amount: :rand.uniform(100), credit: true, debit: false, description: Faker.Commerce.En.department(), - merchant_id: merchant.id + merchant_id: merchant.id, user_id: user.id, + company_id: company.id } end + def generate_data_set() do + (1 .. 5) |> Enum.each(fn _ -> Homework.DatabaseSeeder.insert_company() end) + + c = Homework.Repo.all(Homework.Companies.Company) + Enum.each(c, fn comp -> + (1 .. 10) |> Enum.each( + fn _ -> Homework.DatabaseSeeder.insert_user(comp) + end + ) + end) + # + # Enum.each(p, fn (person) -> IO.puts Map.get(person, :id) end) + end end -(1 .. 5) |> Enum.each(fn _ -> Homework.DatabaseSeeder.insert_company |> Homework.DatabaseSeeder.create_user() |> new_merechant_transaction() end) + + + + # Homework.DatabaseSeeder.generate_data_set() +# (1 .. 5) |> Enum.each( +# fn _ -> Homework.DatabaseSeeder.generate_data_set() +# end +# ) From 6dc268ab3fb755703a8ac09aa95bfb7650eabacd Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Thu, 6 Jan 2022 22:17:16 -0600 Subject: [PATCH 21/32] Laying ground work for transactions --- elixir/priv/repo/seeds.exs | 42 +++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/elixir/priv/repo/seeds.exs b/elixir/priv/repo/seeds.exs index eb3476de..0516c747 100644 --- a/elixir/priv/repo/seeds.exs +++ b/elixir/priv/repo/seeds.exs @@ -1,18 +1,3 @@ -# Script for populating the database. You can run it as: -# -# mix run priv/repo/seeds.exs -# -# -# Inside the script, you can read and write to any of your -# repositories directly: -# -# Homework.Repo.insert!(%Homework.SomeSchema{}) -# -# We recommend using the bang functions (`insert!`, `update!` -# and so on) as they will fail if something goes wrong. -# -# - defmodule Homework.DatabaseSeeder do alias Homework.Companies.Company alias Homework.Repo @@ -20,7 +5,6 @@ defmodule Homework.DatabaseSeeder do alias Homework.Merchants.Merchant alias Homework.Transactions.Transaction - def insert_company do Repo.insert! %Company{ available_credit: 99, @@ -51,22 +35,34 @@ defmodule Homework.DatabaseSeeder do credit: true, debit: false, description: Faker.Commerce.En.department(), - merchant_id: merchant.id, - user_id: user.id, - company_id: company.id + merchant_id: Map.get(merchant, :id), + user_id: Map.get(user, :id), + company_id: Map.get(company, :id) } end def generate_data_set() do (1 .. 5) |> Enum.each(fn _ -> Homework.DatabaseSeeder.insert_company() end) - + c = Homework.Repo.all(Homework.Companies.Company) Enum.each(c, fn comp -> (1 .. 10) |> Enum.each( - fn _ -> Homework.DatabaseSeeder.insert_user(comp) + fn _ -> + Homework.DatabaseSeeder.insert_user(comp) end - ) + Homework.DatabaseSeeder.insert_merchant() + m = Homework.Repo.all(Homework.Merchants.Merchant) + u = Homework.Repo.all(Homework.Users.User) + Enum.each(u, fn usr -> + (1 .. 20) |> Enum.each( + fn _ -> + IO.puts "hello world" + + end + ) + + end) end) # # Enum.each(p, fn (person) -> IO.puts Map.get(person, :id) end) @@ -76,7 +72,7 @@ end - # Homework.DatabaseSeeder.generate_data_set() + Homework.DatabaseSeeder.generate_data_set() # (1 .. 5) |> Enum.each( # fn _ -> Homework.DatabaseSeeder.generate_data_set() # end From e2ebdd02f8636dc22b60139eb4e2852df6b52033 Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Sat, 8 Jan 2022 12:24:38 -0600 Subject: [PATCH 22/32] Working seeding script. Adds everything. But does not calculate company credit line --- elixir/priv/repo/seeds.exs | 40 ++++++++++++++------------------------ 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/elixir/priv/repo/seeds.exs b/elixir/priv/repo/seeds.exs index 0516c747..3a8cee83 100644 --- a/elixir/priv/repo/seeds.exs +++ b/elixir/priv/repo/seeds.exs @@ -29,7 +29,7 @@ defmodule Homework.DatabaseSeeder do } end - def insert_transaction(user, company, merchant) do + def insert_transaction(user, merchant) do Repo.insert! %Transaction{ amount: :rand.uniform(100), credit: true, @@ -37,43 +37,33 @@ defmodule Homework.DatabaseSeeder do description: Faker.Commerce.En.department(), merchant_id: Map.get(merchant, :id), user_id: Map.get(user, :id), - company_id: Map.get(company, :id) + company_id: Map.get(user, :company_id) } end def generate_data_set() do + # create companies and merchants + (1 .. 10) |> Enum.each(fn _ -> Homework.DatabaseSeeder.insert_merchant() end) (1 .. 5) |> Enum.each(fn _ -> Homework.DatabaseSeeder.insert_company() end) - + # get companaies and merchants in a list c = Homework.Repo.all(Homework.Companies.Company) - Enum.each(c, fn comp -> - (1 .. 10) |> Enum.each( - fn _ -> - Homework.DatabaseSeeder.insert_user(comp) - end - ) - Homework.DatabaseSeeder.insert_merchant() m = Homework.Repo.all(Homework.Merchants.Merchant) - u = Homework.Repo.all(Homework.Users.User) - Enum.each(u, fn usr -> - (1 .. 20) |> Enum.each( - fn _ -> - IO.puts "hello world" - - end - ) + # create users beloning to companies + Enum.each(c, fn comp -> (1 .. 10) |> Enum.each(fn _ -> Homework.DatabaseSeeder.insert_user(comp)end)end) + u = Homework.Repo.all(Homework.Users.User) + # loop through merchants, loop through users. Create tranactions assign transaction to user, company and merchant + Enum.each(m, fn (merch) -> + Enum.each(u, fn (usr) -> + (1 .. 10) |> Enum.each(fn _ -> Homework.DatabaseSeeder.insert_transaction(usr, merch) end) end) + end) - # - # Enum.each(p, fn (person) -> IO.puts Map.get(person, :id) end) + end end - Homework.DatabaseSeeder.generate_data_set() -# (1 .. 5) |> Enum.each( -# fn _ -> Homework.DatabaseSeeder.generate_data_set() -# end -# ) +Homework.DatabaseSeeder.generate_data_set() From 44d2e573a3d69758643c7819acdbe1ec35fa9fac Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Sat, 8 Jan 2022 13:13:08 -0600 Subject: [PATCH 23/32] Restored the default variables. Added the POSTGRES_USER variable to my system variables --- elixir/config/dev.exs | 2 +- elixir/config/test.exs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/elixir/config/dev.exs b/elixir/config/dev.exs index 4a8fea95..f2d078f5 100644 --- a/elixir/config/dev.exs +++ b/elixir/config/dev.exs @@ -2,7 +2,7 @@ use Mix.Config # Configure your database config :homework, Homework.Repo, - username: System.get_env("POSTGRES_USER") || "cjem", + username: System.get_env("POSTGRES_USER") || "postgres", password: System.get_env("POSTGRES_PASSWORD") || "postgres", hostname: System.get_env("POSTGRES_HOST") || "localhost", database: System.get_env("POSTGRES_DATABASE") || "homework_dev", diff --git a/elixir/config/test.exs b/elixir/config/test.exs index ef21afd3..58fc2948 100644 --- a/elixir/config/test.exs +++ b/elixir/config/test.exs @@ -6,7 +6,7 @@ use Mix.Config # to provide built-in test partitioning in CI environment. # Run `mix help test` for more information. config :homework, Homework.Repo, - username: System.get_env("POSTGRES_USER") || "cjem", + username: System.get_env("POSTGRES_USER") || "postgres", password: System.get_env("POSTGRES_PASSWORD") || "", hostname: System.get_env("POSTGRES_HOST") || "localhost", database: System.get_env("POSTGRES_DATABASE") || "homework_dev", From a7d302f0899c434e1a75c829fe0477940db8fc39 Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Sun, 9 Jan 2022 21:18:13 -0600 Subject: [PATCH 24/32] updated readme and seed file --- README.md | 73 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 805d639e..ab157ff8 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,72 @@ # Divvy Homework Assignment -### Chad Jemmett's Divvy Homework Project +### Chad Jemmett's Divvy Homework Project -- Updated Jan 9, 2022 -Greetings Divvy Devs. -I have completed the homework in the application process to a Backend Developer Position at Divvy. -This is a strong example of the work you can expect from me when I start at Divvy. You will give me a project, I will -read and understand the documentation. Then I will implement the feature. -I work idependently, but I always know when to ask the right questions about the process and I enjoy collaboration and code -reviews. +To Divvy Devs, +Thank you for your feedback on my homework project. Kris Rickard sent me the feedback you gave on my work. I've copied +the pros and cons list here for your convenience. +To reiterate, this is the kind of work you can expect from me as a memeber of the Divvy team. I welcome feedback. I +research my mistakes and upate my work in a timely manner. I enjoy collaboration and being part of a team. I look +forward to doing an in-person code review with the Divvy Team. -Please review the following two projects. +> Pros: +> Company addition is clean and tests look good +> Seeds file is really robust… but it’s in python +> Cons: +> Definitely signs of a mid-level. Replaced default database creds instead of using system env, wrote a python seeds file instead of using elixir because it was more familiar. +> Questions: +> What is the risk/reward of adding python to an elixir project? +> How will you plan to learn elixir? + +The following are my corrections listed under CONS. + +I've written a [seed file in Elixir here.](https://github.com/ceejaay/web-homework/blob/master/elixir/priv/repo/seeds.exs) +This is written entirely in Elixir. I enumerate over a range of integers and lists of items retreived from the database +to insert Companies, Users, Merchants and Transactions into the database. I used the Faker module to write dummy data. + +I solved the problem of altering the default database credentials. I did research on Elixir's `System` module. I +set my PostgreSQL username in my `.zshrc` file. It solved the problem and I restored the default variables in the +[config/dev.exs](https://github.com/ceejaay/web-homework/blob/master/elixir/config/dev.exs) and the [prod.secret.exs](https://github.com/ceejaay/web-homework/blob/master/elixir/config/prod.secret.exs) files. + + +### Answers to Questions + +#### What the risk/reward of adding Python to an Elixir project? + + I would say the risks outweigh the rewards when adding Python to an Elixir application. I currently work on a Python and Django project with several apps. It’s beneficial to my team and I that we only have one language to manage when doing the majority of our work. Only a very serious problem would cause me to consider adding another language. And that problem would be one that would only be solved by an additional language. I would first attempt to solve the problem using Python. If that didn’t work, I’d consider something else. + + + I think the most frustrating risk of adding Python to an Elixir app would be a workflow problem. I personally dislike stopping my work in Python and moving to another language in my process. It’s more efficient to stay working in one language and its related framework. + + + As far as rewards, any script or app written in Python would be easy to get up and running. For a short-term solution to a problem, Python is a good choice. Right now, [Python is the second most popular language on Github.](https://madnight.github.io/githut/#/pull_requests/2021/4) Many experienced developers would easily find the right Python library to solve the problem. You may not even need extra libraries. Python has many options right out of the box. And the popularity of Python means any future developer wouldn’t need much to write new features for the app. + + + Overall, It wouldn’t be my first choice to add Python to an Elixir app. But if I had to, Python wouldn’t be a bad choice. + +#### How will you plan to learn Elixir? + +This bit of pseudo-code illustrates my learning process. +``` +while elixir_expert == False: + study_elixir_topic() + apply_knowledge_to_simple_project() + ask_for_feedback_from_experienced_devs() + +``` + + I’ve already started the feedback process. I’ve taken a Udemy course on Elixir. It’s a bit dated but I learned the + basics of the language. The tutorial builds two small programs. [The first is a basic program to shuffle and deal a + deck of cards.](https://github.com/ceejaay/elixir_card_shuffler) The second is far more interesting and fun. [It’s a script that generates identicon images.](https://github.com/ceejaay/elixir_project) Identicons are those random geometric images you see as profile pictures on some websites. + + As for questions and feedback. I’ve asked some questions in the Discord Elixir channel. The people there are very helpful. I look forward to working on the Divvy team and getting feedback from experienced developers. + + Part of my strategy is looking for interesting problem when building a simple project.I really enjoyed the problems presented in writing the `seed.exs` file for the homework. I understood the basics of creating and inserting an item into the database. But I needed a lot of research on how to handle the relationships and inserting a large amount of data. + + This process has resulted in success for me. Doing hobby projects in Ruby laid the foundation for the work I would do in my bootcamp, and that success brought me to my current job. You’ll see that this process will make me an excellent addition to the Divvy team. + + +Below is my original homework project you gave feedback on. The first is in this repository. It demonstrates my abilities in Elixir, Ecto and Phoenix. From 3848687b5f369e7dbaec98a35ecaa33431bd48e6 Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Sun, 9 Jan 2022 21:25:09 -0600 Subject: [PATCH 25/32] Fixed formatting on README --- README.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index ab157ff8..5cd857c0 100644 --- a/README.md +++ b/README.md @@ -33,16 +33,17 @@ set my PostgreSQL username in my `.zshrc` file. It solved the problem and I rest #### What the risk/reward of adding Python to an Elixir project? - I would say the risks outweigh the rewards when adding Python to an Elixir application. I currently work on a Python and Django project with several apps. It’s beneficial to my team and I that we only have one language to manage when doing the majority of our work. Only a very serious problem would cause me to consider adding another language. And that problem would be one that would only be solved by an additional language. I would first attempt to solve the problem using Python. If that didn’t work, I’d consider something else. +I would say the risks outweigh the rewards when adding Python to an Elixir application. I currently work on a Python and Django project with several apps. It’s beneficial to my team and I that we only have one language to manage when doing the majority of our work. Only a very serious problem would cause me to consider adding another language. And that problem would be one that would only be solved by an additional language. I would first attempt to solve the problem using Python. If that didn’t work, I’d consider something else. - I think the most frustrating risk of adding Python to an Elixir app would be a workflow problem. I personally dislike stopping my work in Python and moving to another language in my process. It’s more efficient to stay working in one language and its related framework. +I think the most frustrating risk of adding Python to an Elixir app would be a workflow problem. I personally dislike stopping my work in Python and moving to another language in my process. It’s more efficient to stay working in one language and its related framework. - As far as rewards, any script or app written in Python would be easy to get up and running. For a short-term solution to a problem, Python is a good choice. Right now, [Python is the second most popular language on Github.](https://madnight.github.io/githut/#/pull_requests/2021/4) Many experienced developers would easily find the right Python library to solve the problem. You may not even need extra libraries. Python has many options right out of the box. And the popularity of Python means any future developer wouldn’t need much to write new features for the app. + +As far as rewards, any script or app written in Python would be easy to get up and running. For a short-term solution to a problem, Python is a good choice. Right now, [Python is the second most popular language on Github.](https://madnight.github.io/githut/#/pull_requests/2021/4) Many experienced developers would easily find the right Python library to solve the problem. You may not even need extra libraries. Python has many options right out of the box. And the popularity of Python means any future developer wouldn’t need much to write new features for the app. - Overall, It wouldn’t be my first choice to add Python to an Elixir app. But if I had to, Python wouldn’t be a bad choice. +Overall, It wouldn’t be my first choice to add Python to an Elixir app. But if I had to, Python wouldn’t be a bad choice. #### How will you plan to learn Elixir? @@ -55,15 +56,15 @@ while elixir_expert == False: ``` - I’ve already started the feedback process. I’ve taken a Udemy course on Elixir. It’s a bit dated but I learned the - basics of the language. The tutorial builds two small programs. [The first is a basic program to shuffle and deal a - deck of cards.](https://github.com/ceejaay/elixir_card_shuffler) The second is far more interesting and fun. [It’s a script that generates identicon images.](https://github.com/ceejaay/elixir_project) Identicons are those random geometric images you see as profile pictures on some websites. +I’ve already started the feedback process. I’ve taken a Udemy course on Elixir. It’s a bit dated but I learned the +basics of the language. The tutorial builds two small programs. [The first is a basic program to shuffle and deal a +deck of cards.](https://github.com/ceejaay/elixir_card_shuffler) The second is far more interesting and fun. [It’s a script that generates identicon images.](https://github.com/ceejaay/elixir_project) Identicons are those random geometric images you see as profile pictures on some websites. - As for questions and feedback. I’ve asked some questions in the Discord Elixir channel. The people there are very helpful. I look forward to working on the Divvy team and getting feedback from experienced developers. +As for questions and feedback. I’ve asked some questions in the Discord Elixir channel. The people there are very helpful. I look forward to working on the Divvy team and getting feedback from experienced developers. - Part of my strategy is looking for interesting problem when building a simple project.I really enjoyed the problems presented in writing the `seed.exs` file for the homework. I understood the basics of creating and inserting an item into the database. But I needed a lot of research on how to handle the relationships and inserting a large amount of data. +Part of my strategy is looking for interesting problem when building a simple project.I really enjoyed the problems presented in writing the `seed.exs` file for the homework. I understood the basics of creating and inserting an item into the database. But I needed a lot of research on how to handle the relationships and inserting a large amount of data. - This process has resulted in success for me. Doing hobby projects in Ruby laid the foundation for the work I would do in my bootcamp, and that success brought me to my current job. You’ll see that this process will make me an excellent addition to the Divvy team. +This process has resulted in success for me. Doing hobby projects in Ruby laid the foundation for the work I would do in my bootcamp, and that success brought me to my current job. You’ll see that this process will make me an excellent addition to the Divvy team. Below is my original homework project you gave feedback on. From fd6bf84168d149c2c7713db1b76f26c3f638b9ca Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Sun, 9 Jan 2022 21:26:07 -0600 Subject: [PATCH 26/32] Fixed more formatting on README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5cd857c0..ad67249d 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ Part of my strategy is looking for interesting problem when building a simple pr This process has resulted in success for me. Doing hobby projects in Ruby laid the foundation for the work I would do in my bootcamp, and that success brought me to my current job. You’ll see that this process will make me an excellent addition to the Divvy team. -Below is my original homework project you gave feedback on. +# Below is my original homework project you gave feedback on. The first is in this repository. It demonstrates my abilities in Elixir, Ecto and Phoenix. From 42203a9f7b033f33a88b03e0477ce13b485e4ebc Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Sun, 9 Jan 2022 21:27:07 -0600 Subject: [PATCH 27/32] Fixed further problems on the README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ad67249d..b389e6af 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ set my PostgreSQL username in my `.zshrc` file. It solved the problem and I rest ### Answers to Questions -#### What the risk/reward of adding Python to an Elixir project? +#### What is the risk/reward of adding Python to an Elixir project? I would say the risks outweigh the rewards when adding Python to an Elixir application. I currently work on a Python and Django project with several apps. It’s beneficial to my team and I that we only have one language to manage when doing the majority of our work. Only a very serious problem would cause me to consider adding another language. And that problem would be one that would only be solved by an additional language. I would first attempt to solve the problem using Python. If that didn’t work, I’d consider something else. From c85b91444acbe7701bbfe7aa53306c67d99108f5 Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Mon, 10 Jan 2022 16:52:53 -0600 Subject: [PATCH 28/32] Fixed some grammar and tagged the Devs for review @jakerichan @thawk55 Hi, Please review my updated work on the Homework Project I worked on in application to a backend developer role at Divvy. Thank you. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b389e6af..c77b69dc 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ set my PostgreSQL username in my `.zshrc` file. It solved the problem and I rest #### What is the risk/reward of adding Python to an Elixir project? -I would say the risks outweigh the rewards when adding Python to an Elixir application. I currently work on a Python and Django project with several apps. It’s beneficial to my team and I that we only have one language to manage when doing the majority of our work. Only a very serious problem would cause me to consider adding another language. And that problem would be one that would only be solved by an additional language. I would first attempt to solve the problem using Python. If that didn’t work, I’d consider something else. +I would say the risks outweigh the rewards when adding Python to an Elixir application. I currently work on a Python and Django project with several apps. It’s beneficial to my team and I that we only have one language to manage when doing the majority of our work. Only a very serious problem would cause me to consider adding another language. And the solution to that problem would be something that *only* a new language could solve. I would first attempt to solve the problem using Python. If that didn’t work, I’d consider something else. I think the most frustrating risk of adding Python to an Elixir app would be a workflow problem. I personally dislike stopping my work in Python and moving to another language in my process. It’s more efficient to stay working in one language and its related framework. From ff4c9e836abe022ae003466805866f435996dcbf Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Sun, 29 May 2022 15:29:28 -0500 Subject: [PATCH 29/32] Added a some new files for toy db --- elixir/.env | 1 + elixir/config/config.exs | 3 +- elixir/config/dev.exs | 4 +- elixir/lib/homework/account.ex | 104 ++++++++++++++++++ elixir/lib/homework/account/card.ex | 17 +++ elixir/lib/homework/shiren.ex | 104 ++++++++++++++++++ elixir/lib/homework/shiren/prices.ex | 19 ++++ .../controllers/fallback_controller.ex | 16 +++ .../controllers/prices_controller.ex | 44 ++++++++ elixir/lib/homework_web/router.ex | 15 ++- .../lib/homework_web/views/changeset_view.ex | 19 ++++ elixir/lib/homework_web/views/prices_view.ex | 19 ++++ .../20220503015957_create_cards.exs | 12 ++ .../20220503021205_create_price.exs | 14 +++ elixir/test/homework/account_test.exs | 64 +++++++++++ elixir/test/homework/shiren_test.exs | 68 ++++++++++++ .../controllers/prices_controller_test.exs | 96 ++++++++++++++++ 17 files changed, 611 insertions(+), 8 deletions(-) create mode 100644 elixir/.env create mode 100644 elixir/lib/homework/account.ex create mode 100644 elixir/lib/homework/account/card.ex create mode 100644 elixir/lib/homework/shiren.ex create mode 100644 elixir/lib/homework/shiren/prices.ex create mode 100644 elixir/lib/homework_web/controllers/fallback_controller.ex create mode 100644 elixir/lib/homework_web/controllers/prices_controller.ex create mode 100644 elixir/lib/homework_web/views/changeset_view.ex create mode 100644 elixir/lib/homework_web/views/prices_view.ex create mode 100644 elixir/priv/repo/migrations/20220503015957_create_cards.exs create mode 100644 elixir/priv/repo/migrations/20220503021205_create_price.exs create mode 100644 elixir/test/homework/account_test.exs create mode 100644 elixir/test/homework/shiren_test.exs create mode 100644 elixir/test/homework_web/controllers/prices_controller_test.exs diff --git a/elixir/.env b/elixir/.env new file mode 100644 index 00000000..fb3fad1b --- /dev/null +++ b/elixir/.env @@ -0,0 +1 @@ +"POSTGRES_USER" = "cjem" diff --git a/elixir/config/config.exs b/elixir/config/config.exs index adeea69b..4657cabd 100644 --- a/elixir/config/config.exs +++ b/elixir/config/config.exs @@ -5,7 +5,8 @@ # is restricted to this project. # General application configuration -use Mix.Config +# use Mix.Config +import Config config :homework, ecto_repos: [Homework.Repo] diff --git a/elixir/config/dev.exs b/elixir/config/dev.exs index 4a8fea95..6fb34864 100644 --- a/elixir/config/dev.exs +++ b/elixir/config/dev.exs @@ -1,4 +1,6 @@ -use Mix.Config +# use Mix.Config + +import Config # Configure your database config :homework, Homework.Repo, diff --git a/elixir/lib/homework/account.ex b/elixir/lib/homework/account.ex new file mode 100644 index 00000000..c24c8d71 --- /dev/null +++ b/elixir/lib/homework/account.ex @@ -0,0 +1,104 @@ +defmodule Homework.Account do + @moduledoc """ + The Account context. + """ + + import Ecto.Query, warn: false + alias Homework.Repo + + alias Homework.Account.Card + + @doc """ + Returns the list of cards. + + ## Examples + + iex> list_cards() + [%Card{}, ...] + + """ + def list_cards do + Repo.all(Card) + end + + @doc """ + Gets a single card. + + Raises `Ecto.NoResultsError` if the Card does not exist. + + ## Examples + + iex> get_card!(123) + %Card{} + + iex> get_card!(456) + ** (Ecto.NoResultsError) + + """ + def get_card!(id), do: Repo.get!(Card, id) + + @doc """ + Creates a card. + + ## Examples + + iex> create_card(%{field: value}) + {:ok, %Card{}} + + iex> create_card(%{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def create_card(attrs \\ %{}) do + %Card{} + |> Card.changeset(attrs) + |> Repo.insert() + end + + @doc """ + Updates a card. + + ## Examples + + iex> update_card(card, %{field: new_value}) + {:ok, %Card{}} + + iex> update_card(card, %{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def update_card(%Card{} = card, attrs) do + card + |> Card.changeset(attrs) + |> Repo.update() + end + + @doc """ + Deletes a card. + + ## Examples + + iex> delete_card(card) + {:ok, %Card{}} + + iex> delete_card(card) + {:error, %Ecto.Changeset{}} + + """ + def delete_card(%Card{} = card) do + Repo.delete(card) + end + + @doc """ + Returns an `%Ecto.Changeset{}` for tracking card changes. + + ## Examples + + iex> change_card(card) + %Ecto.Changeset{data: %Card{}} + + """ + def change_card(%Card{} = card, attrs \\ %{}) do + Card.changeset(card, attrs) + end +end diff --git a/elixir/lib/homework/account/card.ex b/elixir/lib/homework/account/card.ex new file mode 100644 index 00000000..395e7c73 --- /dev/null +++ b/elixir/lib/homework/account/card.ex @@ -0,0 +1,17 @@ +defmodule Homework.Account.Card do + use Ecto.Schema + import Ecto.Changeset + + schema "cards" do + field :description, :string + + timestamps() + end + + @doc false + def changeset(card, attrs) do + card + |> cast(attrs, [:description]) + |> validate_required([:description]) + end +end diff --git a/elixir/lib/homework/shiren.ex b/elixir/lib/homework/shiren.ex new file mode 100644 index 00000000..5562b5da --- /dev/null +++ b/elixir/lib/homework/shiren.ex @@ -0,0 +1,104 @@ +defmodule Homework.Shiren do + @moduledoc """ + The Shiren context. + """ + + import Ecto.Query, warn: false + alias Homework.Repo + + alias Homework.Shiren.Prices + + @doc """ + Returns the list of price. + + ## Examples + + iex> list_price() + [%Prices{}, ...] + + """ + def list_price do + Repo.all(Prices) + end + + @doc """ + Gets a single prices. + + Raises `Ecto.NoResultsError` if the Prices does not exist. + + ## Examples + + iex> get_prices!(123) + %Prices{} + + iex> get_prices!(456) + ** (Ecto.NoResultsError) + + """ + def get_prices!(id), do: Repo.get!(Prices, id) + + @doc """ + Creates a prices. + + ## Examples + + iex> create_prices(%{field: value}) + {:ok, %Prices{}} + + iex> create_prices(%{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def create_prices(attrs \\ %{}) do + %Prices{} + |> Prices.changeset(attrs) + |> Repo.insert() + end + + @doc """ + Updates a prices. + + ## Examples + + iex> update_prices(prices, %{field: new_value}) + {:ok, %Prices{}} + + iex> update_prices(prices, %{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def update_prices(%Prices{} = prices, attrs) do + prices + |> Prices.changeset(attrs) + |> Repo.update() + end + + @doc """ + Deletes a prices. + + ## Examples + + iex> delete_prices(prices) + {:ok, %Prices{}} + + iex> delete_prices(prices) + {:error, %Ecto.Changeset{}} + + """ + def delete_prices(%Prices{} = prices) do + Repo.delete(prices) + end + + @doc """ + Returns an `%Ecto.Changeset{}` for tracking prices changes. + + ## Examples + + iex> change_prices(prices) + %Ecto.Changeset{data: %Prices{}} + + """ + def change_prices(%Prices{} = prices, attrs \\ %{}) do + Prices.changeset(prices, attrs) + end +end diff --git a/elixir/lib/homework/shiren/prices.ex b/elixir/lib/homework/shiren/prices.ex new file mode 100644 index 00000000..ff0f889f --- /dev/null +++ b/elixir/lib/homework/shiren/prices.ex @@ -0,0 +1,19 @@ +defmodule Homework.Shiren.Prices do + use Ecto.Schema + import Ecto.Changeset + + schema "price" do + field :amount, :integer + field :category, :string + field :type, :string + + timestamps() + end + + @doc false + def changeset(prices, attrs) do + prices + |> cast(attrs, [:category, :amount, :type]) + |> validate_required([:category, :amount, :type]) + end +end diff --git a/elixir/lib/homework_web/controllers/fallback_controller.ex b/elixir/lib/homework_web/controllers/fallback_controller.ex new file mode 100644 index 00000000..e0e7f474 --- /dev/null +++ b/elixir/lib/homework_web/controllers/fallback_controller.ex @@ -0,0 +1,16 @@ +defmodule HomeworkWeb.FallbackController do + @moduledoc """ + Translates controller action results into valid `Plug.Conn` responses. + + See `Phoenix.Controller.action_fallback/1` for more details. + """ + use HomeworkWeb, :controller + + # This clause is an example of how to handle resources that cannot be found. + def call(conn, {:error, :not_found}) do + conn + |> put_status(:not_found) + |> put_view(HomeworkWeb.ErrorView) + |> render(:"404") + end +end diff --git a/elixir/lib/homework_web/controllers/prices_controller.ex b/elixir/lib/homework_web/controllers/prices_controller.ex new file mode 100644 index 00000000..67f01781 --- /dev/null +++ b/elixir/lib/homework_web/controllers/prices_controller.ex @@ -0,0 +1,44 @@ +defmodule HomeworkWeb.PricesController do + use HomeworkWeb, :controller + + alias Homework.Shiren + alias Homework.Shiren.Prices + + action_fallback HomeworkWeb.FallbackController + + def index(conn, _params) do + price = Shiren.list_price() + render(conn, "index.json", price: price) + end + + def create(conn, %{"prices" => prices_params}) do + with {:ok, %Prices{} = prices} <- Shiren.create_prices(prices_params) do + conn + |> put_status(:created) + |> put_resp_header("location", Routes.prices_path(conn, :show, prices)) + |> render("show.json", prices: prices) + end + end + + + def show(conn, %{"id" => id}) do + prices = Shiren.get_prices!(id) + render(conn, "show.json", prices: prices) + end + + def update(conn, %{"id" => id, "prices" => prices_params}) do + prices = Shiren.get_prices!(id) + + with {:ok, %Prices{} = prices} <- Shiren.update_prices(prices, prices_params) do + render(conn, "show.json", prices: prices) + end + end + + def delete(conn, %{"id" => id}) do + prices = Shiren.get_prices!(id) + + with {:ok, %Prices{}} <- Shiren.delete_prices(prices) do + send_resp(conn, :no_content, "") + end + end +end diff --git a/elixir/lib/homework_web/router.ex b/elixir/lib/homework_web/router.ex index d6e78852..63cb00e4 100644 --- a/elixir/lib/homework_web/router.ex +++ b/elixir/lib/homework_web/router.ex @@ -1,17 +1,20 @@ defmodule HomeworkWeb.Router do + use HomeworkWeb, :router + pipeline :api do plug(:accepts, ["json"]) end - scope "/" do + scope "/api" do pipe_through(:api) + resources "/price", HomeworkWeb.PricesController, except: [:edit] - forward("/graphiql", Absinthe.Plug.GraphiQL, - schema: HomeworkWeb.Schema, - interface: :simple, - context: %{pubsub: HomeworkWeb.Endpoint} - ) + # forward("/graphiql", Absinthe.Plug.GraphiQL, + # schema: HomeworkWeb.Schema, + # interface: :simple, + # context: %{pubsub: HomeworkWeb.Endpoint} + # ) end end diff --git a/elixir/lib/homework_web/views/changeset_view.ex b/elixir/lib/homework_web/views/changeset_view.ex new file mode 100644 index 00000000..3f5c1238 --- /dev/null +++ b/elixir/lib/homework_web/views/changeset_view.ex @@ -0,0 +1,19 @@ +defmodule HomeworkWeb.ChangesetView do + use HomeworkWeb, :view + + @doc """ + Traverses and translates changeset errors. + + See `Ecto.Changeset.traverse_errors/2` and + `HomeworkWeb.ErrorHelpers.translate_error/1` for more details. + """ + def translate_errors(changeset) do + Ecto.Changeset.traverse_errors(changeset, &translate_error/1) + end + + def render("error.json", %{changeset: changeset}) do + # When encoded, the changeset returns its errors + # as a JSON object. So we just pass it forward. + %{errors: translate_errors(changeset)} + end +end diff --git a/elixir/lib/homework_web/views/prices_view.ex b/elixir/lib/homework_web/views/prices_view.ex new file mode 100644 index 00000000..d998e548 --- /dev/null +++ b/elixir/lib/homework_web/views/prices_view.ex @@ -0,0 +1,19 @@ +defmodule HomeworkWeb.PricesView do + use HomeworkWeb, :view + alias HomeworkWeb.PricesView + + def render("index.json", %{price: price}) do + %{data: render_many(price, PricesView, "prices.json")} + end + + def render("show.json", %{prices: prices}) do + %{data: render_one(prices, PricesView, "prices.json")} + end + + def render("prices.json", %{prices: prices}) do + %{id: prices.id, + amount: prices.amount, + category: prices.category, + type: prices.type} + end +end diff --git a/elixir/priv/repo/migrations/20220503015957_create_cards.exs b/elixir/priv/repo/migrations/20220503015957_create_cards.exs new file mode 100644 index 00000000..a130b050 --- /dev/null +++ b/elixir/priv/repo/migrations/20220503015957_create_cards.exs @@ -0,0 +1,12 @@ +defmodule Homework.Repo.Migrations.CreateCards do + use Ecto.Migration + + def change do + create table(:cards) do + add :description, :string + + timestamps() + end + + end +end diff --git a/elixir/priv/repo/migrations/20220503021205_create_price.exs b/elixir/priv/repo/migrations/20220503021205_create_price.exs new file mode 100644 index 00000000..cb007bde --- /dev/null +++ b/elixir/priv/repo/migrations/20220503021205_create_price.exs @@ -0,0 +1,14 @@ +defmodule Homework.Repo.Migrations.CreatePrice do + use Ecto.Migration + + def change do + create table(:price) do + add :category, :string + add :amount, :integer + add :type, :string + + timestamps() + end + + end +end diff --git a/elixir/test/homework/account_test.exs b/elixir/test/homework/account_test.exs new file mode 100644 index 00000000..08facf6f --- /dev/null +++ b/elixir/test/homework/account_test.exs @@ -0,0 +1,64 @@ +defmodule Homework.AccountTest do + use Homework.DataCase + + alias Homework.Account + + describe "cards" do + alias Homework.Account.Card + + @valid_attrs %{description: "some description"} + @update_attrs %{description: "some updated description"} + @invalid_attrs %{description: nil} + + def card_fixture(attrs \\ %{}) do + {:ok, card} = + attrs + |> Enum.into(@valid_attrs) + |> Account.create_card() + + card + end + + test "list_cards/0 returns all cards" do + card = card_fixture() + assert Account.list_cards() == [card] + end + + test "get_card!/1 returns the card with given id" do + card = card_fixture() + assert Account.get_card!(card.id) == card + end + + test "create_card/1 with valid data creates a card" do + assert {:ok, %Card{} = card} = Account.create_card(@valid_attrs) + assert card.description == "some description" + end + + test "create_card/1 with invalid data returns error changeset" do + assert {:error, %Ecto.Changeset{}} = Account.create_card(@invalid_attrs) + end + + test "update_card/2 with valid data updates the card" do + card = card_fixture() + assert {:ok, %Card{} = card} = Account.update_card(card, @update_attrs) + assert card.description == "some updated description" + end + + test "update_card/2 with invalid data returns error changeset" do + card = card_fixture() + assert {:error, %Ecto.Changeset{}} = Account.update_card(card, @invalid_attrs) + assert card == Account.get_card!(card.id) + end + + test "delete_card/1 deletes the card" do + card = card_fixture() + assert {:ok, %Card{}} = Account.delete_card(card) + assert_raise Ecto.NoResultsError, fn -> Account.get_card!(card.id) end + end + + test "change_card/1 returns a card changeset" do + card = card_fixture() + assert %Ecto.Changeset{} = Account.change_card(card) + end + end +end diff --git a/elixir/test/homework/shiren_test.exs b/elixir/test/homework/shiren_test.exs new file mode 100644 index 00000000..579bc1d8 --- /dev/null +++ b/elixir/test/homework/shiren_test.exs @@ -0,0 +1,68 @@ +defmodule Homework.ShirenTest do + use Homework.DataCase + + alias Homework.Shiren + + describe "price" do + alias Homework.Shiren.Prices + + @valid_attrs %{amount: 42, category: "some category", type: "some type"} + @update_attrs %{amount: 43, category: "some updated category", type: "some updated type"} + @invalid_attrs %{amount: nil, category: nil, type: nil} + + def prices_fixture(attrs \\ %{}) do + {:ok, prices} = + attrs + |> Enum.into(@valid_attrs) + |> Shiren.create_prices() + + prices + end + + test "list_price/0 returns all price" do + prices = prices_fixture() + assert Shiren.list_price() == [prices] + end + + test "get_prices!/1 returns the prices with given id" do + prices = prices_fixture() + assert Shiren.get_prices!(prices.id) == prices + end + + test "create_prices/1 with valid data creates a prices" do + assert {:ok, %Prices{} = prices} = Shiren.create_prices(@valid_attrs) + assert prices.amount == 42 + assert prices.category == "some category" + assert prices.type == "some type" + end + + test "create_prices/1 with invalid data returns error changeset" do + assert {:error, %Ecto.Changeset{}} = Shiren.create_prices(@invalid_attrs) + end + + test "update_prices/2 with valid data updates the prices" do + prices = prices_fixture() + assert {:ok, %Prices{} = prices} = Shiren.update_prices(prices, @update_attrs) + assert prices.amount == 43 + assert prices.category == "some updated category" + assert prices.type == "some updated type" + end + + test "update_prices/2 with invalid data returns error changeset" do + prices = prices_fixture() + assert {:error, %Ecto.Changeset{}} = Shiren.update_prices(prices, @invalid_attrs) + assert prices == Shiren.get_prices!(prices.id) + end + + test "delete_prices/1 deletes the prices" do + prices = prices_fixture() + assert {:ok, %Prices{}} = Shiren.delete_prices(prices) + assert_raise Ecto.NoResultsError, fn -> Shiren.get_prices!(prices.id) end + end + + test "change_prices/1 returns a prices changeset" do + prices = prices_fixture() + assert %Ecto.Changeset{} = Shiren.change_prices(prices) + end + end +end diff --git a/elixir/test/homework_web/controllers/prices_controller_test.exs b/elixir/test/homework_web/controllers/prices_controller_test.exs new file mode 100644 index 00000000..a76afcff --- /dev/null +++ b/elixir/test/homework_web/controllers/prices_controller_test.exs @@ -0,0 +1,96 @@ +defmodule HomeworkWeb.PricesControllerTest do + use HomeworkWeb.ConnCase + + alias Homework.Shiren + alias Homework.Shiren.Prices + + @create_attrs %{ + amount: 42, + category: "some category", + type: "some type" + } + @update_attrs %{ + amount: 43, + category: "some updated category", + type: "some updated type" + } + @invalid_attrs %{amount: nil, category: nil, type: nil} + + def fixture(:prices) do + {:ok, prices} = Shiren.create_prices(@create_attrs) + prices + end + + setup %{conn: conn} do + {:ok, conn: put_req_header(conn, "accept", "application/json")} + end + + describe "index" do + test "lists all price", %{conn: conn} do + conn = get(conn, Routes.prices_path(conn, :index)) + assert json_response(conn, 200)["data"] == [] + end + end + + describe "create prices" do + test "renders prices when data is valid", %{conn: conn} do + conn = post(conn, Routes.prices_path(conn, :create), prices: @create_attrs) + assert %{"id" => id} = json_response(conn, 201)["data"] + + conn = get(conn, Routes.prices_path(conn, :show, id)) + + assert %{ + "id" => id, + "amount" => 42, + "category" => "some category", + "type" => "some type" + } = json_response(conn, 200)["data"] + end + + test "renders errors when data is invalid", %{conn: conn} do + conn = post(conn, Routes.prices_path(conn, :create), prices: @invalid_attrs) + assert json_response(conn, 422)["errors"] != %{} + end + end + + describe "update prices" do + setup [:create_prices] + + test "renders prices when data is valid", %{conn: conn, prices: %Prices{id: id} = prices} do + conn = put(conn, Routes.prices_path(conn, :update, prices), prices: @update_attrs) + assert %{"id" => ^id} = json_response(conn, 200)["data"] + + conn = get(conn, Routes.prices_path(conn, :show, id)) + + assert %{ + "id" => id, + "amount" => 43, + "category" => "some updated category", + "type" => "some updated type" + } = json_response(conn, 200)["data"] + end + + test "renders errors when data is invalid", %{conn: conn, prices: prices} do + conn = put(conn, Routes.prices_path(conn, :update, prices), prices: @invalid_attrs) + assert json_response(conn, 422)["errors"] != %{} + end + end + + describe "delete prices" do + setup [:create_prices] + + test "deletes chosen prices", %{conn: conn, prices: prices} do + conn = delete(conn, Routes.prices_path(conn, :delete, prices)) + assert response(conn, 204) + + assert_error_sent 404, fn -> + get(conn, Routes.prices_path(conn, :show, prices)) + end + end + end + + defp create_prices(_) do + prices = fixture(:prices) + %{prices: prices} + end +end From ed7f8c9a72d3393b73e34d876493c63ce573409c Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Sat, 13 Aug 2022 11:43:30 -0500 Subject: [PATCH 30/32] Updated the tests to handle the new company module --- elixir/lib/homework_web/router.ex | 12 ++-- elixir/priv/repo/seeds.exs | 2 +- elixir/test/homework/companies_test.exs | 8 ++- elixir/test/homework/transactions_test.exs | 41 +++++++++--- elixir/test/homework/users_test.exs | 73 ++++++++++++++-------- 5 files changed, 93 insertions(+), 43 deletions(-) diff --git a/elixir/lib/homework_web/router.ex b/elixir/lib/homework_web/router.ex index 63cb00e4..94707a77 100644 --- a/elixir/lib/homework_web/router.ex +++ b/elixir/lib/homework_web/router.ex @@ -7,14 +7,14 @@ defmodule HomeworkWeb.Router do plug(:accepts, ["json"]) end - scope "/api" do + scope "/api/" do pipe_through(:api) resources "/price", HomeworkWeb.PricesController, except: [:edit] - # forward("/graphiql", Absinthe.Plug.GraphiQL, - # schema: HomeworkWeb.Schema, - # interface: :simple, - # context: %{pubsub: HomeworkWeb.Endpoint} - # ) + forward("/graphiql", Absinthe.Plug.GraphiQL, + schema: HomeworkWeb.Schema, + interface: :simple, + context: %{pubsub: HomeworkWeb.Endpoint} + ) end end diff --git a/elixir/priv/repo/seeds.exs b/elixir/priv/repo/seeds.exs index 3a8cee83..5a8e98f3 100644 --- a/elixir/priv/repo/seeds.exs +++ b/elixir/priv/repo/seeds.exs @@ -66,4 +66,4 @@ end -Homework.DatabaseSeeder.generate_data_set() +# Homework.DatabaseSeeder.generate_data_set() diff --git a/elixir/test/homework/companies_test.exs b/elixir/test/homework/companies_test.exs index 49a9b2b4..92f6d372 100644 --- a/elixir/test/homework/companies_test.exs +++ b/elixir/test/homework/companies_test.exs @@ -21,7 +21,7 @@ defmodule Homework.CompaniesTest do test "list_company/0 returns all company" do company = company_fixture() - assert Companies.list_company() == [company] + assert Companies.list_company([]) == [company] end test "get_company!/1 returns the company with given id" do @@ -64,5 +64,11 @@ defmodule Homework.CompaniesTest do company = company_fixture() assert %Ecto.Changeset{} = Companies.change_company(company) end + + test "chanage_company/1 updates avaialble credit after transaction" do + company = company_fixture() + assert company.available_credit == 42 + + end end end diff --git a/elixir/test/homework/transactions_test.exs b/elixir/test/homework/transactions_test.exs index 03071aff..53427d73 100644 --- a/elixir/test/homework/transactions_test.exs +++ b/elixir/test/homework/transactions_test.exs @@ -5,11 +5,26 @@ 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(%{ + available_credit: 100, + credit_line: 200, + name: "company1" + }) + + {:ok, company2} = + Companies.create_company(%{ + available_credit: 200, + credit_line: 300, + name: "company2" + }) + {:ok, merchant1} = Merchants.create_merchant(%{description: "some description", name: "some name"}) @@ -23,6 +38,7 @@ defmodule Homework.TransactionsTest do Users.create_user(%{ dob: "some dob", first_name: "some first_name", + company_id: company1.id, last_name: "some last_name" }) @@ -30,25 +46,29 @@ defmodule Homework.TransactionsTest do 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, + debit: false, description: "some description", merchant_id: merchant1.id, - user_id: user1.id + user_id: user1.id, + company_id: company1.id } update_attrs = %{ amount: 43, credit: false, - debit: false, + debit: true, description: "some updated description", merchant_id: merchant2.id, - user_id: user2.id + user_id: user2.id, + company_id: company2.id } invalid_attrs = %{ @@ -57,7 +77,8 @@ defmodule Homework.TransactionsTest do debit: nil, description: nil, merchant_id: nil, - user_id: nil + user_id: nil, + company_id: nil } {:ok, @@ -68,7 +89,9 @@ defmodule Homework.TransactionsTest do merchant1: merchant1, merchant2: merchant2, user1: user1, - user2: user2 + user2: user2, + company1: company1, + company2: company2 }} end @@ -94,7 +117,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 +127,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", %{ diff --git a/elixir/test/homework/users_test.exs b/elixir/test/homework/users_test.exs index e1ae65c2..0e2a8369 100644 --- a/elixir/test/homework/users_test.exs +++ b/elixir/test/homework/users_test.exs @@ -2,70 +2,89 @@ defmodule Homework.UsersTest do use Homework.DataCase alias Homework.Users + alias Homework.Companies describe "users" do alias Homework.Users.User + setup do + {:ok, company1} = Companies.create_company(%{name: "some company", credit_line: 99, available_credit: 100}) - @valid_attrs %{dob: "some dob", first_name: "some first_name", last_name: "some last_name"} - @update_attrs %{ + {:ok, company2} = Companies.create_company(%{name: "some company2", credit_line: 199, available_credit: 200}) + + 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" + last_name: "some updated last_name", + company_id: company1.id } - @invalid_attrs %{dob: nil, first_name: nil, last_name: nil} - def user_fixture(attrs \\ %{}) do - {:ok, user} = - attrs - |> Enum.into(@valid_attrs) - |> Users.create_user() + invalid_attrs = %{dob: nil, first_name: nil, last_name: nil, company_id: company1.id} + {:ok, + %{ + valid_attrs: valid_attrs, + update_attrs: update_attrs, + invalid_attrs: invalid_attrs, + company1: company1, + comopany2: company2 + }} + + end + def user_fixture(valid_attrs, attrs \\ %{}) do + {:ok, user} = 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} 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" 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", %{ + update_attrs: update_attrs, + valid_attrs: valid_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.compan_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", %{invalid_attrs: invalid_attrs} do + user = user_fixture(invalid_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", %{updated_user: updated_user} do + user = user_fixture(updated_user) assert %Ecto.Changeset{} = Users.change_user(user) end end From 9845bb9931c64ed13f9e39bfac4385f8b9aeee2b Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Sat, 13 Aug 2022 21:33:55 -0500 Subject: [PATCH 31/32] Wrote a test to check for new credit line after new transaction --- elixir/lib/homework/transactions.ex | 8 +- elixir/test/homework/companies_test.exs | 115 ++++++++++++++++++------ 2 files changed, 96 insertions(+), 27 deletions(-) diff --git a/elixir/lib/homework/transactions.ex b/elixir/lib/homework/transactions.ex index f7ec3dfb..5e8f6b69 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 @doc """ Returns the list of transactions. @@ -50,11 +51,16 @@ defmodule Homework.Transactions do """ def create_transaction(attrs \\ %{}) do + company_id = Map.get(attrs, :company_id) + co = Companies.get_company!(company_id) + amount = Map.get(attrs, :amount) + credit = Map.get(co, :available_credit) + new_amount = credit - amount + Companies.update_company(co, %{available_credit: new_amount}) %Transaction{} |> Transaction.changeset(attrs) |> Repo.insert() end - @doc """ Updates a transaction. diff --git a/elixir/test/homework/companies_test.exs b/elixir/test/homework/companies_test.exs index 92f6d372..810160b5 100644 --- a/elixir/test/homework/companies_test.exs +++ b/elixir/test/homework/companies_test.exs @@ -2,72 +2,135 @@ defmodule Homework.CompaniesTest do use Homework.DataCase alias Homework.Companies + alias Homework.Transactions + alias Homework.Merchants + alias Homework.Users describe "company" do alias Homework.Companies.Company - @valid_attrs %{available_credit: 42, credit_line: 42, name: "some name"} - @update_attrs %{available_credit: 43, credit_line: 43, name: "some updated name"} - @invalid_attrs %{available_credit: nil, credit_line: nil, name: nil} + setup do + valid_attrs = %{available_credit: 42, credit_line: 42, name: "some name"} + update_attrs = %{available_credit: 43, credit_line: 43, name: "some updated name"} + invalid_attrs = %{available_credit: nil, credit_line: nil, name: nil} - def company_fixture(attrs \\ %{}) do + {:ok, company1} = Companies.create_company(%{ + available_credit: 100, + credit_line: 300, + name: "Company One" + }) + + {:ok, merchant} = + Merchants.create_merchant(%{ + description: "some updated description", + name: "some updated name" + }) + + {:ok, user} = + Users.create_user(%{ + dob: "some dob", + first_name: "some first_name", + company_id: company1.id, + last_name: "some last_name", + }) + + {:ok, %{ + valid_attrs: valid_attrs, + update_attrs: update_attrs, + invalid_attrs: invalid_attrs, + merchant: merchant, + user: user, + company1: company1 + }} + end + + + def company_fixture(valid_attrs, attrs \\ %{}) do {:ok, company} = attrs - |> Enum.into(@valid_attrs) + |> Enum.into(valid_attrs) |> Companies.create_company() company end - test "list_company/0 returns all company" do - company = company_fixture() + test "list_company/0 returns all company", %{valid_attrs: valid_attrs} do + company = company_fixture(valid_attrs) assert Companies.list_company([]) == [company] end - test "get_company!/1 returns the company with given id" do - company = company_fixture() + test "get_company!/1 returns the company with given id", %{valid_attrs: valid_attrs} do + company = company_fixture(valid_attrs) 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) + test "create_company/1 with valid data creates a company", %{valid_attrs: valid_attrs} do + assert {:ok, %Company{} = company} = Companies.create_company(valid_attrs) assert company.available_credit == 42 assert company.credit_line == 42 assert company.name == "some name" end - test "create_company/1 with invalid data returns error changeset" do - assert {:error, %Ecto.Changeset{}} = Companies.create_company(@invalid_attrs) + test "create_company/1 with invalid data returns error changeset", %{invalid_attrs: invalid_attrs} 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) + test "update_company/2 with valid data updates the company", %{ + update_attrs: update_attrs, + valid_attrs: valid_attrs + + } do + company = company_fixture(valid_attrs) + assert {:ok, %Company{} = company} = Companies.update_company(company, update_attrs) assert company.available_credit == 43 assert company.credit_line == 43 assert company.name == "some updated name" 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) + test "update_company/2 with invalid data returns error changeset", %{ + invalid_attrs: invalid_attrs, + valid_attrs: valid_attrs + } do + company = company_fixture(valid_attrs) + 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() + test "delete_company/1 deletes the company", %{valid_attrs: valid_attrs} do + company = company_fixture(valid_attrs) 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() + test "change_company/1 returns a company changeset", %{ + valid_attrs: valid_attrs, + } + do + company = company_fixture(valid_attrs) assert %Ecto.Changeset{} = Companies.change_company(company) end - test "chanage_company/1 updates avaialble credit after transaction" do - company = company_fixture() - assert company.available_credit == 42 + test "chanage_company/1 updates avaialble credit after transaction", %{ + user: user1, + merchant: merchant, + company1: company1 + }do + + {:ok, transaction} = Transactions.create_transaction(%{ + amount: 100, + credit: true, + debit: false, + description: "some description", + company_id: company1.id, + user_id: user1.id, + merchant_id: merchant.id + }) + co = Companies.get_company!(company1.id) + + + assert transaction.amount == 100 + assert co.available_credit == 0 + end end From 0ac68b7159e5a5d6b32c0c6f555f74c972da7335 Mon Sep 17 00:00:00 2001 From: Chad Jemmett Date: Tue, 16 Aug 2022 21:03:28 -0500 Subject: [PATCH 32/32] Fixed the broken company_list tests. needed to add the OTHER company I made in the setup. --- elixir/test/homework/companies_test.exs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/elixir/test/homework/companies_test.exs b/elixir/test/homework/companies_test.exs index 810160b5..d34e384b 100644 --- a/elixir/test/homework/companies_test.exs +++ b/elixir/test/homework/companies_test.exs @@ -54,9 +54,9 @@ defmodule Homework.CompaniesTest do company end - test "list_company/0 returns all company", %{valid_attrs: valid_attrs} do + test "list_company/0 returns all company", %{valid_attrs: valid_attrs, company1: company1} do company = company_fixture(valid_attrs) - assert Companies.list_company([]) == [company] + assert Companies.list_company([]) == [company1, company] end test "get_company!/1 returns the company with given id", %{valid_attrs: valid_attrs} do