Module: Spree::BankPayments

Defined in:
lib/spree/bank_payments.rb,
lib/spree/bank_payments/engine.rb,
lib/spree/bank_payments/version.rb,
app/models/spree/bank_payments/base.rb,
lib/spree/bank_payments/subscribers.rb,
app/jobs/spree/bank_payments/poll_job.rb,
lib/spree/bank_payments/configuration.rb,
app/models/spree/bank_payments/gateway.rb,
app/models/spree/bank_payments/detail_set.rb,
app/models/spree/bank_payments/account_data.rb,
app/models/spree/bank_payments/bank_account.rb,
app/models/spree/bank_payments/transfer_data.rb,
app/services/spree/bank_payments/sync_accounts.rb,
app/jobs/spree/bank_payments/send_reminders_job.rb,
app/models/spree/bank_payments/reconciler_state.rb,
app/models/spree/bank_payments/reconcilers/base.rb,
app/services/spree/bank_payments/apply_discount.rb,
app/services/spree/bank_payments/apply_transfer.rb,
app/jobs/spree/bank_payments/expire_sessions_job.rb,
app/models/spree/bank_payments/adjuster/discount.rb,
app/models/spree/bank_payments/incoming_transfer.rb,
app/models/spree/bank_payments/payment_decorator.rb,
app/services/spree/bank_payments/health_reporter.rb,
app/services/spree/bank_payments/ingest_transfer.rb,
app/services/spree/bank_payments/suggest_matches.rb,
app/models/spree/bank_payments/reconcilers/manual.rb,
app/mailers/spree/bank_payments/instructions_mailer.rb,
app/services/spree/bank_payments/reference_generator.rb,
app/services/spree/bank_payments/migrate_legacy_accounts.rb,
lib/generators/spree/bank_payments/install/install_generator.rb

Defined Under Namespace

Modules: Adjuster, Generators, PaymentDecorator, Reconcilers Classes: AccountData, ApplyDiscount, ApplyTransfer, BankAccount, Base, Configuration, DetailSet, Engine, ExpireSessionsJob, Gateway, HealthReporter, IncomingTransfer, IngestTransfer, InstructionsMailer, MigrateLegacyAccounts, PollJob, ReconcilerState, ReferenceGenerator, SendRemindersJob, SuggestMatches, SyncAccounts, TransferData

Constant Summary collapse

VERSION =

Major version tracks Spree's major version: 5.x supports Spree 5.x.

'5.3.0'.freeze

Class Method Summary collapse

Class Method Details

.gateway_scopeObject

Subquery of payment-method ids for those types. unscoped deliberately: a soft-deleted payment method must still have its stale adjustments found and removed.



84
85
86
# File 'lib/spree/bank_payments.rb', line 84

def self.gateway_scope
  Spree::PaymentMethod.unscoped.where(type: gateway_type_names)
end

.gateway_type_namesObject

Every STI type name that counts as one of this gem's gateways.

ApplyDiscount#bank_transfer? tests with is_a?, which matches subclasses, so a store subclassing the gateway HAS the discount applied. The SQL filters must agree, or those adjustments would be created but never counted into taxable_adjustment_total (VAT silently unfixed -- the exact bug 5.1.0 fixes) and never removed on a payment-method switch (leaking margin). Resolved at call time so it reflects whatever is loaded.



77
78
79
# File 'lib/spree/bank_payments.rb', line 77

def self.gateway_type_names
  ([Spree::BankPayments::Gateway] + Spree::BankPayments::Gateway.descendants).map(&:name).uniq
end

.pg_trgm_available?Boolean

Returns:

  • (Boolean)


88
89
90
91
92
93
94
95
96
# File 'lib/spree/bank_payments.rb', line 88

def self.pg_trgm_available?
  return @pg_trgm_available if defined?(@pg_trgm_available)

  @pg_trgm_available = ActiveRecord::Base.connection.extension_enabled?('pg_trgm')
rescue StandardError
  # Deliberately NOT memoized: a transient connection failure must not disable
  # payer-name suggestions for the lifetime of the process.
  false
end

.register_default_mailer_subscribers!Object

Registers the default mailer's Spree::Events subscriptions.

Called from Rails.application.config.to_prepare, not after_initialize (see config/initializers/spree.rb): spree_core's own Engine runs Spree::Events.reset! + Spree::Events.activate! from its own to_prepare hook on every code reload, and activate! only re-registers subscribers listed in Spree.subscribers (class-based) — it drops these Proc-based subscriptions. A boot-once after_initialize registration would mean the default mailer silently stops working after the first code edit in development, same failure shape as the reconciler registry bug fixed in Task 5. to_prepare re-runs on every reload, so calling this again heals it.

Must be idempotent: to_prepare can fire multiple times without an intervening Spree::Events.reset! (e.g. several engines' to_prepare blocks running in one reload pass), and Spree::Events::Registry#register has no built-in dedupe — a second subscribe call with the same pattern would add a second subscription and send duplicate mail. Guard with registry.registered?, which checks for an existing subscription with this exact pattern string.



23
24
25
26
27
28
29
30
31
32
33
# File 'lib/spree/bank_payments/subscribers.rb', line 23

def self.register_default_mailer_subscribers!
  subscribe_once('bank_transfer.instructions_ready') do |event|
    Spree::BankPayments::InstructionsMailer.
      instructions(event.payload[:payment_session_id]).deliver_later
  end

  subscribe_once('bank_transfer.reminder_due') do |event|
    Spree::BankPayments::InstructionsMailer.
      reminder(event.payload[:payment_session_id]).deliver_later
  end
end

.register_discount_adjuster!Object

Registers Spree::BankPayments::Adjuster::Discount in Rails.application.config.spree.adjusters.

Being in that array at all is what matters: AdjustmentsUpdater runs every registered non-tax adjuster and persists the resulting totals onto the adjustable BEFORE computing tax, so an unregistered adjuster means the line-item discounts never reach taxable_adjustment_total and tax is still computed on the undiscounted price.

Position within the array is NOT significant. AdjustmentsUpdater picks the tax adjuster out by name (adjusters - [tax_adjuster]) and always runs it last, whatever the order. We insert ahead of it so the array reads in execution order, but appending would behave identically -- do not treat the insertion point as load-bearing.

Called from BOTH hooks in config/initializers/spree.rb, for two different reasons:

  • after_initialize, because spree_core assigns (not appends to) config.spree.adjusters in its own after_initialize. A to_prepare registration runs earlier in boot (run_prepare_callbacks is a finisher ahead of finisher_hook) and would be wiped by that assignment.
  • to_prepare, because the adjuster autoloads from app/models: Zeitwerk re-creates the class on every code reload in development, leaving the array holding a stale, unloaded constant. Re-running swaps in the fresh one.

Idempotent, and safe to call before spree_core has seeded the array (a no-op then -- the after_initialize call registers for real).



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/spree/bank_payments.rb', line 50

def self.register_discount_adjuster!
  adjusters = Rails.application.config.spree.adjusters
  return if adjusters.blank?

  # Reject by NAME, not by identity: after a reload the array holds the
  # previous incarnation of the class, which is not `equal?` to the fresh
  # constant, so a `include?` guard would let duplicates accumulate.
  adjusters.reject! { |adjuster| adjuster.name == 'Spree::BankPayments::Adjuster::Discount' }

  # Cosmetic: keeps the array in execution order. AdjustmentsUpdater runs
  # the tax adjuster last regardless, so `<<` would be equivalent.
  tax_index = adjusters.index { |adjuster| adjuster.name == 'Spree::Adjustable::Adjuster::Tax' }
  if tax_index
    adjusters.insert(tax_index, Spree::BankPayments::Adjuster::Discount)
  else
    adjusters << Spree::BankPayments::Adjuster::Discount
  end
end

.table_name_prefixObject

Must live on the module, not on Spree::BankPayments::Base.

ActiveRecord resolves a table prefix with (module_parents.detect { |p| p.respond_to?(:table_name_prefix) } || self).table_name_prefix and Spree itself defines table_name_prefix as "spree_". Now that these models are nested under Spree, that parent is found first and a class-level method on Base is never consulted -- every table would resolve to spree_ instead of spree_bank_payments_. Defining it here puts a closer parent in the chain.



17
18
19
# File 'lib/spree/bank_payments.rb', line 17

def self.table_name_prefix
  'spree_bank_payments_'
end