Class: Wallets::Transaction

Inherits:
ApplicationRecord show all
Defined in:
lib/wallets/models/transaction.rb

Overview

Transactions are the append-only source of truth for wallet balance changes. Positive rows add value, negative rows consume value, and transfers link both sides of an internal movement through ‘transfer_id`.

This class supports embedding: subclasses can override config and table names without affecting the base Wallets::* behavior.

Constant Summary collapse

DEFAULT_CATEGORIES =
[
  "credit",
  "debit",
  "transfer_in",
  "transfer_out",
  "refund",
  "reward",
  "purchase",
  "top_up",
  "adjustment"
].freeze
CATEGORIES =
DEFAULT_CATEGORIES

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.categoriesObject



36
37
38
39
40
41
42
43
44
45
# File 'lib/wallets/models/transaction.rb', line 36

def self.categories
  extra_categories =
    if resolved_config.respond_to?(:additional_categories)
      resolved_config.additional_categories
    else
      []
    end

  (DEFAULT_CATEGORIES + extra_categories).uniq
end

.resolved_configObject



18
19
20
21
# File 'lib/wallets/models/transaction.rb', line 18

def self.resolved_config
  value = config_provider
  value.respond_to?(:call) ? value.call : value
end

.table_nameObject



14
15
16
# File 'lib/wallets/models/transaction.rb', line 14

def self.table_name
  embedded_table_name || "#{resolved_config.table_prefix}transactions"
end

Instance Method Details

#allocated_amountObject



103
104
105
# File 'lib/wallets/models/transaction.rb', line 103

def allocated_amount
  incoming_allocations.sum(:amount)
end

#balance_afterObject



127
128
129
# File 'lib/wallets/models/transaction.rb', line 127

def balance_after
  [:balance_after]
end

#balance_beforeObject



123
124
125
# File 'lib/wallets/models/transaction.rb', line 123

def balance_before
  [:balance_before]
end

#credit?Boolean

Returns:

  • (Boolean)


95
96
97
# File 'lib/wallets/models/transaction.rb', line 95

def credit?
  amount.positive?
end

#debit?Boolean

Returns:

  • (Boolean)


99
100
101
# File 'lib/wallets/models/transaction.rb', line 99

def debit?
  amount.negative?
end

#expired?Boolean

Returns:

  • (Boolean)


91
92
93
# File 'lib/wallets/models/transaction.rb', line 91

def expired?
  expires_at.present? && expires_at < Time.current
end

#metadataObject



73
74
75
# File 'lib/wallets/models/transaction.rb', line 73

def 
  @indifferent_metadata ||= ActiveSupport::HashWithIndifferentAccess.new(super || {})
end

#metadata=(hash) ⇒ Object



77
78
79
80
# File 'lib/wallets/models/transaction.rb', line 77

def metadata=(hash)
  @indifferent_metadata = nil
  super(hash.respond_to?(:to_h) ? hash.to_h : {})
end

#ownerObject



87
88
89
# File 'lib/wallets/models/transaction.rb', line 87

def owner
  wallet.owner
end

#reloadObject



82
83
84
85
# File 'lib/wallets/models/transaction.rb', line 82

def reload(*)
  @indifferent_metadata = nil
  super
end

#remaining_amountObject



111
112
113
114
115
# File 'lib/wallets/models/transaction.rb', line 111

def remaining_amount
  return 0 unless credit?

  amount - allocated_amount
end

#spent_amountObject



107
108
109
# File 'lib/wallets/models/transaction.rb', line 107

def spent_amount
  outgoing_allocations.sum(:amount)
end

#sync_balance_snapshot!(before:, after:) ⇒ Object



131
132
133
134
135
136
# File 'lib/wallets/models/transaction.rb', line 131

def sync_balance_snapshot!(before:, after:)
  update!(metadata: .merge(
    balance_before: before,
    balance_after: after
  ))
end

#unbacked_amountObject



117
118
119
120
121
# File 'lib/wallets/models/transaction.rb', line 117

def unbacked_amount
  return 0 unless debit?

  amount.abs - spent_amount
end