Move event publisher into Bess
This commit is contained in:
parent
af984f2a90
commit
6dbe500043
18 changed files with 50 additions and 33 deletions
2
Gemfile
2
Gemfile
|
@ -53,8 +53,6 @@ gem 'devise', '~> 4.7'
|
||||||
|
|
||||||
# API Tools
|
# API Tools
|
||||||
gem 'foreman', '~> 0.87.1'
|
gem 'foreman', '~> 0.87.1'
|
||||||
gem 'wisper', '~> 2.0'
|
|
||||||
gem 'wisper-activejob', '~> 1.0.0'
|
|
||||||
|
|
||||||
group :development, :ci do
|
group :development, :ci do
|
||||||
gem 'traceroute', '~> 0.8.0'
|
gem 'traceroute', '~> 0.8.0'
|
||||||
|
|
|
@ -13,6 +13,8 @@ PATH
|
||||||
specs:
|
specs:
|
||||||
bess (0.1.0)
|
bess (0.1.0)
|
||||||
rails (~> 6.0.3, >= 6.0.3.1)
|
rails (~> 6.0.3, >= 6.0.3.1)
|
||||||
|
wisper (~> 2.0)
|
||||||
|
wisper-activejob (~> 1.0.0)
|
||||||
|
|
||||||
PATH
|
PATH
|
||||||
remote: gems/ruby-param-validation
|
remote: gems/ruby-param-validation
|
||||||
|
@ -463,8 +465,6 @@ DEPENDENCIES
|
||||||
traceroute (~> 0.8.0)
|
traceroute (~> 0.8.0)
|
||||||
webmock (~> 3.6, >= 3.6.2)
|
webmock (~> 3.6, >= 3.6.2)
|
||||||
webpacker (~> 5.1.1)
|
webpacker (~> 5.1.1)
|
||||||
wisper (~> 2.0)
|
|
||||||
wisper-activejob (~> 1.0.0)
|
|
||||||
wisper-rspec (~> 1.1.0)
|
wisper-rspec (~> 1.1.0)
|
||||||
|
|
||||||
RUBY VERSION
|
RUBY VERSION
|
||||||
|
|
|
@ -106,7 +106,7 @@ class Campaign < ApplicationRecord
|
||||||
after_create do
|
after_create do
|
||||||
user = profile.user
|
user = profile.user
|
||||||
Role.create(name: :campaign_editor, user_id: user.id, host: self)
|
Role.create(name: :campaign_editor, user_id: user.id, host: self)
|
||||||
HoudiniEventPublisher.announce(:campaign_create, self)
|
Houdini.event_publisher.announce(:campaign_create, self)
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
|
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
|
||||||
HoudiniEventPublisher = EventPublisher.new
|
|
||||||
|
|
||||||
Rails.application.config.to_prepare do
|
Wisper.clear if Rails.env.development?
|
||||||
Wisper.clear if Rails.env.development?
|
|
||||||
[NonprofitMailerListener, CreditCardPaymentListener, SepaPaymentListener, TicketListener].each do |listener|
|
Rails.application.config.houdini.listeners << [NonprofitMailerListener,
|
||||||
HoudiniEventPublisher.subscribe_async(listener)
|
CreditCardPaymentListener,
|
||||||
end
|
SepaPaymentListener,
|
||||||
end
|
TicketListener]
|
||||||
|
|
|
@ -16,6 +16,11 @@ Gem::Specification.new do |spec|
|
||||||
spec.files = Dir["{app,config,db,lib}/**/*", "LICENSE", "AGPL-3.0.txt", "GPL-3.0.txt", "LGPL-3.0.txt", "Rakefile", "README.md"]
|
spec.files = Dir["{app,config,db,lib}/**/*", "LICENSE", "AGPL-3.0.txt", "GPL-3.0.txt", "LGPL-3.0.txt", "Rakefile", "README.md"]
|
||||||
|
|
||||||
spec.add_dependency "rails", "~> 6.0.3", ">= 6.0.3.1"
|
spec.add_dependency "rails", "~> 6.0.3", ">= 6.0.3.1"
|
||||||
|
spec.add_dependency 'wisper', '~> 2.0'
|
||||||
|
spec.add_dependency 'wisper-activejob', '~> 1.0.0'
|
||||||
|
|
||||||
spec.add_development_dependency 'rspec', '~> 3.9.0'
|
spec.add_development_dependency 'rspec', '~> 3.9.0'
|
||||||
spec.add_development_dependency 'rspec-rails', '~> 4.0.0'
|
spec.add_development_dependency 'rspec-rails', '~> 4.0.0'
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,6 +10,7 @@ module Houdini
|
||||||
autoload :Maintenance
|
autoload :Maintenance
|
||||||
autoload :Intl
|
autoload :Intl
|
||||||
autoload :PaymentProvider
|
autoload :PaymentProvider
|
||||||
|
autoload :EventPublisher
|
||||||
|
|
||||||
mattr_accessor :intl, :maintenance, :ccs
|
mattr_accessor :intl, :maintenance, :ccs
|
||||||
|
|
||||||
|
@ -34,4 +35,6 @@ module Houdini
|
||||||
mattr_accessor :support_email
|
mattr_accessor :support_email
|
||||||
|
|
||||||
mattr_accessor :core_classes, default: {supporter: 'Supporter', nonprofit: 'Nonprofit'}
|
mattr_accessor :core_classes, default: {supporter: 'Supporter', nonprofit: 'Nonprofit'}
|
||||||
|
|
||||||
|
mattr_accessor :event_publisher, default: Houdini::EventPublisher.new
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
|
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
|
||||||
class EventPublisher
|
require 'wisper'
|
||||||
|
require 'wisper/activejob'
|
||||||
|
class Houdini::EventPublisher
|
||||||
include Wisper::Publisher
|
include Wisper::Publisher
|
||||||
|
|
||||||
def announce(event, *args)
|
def announce(event, *args)
|
||||||
|
@ -11,4 +13,10 @@ class EventPublisher
|
||||||
def subscribe_async(listener, options = {})
|
def subscribe_async(listener, options = {})
|
||||||
subscribe(listener, options.merge(async: true))
|
subscribe(listener, options.merge(async: true))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def subscribe_all(listeners, options = {})
|
||||||
|
listeners.each do |listener|
|
||||||
|
subscribe(listener, options.merge(async: true))
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
|
@ -62,6 +62,8 @@ module Houdini
|
||||||
config.houdini.maintenance = ActiveSupport::OrderedOptions.new
|
config.houdini.maintenance = ActiveSupport::OrderedOptions.new
|
||||||
config.houdini.maintenance.active = false
|
config.houdini.maintenance.active = false
|
||||||
|
|
||||||
|
config.houdini.listeners = []
|
||||||
|
|
||||||
|
|
||||||
initializer 'houdini.set_configuration', before: 'factory_bot.set_fixture_replacement' do |app|
|
initializer 'houdini.set_configuration', before: 'factory_bot.set_fixture_replacement' do |app|
|
||||||
app.config.to_prepare do
|
app.config.to_prepare do
|
||||||
|
@ -100,6 +102,8 @@ in the provided locales: #{Houdini.intl.available_locales.join(', ')}") if Houdi
|
||||||
Houdini.nonprofits_must_be_vetted = app.config.houdini.nonprofits_must_be_vetted
|
Houdini.nonprofits_must_be_vetted = app.config.houdini.nonprofits_must_be_vetted
|
||||||
Houdini.show_state_fields = app.config.houdini.show_state_fields
|
Houdini.show_state_fields = app.config.houdini.show_state_fields
|
||||||
Houdini.default_bp = app.config.houdini.default_bp.id
|
Houdini.default_bp = app.config.houdini.default_bp.id
|
||||||
|
|
||||||
|
Houdini.event_publisher.subscribe_all(app.config.houdini.listeners.flatten)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -43,7 +43,7 @@ module InsertDonation
|
||||||
result['donation'] = insert_donation(data, entities)
|
result['donation'] = insert_donation(data, entities)
|
||||||
update_donation_keys(result)
|
update_donation_keys(result)
|
||||||
result['activity'] = InsertActivities.for_one_time_donations([result['payment'].id])
|
result['activity'] = InsertActivities.for_one_time_donations([result['payment'].id])
|
||||||
HoudiniEventPublisher.announce(:donation_create, result['donation'], result['donation'].supporter.locale)
|
Houdini.event_publisher.announce(:donation_create, result['donation'], result['donation'].supporter.locale)
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ module InsertDonation
|
||||||
result['donation'] = insert_donation(data, entities)
|
result['donation'] = insert_donation(data, entities)
|
||||||
update_donation_keys(result)
|
update_donation_keys(result)
|
||||||
|
|
||||||
HoudiniEventPublisher.announce(:donation_create, result['donation'], locale_for_supporter(result['donation'].supporter.id))
|
Houdini.event_publisher.announce(:donation_create, result['donation'], locale_for_supporter(result['donation'].supporter.id))
|
||||||
|
|
||||||
# do this for making test consistent
|
# do this for making test consistent
|
||||||
result['activity'] = {}
|
result['activity'] = {}
|
||||||
|
|
|
@ -70,7 +70,7 @@ module InsertRecurringDonation
|
||||||
result['activity'] = InsertActivities.for_recurring_donations([result['payment'].id])
|
result['activity'] = InsertActivities.for_recurring_donations([result['payment'].id])
|
||||||
end
|
end
|
||||||
# Send receipts
|
# Send receipts
|
||||||
HoudiniEventPublisher.announce(:recurring_donation_create, result['donation'], entities[:supporter_id].locale)
|
Houdini.event_publisher.announce(:recurring_donation_create, result['donation'], entities[:supporter_id].locale)
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ module InsertRecurringDonation
|
||||||
|
|
||||||
InsertDonation.update_donation_keys(result) if result['payment']
|
InsertDonation.update_donation_keys(result) if result['payment']
|
||||||
|
|
||||||
HoudiniEventPublisher.announce(:recurring_donation_create, result['donation'], entities[:supporter_id].locale)
|
Houdini.event_publisher.announce(:recurring_donation_create, result['donation'], entities[:supporter_id].locale)
|
||||||
|
|
||||||
{ status: 200, json: result }
|
{ status: 200, json: result }
|
||||||
end
|
end
|
||||||
|
|
|
@ -66,7 +66,7 @@ module InsertRefunds
|
||||||
# Update original payment to increment its refund_total for any future refund attempts
|
# Update original payment to increment its refund_total for any future refund attempts
|
||||||
Qx.update(:payments).set("refund_total=refund_total + #{h['amount'].to_i}").ts.where(id: original_payment['id']).execute
|
Qx.update(:payments).set("refund_total=refund_total + #{h['amount'].to_i}").ts.where(id: original_payment['id']).execute
|
||||||
# Send the refund receipts in a delayed job
|
# Send the refund receipts in a delayed job
|
||||||
HoudiniEventPublisher.announce(:create_refund, Refund.find(refund_row['id']))
|
Houdini.event_publisher.announce(:create_refund, Refund.find(refund_row['id']))
|
||||||
{ 'payment' => payment_row, 'refund' => refund_row }
|
{ 'payment' => payment_row, 'refund' => refund_row }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -100,7 +100,7 @@ module InsertTickets
|
||||||
ticket_ids = result['tickets'].map(&:id)
|
ticket_ids = result['tickets'].map(&:id)
|
||||||
charge_id = result['charge'] ? result['charge'].id : nil
|
charge_id = result['charge'] ? result['charge'].id : nil
|
||||||
|
|
||||||
HoudiniEventPublisher.announce(:ticket_create, result['tickets'], result['charge'])
|
Houdini.event_publisher.announce(:ticket_create, result['tickets'], result['charge'])
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -77,14 +77,14 @@ module PayRecurringDonation
|
||||||
if result['charge']['status'] != 'failed'
|
if result['charge']['status'] != 'failed'
|
||||||
rd.update(n_failures: 0)
|
rd.update(n_failures: 0)
|
||||||
result['recurring_donation'] = rd
|
result['recurring_donation'] = rd
|
||||||
HoudiniEventPublisher.announce(:recurring_donation_payment_succeeded, donation, donation&.supporter&.locale || 'en')
|
Houdini.event_publisher.announce(:recurring_donation_payment_succeeded, donation, donation&.supporter&.locale || 'en')
|
||||||
InsertActivities.for_recurring_donations([result['payment']['id']])
|
InsertActivities.for_recurring_donations([result['payment']['id']])
|
||||||
else
|
else
|
||||||
|
|
||||||
rd.n_failures += 1
|
rd.n_failures += 1
|
||||||
rd.save!
|
rd.save!
|
||||||
result['recurring_donation'] = rd
|
result['recurring_donation'] = rd
|
||||||
HoudiniEventPublisher.announce(:recurring_donation_payment_failed, donation)
|
Houdini.event_publisher.announce(:recurring_donation_payment_failed, donation)
|
||||||
InsertSupporterNotes.create([{ content: "This supporter had a payment failure for their recurring donation with ID #{rd_id}", supporter_id: donation['supporter_id'], user_id: 540 }])
|
InsertSupporterNotes.create([{ content: "This supporter had a payment failure for their recurring donation with ID #{rd_id}", supporter_id: donation['supporter_id'], user_id: 540 }])
|
||||||
end
|
end
|
||||||
result
|
result
|
||||||
|
|
|
@ -94,7 +94,7 @@ describe InsertDonation do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'process campaign donation' do
|
it 'process campaign donation' do
|
||||||
expect(HoudiniEventPublisher).to receive(:announce).with(:campaign_create, any_args)
|
expect(Houdini.event_publisher).to receive(:announce).with(:campaign_create, any_args)
|
||||||
process_campaign_donation { InsertDonation.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, campaign_id: campaign.id, date: (Time.now + 1.day).to_s, dedication: 'dedication', designation: 'designation') }
|
process_campaign_donation { InsertDonation.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, campaign_id: campaign.id, date: (Time.now + 1.day).to_s, dedication: 'dedication', designation: 'designation') }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ describe InsertDonation do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'process campaign donation' do
|
it 'process campaign donation' do
|
||||||
expect(HoudiniEventPublisher).to receive(:announce).with(:campaign_create, any_args)
|
expect(Houdini.event_publisher).to receive(:announce).with(:campaign_create, any_args)
|
||||||
process_campaign_donation(sepa: true) { InsertDonation.with_sepa(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, direct_debit_detail_id: direct_debit_detail.id, campaign_id: campaign.id, date: (Time.now + 1.day).to_s, dedication: 'dedication', designation: 'designation') }
|
process_campaign_donation(sepa: true) { InsertDonation.with_sepa(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, direct_debit_detail_id: direct_debit_detail.id, campaign_id: campaign.id, date: (Time.now + 1.day).to_s, dedication: 'dedication', designation: 'designation') }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -131,7 +131,7 @@ describe InsertRecurringDonation do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'process campaign donation' do
|
it 'process campaign donation' do
|
||||||
expect(HoudiniEventPublisher).to receive(:announce).with(:campaign_create, any_args)
|
expect(Houdini.event_publisher).to receive(:announce).with(:campaign_create, any_args)
|
||||||
process_campaign_donation(recurring_donation: { paydate: nil, interval: 2, time_unit: 'month', start_date: Time.current.beginning_of_day }) { InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, campaign_id: campaign.id, date: (Time.now + 1.day).to_s, dedication: 'dedication', designation: 'designation', recurring_donation: { interval: 2 }) }
|
process_campaign_donation(recurring_donation: { paydate: nil, interval: 2, time_unit: 'month', start_date: Time.current.beginning_of_day }) { InsertRecurringDonation.with_stripe(amount: charge_amount, nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, campaign_id: campaign.id, date: (Time.now + 1.day).to_s, dedication: 'dedication', designation: 'designation', recurring_donation: { interval: 2 }) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -285,7 +285,7 @@ describe InsertTickets do
|
||||||
success_expectations
|
success_expectations
|
||||||
expect(QueryRoles).to receive(:is_authorized_for_nonprofit?).with(user.id, nonprofit.id).and_return true
|
expect(QueryRoles).to receive(:is_authorized_for_nonprofit?).with(user.id, nonprofit.id).and_return true
|
||||||
result = nil
|
result = nil
|
||||||
expect(HoudiniEventPublisher).to receive(:announce).with(:ticket_create, any_args)
|
expect(Houdini.event_publisher).to receive(:announce).with(:ticket_create, any_args)
|
||||||
result = InsertTickets.create(tickets: [{ quantity: 1, ticket_level_id: ticket_level.id }], nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: event.id, kind: 'offsite', offsite_payment: { kind: 'check', check_number: 'fake_checknumber' }, current_user: user)
|
result = InsertTickets.create(tickets: [{ quantity: 1, ticket_level_id: ticket_level.id }], nonprofit_id: nonprofit.id, supporter_id: supporter.id, token: source_token.token, event_id: event.id, kind: 'offsite', offsite_payment: { kind: 'check', check_number: 'fake_checknumber' }, current_user: user)
|
||||||
|
|
||||||
expected = generate_expected_tickets(payment_id: result['payment'].id,
|
expected = generate_expected_tickets(payment_id: result['payment'].id,
|
||||||
|
|
|
@ -16,12 +16,12 @@ RSpec.describe Campaign, type: :model do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'parent campaign sends out a create job' do
|
it 'parent campaign sends out a create job' do
|
||||||
expect(HoudiniEventPublisher).to receive(:announce).with(:campaign_create, any_args).exactly(:once)
|
expect(Houdini.event_publisher).to receive(:announce).with(:campaign_create, any_args).exactly(:once)
|
||||||
parent_campaign
|
parent_campaign
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'child campaign sends out federated create job' do
|
it 'child campaign sends out federated create job' do
|
||||||
expect(HoudiniEventPublisher).to receive(:announce).with(:campaign_create, any_args).exactly(:twice)
|
expect(Houdini.event_publisher).to receive(:announce).with(:campaign_create, any_args).exactly(:twice)
|
||||||
parent_campaign
|
parent_campaign
|
||||||
child_campaign
|
child_campaign
|
||||||
end
|
end
|
||||||
|
|
|
@ -376,9 +376,9 @@ RSpec.shared_context :shared_rd_donation_value_context do
|
||||||
pay_method = data[:sepa] ? direct_debit_detail : card
|
pay_method = data[:sepa] ? direct_debit_detail : card
|
||||||
|
|
||||||
unless (data[:recurring_donation])
|
unless (data[:recurring_donation])
|
||||||
expect(HoudiniEventPublisher).to receive(:announce).with(:donation_create,instance_of(Donation), supporter.locale )
|
expect(Houdini.event_publisher).to receive(:announce).with(:donation_create,instance_of(Donation), supporter.locale )
|
||||||
else
|
else
|
||||||
expect(HoudiniEventPublisher).to receive(:announce).with(:recurring_donation_create,instance_of(Donation), supporter.locale )
|
expect(Houdini.event_publisher).to receive(:announce).with(:recurring_donation_create,instance_of(Donation), supporter.locale )
|
||||||
end
|
end
|
||||||
result = yield
|
result = yield
|
||||||
expected = generate_expected(@donation_id, result['payment'].id, result['charge'].id, pay_method, supporter, nonprofit, @stripe_charge_id, event: event, recurring_donation_expected: data[:recurring_donation], recurring_donation: result['recurring_donation'])
|
expected = generate_expected(@donation_id, result['payment'].id, result['charge'].id, pay_method, supporter, nonprofit, @stripe_charge_id, event: event, recurring_donation_expected: data[:recurring_donation], recurring_donation: result['recurring_donation'])
|
||||||
|
@ -399,9 +399,9 @@ RSpec.shared_context :shared_rd_donation_value_context do
|
||||||
pay_method = data[:sepa] ? direct_debit_detail : card
|
pay_method = data[:sepa] ? direct_debit_detail : card
|
||||||
|
|
||||||
unless (data[:recurring_donation])
|
unless (data[:recurring_donation])
|
||||||
expect(HoudiniEventPublisher).to receive(:announce).with(:donation_create,instance_of(Donation), supporter.locale )
|
expect(Houdini.event_publisher).to receive(:announce).with(:donation_create,instance_of(Donation), supporter.locale )
|
||||||
else
|
else
|
||||||
expect(HoudiniEventPublisher).to receive(:announce).with(:recurring_donation_create,instance_of(Donation), supporter.locale )
|
expect(Houdini.event_publisher).to receive(:announce).with(:recurring_donation_create,instance_of(Donation), supporter.locale )
|
||||||
end
|
end
|
||||||
result = yield
|
result = yield
|
||||||
expected = generate_expected(@donation_id, result['payment'].id, result['charge'].id, pay_method, supporter, nonprofit, @stripe_charge_id, campaign: campaign, recurring_donation_expected: data[:recurring_donation], recurring_donation: result['recurring_donation'])
|
expected = generate_expected(@donation_id, result['payment'].id, result['charge'].id, pay_method, supporter, nonprofit, @stripe_charge_id, campaign: campaign, recurring_donation_expected: data[:recurring_donation], recurring_donation: result['recurring_donation'])
|
||||||
|
@ -419,9 +419,9 @@ RSpec.shared_context :shared_rd_donation_value_context do
|
||||||
def process_general_donation(data = {})
|
def process_general_donation(data = {})
|
||||||
pay_method = data[:sepa] ? direct_debit_detail : card
|
pay_method = data[:sepa] ? direct_debit_detail : card
|
||||||
unless (data[:recurring_donation])
|
unless (data[:recurring_donation])
|
||||||
expect(HoudiniEventPublisher).to receive(:announce).with(:donation_create,instance_of(Donation), supporter.locale )
|
expect(Houdini.event_publisher).to receive(:announce).with(:donation_create,instance_of(Donation), supporter.locale )
|
||||||
else
|
else
|
||||||
expect(HoudiniEventPublisher).to receive(:announce).with(:recurring_donation_create,instance_of(Donation), supporter.locale )
|
expect(Houdini.event_publisher).to receive(:announce).with(:recurring_donation_create,instance_of(Donation), supporter.locale )
|
||||||
end
|
end
|
||||||
result = yield
|
result = yield
|
||||||
expect_payment = nil_or_true(data[:expect_payment])
|
expect_payment = nil_or_true(data[:expect_payment])
|
||||||
|
|
Loading…
Reference in a new issue