@@ -256,15 +256,10 @@ defmodule Algora.Bounties do
256
256
Repo . transact ( fn ->
257
257
with { :ok , tip } <- Repo . insert ( changeset ) do
258
258
create_payment_session (
259
- % {
260
- creator: creator ,
261
- owner: owner ,
262
- recipient: recipient ,
263
- amount: amount ,
264
- description: "Tip payment for OSS contributions"
265
- } ,
259
+ % { creator: creator , amount: amount , description: "Tip payment for OSS contributions" } ,
266
260
ticket_ref: opts [ :ticket_ref ] ,
267
- tip_id: tip . id
261
+ tip_id: tip . id ,
262
+ recipient: recipient
268
263
)
269
264
end
270
265
end )
@@ -273,132 +268,124 @@ defmodule Algora.Bounties do
273
268
@ spec reward_bounty (
274
269
% {
275
270
creator: User . t ( ) ,
276
- owner: User . t ( ) ,
277
- recipient: User . t ( ) ,
278
271
amount: Money . t ( ) ,
279
272
bounty_id: String . t ( ) ,
280
- claim_id: String . t ( )
273
+ claims: [ Claim . t ( ) ]
281
274
} ,
282
275
opts :: [ ticket_ref: % { owner: String . t ( ) , repo: String . t ( ) , number: integer ( ) } ]
283
276
) ::
284
277
{ :ok , String . t ( ) } | { :error , atom ( ) }
285
- def reward_bounty (
286
- % { creator: creator , owner: owner , recipient: recipient , amount: amount , bounty_id: bounty_id , claim_id: claim_id } ,
287
- opts \\ [ ]
288
- ) do
289
- # TODO: handle bounty splits
278
+ def reward_bounty ( % { creator: creator , amount: amount , bounty_id: bounty_id , claims: claims } , opts \\ [ ] ) do
290
279
create_payment_session (
291
- % {
292
- creator: creator ,
293
- owner: owner ,
294
- recipient: recipient ,
295
- amount: amount ,
296
- description: "Bounty payment for OSS contributions"
297
- } ,
280
+ % { creator: creator , amount: amount , description: "Bounty payment for OSS contributions" } ,
298
281
ticket_ref: opts [ :ticket_ref ] ,
299
282
bounty_id: bounty_id ,
300
- claim_id: claim_id
283
+ claims: claims
301
284
)
302
285
end
303
286
304
287
@ spec create_payment_session (
305
- % { creator: User . t ( ) , owner: User . t ( ) , recipient: User . t ( ) , amount: Money . t ( ) , description: String . t ( ) } ,
288
+ % { creator: User . t ( ) , amount: Money . t ( ) , description: String . t ( ) } ,
306
289
opts :: [
307
290
ticket_ref: % { owner: String . t ( ) , repo: String . t ( ) , number: integer ( ) } ,
308
291
tip_id: String . t ( ) ,
309
292
bounty_id: String . t ( ) ,
310
- claim_id: String . t ( )
293
+ claims: [ Claim . t ( ) ] ,
294
+ recipient: User . t ( )
311
295
]
312
296
) ::
313
297
{ :ok , String . t ( ) } | { :error , atom ( ) }
314
- def create_payment_session (
315
- % { creator: creator , owner: owner , recipient: recipient , amount: amount , description: description } ,
316
- opts \\ [ ]
317
- ) do
298
+ def create_payment_session ( % { creator: creator , amount: amount , description: description } , opts \\ [ ] ) do
318
299
ticket_ref = opts [ :ticket_ref ]
300
+ recipient = opts [ :recipient ]
301
+ claims = opts [ :claims ]
319
302
320
- # Initialize transaction IDs
321
- charge_id = Nanoid . generate ( )
322
- debit_id = Nanoid . generate ( )
323
- credit_id = Nanoid . generate ( )
324
303
tx_group_id = Nanoid . generate ( )
325
304
326
305
# Calculate fees
327
306
currency = to_string ( amount . currency )
328
- total_paid = Payments . get_total_paid ( owner . id , recipient . id )
329
- platform_fee_pct = FeeTier . calculate_fee_percentage ( total_paid )
307
+ platform_fee_pct = FeeTier . calculate_fee_percentage ( Money . zero ( :USD ) )
330
308
transaction_fee_pct = Payments . get_transaction_fee_pct ( )
331
309
332
310
platform_fee = Money . mult! ( amount , platform_fee_pct )
333
311
transaction_fee = Money . mult! ( amount , transaction_fee_pct )
334
312
total_fee = Money . add! ( platform_fee , transaction_fee )
335
313
gross_amount = Money . add! ( amount , total_fee )
336
314
337
- line_items = [
338
- % {
339
- price_data: % {
340
- unit_amount: MoneyUtils . to_minor_units ( amount ) ,
341
- currency: currency ,
342
- product_data: % {
343
- name: "Payment to @#{ recipient . provider_login } " ,
344
- description: if ( ticket_ref , do: "#{ ticket_ref [ :owner ] } /#{ ticket_ref [ :repo ] } ##{ ticket_ref [ :number ] } " ) ,
345
- images: [ recipient . avatar_url ]
315
+ line_items =
316
+ if recipient do
317
+ [
318
+ % {
319
+ price_data: % {
320
+ unit_amount: MoneyUtils . to_minor_units ( amount ) ,
321
+ currency: currency ,
322
+ product_data: % {
323
+ name: "Payment to @#{ recipient . provider_login } " ,
324
+ description: if ( ticket_ref , do: "#{ ticket_ref [ :owner ] } /#{ ticket_ref [ :repo ] } ##{ ticket_ref [ :number ] } " ) ,
325
+ images: [ recipient . avatar_url ]
326
+ }
327
+ } ,
328
+ quantity: 1
346
329
}
347
- } ,
348
- quantity: 1
349
- } ,
350
- % {
351
- price_data: % {
352
- unit_amount: MoneyUtils . to_minor_units ( Money . mult! ( amount , platform_fee_pct ) ) ,
353
- currency: currency ,
354
- product_data: % { name: "Algora platform fee (#{ Util . format_pct ( platform_fee_pct ) } )" }
355
- } ,
356
- quantity: 1
357
- } ,
358
- % {
359
- price_data: % {
360
- unit_amount: MoneyUtils . to_minor_units ( Money . mult! ( amount , transaction_fee_pct ) ) ,
361
- currency: currency ,
362
- product_data: % { name: "Transaction fee (#{ Util . format_pct ( transaction_fee_pct ) } )" }
363
- } ,
364
- quantity: 1
365
- }
366
- ]
330
+ ]
331
+ else
332
+ [ ]
333
+ end ++
334
+ Enum . map ( claims , fn claim ->
335
+ % {
336
+ price_data: % {
337
+ # TODO: ensure shares are normalized
338
+ unit_amount: amount |> Money . mult! ( claim . group_share ) |> MoneyUtils . to_minor_units ( ) ,
339
+ currency: currency ,
340
+ product_data: % {
341
+ name: "Payment to @#{ claim . user . provider_login } " ,
342
+ description: if ( ticket_ref , do: "#{ ticket_ref [ :owner ] } /#{ ticket_ref [ :repo ] } ##{ ticket_ref [ :number ] } " ) ,
343
+ images: [ claim . user . avatar_url ]
344
+ }
345
+ } ,
346
+ quantity: 1
347
+ }
348
+ end ) ++
349
+ [
350
+ % {
351
+ price_data: % {
352
+ unit_amount: MoneyUtils . to_minor_units ( Money . mult! ( amount , platform_fee_pct ) ) ,
353
+ currency: currency ,
354
+ product_data: % { name: "Algora platform fee (#{ Util . format_pct ( platform_fee_pct ) } )" }
355
+ } ,
356
+ quantity: 1
357
+ } ,
358
+ % {
359
+ price_data: % {
360
+ unit_amount: MoneyUtils . to_minor_units ( Money . mult! ( amount , transaction_fee_pct ) ) ,
361
+ currency: currency ,
362
+ product_data: % { name: "Transaction fee (#{ Util . format_pct ( transaction_fee_pct ) } )" }
363
+ } ,
364
+ quantity: 1
365
+ }
366
+ ]
367
367
368
368
Repo . transact ( fn ->
369
369
with { :ok , _charge } <-
370
370
initialize_charge ( % {
371
- id: charge_id ,
371
+ id: Nanoid . generate ( ) ,
372
372
tip_id: opts [ :tip_id ] ,
373
373
bounty_id: opts [ :bounty_id ] ,
374
- claim_id: opts [ :claim_id ] ,
374
+ claim_id: nil ,
375
375
user_id: creator . id ,
376
376
gross_amount: gross_amount ,
377
377
net_amount: amount ,
378
378
total_fee: total_fee ,
379
379
line_items: line_items ,
380
380
group_id: tx_group_id
381
381
} ) ,
382
- { :ok , _debit } <-
383
- initialize_debit ( % {
384
- id: debit_id ,
385
- tip_id: opts [ :tip_id ] ,
386
- bounty_id: opts [ :bounty_id ] ,
387
- claim_id: opts [ :claim_id ] ,
388
- amount: amount ,
389
- user_id: creator . id ,
390
- linked_transaction_id: credit_id ,
391
- group_id: tx_group_id
392
- } ) ,
393
- { :ok , _credit } <-
394
- initialize_credit ( % {
395
- id: credit_id ,
382
+ { :ok , _transactions } <-
383
+ create_transaction_pairs ( % {
384
+ claims: opts [ :claims ] || [ ] ,
396
385
tip_id: opts [ :tip_id ] ,
397
386
bounty_id: opts [ :bounty_id ] ,
398
- claim_id: opts [ :claim_id ] ,
399
387
amount: amount ,
400
- user_id: recipient . id ,
401
- linked_transaction_id: debit_id ,
388
+ creator_id: creator . id ,
402
389
group_id: tx_group_id
403
390
} ) ,
404
391
{ :ok , session } <-
@@ -415,7 +402,6 @@ defmodule Algora.Bounties do
415
402
id: id ,
416
403
tip_id: tip_id ,
417
404
bounty_id: bounty_id ,
418
- claim_id: claim_id ,
419
405
user_id: user_id ,
420
406
gross_amount: gross_amount ,
421
407
net_amount: net_amount ,
@@ -431,7 +417,6 @@ defmodule Algora.Bounties do
431
417
status: :initialized ,
432
418
tip_id: tip_id ,
433
419
bounty_id: bounty_id ,
434
- claim_id: claim_id ,
435
420
user_id: user_id ,
436
421
gross_amount: gross_amount ,
437
422
net_amount: net_amount ,
@@ -643,4 +628,52 @@ defmodule Algora.Bounties do
643
628
reviews_count: 4
644
629
}
645
630
end
631
+
632
+ # Helper function to create transaction pairs
633
+ defp create_transaction_pairs ( % { claims: claims } = params ) when length ( claims ) > 0 do
634
+ Enum . reduce_while ( claims , { :ok , [ ] } , fn claim , { :ok , acc } ->
635
+ params
636
+ |> Map . put ( :claim_id , claim . id )
637
+ |> Map . put ( :recipient_id , claim . user . id )
638
+ |> create_single_transaction_pair ( )
639
+ |> case do
640
+ { :ok , transactions } -> { :cont , { :ok , transactions ++ acc } }
641
+ error -> { :halt , error }
642
+ end
643
+ end )
644
+ end
645
+
646
+ defp create_transaction_pairs ( params ) do
647
+ create_single_transaction_pair ( params )
648
+ end
649
+
650
+ defp create_single_transaction_pair ( params ) do
651
+ debit_id = Nanoid . generate ( )
652
+ credit_id = Nanoid . generate ( )
653
+
654
+ with { :ok , debit } <-
655
+ initialize_debit ( % {
656
+ id: debit_id ,
657
+ tip_id: params . tip_id ,
658
+ bounty_id: params . bounty_id ,
659
+ claim_id: params . claim_id ,
660
+ amount: params . amount ,
661
+ user_id: params . creator_id ,
662
+ linked_transaction_id: credit_id ,
663
+ group_id: params . group_id
664
+ } ) ,
665
+ { :ok , credit } <-
666
+ initialize_credit ( % {
667
+ id: credit_id ,
668
+ tip_id: params . tip_id ,
669
+ bounty_id: params . bounty_id ,
670
+ claim_id: params . claim_id ,
671
+ amount: params . amount ,
672
+ user_id: params . recipient_id ,
673
+ linked_transaction_id: debit_id ,
674
+ group_id: params . group_id
675
+ } ) do
676
+ { :ok , [ debit , credit ] }
677
+ end
678
+ end
646
679
end
0 commit comments