Skip to content

Commit 6a4efb1

Browse files
[Legal Entity Payout] use new create_transfer method for LEPM (#14023)
Consolidates information from nightly method by using the new create_transfer method which uses the provided information in payout method along with provided attributes. --------- Co-authored-by: Samuel Fernandez <me@sfernandez.dev>
1 parent d516da4 commit 6a4efb1

9 files changed

Lines changed: 226 additions & 134 deletions

File tree

app/models/legal_entity/payout_method.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,23 @@ class PayoutMethod < ApplicationRecord
5555
# type-specific presentation lives on the detail record
5656
delegate :kind, :icon, :name, :human_kind, :title_kind, :currency, :short_label, :detail_summary, to: :details
5757

58+
# Shared contract for `create_transfer(event, **attrs)` across every payout
59+
# method. Each detail class pulls only the attributes its transfer type
60+
# supports.
61+
#
62+
# Required (MUST be passed):
63+
# amount: Integer — amount in cents
64+
# payment_for: String — description of the payment
65+
# recipient_name: String
66+
# recipient_email: String
67+
# user: User — the user initiating the transfer
68+
# memo: String — required by Check and Wire; ignored by ACH and Wise
69+
#
70+
# Optional (MAY be passed):
71+
# send_email_notification: Boolean — default false
72+
# company_entry_description: String — ACH only
73+
delegate :create_transfer, to: :details
74+
5875
def self.unsupported?(details_class)
5976
UNSUPPORTED_METHODS.key?(details_class)
6077
end

app/models/legal_entity/payout_method/ach_transfer.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,24 @@ def currency
5656
"USD"
5757
end
5858

59+
# See LegalEntity::PayoutMethod for the shared `create_transfer` contract.
60+
def create_transfer(event, amount:, payment_for:, recipient_name:, recipient_email:, user:, company_entry_description: nil, send_email_notification: false, **)
61+
bank_name = ColumnService.get("/institutions/#{routing_number}")["full_name"] rescue "Bank Account"
62+
63+
event.ach_transfers.build(
64+
routing_number:,
65+
account_number:,
66+
creator: user,
67+
amount:,
68+
bank_name:,
69+
payment_for:,
70+
recipient_name:,
71+
recipient_email:,
72+
company_entry_description:,
73+
send_email_notification:,
74+
)
75+
end
76+
5977
end
6078

6179
end

app/models/legal_entity/payout_method/check.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,24 @@ def currency
6868
"USD"
6969
end
7070

71+
# See LegalEntity::PayoutMethod for the shared `create_transfer` contract.
72+
def create_transfer(event, amount:, payment_for:, recipient_name:, recipient_email:, user:, memo:, send_email_notification: false, **)
73+
event.increase_checks.build(
74+
address_line1:,
75+
address_line2:,
76+
address_city:,
77+
address_state:,
78+
address_zip: address_postal_code,
79+
amount:,
80+
memo: memo&.slice(0...40),
81+
payment_for:,
82+
recipient_name:,
83+
recipient_email:,
84+
user:,
85+
send_email_notification:,
86+
)
87+
end
88+
7189
end
7290

7391
end

app/models/legal_entity/payout_method/wire.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,32 @@ def currency
6868
"USD"
6969
end
7070

71+
# See LegalEntity::PayoutMethod for the shared `create_transfer` contract.
72+
def create_transfer(event, amount:, payment_for:, recipient_email:, user:, recipient_name:, memo:, send_email_notification: false, **)
73+
event.wires.build(
74+
address_line1:,
75+
address_line2:,
76+
address_city:,
77+
address_state:,
78+
address_postal_code:,
79+
recipient_country:,
80+
account_number:,
81+
bic_code:,
82+
recipient_information: recipient_information.merge({
83+
purpose_code: Wire.reimbursement_purpose_code_for(recipient_country),
84+
remittance_info: Wire.reimbursement_remittance_info_for(recipient_country),
85+
}),
86+
amount_cents: amount,
87+
recipient_name: self.recipient_name.presence || recipient_name,
88+
recipient_email:,
89+
payment_for: payment_for&.slice(0...140),
90+
memo:,
91+
user:,
92+
currency:,
93+
send_email_notification:,
94+
)
95+
end
96+
7197
end
7298

7399
end

app/models/legal_entity/payout_method/wise_transfer.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,27 @@ def title_kind
4848
"Wise Transfer"
4949
end
5050

51+
# See LegalEntity::PayoutMethod for the shared `create_transfer` contract.
52+
def create_transfer(event, amount:, payment_for:, recipient_name:, recipient_email:, user:, bank_name: nil, **)
53+
event.wise_transfers.build(
54+
address_line1:,
55+
address_line2:,
56+
address_city:,
57+
address_state:,
58+
address_postal_code:,
59+
recipient_country:,
60+
currency:,
61+
wise_recipient_id:,
62+
recipient_information:,
63+
amount_cents: amount,
64+
payment_for:,
65+
recipient_name:,
66+
recipient_email:,
67+
user:,
68+
bank_name:
69+
)
70+
end
71+
5172
def payout_summary
5273
["wise transfer", ("to #{bank_name}" if bank_name.present?), ("(#{currency})" if currency.present?)].compact.join(" ")
5374
end

app/models/payment/attempt.rb

Lines changed: 21 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -96,112 +96,30 @@ class Attempt < ApplicationRecord
9696
def create_transfer!
9797
self.with_lock do
9898
payout_method = payment.legal_entity.default_payout_method
99-
case payout_method.details
100-
when LegalEntity::PayoutMethod::Check
101-
safely do
102-
check = payment.event.increase_checks.build(
103-
memo: "Payment for \"#{payment.purpose}\"."[0...40],
104-
amount: payment.estimate_usd_amount_cents,
105-
payment_for: "Payment for \"#{payment.purpose}\".",
106-
recipient_name: payment.payee.display_name,
107-
recipient_email: payment.payee.email,
108-
address_line1: payout_method.details.address_line1,
109-
address_line2: payout_method.details.address_line2,
110-
address_city: payout_method.details.address_city,
111-
address_state: payout_method.details.address_state,
112-
address_zip: payout_method.details.address_postal_code,
113-
user: payment.creator
114-
)
115-
116-
check.save!
117-
118-
self.payout = check
119-
save!
120-
121-
Receipt.reupload(old_receiptable: payment, new_receiptable: check.local_hcb_code)
122-
end
123-
when LegalEntity::PayoutMethod::AchTransfer
124-
safely do
125-
ach_transfer = payment.event.ach_transfers.build(
126-
amount: payment.estimate_usd_amount_cents,
127-
payment_for: "Payment for \"#{payment.purpose}\".",
128-
recipient_name: payment.payee.display_name,
129-
recipient_email: payment.payee.email,
130-
routing_number: payout_method.details.routing_number,
131-
account_number: payout_method.details.account_number,
132-
bank_name: (ColumnService.get("/institutions/#{payout_method.routing_number}")["full_name"] rescue "Bank Account"),
133-
creator: payment.creator
134-
)
135-
136-
ach_transfer.save!
137-
138-
self.payout = ach_transfer
139-
save!
140-
141-
Receipt.reupload(old_receiptable: payment, new_receiptable: ach_transfer.local_hcb_code)
142-
end
143-
when LegalEntity::PayoutMethod::Wire
144-
safely do
145-
wire = payment.event.wires.build(
146-
memo: "Payment for \"#{payment.purpose}\".",
147-
payment_for: "Payment for #{payment.purpose}."[0...140],
148-
amount_cents: payment.amount_cents,
149-
address_line1: payout_method.details.address_line1,
150-
address_line2: payout_method.details.address_line2,
151-
address_city: payout_method.details.address_city,
152-
address_state: payout_method.details.address_state,
153-
address_postal_code: payout_method.details.address_postal_code,
154-
recipient_country: payout_method.details.recipient_country,
155-
recipient_name: payout_method.details.recipient_name.presence || payment.payee.display_name,
156-
recipient_email: payment.payee.email,
157-
account_number: payout_method.details.account_number,
158-
bic_code: payout_method.details.bic_code,
159-
recipient_information: payout_method.details.recipient_information.merge({
160-
purpose_code: Wire.payment_payment.purpose_code_for(payout_method.details.recipient_country),
161-
remittance_info: Wire.payment_remittance_info_for(payout_method.details.recipient_country),
162-
}),
163-
currency:,
164-
user: payment.creator
165-
)
166-
167-
wire.save!
168-
169-
self.payout = wire
170-
save!
171-
172-
Receipt.reupload(old_receiptable: payment, new_receiptable: wire.local_hcb_code)
173-
end
174-
when LegalEntity::PayoutMethod::WiseTransfer
175-
safely do
176-
wise = payment.event.wise_transfers.build(
177-
memo: "Payment for \"#{payment.purpose}\"",
178-
amount: payment.amount_cents,
179-
payment_for: "Payment for \"#{payment.purpose}\"",
180-
recipient_name: payment.payee.display_name,
181-
recipient_email: payment.payee.email,
182-
address_line1: payout_method.details.address_line1,
183-
address_line2: payout_method.details.address_line2,
184-
address_city: payout_method.details.address_city,
185-
address_state: payout_method.details.address_state,
186-
address_postal_code: payout_method.details.address_postal_code,
187-
recipient_country: payout_method.details.recipient_country,
188-
bank_name: payout_method.details.bank_name,
189-
recipient_information: payout_method.details.recipient_information,
190-
currency:,
191-
user: payment.creator
192-
)
193-
194-
wise.save!
195-
196-
self.payout = wise
197-
save!
198-
199-
Receipt.reupload(old_receiptable: payment, new_receiptable: wise.local_hcb_code)
200-
end
201-
else
99+
unless PAYOUT_METHOD_TRANSFER_MAPPING.key?(payout_method.details.class)
202100
raise ArgumentError, "🚨⚠️ unsupported payout method!"
203101
end
204102

103+
safely do
104+
transfer = payout_method.create_transfer(
105+
payment.event,
106+
amount: payment.amount_cents,
107+
memo: "Payment for \"#{payment.purpose}\".",
108+
payment_for: "Payment for \"#{payment.purpose}\".",
109+
recipient_name: payment.payee.display_name,
110+
recipient_email: payment.payee.email,
111+
currency: payment.currency,
112+
user: payment.creator,
113+
)
114+
115+
transfer.save!
116+
117+
self.payout = transfer
118+
save!
119+
120+
Receipt.reupload(old_receiptable: payment, new_receiptable: transfer.local_hcb_code)
121+
end
122+
205123
mark_under_review!
206124
end
207125
end

app/services/reimbursement/payout_holding_service/nightly.rb

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,16 @@ def run
1414
case payout_method
1515
when LegalEntity::PayoutMethod::Wire
1616
Rails.error.handle do
17-
wire = clearinghouse.wires.build(
17+
wire = payout_method.create_transfer(
18+
clearinghouse,
19+
amount: payout_holding.amount_cents,
1820
memo: "Reimbursement for #{payout_holding.report.name}.",
19-
payment_for: "Reimbursement for #{payout_holding.report.name}."[0...140],
20-
amount_cents: payout_holding.amount_cents,
21-
address_line1: payout_method.address_line1,
22-
address_line2: payout_method.address_line2,
23-
address_city: payout_method.address_city,
24-
address_state: payout_method.address_state,
25-
address_postal_code: payout_method.address_postal_code,
26-
recipient_country: payout_method.recipient_country,
21+
payment_for: "Reimbursement for #{payout_holding.report.name}.",
22+
recipient_name: payout_holding.report.user.full_name,
2723
recipient_email: payout_holding.report.user.email,
2824
send_email_notification: false,
29-
recipient_name: payout_method.recipient_name.presence || payout_holding.report.user.full_name,
30-
account_number: payout_method.account_number,
31-
bic_code: payout_method.bic_code,
32-
recipient_information: payout_method.recipient_information.merge({
33-
purpose_code: Wire.reimbursement_purpose_code_for(payout_method.recipient_country),
34-
remittance_info: Wire.reimbursement_remittance_info_for(payout_method.recipient_country),
35-
}),
36-
currency: "USD",
37-
user: User.system_user
25+
user: User.system_user,
26+
currency: "USD"
3827
)
3928
begin
4029
wire.save!
@@ -56,18 +45,14 @@ def run
5645
end
5746
when LegalEntity::PayoutMethod::Check
5847
Rails.error.handle do
59-
check = clearinghouse.increase_checks.build(
60-
memo: "Reimbursement for #{payout_holding.report.name}."[0...40],
48+
check = payout_method.create_transfer(
49+
clearinghouse,
6150
amount: payout_holding.amount_cents,
51+
memo: "Reimbursement for #{payout_holding.report.name}.",
6252
payment_for: "Reimbursement for #{payout_holding.report.name}.",
6353
recipient_name: payout_holding.report.user.full_name,
64-
address_line1: payout_method.address_line1,
65-
address_line2: payout_method.address_line2,
66-
address_city: payout_method.address_city,
67-
address_state: payout_method.address_state,
6854
recipient_email: payout_holding.report.user.email,
6955
send_email_notification: false,
70-
address_zip: payout_method.address_postal_code,
7156
user: User.system_user
7257
)
7358
check.save!
@@ -84,16 +69,14 @@ def run
8469
end
8570
when LegalEntity::PayoutMethod::AchTransfer
8671
Rails.error.handle do
87-
ach_transfer = clearinghouse.ach_transfers.build(
72+
ach_transfer = payout_method.create_transfer(
73+
clearinghouse,
8874
amount: payout_holding.amount_cents,
8975
payment_for: "Reimbursement for #{payout_holding.report.name}.",
9076
recipient_name: payout_holding.report.user.full_name,
9177
recipient_email: payout_holding.report.user.email,
9278
send_email_notification: false,
93-
routing_number: payout_method.routing_number,
94-
account_number: payout_method.account_number,
95-
bank_name: (ColumnService.get("/institutions/#{payout_method.routing_number}")["full_name"] rescue "Bank Account"),
96-
creator: User.system_user,
79+
user: User.system_user,
9780
company_entry_description: "REIMBURSE"
9881
)
9982
ach_transfer.save!

0 commit comments

Comments
 (0)