debitcredit 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +22 -14
- data/app/models/debitcredit/{transaction.rb → entry.rb} +9 -9
- data/app/models/debitcredit/entry/dsl.rb +36 -0
- data/app/models/debitcredit/extension.rb +2 -2
- data/app/models/debitcredit/item.rb +4 -4
- data/config/locales/en.yml +1 -1
- data/db/migrate/20150106165647_rename_transactions.rb +9 -0
- data/lib/debitcredit/version.rb +1 -1
- metadata +7 -6
- data/app/models/debitcredit/transaction/dsl.rb +0 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9d5bcf4938491d376adc5a00d2635bd1d3c7de59
|
4
|
+
data.tar.gz: cb1ec56618c56492739e6f283bd6df21b0789928
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d95a97ce0104513e21e0c354bf24d180b44727119fe738fe7b67ed0a508a48c2c6b9606463d6e7cd7cc737b26e5f0dd2a5b4e24519d57aed3f0aedb1e9c9ce15
|
7
|
+
data.tar.gz: ec3c2ac293655a912936f4455ea97212d57f28f95a42fa4a07a0a73fc95b09d6d73703d9fd5c192749d3b2ff05996166032894affc21360599cd035f609e75d9
|
data/README.md
CHANGED
@@ -7,15 +7,23 @@ Double Entry Accounting for Rails Applications
|
|
7
7
|
|
8
8
|
## Installation
|
9
9
|
|
10
|
-
* add `
|
10
|
+
* add `gem 'debitcredit'` to your `Gemfile`
|
11
11
|
* and run `bundle install`
|
12
|
-
* run `rake debitcredit:install:migrations db:migrate`
|
12
|
+
* run `rake debitcredit:install:migrations db:migrate db:test:prepare`
|
13
13
|
|
14
|
-
##
|
14
|
+
## Upgrade
|
15
15
|
|
16
16
|
* and run `bundle update debitcredit`
|
17
17
|
* run `rake debitcredit:install:migrations db:migrate`
|
18
18
|
|
19
|
+
### IMPORTANT: version 0.2.0 introduced backwards incompatible changes:
|
20
|
+
|
21
|
+
Transactions were renamed to entries. You need to rename:
|
22
|
+
|
23
|
+
* Transaction to Entry
|
24
|
+
* transactions to entries
|
25
|
+
* has_transactions to has_entries
|
26
|
+
|
19
27
|
## Account Types, Debits and Credits
|
20
28
|
|
21
29
|
<http://en.wikipedia.org/wiki/Debits_and_credits>
|
@@ -27,7 +35,7 @@ Expense and Equity defined as follows:
|
|
27
35
|
from which future economic benefits are expected to flow to the entity
|
28
36
|
|
29
37
|
**Liability** is defined as an obligation of an entity arising from past
|
30
|
-
|
38
|
+
entries or events, the settlement of which may result in the transfer or
|
31
39
|
use of assets, provision of services or other yielding of economic benefits in
|
32
40
|
the future.
|
33
41
|
|
@@ -45,7 +53,7 @@ equity participants.
|
|
45
53
|
difference between the total assets of the entity and all its liabilities.
|
46
54
|
|
47
55
|
|
48
|
-
In each
|
56
|
+
In each entry, sources are credited and destinations are debited.
|
49
57
|
|
50
58
|
I repeat: credit is the **source** and debit is the **destination**.
|
51
59
|
|
@@ -97,7 +105,7 @@ Or better yet:
|
|
97
105
|
include Debitcredit::Extension
|
98
106
|
|
99
107
|
has_accounts
|
100
|
-
|
108
|
+
has_entries do
|
101
109
|
def pay!
|
102
110
|
...
|
103
111
|
end
|
@@ -123,11 +131,11 @@ You can pass a block to `has_accounts` and to define referenced accounts:
|
|
123
131
|
|
124
132
|
User.first.accounts.salary # will be created on first use
|
125
133
|
|
126
|
-
##
|
134
|
+
## Entries
|
127
135
|
|
128
|
-
You can prepare
|
136
|
+
You can prepare entries using DSL:
|
129
137
|
|
130
|
-
t =
|
138
|
+
t = Entry.prepare(description: 'rent payment') do
|
131
139
|
debit expense_account, 100, "you can also provide a comment"
|
132
140
|
credit bank_account, 50
|
133
141
|
credit creditcard, 50
|
@@ -137,21 +145,21 @@ You can prepare transactions using DSL:
|
|
137
145
|
Sum of the debits must be equal to the sum of the credits. Amounts can not be
|
138
146
|
negative.
|
139
147
|
|
140
|
-
You can create
|
148
|
+
You can create entries with a reference. For this case, and in case that
|
141
149
|
reference has 'accounts' association, you can use account names instead of objects:
|
142
150
|
|
143
|
-
t = user1.
|
151
|
+
t = user1.entries.prepare(description: 'sale') do
|
144
152
|
debit :checking, 100 # will use user1.accounts[:checking]
|
145
153
|
credit user2.accounts[:checking], 100
|
146
154
|
end
|
147
155
|
|
148
|
-
You can prepare an inverse
|
149
|
-
existing
|
156
|
+
You can prepare an inverse entry. For example if you want to rollback an
|
157
|
+
existing entry:
|
150
158
|
|
151
159
|
rollback = existing.inverse(kind: 'refund', description: 'item is out of stock')
|
152
160
|
rollback.save!
|
153
161
|
|
154
|
-
> Note: by inverse
|
162
|
+
> Note: by inverse entries are allowed to take accounts into overdraft. if
|
155
163
|
> this is undesirable, pass `enable_overdraft` to the `inverse` call.
|
156
164
|
|
157
165
|
## Contributing
|
@@ -1,11 +1,11 @@
|
|
1
1
|
require 'docile'
|
2
2
|
module Debitcredit
|
3
|
-
class
|
3
|
+
class Entry < ActiveRecord::Base
|
4
4
|
belongs_to :reference, polymorphic: true
|
5
|
-
belongs_to :
|
6
|
-
has_many :
|
7
|
-
belongs_to :
|
8
|
-
has_many :items, dependent: :destroy, autosave: true
|
5
|
+
belongs_to :parent_entry, class_name: 'Debitcredit::Entry'
|
6
|
+
has_many :child_entries, class_name: 'Debitcredit::Entry', foreign_key: 'parent_entry_id'
|
7
|
+
belongs_to :inverse_entry, class_name: 'Debitcredit::Entry'
|
8
|
+
has_many :items, dependent: :destroy, autosave: true, inverse_of: :entry
|
9
9
|
|
10
10
|
validates :reference, :description, presence: true
|
11
11
|
validate :ensure_balanced
|
@@ -30,8 +30,8 @@ module Debitcredit
|
|
30
30
|
res.description ||= "reverse of tr ##{id}: #{description}"
|
31
31
|
res.kind ||= 'rollback'
|
32
32
|
res.reference ||= reference
|
33
|
-
res.
|
34
|
-
self.
|
33
|
+
res.parent_entry = self
|
34
|
+
self.inverse_entry ||= res
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
@@ -56,11 +56,11 @@ module Debitcredit
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def save_parent
|
59
|
-
|
59
|
+
parent_entry.save! if parent_entry.try(:inverse_entry) == self
|
60
60
|
end
|
61
61
|
|
62
62
|
def parent_not_inversed
|
63
|
-
errors.add(:base, :already_inversed) if
|
63
|
+
errors.add(:base, :already_inversed) if parent_entry.inverse_entry_id
|
64
64
|
end
|
65
65
|
end
|
66
66
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class Debitcredit::Entry::Dsl
|
2
|
+
attr_accessor :entry
|
3
|
+
attr_accessor :accounts
|
4
|
+
|
5
|
+
def initialize(entry)
|
6
|
+
@entry = entry
|
7
|
+
end
|
8
|
+
|
9
|
+
def kind(kind)
|
10
|
+
@entry.kind = kind
|
11
|
+
end
|
12
|
+
|
13
|
+
def description(desc)
|
14
|
+
@entry.description = desc
|
15
|
+
end
|
16
|
+
alias desc description
|
17
|
+
|
18
|
+
def reference(ref)
|
19
|
+
@entry.reference = ref
|
20
|
+
end
|
21
|
+
alias ref reference
|
22
|
+
|
23
|
+
def debit(account, amount, comment = nil)
|
24
|
+
build_item true, account, amount, comment
|
25
|
+
end
|
26
|
+
|
27
|
+
def credit(account, amount, comment = nil)
|
28
|
+
build_item false, account, amount, comment
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def build_item(debit, account, amount, comment)
|
33
|
+
account = entry.reference.accounts[account] if account.is_a?(Symbol) && entry.reference.try(:respond_to?, :accounts)
|
34
|
+
entry.items.build debit: debit, account: account, amount: amount, comment: comment
|
35
|
+
end
|
36
|
+
end
|
@@ -18,8 +18,8 @@ module Debitcredit
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
22
|
-
has_many :
|
21
|
+
def has_entries(&block)
|
22
|
+
has_many :entries, as: :reference, class_name: 'Debitcredit::Entry' do
|
23
23
|
def [](kind)
|
24
24
|
find_by kind: kind
|
25
25
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module Debitcredit
|
2
2
|
class Item < ActiveRecord::Base
|
3
|
-
belongs_to :
|
3
|
+
belongs_to :entry
|
4
4
|
belongs_to :account
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
validates :entry, :account, presence: true
|
7
|
+
validates :amount, numericality: {greater_than_or_equal_to: 0}
|
8
8
|
|
9
9
|
scope :debit, ->{where(debit: true)}
|
10
10
|
scope :credit, ->{where(debit: false)}
|
@@ -22,7 +22,7 @@ module Debitcredit
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def inverse
|
25
|
-
self.class.new account: account,
|
25
|
+
self.class.new account: account, entry: entry, amount: amount, debit: credit?
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
data/config/locales/en.yml
CHANGED
@@ -0,0 +1,9 @@
|
|
1
|
+
class RenameTransactions < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
rename_table :debitcredit_transactions, :debitcredit_entries
|
4
|
+
rename_column :debitcredit_entries, :parent_transaction_id, :parent_entry_id
|
5
|
+
rename_column :debitcredit_entries, :inverse_transaction_id, :inverse_entry_id
|
6
|
+
|
7
|
+
rename_column :debitcredit_items, :transaction_id, :entry_id
|
8
|
+
end
|
9
|
+
end
|
data/lib/debitcredit/version.rb
CHANGED
metadata
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: debitcredit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vitaly Kushner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 4.0.4
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 4.0.4
|
27
27
|
- !ruby/object:Gem::Dependency
|
@@ -189,14 +189,14 @@ files:
|
|
189
189
|
- app/models/debitcredit/asset_account.rb
|
190
190
|
- app/models/debitcredit/credit_account.rb
|
191
191
|
- app/models/debitcredit/debit_account.rb
|
192
|
+
- app/models/debitcredit/entry/dsl.rb
|
193
|
+
- app/models/debitcredit/entry.rb
|
192
194
|
- app/models/debitcredit/equity_account.rb
|
193
195
|
- app/models/debitcredit/expense_account.rb
|
194
196
|
- app/models/debitcredit/extension.rb
|
195
197
|
- app/models/debitcredit/income_account.rb
|
196
198
|
- app/models/debitcredit/item.rb
|
197
199
|
- app/models/debitcredit/liability_account.rb
|
198
|
-
- app/models/debitcredit/transaction/dsl.rb
|
199
|
-
- app/models/debitcredit/transaction.rb
|
200
200
|
- config/locales/en.yml
|
201
201
|
- db/migrate/20140121145455_create_debitcredit_accounts.rb
|
202
202
|
- db/migrate/20140121181304_create_debitcredit_transactions.rb
|
@@ -206,6 +206,7 @@ files:
|
|
206
206
|
- db/migrate/20140128153104_add_account_overdraft.rb
|
207
207
|
- db/migrate/20140130095257_no_overdraft_by_default.rb
|
208
208
|
- db/migrate/20140612113944_add_inverse_transaction_id.rb
|
209
|
+
- db/migrate/20150106165647_rename_transactions.rb
|
209
210
|
- lib/debitcredit/engine.rb
|
210
211
|
- lib/debitcredit/version.rb
|
211
212
|
- lib/debitcredit.rb
|
@@ -1,36 +0,0 @@
|
|
1
|
-
class Debitcredit::Transaction::Dsl
|
2
|
-
attr_accessor :transaction
|
3
|
-
attr_accessor :accounts
|
4
|
-
|
5
|
-
def initialize(transaction)
|
6
|
-
@transaction = transaction
|
7
|
-
end
|
8
|
-
|
9
|
-
def kind(kind)
|
10
|
-
@transaction.kind = kind
|
11
|
-
end
|
12
|
-
|
13
|
-
def description(desc)
|
14
|
-
@transaction.description = desc
|
15
|
-
end
|
16
|
-
alias desc description
|
17
|
-
|
18
|
-
def reference(ref)
|
19
|
-
@transaction.reference = ref
|
20
|
-
end
|
21
|
-
alias ref reference
|
22
|
-
|
23
|
-
def debit(account, amount, comment = nil)
|
24
|
-
build_item true, account, amount, comment
|
25
|
-
end
|
26
|
-
|
27
|
-
def credit(account, amount, comment = nil)
|
28
|
-
build_item false, account, amount, comment
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
def build_item(debit, account, amount, comment)
|
33
|
-
account = transaction.reference.accounts[account] if account.is_a?(Symbol) && transaction.reference.try(:respond_to?, :accounts)
|
34
|
-
transaction.items.build debit: debit, account: account, amount: amount, comment: comment
|
35
|
-
end
|
36
|
-
end
|