diff --git a/lib/algora/bounties/schemas/bounty.ex b/lib/algora/bounties/schemas/bounty.ex index 1f1dedc57..63fb274cd 100644 --- a/lib/algora/bounties/schemas/bounty.ex +++ b/lib/algora/bounties/schemas/bounty.ex @@ -9,6 +9,7 @@ defmodule Algora.Bounties.Bounty do field :amount, Algora.Types.Money field :status, Ecto.Enum, values: [:open, :cancelled, :paid] field :number, :integer, default: 0 + field :autopay_disabled, :boolean, default: false belongs_to :ticket, Algora.Workspace.Ticket belongs_to :owner, User diff --git a/lib/algora_web/controllers/webhooks/github_controller.ex b/lib/algora_web/controllers/webhooks/github_controller.ex index 0fd09c82e..d6d138546 100644 --- a/lib/algora_web/controllers/webhooks/github_controller.ex +++ b/lib/algora_web/controllers/webhooks/github_controller.ex @@ -131,7 +131,8 @@ defmodule AlgoraWeb.Webhooks.GithubController do autopayable_bounty = Enum.find( bounties, - &(not is_nil(installation) and + &(not &1.autopay_disabled and + not is_nil(installation) and &1.owner.id == installation.connected_user_id and not is_nil(&1.owner.customer) and not is_nil(&1.owner.customer.default_payment_method)) diff --git a/priv/repo/migrations/20250228223010_add_autopay_disabled_to_bounties.exs b/priv/repo/migrations/20250228223010_add_autopay_disabled_to_bounties.exs new file mode 100644 index 000000000..e96b4176f --- /dev/null +++ b/priv/repo/migrations/20250228223010_add_autopay_disabled_to_bounties.exs @@ -0,0 +1,9 @@ +defmodule Algora.Repo.Migrations.AddAutopayDisabledToBounties do + use Ecto.Migration + + def change do + alter table(:bounties) do + add :autopay_disabled, :boolean, default: false, null: false + end + end +end diff --git a/scripts/database_migration.exs b/scripts/database_migration.exs index d3bd4bae4..d42b3bb5e 100644 --- a/scripts/database_migration.exs +++ b/scripts/database_migration.exs @@ -376,7 +376,8 @@ defmodule DatabaseMigration do "creator_id" => row["poster_id"], "inserted_at" => row["created_at"], "updated_at" => row["updated_at"], - "number" => row["number"] + "number" => row["number"], + "autopay_disabled" => row["autopay_disabled"] } end end diff --git a/scripts/v1-progress.yaml b/scripts/v1-progress.yaml index 76f6ab349..c57214376 100644 --- a/scripts/v1-progress.yaml +++ b/scripts/v1-progress.yaml @@ -80,7 +80,7 @@ - number: 1 - deleted: 0 - reward_type: 0 - - autopay_disabled: 0 + - autopay_disabled: 1 - manual_assignments: 0 - timeouts_disabled: 0 - experts_only: 0 diff --git a/scripts/v2-progress.yaml b/scripts/v2-progress.yaml index 116c20a48..b351635d6 100644 --- a/scripts/v2-progress.yaml +++ b/scripts/v2-progress.yaml @@ -34,6 +34,7 @@ - creator_id: 1 - inserted_at: 1 - updated_at: 1 + - autopay_disabled: 1 - chat_participants: - id: -1 - last_read_at: -1 diff --git a/test/algora_web/controllers/webhooks/github_controller_test.exs b/test/algora_web/controllers/webhooks/github_controller_test.exs index 50cb95751..12b620bf2 100644 --- a/test/algora_web/controllers/webhooks/github_controller_test.exs +++ b/test/algora_web/controllers/webhooks/github_controller_test.exs @@ -4,6 +4,7 @@ defmodule AlgoraWeb.Webhooks.GithubControllerTest do use Oban.Testing, repo: Algora.Repo import Algora.Factory + import Ecto.Changeset import Ecto.Query import ExUnit.CaptureLog import Money.Sigil @@ -830,6 +831,46 @@ defmodule AlgoraWeb.Webhooks.GithubControllerTest do assert Repo.aggregate(Transaction, :count) == 0 end + test "does not autopay when autopay is disabled", ctx do + issue_number = :rand.uniform(1000) + pr_number = :rand.uniform(1000) + + customer = insert!(:customer, user: ctx[:org]) + _payment_method = insert!(:payment_method, customer: customer) + + process_scenario!(ctx, [ + %{ + event_action: "issue_comment.created", + user_type: :admin, + body: "/bounty $100", + params: %{"issue" => %{"number" => issue_number}} + }, + %{ + event_action: "pull_request.opened", + user_type: :unauthorized, + body: "/claim #{issue_number}", + params: %{"pull_request" => %{"number" => pr_number}} + } + ]) + + Bounty |> Repo.one!() |> change(%{autopay_disabled: true}) |> Repo.update!() + + process_scenario!(ctx, [ + %{ + event_action: "pull_request.closed", + user_type: :unauthorized, + body: "/claim #{issue_number}", + params: %{"pull_request" => %{"number" => pr_number, "merged_at" => DateTime.to_iso8601(DateTime.utc_now())}} + } + ]) + + bounty = Repo.one!(Bounty) + claim = Repo.one!(Claim) + assert claim.target_id == bounty.ticket_id + assert claim.status == :approved + assert Repo.aggregate(Transaction, :count) == 0 + end + test "handles autopay when claim is changed to a different bounty and PR is merged", ctx do issue_number1 = :rand.uniform(1000) issue_number2 = issue_number1 + :rand.uniform(1000)