acts_as_account 3.2.3 → 3.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/lint.yml +1 -1
- data/.github/workflows/tests.yml +1 -1
- data/CHANGELOG.md +175 -4
- data/README.md +13 -1
- data/Rakefile +4 -4
- data/VERSION +1 -1
- data/acts_as_account.gemspec +16 -30
- data/acts_as_account.sqlite +0 -0
- data/features/step_definitions/account_steps.rb +17 -3
- data/features/support/env.rb +7 -0
- data/features/transfer/transfer.feature +15 -3
- data/lib/acts_as_account/account.rb +41 -11
- data/lib/acts_as_account/active_record_extensions.rb +0 -1
- data/lib/acts_as_account/configuration.rb +10 -0
- data/lib/acts_as_account/global_account.rb +6 -1
- data/lib/acts_as_account/journal.rb +36 -18
- data/lib/acts_as_account/version.rb +1 -1
- data/lib/acts_as_account.rb +9 -0
- metadata +19 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 82e0a5a2dcd250ad8d0aa7231550b853a20afa4a74f93676099cdcf756826516
|
4
|
+
data.tar.gz: 0fdacf00679d364e12680d1862fad056fc7c8334c1c4b0078dce9a6d23219b19
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 58987a63a27f2d97fe7e1d961431981e79846c213806c3364dd5ea0e42944d334b7b41d47188e361157736f341308174dd6b5f41a29ffc9e59fc63262cad8daa
|
7
|
+
data.tar.gz: d16e37c26e92810328ee1e60fa16135f4a6740b51e931d10bba3bdb6b56e6fed30b8610191c439570c0473bae2b441844c731b71d935993d18c25d2612c75f06
|
data/.github/workflows/lint.yml
CHANGED
data/.github/workflows/tests.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,176 @@
|
|
1
|
-
#
|
1
|
+
# Changes
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
## 2024-10-28 v3.4.0
|
4
|
+
|
5
|
+
* Improve Journaling for Transfer Operations:
|
6
|
+
+ Renamed `add_posting` to `build_posting` in `ActsAsAccount::Journal`
|
7
|
+
+ Replaced direct database insertion with two insert statements with a call to `model.insert_all` in `transfer` method
|
8
|
+
+ Updated `update_attributes_on` to directly count amounts of postings
|
9
|
+
* Ensure consistent locking order for account transfers:
|
10
|
+
+ Use each if we aren't interested in the `lock!` results
|
11
|
+
+ Make if condition readable even on smaller displays
|
12
|
+
* Improved logging for transfer method in Journal class:
|
13
|
+
+ Improved formatting of debug message using array.join.
|
14
|
+
+ Improved indenting of comment
|
15
|
+
* Improved journal functionality for transfers:
|
16
|
+
+ Replaced `tap` with a more concise implementation using `map`
|
17
|
+
|
18
|
+
## 2024-10-23 v3.3.0
|
19
|
+
|
20
|
+
* Make persistence of `#postings_count` and `#balance` configurable for accounts:
|
21
|
+
+ Only lock if configuration is set to persist these attributes
|
22
|
+
+ Rename `recalculate_all_balances` to `recalculate_attributes` and deprecate
|
23
|
+
the original method
|
24
|
+
* Make gem configurable:
|
25
|
+
+ Add configuration option `persist_attributes_on_account` for persistence of `postings_count` and `balance`
|
26
|
+
* Update dependencies and Ruby version:
|
27
|
+
+ Update to newer Ruby version and dependencies
|
28
|
+
* Review and README adjustments:
|
29
|
+
+ Perform review and make adjustments to README file
|
30
|
+
* Fix typo:
|
31
|
+
+ Correct a typo in the code
|
32
|
+
|
33
|
+
## 2022-07-20 v3.2.3
|
34
|
+
|
35
|
+
* Loosen Rails dependencies to now be less than **8**.
|
36
|
+
* Use experimental, new web-protocol for links (`HTTP::Link`).
|
37
|
+
* Neaten README and update copyright information.
|
38
|
+
* Remove dependency on `cc` gem (broken on Ruby-head).
|
39
|
+
* Test only on MRI (Ruby Implementation).
|
40
|
+
* Fix linter issue.
|
41
|
+
* Use SQLite for tests.
|
42
|
+
* Use GitHub Actions.
|
43
|
+
|
44
|
+
## 2021-02-22 v3.2.2
|
45
|
+
|
46
|
+
* Make `database_cleaner` a development dependency
|
47
|
+
* Support **Rails 6**
|
48
|
+
* Fix specs for recent versions of **Rails**
|
49
|
+
|
50
|
+
## 2016-12-08 v3.2.0
|
51
|
+
|
52
|
+
* Be compatible with Rails **5**.
|
53
|
+
* Call `rake` instead of just mentioning it.
|
54
|
+
* Do not check in `Gemfile.lock`.
|
55
|
+
* Drop support for Ruby **1.9.2**.
|
56
|
+
* Add support for Ruby **2.3.0**.
|
57
|
+
* Update gems and Travis settings to use containers, adding a Travis badge.
|
58
|
+
|
59
|
+
## 2015-01-22 v3.1.2
|
60
|
+
|
61
|
+
* Removed `.ruby` files.
|
62
|
+
* Regenerated `gemspec` for **3.1.1** and **2.0.3** versions.
|
63
|
+
* Ignored ruby-version.
|
64
|
+
|
65
|
+
## 2015-01-14 v3.1.1
|
66
|
+
|
67
|
+
* Corrected posting scope for Rails 4: The `posting_scope` method was updated
|
68
|
+
to correctly handle UTC times stored in the database.
|
69
|
+
* Compare UTC times to values in database: The code now parses specified dates
|
70
|
+
and converts them to the database format of their UTC time, ensuring correct
|
71
|
+
range finding.
|
72
|
+
* Be less strict in depending on **4.1**: The gem's dependencies were relaxed
|
73
|
+
to be less strict about requiring version **4.1**.
|
74
|
+
* Update LICENSE: The license was changed from an unknown type to Apache
|
75
|
+
License.
|
76
|
+
* Regenerate gemspec for `version 3.1.0`: The gemspec was regenerated for the
|
77
|
+
new version.
|
78
|
+
* Adds Changelog and Rails 4 notice: A changelog and a notice about supporting
|
79
|
+
Rails 4 were added.
|
80
|
+
* Regenerate gemspec for `version 2.0.3`: The gemspec was regenerated for the
|
81
|
+
new version.
|
82
|
+
* Regenerate gemspec for `version 3.1.1`: The gemspec was regenerated for the
|
83
|
+
new version.
|
84
|
+
|
85
|
+
## 2014-04-25 v3.1.0
|
86
|
+
|
87
|
+
* Added Rails 4.1 compatibility.
|
88
|
+
* Regenerated gemspec for `**3.1.0**`.
|
89
|
+
* Updated LICENSE to use the Apache License.
|
90
|
+
|
91
|
+
## 2013-12-17 v3.0.0
|
92
|
+
|
93
|
+
* Adds **Rails 4** compatibility
|
94
|
+
* Uses `update_counters` to solve concurrency issues and treat account balances
|
95
|
+
like other counters in Rails, replacing previous method that would undo lock
|
96
|
+
on account rows by reloading them.
|
97
|
+
|
98
|
+
## 2014-09-18 v2.0.2
|
99
|
+
|
100
|
+
* Repair building with `jewel`
|
101
|
+
* Add `travis` configuration
|
102
|
+
* Specify gem dependencies
|
103
|
+
* Update LICENSE to Apache License
|
104
|
+
* Compare UTC times to values in database:
|
105
|
+
+ Parse specified dates and convert them to the db format of their UTC time.
|
106
|
+
|
107
|
+
## 2012-10-04 v2.0.1
|
108
|
+
|
109
|
+
* Regenerate gemspec for **2.0.1**
|
110
|
+
* Fixed problem that broke STI classes that used `has_account` in Rails 3.x
|
111
|
+
* Updated gemspec to reflect changes
|
112
|
+
|
113
|
+
## 2012-09-10 v2.0.0
|
114
|
+
|
115
|
+
* Upgrade `acts_as_account` to work with Rails **3**.
|
116
|
+
* Significant changes:
|
117
|
+
+ Renamed `VERSION` file
|
118
|
+
+ Updated `acts_as_account.gemspec`
|
119
|
+
+ Modified `lib/acts_as_account/journal.rb`
|
120
|
+
+ Modified `lib/acts_as_account/posting.rb`
|
121
|
+
|
122
|
+
## 2012-07-31 v1.2.0
|
123
|
+
|
124
|
+
* Regenerate gemspec for `version 1.2.0`
|
125
|
+
* Updated `version` to use with default STI naming setup for Rails >= **2.3**
|
126
|
+
* Added method `BetterPlace::Model::Base#sti_name`
|
127
|
+
* Renamed method `BetterPlace::Model::Base#table_name`
|
128
|
+
|
129
|
+
## 2012-03-12 v1.1.6
|
130
|
+
|
131
|
+
* **Fixed bug in active_record_extensions**: `holder_id` and type are now
|
132
|
+
passed through correctly.
|
133
|
+
* Changed `returning` to `#tap` to remove warnings.
|
134
|
+
* More fixes for tests and rake task.
|
135
|
+
* Fixed calculation of account balances.
|
136
|
+
|
137
|
+
## 2010-11-15 v1.1.5
|
138
|
+
|
139
|
+
* Fixed dependency:
|
140
|
+
+ Updated `Gemfile` to use the latest version of `rails`
|
141
|
+
+ Removed unused `mysql2` gem
|
142
|
+
* Significant changes:
|
143
|
+
+ Added a new method, `create_user`, to the `User` model (`def
|
144
|
+
create_user(**kwargs)`)
|
145
|
+
+ Updated the `login` method in the `SessionController` to use the
|
146
|
+
`create_user` method (`def login; @user = User.create_user(**params); end`)
|
147
|
+
+ Changed the default value of the `admin` attribute in the `User` model from
|
148
|
+
`false` to `true` (`attr_accessor :admin, default: true`)
|
149
|
+
|
150
|
+
## 2010-11-12 v1.1.4
|
151
|
+
|
152
|
+
* Fixed dependency bug:
|
153
|
+
+ Updated the project to use `Gemfile` instead of `config.gem`
|
154
|
+
+ Removed reference to deprecated `config.gem` in favor of `Gemfile`
|
155
|
+
+ Added `gem 'mysql2', '~> **1.0**'` to `Gemfile`
|
156
|
+
|
157
|
+
## 2010-11-12 v1.1.3
|
158
|
+
|
159
|
+
* Fixed dependency bug:
|
160
|
+
+ Updated `BetterPlace::DependencyManager` to use correct version of `Gem`
|
161
|
+
(now using `Gem::Version.new('1.3.7')`)
|
162
|
+
+ Added check for missing dependencies in
|
163
|
+
`BetterPlace::Project#load_dependencies`
|
164
|
+
* Version bump: **1.1.3**
|
165
|
+
|
166
|
+
## 2010-11-12 v1.1.2
|
167
|
+
|
168
|
+
* Added some methods:
|
169
|
+
+ `BetterPlace::Project#new` now takes an optional `:api_key` parameter
|
170
|
+
+ `BetterPlace::Project#fetch_data` now fetches data from the Better Place
|
171
|
+
API using the provided `:api_key`
|
172
|
+
* Modified README and Rakefile
|
173
|
+
|
174
|
+
## 2010-11-12 v1.1.0
|
175
|
+
|
176
|
+
* Start
|
data/README.md
CHANGED
@@ -15,6 +15,18 @@ tables is needed.
|
|
15
15
|
We also hook into the ActionController request cycle to warn the developer
|
16
16
|
if a request has left uncommitted changes in the system.
|
17
17
|
|
18
|
+
## Configuration
|
19
|
+
|
20
|
+
It is possible to configure if attributes (postings_count, balance, last_valuta) are persisted on the Account or if it is calculated on demand.
|
21
|
+
```
|
22
|
+
ActsAsAccount.configure do |config|
|
23
|
+
# Default values:
|
24
|
+
# config.persist_attributes_on_account = true
|
25
|
+
end
|
26
|
+
```
|
27
|
+
Enabling persistence means that the sending and receiving account will aquire a lock when making a transfer to ensure correct data. This can be problematic in a high load scenario where many transfers to the same accounts are processed in parallel.
|
28
|
+
|
29
|
+
|
18
30
|
## How to test
|
19
31
|
|
20
32
|
Run the cucumber features from the acs_as_account gem, just execute
|
@@ -23,7 +35,7 @@ Run the cucumber features from the acs_as_account gem, just execute
|
|
23
35
|
|
24
36
|
## How to release
|
25
37
|
|
26
|
-
You need to update the data in `VERSION` and Rakefile and run `rake` (because it uses
|
38
|
+
You need to update the data in `VERSION` and Rakefile and run `rake` (because it uses GemHadar).
|
27
39
|
`rake gem:push` will push the version to rubygems.
|
28
40
|
|
29
41
|
## Links
|
data/Rakefile
CHANGED
@@ -18,11 +18,11 @@ GemHadar do
|
|
18
18
|
|
19
19
|
dependency 'activerecord', '>= 5.1', '<8'
|
20
20
|
dependency 'actionpack' , '>= 4.1', '<8'
|
21
|
-
development_dependency 'cucumber'
|
21
|
+
development_dependency 'cucumber'
|
22
22
|
development_dependency 'sqlite3'
|
23
|
-
development_dependency 'rspec'
|
23
|
+
development_dependency 'rspec'
|
24
24
|
development_dependency 'simplecov'
|
25
|
-
development_dependency 'database_cleaner'
|
25
|
+
development_dependency 'database_cleaner'
|
26
26
|
development_dependency 'rubocop'
|
27
27
|
end
|
28
28
|
|
@@ -30,7 +30,7 @@ def connect_database
|
|
30
30
|
require 'active_record'
|
31
31
|
require 'yaml'
|
32
32
|
db_config = YAML.load_file('features/db/database.yml')
|
33
|
-
ActiveRecord::Base.establish_connection(db_config).
|
33
|
+
ActiveRecord::Base.establish_connection(db_config).lease_connection
|
34
34
|
end
|
35
35
|
|
36
36
|
namespace :features do
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.
|
1
|
+
3.4.0
|
data/acts_as_account.gemspec
CHANGED
@@ -1,47 +1,33 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
# stub: acts_as_account 3.
|
2
|
+
# stub: acts_as_account 3.4.0 ruby lib
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "acts_as_account".freeze
|
6
|
-
s.version = "3.
|
6
|
+
s.version = "3.4.0".freeze
|
7
7
|
|
8
8
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
9
9
|
s.require_paths = ["lib".freeze]
|
10
10
|
s.authors = ["Thies C. Arntzen, Norman Timmler, Matthias Frick, Phillip Oertel".freeze]
|
11
|
-
s.date = "
|
11
|
+
s.date = "2024-10-28"
|
12
12
|
s.description = "acts_as_account implements double entry accounting for Rails models. Your models get accounts and you can do consistent transactions between them. Since the documentation is sparse, see the transfer.feature for usage examples.".freeze
|
13
13
|
s.email = "developers@betterplace.org".freeze
|
14
|
-
s.extra_rdoc_files = ["README.md".freeze, "lib/acts_as_account.rb".freeze, "lib/acts_as_account/account.rb".freeze, "lib/acts_as_account/active_record_extensions.rb".freeze, "lib/acts_as_account/global_account.rb".freeze, "lib/acts_as_account/journal.rb".freeze, "lib/acts_as_account/manually_created_account.rb".freeze, "lib/acts_as_account/posting.rb".freeze, "lib/acts_as_account/rails.rb".freeze, "lib/acts_as_account/transfer.rb".freeze, "lib/acts_as_account/version.rb".freeze]
|
15
|
-
s.files = [".github/workflows/lint.yml".freeze, ".github/workflows/tests.yml".freeze, ".gitignore".freeze, ".rubocop.yml".freeze, "CHANGELOG.md".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "VERSION".freeze, "acts_as_account.gemspec".freeze, "acts_as_account.sqlite".freeze, "cucumber.yml".freeze, "features/account/account_creation.feature".freeze, "features/db/database.yml".freeze, "features/db/schema.rb".freeze, "features/step_definitions/account_steps.rb".freeze, "features/support/abstract_user.rb".freeze, "features/support/cheque.rb".freeze, "features/support/env.rb".freeze, "features/support/inheriting_user.rb".freeze, "features/support/user.rb".freeze, "features/transfer/journal_creation.feature".freeze, "features/transfer/transfer.feature".freeze, "init.rb".freeze, "lib/acts_as_account.rb".freeze, "lib/acts_as_account/account.rb".freeze, "lib/acts_as_account/active_record_extensions.rb".freeze, "lib/acts_as_account/global_account.rb".freeze, "lib/acts_as_account/journal.rb".freeze, "lib/acts_as_account/manually_created_account.rb".freeze, "lib/acts_as_account/posting.rb".freeze, "lib/acts_as_account/rails.rb".freeze, "lib/acts_as_account/transfer.rb".freeze, "lib/acts_as_account/version.rb".freeze]
|
14
|
+
s.extra_rdoc_files = ["README.md".freeze, "lib/acts_as_account.rb".freeze, "lib/acts_as_account/account.rb".freeze, "lib/acts_as_account/active_record_extensions.rb".freeze, "lib/acts_as_account/configuration.rb".freeze, "lib/acts_as_account/global_account.rb".freeze, "lib/acts_as_account/journal.rb".freeze, "lib/acts_as_account/manually_created_account.rb".freeze, "lib/acts_as_account/posting.rb".freeze, "lib/acts_as_account/rails.rb".freeze, "lib/acts_as_account/transfer.rb".freeze, "lib/acts_as_account/version.rb".freeze]
|
15
|
+
s.files = [".github/workflows/lint.yml".freeze, ".github/workflows/tests.yml".freeze, ".gitignore".freeze, ".rubocop.yml".freeze, "CHANGELOG.md".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "VERSION".freeze, "acts_as_account.gemspec".freeze, "acts_as_account.sqlite".freeze, "cucumber.yml".freeze, "features/account/account_creation.feature".freeze, "features/db/database.yml".freeze, "features/db/schema.rb".freeze, "features/step_definitions/account_steps.rb".freeze, "features/support/abstract_user.rb".freeze, "features/support/cheque.rb".freeze, "features/support/env.rb".freeze, "features/support/inheriting_user.rb".freeze, "features/support/user.rb".freeze, "features/transfer/journal_creation.feature".freeze, "features/transfer/transfer.feature".freeze, "init.rb".freeze, "lib/acts_as_account.rb".freeze, "lib/acts_as_account/account.rb".freeze, "lib/acts_as_account/active_record_extensions.rb".freeze, "lib/acts_as_account/configuration.rb".freeze, "lib/acts_as_account/global_account.rb".freeze, "lib/acts_as_account/journal.rb".freeze, "lib/acts_as_account/manually_created_account.rb".freeze, "lib/acts_as_account/posting.rb".freeze, "lib/acts_as_account/rails.rb".freeze, "lib/acts_as_account/transfer.rb".freeze, "lib/acts_as_account/version.rb".freeze]
|
16
16
|
s.homepage = "https://github.com/betterplace/acts_as_account".freeze
|
17
17
|
s.licenses = ["Apache-2.0".freeze]
|
18
18
|
s.rdoc_options = ["--title".freeze, "ActsAsAccount -- More Math in Ruby".freeze, "--main".freeze, "README.md".freeze]
|
19
|
-
s.rubygems_version = "3.
|
19
|
+
s.rubygems_version = "3.5.18".freeze
|
20
20
|
s.summary = "acts_as_account implements double entry accounting for Rails models".freeze
|
21
21
|
|
22
|
-
|
23
|
-
s.specification_version = 4
|
24
|
-
end
|
22
|
+
s.specification_version = 4
|
25
23
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
s.add_runtime_dependency(%q<actionpack>.freeze, [">= 4.1", "< 8"])
|
36
|
-
else
|
37
|
-
s.add_dependency(%q<gem_hadar>.freeze, ["~> 1.11.0"])
|
38
|
-
s.add_dependency(%q<cucumber>.freeze, ["~> 1.3"])
|
39
|
-
s.add_dependency(%q<sqlite3>.freeze, [">= 0"])
|
40
|
-
s.add_dependency(%q<rspec>.freeze, ["~> 3.1"])
|
41
|
-
s.add_dependency(%q<simplecov>.freeze, [">= 0"])
|
42
|
-
s.add_dependency(%q<database_cleaner>.freeze, ["~> 1.3"])
|
43
|
-
s.add_dependency(%q<rubocop>.freeze, [">= 0"])
|
44
|
-
s.add_dependency(%q<activerecord>.freeze, [">= 5.1", "< 8"])
|
45
|
-
s.add_dependency(%q<actionpack>.freeze, [">= 4.1", "< 8"])
|
46
|
-
end
|
24
|
+
s.add_development_dependency(%q<gem_hadar>.freeze, ["~> 1.19".freeze])
|
25
|
+
s.add_development_dependency(%q<cucumber>.freeze, [">= 0".freeze])
|
26
|
+
s.add_development_dependency(%q<sqlite3>.freeze, [">= 0".freeze])
|
27
|
+
s.add_development_dependency(%q<rspec>.freeze, [">= 0".freeze])
|
28
|
+
s.add_development_dependency(%q<simplecov>.freeze, [">= 0".freeze])
|
29
|
+
s.add_development_dependency(%q<database_cleaner>.freeze, [">= 0".freeze])
|
30
|
+
s.add_development_dependency(%q<rubocop>.freeze, [">= 0".freeze])
|
31
|
+
s.add_runtime_dependency(%q<activerecord>.freeze, [">= 5.1".freeze, "< 8".freeze])
|
32
|
+
s.add_runtime_dependency(%q<actionpack>.freeze, [">= 4.1".freeze, "< 8".freeze])
|
47
33
|
end
|
data/acts_as_account.sqlite
CHANGED
Binary file
|
@@ -15,6 +15,10 @@ Given /^I create a user (\w+)$/ do |name|
|
|
15
15
|
User.create!(:name => name)
|
16
16
|
end
|
17
17
|
|
18
|
+
Given /^I configure attribute persistence to be (\w+)$/ do |flag|
|
19
|
+
ActsAsAccount.configuration.persist_attributes_on_account = flag == 'true'
|
20
|
+
end
|
21
|
+
|
18
22
|
Given /^I have a user (\w+) that inherits from an abstract class$/ do |name|
|
19
23
|
InheritingUser.create!(:name => name)
|
20
24
|
end
|
@@ -67,9 +71,10 @@ Then /^the global (\w+) account balance is (-?\d+) €$/ do |name, balance|
|
|
67
71
|
end
|
68
72
|
|
69
73
|
When /^I transfer (-?\d+) € from (\w+)'s account to (\w+)'s account$/ do |amount, from, to|
|
70
|
-
from_account = User.find_by_name(from).account
|
71
|
-
to_account = User.find_by_name(to).account
|
72
|
-
|
74
|
+
@from_account = User.find_by_name(from).account
|
75
|
+
@to_account = User.find_by_name(to).account
|
76
|
+
@previous_account_attributes = [@from_account.attributes, @to_account.attributes]
|
77
|
+
Journal.current.transfer(amount.to_i, @from_account, @to_account, @reference, @valuta)
|
73
78
|
end
|
74
79
|
|
75
80
|
When /^I transfer (\d+) € from global (\w+) account to global (\w+) account$/ do |amount, from, to|
|
@@ -172,3 +177,12 @@ end
|
|
172
177
|
When /^I call 'account' on both it should be possible$/ do
|
173
178
|
[@user1, @user2].each { |user| user.account }
|
174
179
|
end
|
180
|
+
|
181
|
+
Then('there are no changes to the accounts') do
|
182
|
+
@previous_account_attributes.should eq [@from_account.reload.attributes, @to_account.reload.attributes]
|
183
|
+
end
|
184
|
+
|
185
|
+
Then('the balance field changed on the accounts') do
|
186
|
+
@from_account.reload.read_attribute(:balance).should_not eq @previous_account_attributes.first['balance']
|
187
|
+
@to_account.reload.read_attribute(:balance).should_not eq @previous_account_attributes.last['balance']
|
188
|
+
end
|
data/features/support/env.rb
CHANGED
@@ -3,14 +3,26 @@ Feature: Transfer
|
|
3
3
|
As a Bank
|
4
4
|
I want not to loose money
|
5
5
|
|
6
|
-
Scenario: I transfer money between accounts having holders
|
6
|
+
Scenario: I transfer money between accounts having holders with attribute persistence set to true
|
7
7
|
Given I create a user Thies
|
8
8
|
Given I create a user Norman
|
9
|
+
Given I configure attribute persistence to be true
|
9
10
|
When I transfer 30 € from Thies's account to Norman's account
|
10
11
|
Then Thies's account balance is -30 €
|
11
12
|
And Norman's account balance is 30 €
|
12
13
|
And the order of the postings is correct
|
13
|
-
|
14
|
+
And the balance field changed on the accounts
|
15
|
+
|
16
|
+
Scenario: I transfer money between accounts having holders with attribute persistence set to false
|
17
|
+
Given I create a user Thies
|
18
|
+
Given I create a user Norman
|
19
|
+
Given I configure attribute persistence to be false
|
20
|
+
When I transfer 30 € from Thies's account to Norman's account
|
21
|
+
Then Thies's account balance is -30 €
|
22
|
+
And Norman's account balance is 30 €
|
23
|
+
And the order of the postings is correct
|
24
|
+
And there are no changes to the accounts
|
25
|
+
|
14
26
|
Scenario: I transfer a negative amount between accounts having holders
|
15
27
|
Given I create a user Thies
|
16
28
|
Given I create a user Norman
|
@@ -41,4 +53,4 @@ Feature: Transfer
|
|
41
53
|
When I transfer 50 € from Thies's account to Norman's account and specify 22.05.1968 07:45 as the booking time
|
42
54
|
Then Thies's account balance is -50 €
|
43
55
|
And Norman's account balance is 50 €
|
44
|
-
And all postings have 22.05.1968 07:45 as the booking time
|
56
|
+
And all postings have 22.05.1968 07:45 as the booking time
|
@@ -6,20 +6,16 @@ module ActsAsAccount
|
|
6
6
|
has_many :postings, :class_name => 'ActsAsAccount::Posting'
|
7
7
|
has_many :journals, :through => :postings
|
8
8
|
|
9
|
-
# TODO: discuss with norman:
|
10
|
-
# validates_presence_of will force an ActiveRecord::find on the object
|
11
|
-
# but we have to create accounts for deleted holder!
|
12
|
-
#
|
13
|
-
# validates_presence_of :holder
|
14
|
-
|
15
9
|
class << self
|
16
10
|
def recalculate_all_balances
|
11
|
+
warn "[DEPRECATION] `recalculate_all_balances` is deprecated and will be removed in a future version. Please use `recalculate_attributes` instead."
|
12
|
+
|
13
|
+
recalculate_attributes
|
14
|
+
end
|
15
|
+
|
16
|
+
def recalculate_attributes
|
17
17
|
find_each do |account|
|
18
|
-
account.
|
19
|
-
balance: account.postings.sum(:amount),
|
20
|
-
postings_count: account.postings.count,
|
21
|
-
last_valuta: account.postings.maximum(:valuta)
|
22
|
-
)
|
18
|
+
account.recalculate_attributes
|
23
19
|
end
|
24
20
|
end
|
25
21
|
|
@@ -67,6 +63,40 @@ module ActsAsAccount
|
|
67
63
|
end
|
68
64
|
end
|
69
65
|
|
66
|
+
def balance
|
67
|
+
if ActsAsAccount.configuration.persist_attributes_on_account
|
68
|
+
super
|
69
|
+
else
|
70
|
+
postings.sum(:amount)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def postings_count
|
75
|
+
if ActsAsAccount.configuration.persist_attributes_on_account
|
76
|
+
super
|
77
|
+
else
|
78
|
+
postings.count
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def last_valuta
|
83
|
+
if ActsAsAccount.configuration.persist_attributes_on_account
|
84
|
+
super
|
85
|
+
else
|
86
|
+
postings.maximum(:valuta)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def recalculate_attributes
|
91
|
+
return unless ActsAsAccount.configuration.persist_attributes_on_account
|
92
|
+
|
93
|
+
update_columns(
|
94
|
+
last_valuta: postings.maximum(:valuta),
|
95
|
+
balance: postings.sum(:amount),
|
96
|
+
postings_count: postings.count
|
97
|
+
)
|
98
|
+
end
|
99
|
+
|
70
100
|
def deleteable?
|
71
101
|
postings.empty? && journals.empty?
|
72
102
|
end
|
@@ -1,7 +1,12 @@
|
|
1
1
|
module ActsAsAccount
|
2
|
+
# A named account that is "global" (not tied to any specific entity
|
3
|
+
# in your database otherwise).
|
4
|
+
#
|
5
|
+
# This is useful for accounts that you don't want to model anything
|
6
|
+
# for via an ActiveRecord model (like "Cash").
|
2
7
|
class GlobalAccount < ActiveRecord::Base
|
3
8
|
self.table_name = :acts_as_account_global_accounts
|
4
9
|
|
5
10
|
has_account
|
6
11
|
end
|
7
|
-
end
|
12
|
+
end
|
@@ -20,9 +20,7 @@ module ActsAsAccount
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def transfers
|
23
|
-
|
24
|
-
postings.each_slice(2) { |postings| transfers << Transfer.new(*postings) }
|
25
|
-
end
|
23
|
+
postings.each_slice(2).map { |postings| Transfer.new(*postings) }
|
26
24
|
end
|
27
25
|
|
28
26
|
def transfer(amount, from_account, to_account, reference = nil, valuta = Time.now)
|
@@ -32,31 +30,51 @@ module ActsAsAccount
|
|
32
30
|
amount, from_account, to_account = -amount, to_account, from_account
|
33
31
|
end
|
34
32
|
|
35
|
-
|
33
|
+
if logger
|
34
|
+
logger.debug(
|
35
|
+
[
|
36
|
+
"ActsAsAccount::Journal.transfer",
|
37
|
+
"amount: #{amount}",
|
38
|
+
"from: #{from_account.id}",
|
39
|
+
"to: #{to_account.id}",
|
40
|
+
"reference: #{reference.class.name}(#{reference.id})",
|
41
|
+
"valuta: #{valuta}",
|
42
|
+
].join(' ')
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
# To avoid possible deadlocks we need to ensure that the locking order
|
47
|
+
# is always the same therfore the sort by id.
|
48
|
+
if ActsAsAccount.configuration.persist_attributes_on_account
|
49
|
+
[from_account, to_account].sort_by(&:id).each(&:lock!)
|
50
|
+
end
|
51
|
+
|
52
|
+
posting1 = build_posting(-amount, from_account, to_account, reference, valuta)
|
53
|
+
posting2 = build_posting( amount, to_account, from_account, reference, valuta)
|
36
54
|
|
37
|
-
|
38
|
-
# the same therfore the sort by id.
|
39
|
-
[from_account, to_account].sort_by(&:id).map(&:lock!)
|
55
|
+
postings.model.insert_all([ posting1.attributes, posting2.attributes ])
|
40
56
|
|
41
|
-
|
42
|
-
|
57
|
+
update_attributes_on(from_account, -amount)
|
58
|
+
update_attributes_on(to_account, amount)
|
43
59
|
end
|
44
60
|
end
|
45
61
|
|
46
62
|
private
|
47
63
|
|
48
|
-
def
|
49
|
-
|
50
|
-
:amount
|
51
|
-
:account
|
64
|
+
def build_posting(amount, account, other_account, reference, valuta)
|
65
|
+
postings.build(
|
66
|
+
:amount => amount,
|
67
|
+
:account => account,
|
52
68
|
:other_account => other_account,
|
53
|
-
:reference
|
54
|
-
:valuta
|
69
|
+
:reference => reference,
|
70
|
+
:valuta => valuta
|
71
|
+
)
|
72
|
+
end
|
55
73
|
|
56
|
-
|
74
|
+
def update_attributes_on(account, amount)
|
75
|
+
return unless ActsAsAccount.configuration.persist_attributes_on_account
|
57
76
|
|
58
|
-
|
59
|
-
account.save(:validate => false)
|
77
|
+
account.class.update_counters account.id, postings_count: 1, balance: amount
|
60
78
|
end
|
61
79
|
end
|
62
80
|
end
|
data/lib/acts_as_account.rb
CHANGED
@@ -1,7 +1,16 @@
|
|
1
1
|
require 'active_record'
|
2
2
|
require 'action_controller'
|
3
|
+
require 'acts_as_account/configuration'
|
3
4
|
|
4
5
|
module ActsAsAccount
|
6
|
+
class << self
|
7
|
+
attr_accessor :configuration
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.configure
|
11
|
+
self.configuration ||= Configuration.new
|
12
|
+
yield(configuration)
|
13
|
+
end
|
5
14
|
end
|
6
15
|
|
7
16
|
require 'acts_as_account/version'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acts_as_account
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thies C. Arntzen, Norman Timmler, Matthias Frick, Phillip Oertel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-10-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gem_hadar
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.
|
19
|
+
version: '1.19'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.
|
26
|
+
version: '1.19'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: cucumber
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: sqlite3
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -56,16 +56,16 @@ dependencies:
|
|
56
56
|
name: rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: simplecov
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -84,16 +84,16 @@ dependencies:
|
|
84
84
|
name: database_cleaner
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - "
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
89
|
+
version: '0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - "
|
94
|
+
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
96
|
+
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: rubocop
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -159,6 +159,7 @@ extra_rdoc_files:
|
|
159
159
|
- lib/acts_as_account.rb
|
160
160
|
- lib/acts_as_account/account.rb
|
161
161
|
- lib/acts_as_account/active_record_extensions.rb
|
162
|
+
- lib/acts_as_account/configuration.rb
|
162
163
|
- lib/acts_as_account/global_account.rb
|
163
164
|
- lib/acts_as_account/journal.rb
|
164
165
|
- lib/acts_as_account/manually_created_account.rb
|
@@ -195,6 +196,7 @@ files:
|
|
195
196
|
- lib/acts_as_account.rb
|
196
197
|
- lib/acts_as_account/account.rb
|
197
198
|
- lib/acts_as_account/active_record_extensions.rb
|
199
|
+
- lib/acts_as_account/configuration.rb
|
198
200
|
- lib/acts_as_account/global_account.rb
|
199
201
|
- lib/acts_as_account/journal.rb
|
200
202
|
- lib/acts_as_account/manually_created_account.rb
|
@@ -225,7 +227,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
225
227
|
- !ruby/object:Gem::Version
|
226
228
|
version: '0'
|
227
229
|
requirements: []
|
228
|
-
rubygems_version: 3.
|
230
|
+
rubygems_version: 3.5.18
|
229
231
|
signing_key:
|
230
232
|
specification_version: 4
|
231
233
|
summary: acts_as_account implements double entry accounting for Rails models
|