Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions lib/code_corps/analytics/segment_tracking_support.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ defmodule CodeCorps.Analytics.SegmentTrackingSupport do
def includes?(:create, %CodeCorps.StripeConnectSubscription{}), do: true
def includes?(:create, %CodeCorps.StripePlatformCard{}), do: true
def includes?(:create, %CodeCorps.StripePlatformCustomer{}), do: true
def includes?(:create, %CodeCorps.Task{}), do: true
def includes?(:update, %CodeCorps.Task{}), do: true
def includes?(:create, %CodeCorps.User{}), do: true
def includes?(:update, %CodeCorps.User{}), do: true
def includes?(:create, %CodeCorps.UserCategory{}), do: true
Expand Down
191 changes: 153 additions & 38 deletions lib/code_corps/analytics/segment_traits_builder.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,79 @@ defmodule CodeCorps.Analytics.SegmentTraitsBuilder do
Builds Segment traits from provided data
"""

@spec build(struct) :: map
def build(record), do: traits(record)
alias CodeCorps.Repo

defp traits(user = %CodeCorps.User{}) do
%{
admin: user.admin,
biography: user.biography,
created_at: user.inserted_at,
email: user.email,
first_name: user.first_name,
github_id: user.github_id,
github_username: user.github_username,
last_name: user.last_name,
sign_up_context: user.sign_up_context,
state: user.state,
twitter: user.twitter,
type: user.type,
username: user.username,
website: user.website
}
end
@spec build(struct | map) :: map
def build(record), do: traits(record)

defp traits(comment = %CodeCorps.Comment{}) do
comment = comment |> CodeCorps.Repo.preload(:task)
@spec traits(struct | map) :: map
defp traits(%CodeCorps.Comment{} = comment) do
comment = comment |> Repo.preload(:task)
%{
comment_id: comment.id,
task: comment.task.title,
task_id: comment.task.id,
project_id: comment.task.project_id
}
end

defp traits(record = %CodeCorps.ProjectUser{}) do
record = record |> CodeCorps.Repo.preload(:project)
defp traits(%CodeCorps.DonationGoal{} = donation_goal) do
%{
amount: donation_goal.amount,
current: donation_goal.current,
project_id: donation_goal.project_id
}
end
defp traits(%CodeCorps.GithubAppInstallation{} = installation) do
%{
access_token_expires_at: installation.access_token_expires_at,
github_account_login: installation.github_account_login,
github_account_type: installation.github_account_type,
github_id: installation.github_id,
origin: installation.origin,
state: installation.state,
project_id: installation.project_id,
user_id: installation.user_id
}
end
defp traits(%CodeCorps.ProjectGithubRepo{} = record) do
record = record |> Repo.preload([:project, :github_repo])
%{
project: record.project.title,
project_id: record.project_id,
github_repo_id: record.github_repo_id,
github_repo_github_account_login: record.github_repo.github_account_login,
github_repo_github_account_type: record.github_repo.github_account_type,
github_repo_github_id: record.github_repo.github_id,
github_repo_name: record.github_repo.name
}
end
defp traits(%CodeCorps.ProjectSkill{} = record) do
record = record |> Repo.preload([:project, :skill])
%{
skill: record.skill.title,
skill_id: record.skill_id,
project: record.project.title,
project_id: record.project_id
}
end

defp traits(charge = %CodeCorps.StripeConnectCharge{}) do
defp traits(%CodeCorps.ProjectUser{} = record) do
record = record |> Repo.preload(:project)
%{
project: record.project.title,
project_id: record.project_id
}
end
defp traits(%CodeCorps.StripeConnectAccount{} = account) do
%{
id: account.id,
business_name: account.business_name,
display_name: account.display_name,
email: account.email,
id_from_stripe: account.id_from_stripe,
organization_id: account.organization_id,
}
end
defp traits(%CodeCorps.StripeConnectCharge{} = charge) do
# NOTE: this only works for some currencies
revenue = charge.amount / 100
currency = String.capitalize(charge.currency) # ISO 4127 format
Expand All @@ -55,38 +87,121 @@ defmodule CodeCorps.Analytics.SegmentTraitsBuilder do
user_id: charge.user_id
}
end
defp traits(%CodeCorps.StripeConnectPlan{} = plan) do
%{
id: plan.id,
amount: plan.amount,
created: plan.created,
id_from_stripe: plan.id_from_stripe,
name: plan.name,
project_id: plan.project_id
}
end
defp traits(%CodeCorps.StripeConnectSubscription{} = subscription) do
subscription = subscription |> Repo.preload(:stripe_connect_plan)

defp traits(task = %CodeCorps.Task{}) do
%{
id: subscription.id,
created: subscription.created,
cancelled_at: subscription.cancelled_at,
current_period_start: subscription.current_period_start,
current_period_end: subscription.current_period_end,
ended_at: subscription.ended_at,
id_from_stripe: subscription.id_from_stripe,
quantity: subscription.quantity,
status: subscription.status,
start: subscription.start,
plan_id: subscription.stripe_connect_plan_id,
user_id: subscription.user_id,
project_id: subscription.stripe_connect_plan.project_id
}
end
defp traits(%CodeCorps.StripePlatformCard{} = card) do
%{
id: card.id,
brand: card.brand,
exp_month: card.exp_month,
exp_year: card.exp_year,
id_from_stripe: card.id_from_stripe,
last4: card.last4,
name: card.name,
user_id: card.user_id
}
end
defp traits(%CodeCorps.StripePlatformCustomer{} = customer) do
%{
id: customer.id,
created: customer.created,
currency: customer.currency,
delinquent: customer.delinquent,
email: customer.email,
id_from_stripe: customer.id_from_stripe,
user_id: customer.user_id
}
end
defp traits(%CodeCorps.Task{} = task) do
%{
order: task.order,
task: task.title,
task_id: task.id,
task_list_id: task.task_list_id,
project_id: task.project_id
}
end

defp traits(user_category = %CodeCorps.UserCategory{}) do
user_category = user_category |> CodeCorps.Repo.preload(:category)
defp traits(%CodeCorps.TaskSkill{} = task_skill) do
task_skill = task_skill |> Repo.preload([:skill, :task])
%{
skill: task_skill.skill.title,
skill_id: task_skill.skill.id,
task: task_skill.task.title
}
end
defp traits(%CodeCorps.User{} = user) do
%{
admin: user.admin,
biography: user.biography,
created_at: user.inserted_at,
email: user.email,
first_name: user.first_name,
github_id: user.github_id,
github_username: user.github_username,
last_name: user.last_name,
sign_up_context: user.sign_up_context,
state: user.state,
twitter: user.twitter,
type: user.type,
username: user.username,
website: user.website
}
end
defp traits(%CodeCorps.UserCategory{} = user_category) do
user_category = user_category |> Repo.preload(:category)
%{
category: user_category.category.name,
category_id: user_category.category.id
}
end

defp traits(user_role = %CodeCorps.UserRole{}) do
user_role = user_role |> CodeCorps.Repo.preload(:role)
defp traits(%CodeCorps.UserRole{} = user_role) do
user_role = user_role |> Repo.preload(:role)
%{
role: user_role.role.name,
role_id: user_role.role.id
}
end

defp traits(user_skill = %CodeCorps.UserSkill{}) do
user_skill = user_skill |> CodeCorps.Repo.preload(:skill)
defp traits(%CodeCorps.UserSkill{} = user_skill) do
user_skill = user_skill |> Repo.preload(:skill)
%{
skill: user_skill.skill.title,
skill_id: user_skill.skill.id
}
end
defp traits(%CodeCorps.UserTask{} = user_task) do
user_task = user_task |> Repo.preload(:task)

defp traits(_), do: %{}
%{
task: user_task.task.title,
task_id: user_task.task_id
}
end
defp traits(%{token: _, user_id: _}), do: %{}
end
17 changes: 15 additions & 2 deletions lib/code_corps/model/task.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ defmodule CodeCorps.Task do

import EctoOrdered

alias CodeCorps.Services.MarkdownRendererService
alias CodeCorps.{Task, Services.MarkdownRendererService}
alias Ecto.Changeset

@type t :: %__MODULE__{}
Expand Down Expand Up @@ -67,13 +67,15 @@ defmodule CodeCorps.Task do
|> put_change(:status, "open")
end

def update_changeset(struct, params) do
@spec update_changeset(struct, map) :: Ecto.Changeset.t
def update_changeset(struct, %{} = params) do
struct
|> changeset(params)
|> cast(params, [:archived, :status])
|> validate_inclusion(:status, statuses())
|> set_closed_at()
|> update_modified_at()
|> maybe_assoc_with_repo(params)
end

def apply_position(changeset) do
Expand Down Expand Up @@ -109,4 +111,15 @@ defmodule CodeCorps.Task do
defp update_modified_at(changeset) do
put_change(changeset, :modified_at, DateTime.utc_now)
end

@spec maybe_assoc_with_repo(Changeset.t, map) :: Changeset.t
defp maybe_assoc_with_repo(
%Changeset{data: %Task{github_repo_id: nil}} = changeset,
%{} = params) do

changeset
|> cast(params, [:github_repo_id])
|> assoc_constraint(:github_repo)
end
defp maybe_assoc_with_repo(%Changeset{} = changeset, %{}), do: changeset
end
15 changes: 5 additions & 10 deletions lib/code_corps/task/service.ex
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@ defmodule CodeCorps.Task.Service do
end

@spec update(Task.t, map) :: {:ok, Task.t} | {:error, Changeset.t} | {:error, :github}
def update(%Task{github_issue_id: nil} = task, %{} = attributes) do
Multi.new
|> Multi.update(:task, task |> Task.update_changeset(attributes))
|> Repo.transaction
|> marshall_result()
end
def update(%Task{} = task, %{} = attributes) do
Multi.new
|> Multi.update(:task, task |> Task.update_changeset(attributes))
Expand Down Expand Up @@ -64,7 +58,7 @@ defmodule CodeCorps.Task.Service do
defp create_on_github(%Task{github_repo: _} = task) do
with %Task{github_repo: github_repo} = task <- task |> Repo.preload(@preloads),
{:ok, payload} <- GitHub.API.Issue.create(task),
{:ok, %GithubIssue{} = github_issue } <- IssueGithubIssueSyncer.create_or_update_issue({github_repo, nil}, payload) do
{:ok, %GithubIssue{} = github_issue} <- IssueGithubIssueSyncer.create_or_update_issue({github_repo, nil}, payload) do
task |> link_with_github_changeset(github_issue) |> Repo.update
else
{:error, error} -> {:error, error}
Expand All @@ -77,12 +71,13 @@ defmodule CodeCorps.Task.Service do
end

@spec update_on_github(Task.t) :: {:ok, Task.t} :: {:error, GitHub.api_error_struct}
defp update_on_github(%Task{github_repo_id: nil} = task), do: {:ok, task}
defp update_on_github(%Task{github_repo_id: nil, github_issue_id: nil} = task), do: {:ok, task}
defp update_on_github(%Task{github_repo_id: _, github_issue_id: nil} = task), do: task |> create_on_github()
defp update_on_github(%Task{github_repo_id: _} = task) do
with %Task{github_repo: github_repo} = task <- task |> Repo.preload(@preloads),
{:ok, payload} <- GitHub.API.Issue.update(task),
{:ok, %GithubIssue{} } <- IssueGithubIssueSyncer.create_or_update_issue({github_repo, nil}, payload) do
{:ok, task}
{:ok, %GithubIssue{}} <- IssueGithubIssueSyncer.create_or_update_issue({github_repo, nil}, payload) do
{:ok, Task |> Repo.get(task.id)}
else
{:error, github_error} -> {:error, github_error}
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule CodeCorpsWeb.GithubAppInstallationController do

import CodeCorps.Helpers.Query, only: [id_filter: 2]

alias CodeCorps.{GithubAppInstallation, User}
alias CodeCorps.{Analytics.SegmentTracker, GithubAppInstallation, User}

action_fallback CodeCorpsWeb.FallbackController
plug CodeCorpsWeb.Plug.DataToAttributes
Expand All @@ -29,7 +29,14 @@ defmodule CodeCorpsWeb.GithubAppInstallationController do
with %User{} = current_user <- conn |> Guardian.Plug.current_resource,
{:ok, :authorized} <- current_user |> Policy.authorize(:create, %GithubAppInstallation{}, params),
{:ok, %GithubAppInstallation{} = installation} <- %GithubAppInstallation{} |> GithubAppInstallation.create_changeset(params) |> Repo.insert do

current_user |> track_created(installation)
conn |> put_status(:created) |> render("show.json-api", data: installation)
end
end

@spec track_created(User.t, GithubAppInstallation.t) :: any
defp track_created(%User{id: user_id}, %GithubAppInstallation{} = installation) do
user_id |> SegmentTracker.track("Created GitHub App Installation", installation)
end
end
20 changes: 18 additions & 2 deletions lib/code_corps_web/controllers/project_github_repo_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ defmodule CodeCorpsWeb.ProjectGithubRepoController do
@moduledoc false
use CodeCorpsWeb, :controller

alias CodeCorps.{ProjectGithubRepo, User, Helpers.Query}
alias CodeCorps.{Analytics.SegmentTracker, ProjectGithubRepo, User, Helpers.Query}

action_fallback CodeCorpsWeb.FallbackController
plug CodeCorpsWeb.Plug.DataToAttributes
Expand All @@ -27,6 +27,9 @@ defmodule CodeCorpsWeb.ProjectGithubRepoController do
with %User{} = current_user <- conn |> Guardian.Plug.current_resource,
{:ok, :authorized} <- current_user |> Policy.authorize(:create, %ProjectGithubRepo{}, params),
{:ok, %ProjectGithubRepo{} = project_github_repo} <- create_project_repo_changeset(params) |> Repo.insert do

current_user |> track_created(project_github_repo)

conn |> put_status(:created) |> render("show.json-api", data: project_github_repo)
end
end
Expand All @@ -36,7 +39,10 @@ defmodule CodeCorpsWeb.ProjectGithubRepoController do
with %ProjectGithubRepo{} = project_github_repo <- ProjectGithubRepo |> Repo.get(id),
%User{} = current_user <- conn |> Guardian.Plug.current_resource,
{:ok, :authorized} <- current_user |> Policy.authorize(:delete, project_github_repo, params),
{:ok, _project_github_repo} <- project_github_repo |> Repo.delete do
{:ok, project_github_repo} <- project_github_repo |> Repo.delete do

current_user |> track_deleted(project_github_repo)

conn |> send_resp(:no_content, "")
end
end
Expand All @@ -46,4 +52,14 @@ defmodule CodeCorpsWeb.ProjectGithubRepoController do
%ProjectGithubRepo{}
|> ProjectGithubRepo.create_changeset(params)
end

@spec track_created(User.t, ProjectGithubRepo.t) :: any
defp track_created(%User{id: user_id}, %ProjectGithubRepo{} = project_github_repo) do
user_id |> SegmentTracker.track("Connected GitHub Repo to Project", project_github_repo)
end

@spec track_deleted(User.t, ProjectGithubRepo.t) :: any
defp track_deleted(%User{id: user_id}, %ProjectGithubRepo{} = project_github_repo) do
user_id |> SegmentTracker.track("Disconnected GitHub Repo from Project", project_github_repo)
end
end
Loading