@@ -4,107 +4,10 @@ defmodule Algora.Payments.Jobs.ExecutePendingTransfers do
4
4
queue: :transfers ,
5
5
max_attempts: 1
6
6
7
- import Ecto.Changeset
8
- import Ecto.Query
9
-
10
- alias Algora.MoneyUtils
11
- alias Algora.Payments.Account
12
- alias Algora.Payments.Transaction
13
- alias Algora.Repo
14
- alias Algora.Util
15
-
16
- require Logger
7
+ alias Algora.Payments
17
8
18
9
@ impl Oban.Worker
19
- def perform ( % Oban.Job { args: % { user_id: user_id , group_id: group_id } } ) do
20
- pending_amount = get_pending_amount ( user_id )
21
-
22
- with { :ok , account } <- Repo . fetch_by ( Account , user_id: user_id , provider: :stripe , payouts_enabled: true ) ,
23
- true <- Money . positive? ( pending_amount ) do
24
- initialize_and_execute_transfer ( user_id , group_id , pending_amount , account )
25
- else
26
- _ -> :ok
27
- end
28
- end
29
-
30
- defp get_pending_amount ( user_id ) do
31
- total_credits =
32
- Repo . one (
33
- from ( t in Transaction ,
34
- where: t . user_id == ^ user_id ,
35
- where: t . type == :credit ,
36
- where: t . status == :succeeded ,
37
- select: sum ( t . net_amount )
38
- )
39
- ) || Money . zero ( :USD )
40
-
41
- total_transfers =
42
- Repo . one (
43
- from ( t in Transaction ,
44
- where: t . user_id == ^ user_id ,
45
- where: t . type == :transfer ,
46
- where: t . status == :succeeded or t . status == :processing or t . status == :initialized ,
47
- select: sum ( t . net_amount )
48
- )
49
- ) || Money . zero ( :USD )
50
-
51
- Money . sub! ( total_credits , total_transfers )
52
- end
53
-
54
- defp initialize_and_execute_transfer ( user_id , group_id , pending_amount , account ) do
55
- with { :ok , transaction } <- initialize_transfer ( user_id , group_id , pending_amount ) ,
56
- { :ok , transfer } <- execute_transfer ( transaction , account ) do
57
- { :ok , transfer }
58
- else
59
- error ->
60
- Logger . error ( "Failed to execute transfer: #{ inspect ( error ) } " )
61
- error
62
- end
63
- end
64
-
65
- defp initialize_transfer ( user_id , group_id , pending_amount ) do
66
- % Transaction { }
67
- |> change ( % {
68
- provider: "stripe" ,
69
- type: :credit ,
70
- status: :initialized ,
71
- user_id: user_id ,
72
- gross_amount: pending_amount ,
73
- net_amount: pending_amount ,
74
- total_fee: Money . zero ( :USD ) ,
75
- group_id: group_id
76
- } )
77
- |> Algora.Validations . validate_positive ( :gross_amount )
78
- |> Algora.Validations . validate_positive ( :net_amount )
79
- |> foreign_key_constraint ( :user_id )
80
- |> Repo . insert ( )
81
- end
82
-
83
- defp execute_transfer ( transaction , account ) do
84
- # TODO: set other params
85
- # TODO: provide idempotency key
86
- case Stripe.Transfer . create ( % {
87
- amount: MoneyUtils . to_minor_units ( transaction . net_amount ) ,
88
- currency: to_string ( transaction . net_amount . currency ) ,
89
- destination: account . stripe_account_id
90
- } ) do
91
- { :ok , transfer } ->
92
- # it's fine if this fails since we'll receive a webhook
93
- _result = try_update_transaction ( transaction , transfer )
94
- { :ok , transfer }
95
-
96
- { :error , error } ->
97
- { :error , error }
98
- end
99
- end
100
-
101
- defp try_update_transaction ( transaction , transfer ) do
102
- transaction
103
- |> change ( % {
104
- status: if ( transfer . status == :succeeded , do: :succeeded , else: :failed ) ,
105
- provider_id: transfer . id ,
106
- provider_meta: Util . normalize_struct ( transfer )
107
- } )
108
- |> Repo . update ( )
10
+ def perform ( % Oban.Job { args: % { user_id: user_id } } ) do
11
+ Payments . execute_pending_transfers ( user_id )
109
12
end
110
13
end
0 commit comments