has_accounts 2.0.3 → 2.1.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 +1 -1
- data/app/models/account.rb +28 -28
- data/app/models/account_scope_extension.rb +1 -1
- data/app/models/booking.rb +38 -35
- data/app/models/booking_template.rb +32 -32
- data/db/migrate/20111108000000_create_has_accounts_tables.rb +52 -52
- data/db/migrate/20130707121400_create_booking_templates.rb +14 -14
- data/db/migrate/20131021123821_change_bookings_amount_to_use_decimal_scope.rb +1 -1
- data/lib/has_accounts/class_methods.rb +1 -1
- data/lib/has_accounts/core_ext/rounding.rb +3 -3
- data/lib/has_accounts/model.rb +7 -7
- data/lib/has_accounts/railtie.rb +1 -1
- data/lib/has_accounts/version.rb +1 -1
- metadata +4 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 403d094803675510f38b33a494676ed9f70050b5
|
4
|
+
data.tar.gz: 0a39e6943b89d82857bf0386c9342c97c395a355
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 06fad61f4d896918f0bb135062f4a7f29504699e2f1d7544f6e711d25d16034bfa85bf03218b90ed2699453026e6d2ef31543ee7ba6ab18a7ee9181dd4e98589
|
7
|
+
data.tar.gz: f9a03bb6639014b0de59b8a98ba80ef84d1fead4b9f6f922772fecc9d1df65e894d1b14f4426882be1f9abce270e45cfe8754d2248f824baf9e6009b3cf99a91
|
data/README.md
CHANGED
data/app/models/account.rb
CHANGED
@@ -4,7 +4,7 @@ class Account < ActiveRecord::Base
|
|
4
4
|
attr_accessible :title, :code
|
5
5
|
|
6
6
|
# Scopes
|
7
|
-
default_scope :
|
7
|
+
default_scope order: 'code'
|
8
8
|
|
9
9
|
# Dummy scope to make scoped_by happy
|
10
10
|
scope :by_value_period, scoped
|
@@ -13,13 +13,13 @@ class Account < ActiveRecord::Base
|
|
13
13
|
validates_presence_of :code, :title
|
14
14
|
|
15
15
|
# String
|
16
|
-
def to_s(
|
17
|
-
|
16
|
+
def to_s(_format = :default)
|
17
|
+
'%s (%s)' % [title, code]
|
18
18
|
end
|
19
19
|
|
20
20
|
# Parent Account
|
21
21
|
# ==============
|
22
|
-
belongs_to :parent, :
|
22
|
+
belongs_to :parent, class_name: Account
|
23
23
|
attr_accessible :parent, :parent_id
|
24
24
|
|
25
25
|
# Account Type
|
@@ -29,7 +29,7 @@ class Account < ActiveRecord::Base
|
|
29
29
|
validates_presence_of :account_type
|
30
30
|
|
31
31
|
def asset_account?
|
32
|
-
Account.by_type(
|
32
|
+
Account.by_type(%w(current_assets capital_assets costs)).exists?(self)
|
33
33
|
end
|
34
34
|
|
35
35
|
def liability_account?
|
@@ -37,14 +37,14 @@ class Account < ActiveRecord::Base
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def balance_account?
|
40
|
-
Account.by_type(
|
40
|
+
Account.by_type(%w(current_assets capital_assets outside_capital equity_capital)).exists?(self)
|
41
41
|
end
|
42
42
|
|
43
43
|
def profit_account?
|
44
44
|
!balance_account?
|
45
45
|
end
|
46
46
|
|
47
|
-
scope :by_type, lambda {|value| includes(:account_type).where('account_types.name' => value)} do
|
47
|
+
scope :by_type, lambda { |value| includes(:account_type).where('account_types.name' => value) } do
|
48
48
|
include AccountScopeExtension
|
49
49
|
end
|
50
50
|
|
@@ -65,12 +65,12 @@ class Account < ActiveRecord::Base
|
|
65
65
|
|
66
66
|
# Holder
|
67
67
|
# ======
|
68
|
-
belongs_to :holder, :
|
68
|
+
belongs_to :holder, polymorphic: true
|
69
69
|
|
70
70
|
# Bookings
|
71
71
|
# ========
|
72
|
-
has_many :credit_bookings, :
|
73
|
-
has_many :debit_bookings, :
|
72
|
+
has_many :credit_bookings, class_name: 'Booking', foreign_key: 'credit_account_id'
|
73
|
+
has_many :debit_bookings, class_name: 'Booking', foreign_key: 'debit_account_id'
|
74
74
|
|
75
75
|
def bookings
|
76
76
|
Booking.by_account(id)
|
@@ -78,51 +78,51 @@ class Account < ActiveRecord::Base
|
|
78
78
|
|
79
79
|
# Balances grouped by references which have not 0
|
80
80
|
def unbalanced_references
|
81
|
-
bookings.unbalanced_by_grouped_reference(
|
81
|
+
bookings.unbalanced_by_grouped_reference(id)
|
82
82
|
end
|
83
83
|
|
84
84
|
# Helpers
|
85
85
|
# =======
|
86
86
|
def self.overview(value_range = Date.today, format = :default)
|
87
|
-
Account.all.map{|a| a.to_s(value_range, format)}
|
87
|
+
Account.all.map { |a| a.to_s(value_range, format) }
|
88
88
|
end
|
89
89
|
|
90
90
|
# Calculations
|
91
91
|
def turnover(selector = Date.today, inclusive = true)
|
92
|
-
equality =
|
92
|
+
equality = '=' if inclusive
|
93
93
|
|
94
|
-
if selector.respond_to?(:first)
|
94
|
+
if selector.respond_to?(:first) && selector.respond_to?(:last)
|
95
95
|
if selector.first.is_a? Booking
|
96
96
|
if selector.first.value_date == selector.last.value_date
|
97
97
|
condition = ["date(value_date) = :value_date AND id >#{equality} :first_id AND id <#{equality} :last_id", {
|
98
|
-
:
|
99
|
-
:
|
100
|
-
:
|
98
|
+
value_date: selector.first.value_date,
|
99
|
+
first_id: selector.first.id,
|
100
|
+
last_id: selector.last.id
|
101
101
|
}]
|
102
102
|
else
|
103
103
|
condition = ["(value_date > :first_value_date AND value_date < :latest_value_date) OR (date(value_date) = :first_value_date AND id >#{equality} :first_id) OR (date(value_date) = :latest_value_date AND id <#{equality} :last_id)", {
|
104
|
-
:
|
105
|
-
:
|
106
|
-
:
|
107
|
-
:
|
104
|
+
first_value_date: selector.first.value_date,
|
105
|
+
latest_value_date: selector.last.value_date,
|
106
|
+
first_id: selector.first.id,
|
107
|
+
last_id: selector.last.id
|
108
108
|
}]
|
109
109
|
end
|
110
110
|
elsif
|
111
111
|
if selector.first == selector.last
|
112
|
-
condition = [
|
113
|
-
:
|
112
|
+
condition = ['date(value_date) = :value_date', {
|
113
|
+
value_date: selector.first
|
114
114
|
}]
|
115
115
|
else
|
116
|
-
condition = [
|
117
|
-
:
|
118
|
-
:
|
116
|
+
condition = ['date(value_date) BETWEEN :first_value_date AND :latest_value_date', {
|
117
|
+
first_value_date: selector.first,
|
118
|
+
latest_value_date: selector.last
|
119
119
|
}]
|
120
120
|
end
|
121
121
|
end
|
122
122
|
else
|
123
123
|
if selector.is_a? Booking
|
124
124
|
# date(value_date) is needed on sqlite!
|
125
|
-
condition = ["(value_date < :value_date) OR (date(value_date) = :value_date AND id <#{equality} :id)", {:
|
125
|
+
condition = ["(value_date < :value_date) OR (date(value_date) = :value_date AND id <#{equality} :id)", { value_date: selector.value_date, id: selector.id }]
|
126
126
|
else
|
127
127
|
condition = ["date(value_date) <#{equality} ?", selector]
|
128
128
|
end
|
@@ -139,6 +139,6 @@ class Account < ActiveRecord::Base
|
|
139
139
|
|
140
140
|
amount = debit_amount - credit_amount
|
141
141
|
|
142
|
-
|
142
|
+
asset_account? ? amount : -amount
|
143
143
|
end
|
144
144
|
end
|
data/app/models/booking.rb
CHANGED
@@ -4,21 +4,22 @@ class Booking < ActiveRecord::Base
|
|
4
4
|
|
5
5
|
# Validation
|
6
6
|
validates_presence_of :debit_account, :credit_account, :title, :value_date
|
7
|
-
validates :amount, :
|
7
|
+
validates :amount, presence: true, numericality: true
|
8
8
|
validates_time :value_date
|
9
9
|
|
10
10
|
# Template
|
11
|
-
belongs_to :template, :
|
11
|
+
belongs_to :template, polymorphic: true
|
12
12
|
|
13
13
|
# Account
|
14
|
-
belongs_to :debit_account, :
|
14
|
+
belongs_to :debit_account, foreign_key: 'debit_account_id', class_name: 'Account'
|
15
15
|
attr_accessible :debit_account, :debit_account_id
|
16
|
-
belongs_to :credit_account, :
|
16
|
+
belongs_to :credit_account, foreign_key: 'credit_account_id', class_name: 'Account'
|
17
17
|
attr_accessible :credit_account, :credit_account_id
|
18
18
|
|
19
19
|
def debit_account_code
|
20
20
|
debit_account.code
|
21
21
|
end
|
22
|
+
|
22
23
|
def debit_account_code=(value)
|
23
24
|
debit_account = Account.find_by_code(value)
|
24
25
|
end
|
@@ -26,6 +27,7 @@ class Booking < ActiveRecord::Base
|
|
26
27
|
def credit_account_code
|
27
28
|
credit_account.code
|
28
29
|
end
|
30
|
+
|
29
31
|
def credit_account_code=(value)
|
30
32
|
credit_account = Account.find_by_code(value)
|
31
33
|
end
|
@@ -64,12 +66,12 @@ class Booking < ActiveRecord::Base
|
|
64
66
|
# Scoping
|
65
67
|
default_scope order('value_date, id')
|
66
68
|
|
67
|
-
scope :by_value_date, lambda {|value_date| where(
|
69
|
+
scope :by_value_date, lambda { |value_date| where('date(value_date) = ?', value_date) }
|
68
70
|
scope :by_value_period, lambda {|from, to|
|
69
71
|
if from.present?
|
70
|
-
where(
|
72
|
+
where('date(value_date) BETWEEN :from AND :to', from: from, to: to)
|
71
73
|
else
|
72
|
-
where(
|
74
|
+
where('date(value_date) <= :to', to: to)
|
73
75
|
end
|
74
76
|
}
|
75
77
|
|
@@ -77,18 +79,18 @@ class Booking < ActiveRecord::Base
|
|
77
79
|
#
|
78
80
|
# @param account_id [Integer]
|
79
81
|
scope :by_account, lambda {|account_id|
|
80
|
-
where(
|
82
|
+
where('debit_account_id = :account_id OR credit_account_id = :account_id', account_id: account_id)
|
81
83
|
} do
|
82
84
|
# Returns array of all booking titles.
|
83
85
|
def titles
|
84
|
-
find(:all, :
|
86
|
+
find(:all, group: :title).map(&:title)
|
85
87
|
end
|
86
88
|
|
87
89
|
# Statistics per booking title.
|
88
90
|
#
|
89
91
|
# The statistics are an array of hashes with keys title, count, sum, average.
|
90
92
|
def statistics
|
91
|
-
find(:all, :
|
93
|
+
find(:all, select: 'title, count(*) AS count, sum(amount) AS sum, avg(amount) AS avg', group: :title).map(&:attributes)
|
92
94
|
end
|
93
95
|
end
|
94
96
|
|
@@ -96,7 +98,7 @@ class Booking < ActiveRecord::Base
|
|
96
98
|
#
|
97
99
|
# @returns all involved credit and debit accounts
|
98
100
|
def self.accounts
|
99
|
-
Account.where(:
|
101
|
+
Account.where(id: pluck(:debit_account_id).uniq + pluck(:credit_account_id).uniq)
|
100
102
|
end
|
101
103
|
|
102
104
|
# Accounts with balances
|
@@ -112,17 +114,17 @@ class Booking < ActiveRecord::Base
|
|
112
114
|
|
113
115
|
# Accounted bookings
|
114
116
|
# ==================
|
115
|
-
SELECT_ACCOUNTED_AMOUNT=
|
116
|
-
'CASE WHEN credit_account_id = debit_account_id THEN 0.0 WHEN credit_account_id = %{account_id} THEN -bookings.amount WHEN debit_account_id = %{account_id} THEN bookings.amount ELSE 0 END'
|
117
|
+
SELECT_ACCOUNTED_AMOUNT = 'CASE WHEN credit_account_id = debit_account_id THEN 0.0 WHEN credit_account_id = %{account_id} THEN -bookings.amount WHEN debit_account_id = %{account_id} THEN bookings.amount ELSE 0 END'
|
117
118
|
|
118
119
|
private
|
120
|
+
|
119
121
|
def self.get_account_id(account_or_id)
|
120
122
|
if account_or_id.is_a? Account
|
121
123
|
return account_or_id.id
|
122
124
|
elsif Account.exists?(account_or_id)
|
123
125
|
return account_or_id
|
124
126
|
else
|
125
|
-
|
127
|
+
fail 'argument needs to be a record of type Account or an id for an existing Account record.'
|
126
128
|
end
|
127
129
|
end
|
128
130
|
|
@@ -132,14 +134,14 @@ class Booking < ActiveRecord::Base
|
|
132
134
|
#
|
133
135
|
# @param account_or_id Account id or object
|
134
136
|
scope :accounted_by, lambda {|account_or_id|
|
135
|
-
select("bookings.*, #{SELECT_ACCOUNTED_AMOUNT % {:
|
137
|
+
select("bookings.*, #{SELECT_ACCOUNTED_AMOUNT % { account_id: get_account_id(account_or_id) }} AS amount")
|
136
138
|
}
|
137
139
|
|
138
140
|
# Balance of bookings for the specified account
|
139
141
|
#
|
140
142
|
# @param account_or_id Account id or object
|
141
143
|
def self.balance_by(account_or_id)
|
142
|
-
BigDecimal.new(sum(SELECT_ACCOUNTED_AMOUNT % {:
|
144
|
+
BigDecimal.new(sum(SELECT_ACCOUNTED_AMOUNT % { account_id: get_account_id(account_or_id) }), 2)
|
143
145
|
end
|
144
146
|
|
145
147
|
# Balance of bookings for the specified account with 0 balance, grouped by reference
|
@@ -147,24 +149,24 @@ class Booking < ActiveRecord::Base
|
|
147
149
|
# @param account_or_id Account id or object
|
148
150
|
def self.unbalanced_by_grouped_reference(account_or_id)
|
149
151
|
# Do a manual sum using select() to be able to give it an alias we can use in having()
|
150
|
-
balance_select = "sum(#{SELECT_ACCOUNTED_AMOUNT % {:
|
152
|
+
balance_select = "sum(#{SELECT_ACCOUNTED_AMOUNT % { account_id: get_account_id(account_or_id) }})"
|
151
153
|
summs = group(:reference_type, :reference_id).having("#{balance_select} != 0.0").select("reference_type, reference_id, #{balance_select} AS balance").reorder(nil)
|
152
154
|
|
153
155
|
# Simulate Rails grouped summing result format
|
154
|
-
grouped = Hash[summs.map{ |group| [[group[:reference_type], group[:reference_id]], group[:balance]] }]
|
156
|
+
grouped = Hash[summs.map { |group| [[group[:reference_type], group[:reference_id]], group[:balance]] }]
|
155
157
|
|
156
158
|
# Convert value to BigDecimal
|
157
|
-
Hash[grouped.map{|reference, value| [reference, BigDecimal.new(value, 2)] }]
|
159
|
+
Hash[grouped.map { |reference, value| [reference, BigDecimal.new(value, 2)] }]
|
158
160
|
end
|
159
161
|
|
160
162
|
# Balance of bookings for the specified account, grouped by reference
|
161
163
|
#
|
162
164
|
# @param account_or_id Account id or object
|
163
165
|
def self.balance_by_grouped_reference(account_or_id)
|
164
|
-
grouped = group(:reference_type, :reference_id).sum(SELECT_ACCOUNTED_AMOUNT % {:
|
166
|
+
grouped = group(:reference_type, :reference_id).sum(SELECT_ACCOUNTED_AMOUNT % { account_id: get_account_id(account_or_id) })
|
165
167
|
|
166
168
|
# Convert value to BigDecimal
|
167
|
-
Hash[grouped.map{|reference, value| [reference, BigDecimal.new(value, 2)] }]
|
169
|
+
Hash[grouped.map { |reference, value| [reference, BigDecimal.new(value, 2)] }]
|
168
170
|
end
|
169
171
|
|
170
172
|
scope :by_text, lambda {|value|
|
@@ -181,13 +183,13 @@ class Booking < ActiveRecord::Base
|
|
181
183
|
rescue ArgumentError
|
182
184
|
end
|
183
185
|
|
184
|
-
where(
|
186
|
+
where('title ILIKE :text OR comments ILIKE :text OR amount = :amount OR value_date = :value_date', text: text, amount: amount, value_date: date)
|
185
187
|
}
|
186
188
|
|
187
189
|
# Returns array of all years we have bookings for
|
188
190
|
def self.fiscal_years
|
189
191
|
with_exclusive_scope do
|
190
|
-
select(
|
192
|
+
select('DISTINCT year(value_date) AS year').all.map(&:year)
|
191
193
|
end
|
192
194
|
end
|
193
195
|
|
@@ -195,20 +197,20 @@ class Booking < ActiveRecord::Base
|
|
195
197
|
def to_s(format = :default)
|
196
198
|
case format
|
197
199
|
when :long
|
198
|
-
|
200
|
+
'%s: %s an %s CHF %s, %s (%s)' % [
|
199
201
|
value_date ? value_date : '?',
|
200
202
|
debit_account ? "#{debit_account.title} (#{debit_account.code})" : '?',
|
201
203
|
credit_account ? "#{credit_account.title} (#{credit_account.code})" : '?',
|
202
|
-
amount ?
|
204
|
+
amount ? '%0.2f' % amount : '?',
|
203
205
|
title.present? ? title : '?',
|
204
206
|
comments.present? ? comments : '?'
|
205
207
|
]
|
206
208
|
else
|
207
|
-
|
209
|
+
'%s: %s / %s CHF %s' % [
|
208
210
|
value_date ? value_date : '?',
|
209
211
|
debit_account ? debit_account.code : '?',
|
210
212
|
credit_account ? credit_account.code : '?',
|
211
|
-
amount ?
|
213
|
+
amount ? '%0.2f' % amount : '?'
|
212
214
|
]
|
213
215
|
end
|
214
216
|
end
|
@@ -240,31 +242,31 @@ class Booking < ActiveRecord::Base
|
|
240
242
|
|
241
243
|
def rounded_amount
|
242
244
|
if amount.nil?
|
243
|
-
|
245
|
+
return 0
|
244
246
|
else
|
245
|
-
|
247
|
+
return (amount * 20).round / 20.0
|
246
248
|
end
|
247
249
|
end
|
248
250
|
|
249
251
|
# Helpers
|
250
252
|
def split(amount, params = {})
|
251
253
|
# Clone
|
252
|
-
new_booking =
|
254
|
+
new_booking = clone
|
253
255
|
|
254
256
|
# Set amount
|
255
257
|
new_booking[:amount] = amount
|
256
258
|
self.amount -= amount
|
257
259
|
|
258
260
|
# Update attributes
|
259
|
-
params.each
|
261
|
+
params.each do|key, value|
|
260
262
|
new_booking[key] = value
|
261
|
-
|
263
|
+
end
|
262
264
|
|
263
265
|
[self, new_booking]
|
264
266
|
end
|
265
267
|
|
266
268
|
# Reference
|
267
|
-
belongs_to :reference, :
|
269
|
+
belongs_to :reference, polymorphic: true, touch: true, inverse_of: :bookings
|
268
270
|
attr_accessible :reference_id, :reference_type, :reference
|
269
271
|
|
270
272
|
after_save :touch_previous_reference
|
@@ -290,7 +292,7 @@ class Booking < ActiveRecord::Base
|
|
290
292
|
end
|
291
293
|
|
292
294
|
scope :by_reference, lambda {|value|
|
293
|
-
where(:
|
295
|
+
where(reference_id: value.id, reference_type: value.class.base_class)
|
294
296
|
} do
|
295
297
|
# TODO duplicated in Invoice
|
296
298
|
def direct_balance(direct_account)
|
@@ -305,8 +307,9 @@ class Booking < ActiveRecord::Base
|
|
305
307
|
end
|
306
308
|
|
307
309
|
private
|
310
|
+
|
308
311
|
def notify_references
|
309
|
-
return unless reference
|
312
|
+
return unless reference && reference.respond_to?(:booking_saved)
|
310
313
|
reference.booking_saved(self)
|
311
314
|
end
|
312
315
|
end
|
@@ -3,34 +3,34 @@ class BookingTemplate < ActiveRecord::Base
|
|
3
3
|
attr_accessible :title, :code, :amount, :amount_relates_to, :comments, :charge_rate_code
|
4
4
|
|
5
5
|
# Associations
|
6
|
-
belongs_to :debit_account, :
|
6
|
+
belongs_to :debit_account, foreign_key: 'debit_account_id', class_name: 'Account'
|
7
7
|
attr_accessible :debit_account_id, :debit_account
|
8
|
-
belongs_to :credit_account, :
|
8
|
+
belongs_to :credit_account, foreign_key: 'credit_account_id', class_name: 'Account'
|
9
9
|
attr_accessible :credit_account_id, :credit_account
|
10
10
|
|
11
|
-
has_many :bookings, :
|
11
|
+
has_many :bookings, through: :line_items
|
12
12
|
|
13
13
|
# Default ordering
|
14
14
|
default_scope order(:code)
|
15
15
|
|
16
16
|
# Scopes
|
17
|
-
scope :by_type, lambda{|value| where(
|
17
|
+
scope :by_type, lambda { |value| where('code LIKE ?', value + ':%') }
|
18
18
|
|
19
19
|
# Standard methods
|
20
20
|
include ApplicationHelper
|
21
21
|
def to_s(format = :default)
|
22
22
|
case format
|
23
23
|
when :short
|
24
|
-
|
24
|
+
'%s / %s %s' % [
|
25
25
|
debit_account ? debit_account.to_s(:short) : '?',
|
26
26
|
credit_account ? credit_account.to_s(:short) : '?',
|
27
|
-
amount ?
|
27
|
+
amount ? '%0.2f' % amount.to_f : '?'
|
28
28
|
]
|
29
29
|
when :long
|
30
|
-
|
30
|
+
'%s an %s %s, %s (%s)' % [
|
31
31
|
debit_account ? debit_account.to_s : '?',
|
32
32
|
credit_account ? credit_account.to_s : '?',
|
33
|
-
amount ?
|
33
|
+
amount ? '%0.2f' % amount.to_f : '?',
|
34
34
|
title.present? ? title : '?',
|
35
35
|
comments.present? ? comments : '?'
|
36
36
|
]
|
@@ -41,7 +41,7 @@ class BookingTemplate < ActiveRecord::Base
|
|
41
41
|
|
42
42
|
def amount_to_s
|
43
43
|
if amount_relates_to.present?
|
44
|
-
return
|
44
|
+
return '%.2f%%' % (amount.to_f * 100)
|
45
45
|
else
|
46
46
|
return currency_fmt(amount)
|
47
47
|
end
|
@@ -60,17 +60,17 @@ class BookingTemplate < ActiveRecord::Base
|
|
60
60
|
params = HashWithIndifferentAccess.new(params)
|
61
61
|
|
62
62
|
# Prepare parameters set by template
|
63
|
-
booking_params = attributes.reject{|key,
|
63
|
+
booking_params = attributes.reject { |key, _value| !%w(title comments credit_account_id debit_account_id).include?(key) }
|
64
64
|
|
65
65
|
# Calculate amount
|
66
|
-
booking_amount = BigDecimal.new(
|
66
|
+
booking_amount = BigDecimal.new(amount.to_s || '0')
|
67
67
|
|
68
68
|
# Lookup reference
|
69
69
|
reference = params['reference']
|
70
70
|
unless reference
|
71
71
|
ref_type = params['reference_type']
|
72
72
|
ref_id = params['reference_id']
|
73
|
-
if ref_type.present?
|
73
|
+
if ref_type.present? && ref_id.present?
|
74
74
|
reference = ref_type.constantize.find(ref_id)
|
75
75
|
end
|
76
76
|
end
|
@@ -79,15 +79,15 @@ class BookingTemplate < ActiveRecord::Base
|
|
79
79
|
|
80
80
|
if reference
|
81
81
|
# Calculate amount
|
82
|
-
booking_amount = amount(reference.value_date, :
|
82
|
+
booking_amount = amount(reference.value_date, person_id: person_id) if person_id
|
83
83
|
|
84
|
-
case
|
84
|
+
case amount_relates_to
|
85
85
|
when 'reference_amount'
|
86
86
|
booking_amount *= reference.amount unless reference.amount.nil?
|
87
87
|
when 'reference_balance'
|
88
88
|
booking_amount *= reference.balance unless reference.balance.nil?
|
89
89
|
when 'reference_amount_minus_balance'
|
90
|
-
booking_amount *= reference.amount - reference.balance unless
|
90
|
+
booking_amount *= reference.amount - reference.balance unless reference.amount.nil? || reference.balance.nil?
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
@@ -117,7 +117,7 @@ class BookingTemplate < ActiveRecord::Base
|
|
117
117
|
# @return [Booking] unsaved Booking
|
118
118
|
def self.build_booking(code, params = {})
|
119
119
|
template = find_by_code(code)
|
120
|
-
|
120
|
+
fail "BookingTemplate not found for '#{code}'" unless template
|
121
121
|
|
122
122
|
template.build_booking params
|
123
123
|
end
|
@@ -130,36 +130,36 @@ class BookingTemplate < ActiveRecord::Base
|
|
130
130
|
has_many :line_items
|
131
131
|
|
132
132
|
def build_line_item
|
133
|
-
if
|
133
|
+
if amount.match(/%/) || amount_relates_to.blank?
|
134
134
|
line_item_class = LineItem
|
135
135
|
else
|
136
136
|
line_item_class = SaldoLineItem
|
137
137
|
end
|
138
138
|
|
139
139
|
line_item = line_item_class.new(
|
140
|
-
:
|
141
|
-
:
|
142
|
-
:
|
143
|
-
:
|
144
|
-
:
|
145
|
-
:
|
146
|
-
:
|
147
|
-
:
|
140
|
+
booking_template: self,
|
141
|
+
title: title,
|
142
|
+
code: code,
|
143
|
+
credit_account: credit_account,
|
144
|
+
debit_account: debit_account,
|
145
|
+
position: position,
|
146
|
+
include_in_saldo_list: include_in_saldo_list,
|
147
|
+
reference_code: amount_relates_to
|
148
148
|
)
|
149
149
|
|
150
|
-
if
|
150
|
+
if amount.match(/%/)
|
151
151
|
line_item.quantity = '%'
|
152
|
-
line_item.times =
|
152
|
+
line_item.times = amount.delete('%')
|
153
153
|
# TODO: hack
|
154
154
|
line_item.price = line_item.price
|
155
|
-
elsif
|
155
|
+
elsif amount_relates_to.present?
|
156
156
|
line_item.quantity = 'saldo_of'
|
157
157
|
# TODO: hack
|
158
158
|
line_item.price = line_item.price
|
159
159
|
else
|
160
160
|
line_item.quantity = 'x'
|
161
161
|
line_item.times = 1
|
162
|
-
line_item.price =
|
162
|
+
line_item.price = amount
|
163
163
|
end
|
164
164
|
|
165
165
|
line_item
|
@@ -170,10 +170,10 @@ class BookingTemplate < ActiveRecord::Base
|
|
170
170
|
attr_accessible :matcher
|
171
171
|
|
172
172
|
def self.import(struct)
|
173
|
-
templates =
|
174
|
-
puts
|
173
|
+
templates = all.inject([]) do |found, template|
|
174
|
+
puts 'matcher: ' + template.matcher
|
175
175
|
puts 'text: ' + struct.text
|
176
|
-
found << template
|
176
|
+
found << template unless Regexp.new(template.matcher).match(struct.text).eql? nil
|
177
177
|
end
|
178
178
|
puts templates.inspect
|
179
179
|
end
|
@@ -1,68 +1,68 @@
|
|
1
1
|
class CreateHasAccountsTables < ActiveRecord::Migration
|
2
2
|
def self.up
|
3
|
-
create_table
|
4
|
-
t.string
|
5
|
-
t.string
|
6
|
-
t.datetime
|
7
|
-
t.datetime
|
3
|
+
create_table 'account_types' do |t|
|
4
|
+
t.string 'name', limit: 100
|
5
|
+
t.string 'title', limit: 100
|
6
|
+
t.datetime 'created_at'
|
7
|
+
t.datetime 'updated_at'
|
8
8
|
end
|
9
9
|
|
10
|
-
add_index
|
10
|
+
add_index 'account_types', 'name'
|
11
11
|
|
12
|
-
create_table
|
13
|
-
t.string
|
14
|
-
t.integer
|
15
|
-
t.integer
|
16
|
-
t.integer
|
17
|
-
t.string
|
18
|
-
t.string
|
19
|
-
t.integer
|
20
|
-
t.string
|
21
|
-
t.integer
|
22
|
-
t.integer
|
23
|
-
t.string
|
24
|
-
t.datetime
|
25
|
-
t.datetime
|
26
|
-
t.string
|
12
|
+
create_table 'accounts' do |t|
|
13
|
+
t.string 'title', limit: 100
|
14
|
+
t.integer 'parent_id'
|
15
|
+
t.integer 'account_type_id'
|
16
|
+
t.integer 'number'
|
17
|
+
t.string 'code'
|
18
|
+
t.string 'type'
|
19
|
+
t.integer 'holder_id'
|
20
|
+
t.string 'holder_type'
|
21
|
+
t.integer 'bank_id'
|
22
|
+
t.integer 'esr_id'
|
23
|
+
t.string 'pc_id'
|
24
|
+
t.datetime 'created_at'
|
25
|
+
t.datetime 'updated_at'
|
26
|
+
t.string 'iban'
|
27
27
|
end
|
28
28
|
|
29
|
-
add_index
|
30
|
-
add_index
|
31
|
-
add_index
|
32
|
-
add_index
|
33
|
-
add_index
|
29
|
+
add_index 'accounts', ['account_type_id'], name: 'index_accounts_on_account_type_id'
|
30
|
+
add_index 'accounts', ['bank_id'], name: 'index_accounts_on_bank_id'
|
31
|
+
add_index 'accounts', ['code'], name: 'index_accounts_on_code'
|
32
|
+
add_index 'accounts', %w(holder_id holder_type), name: 'index_accounts_on_holder_id_and_holder_type'
|
33
|
+
add_index 'accounts', ['type'], name: 'index_accounts_on_type'
|
34
34
|
|
35
|
-
create_table
|
36
|
-
t.integer
|
37
|
-
t.string
|
38
|
-
t.string
|
39
|
-
t.datetime
|
40
|
-
t.datetime
|
35
|
+
create_table 'banks' do |t|
|
36
|
+
t.integer 'vcard_id'
|
37
|
+
t.string 'swift'
|
38
|
+
t.string 'clearing'
|
39
|
+
t.datetime 'created_at'
|
40
|
+
t.datetime 'updated_at'
|
41
41
|
end
|
42
42
|
|
43
|
-
add_index
|
43
|
+
add_index 'banks', :vcard_id
|
44
44
|
|
45
|
-
create_table
|
46
|
-
t.string
|
47
|
-
t.decimal
|
48
|
-
t.integer
|
49
|
-
t.integer
|
50
|
-
t.date
|
51
|
-
t.text
|
52
|
-
t.string
|
53
|
-
t.string
|
54
|
-
t.string
|
55
|
-
t.float
|
56
|
-
t.datetime
|
57
|
-
t.datetime
|
58
|
-
t.integer
|
59
|
-
t.string
|
45
|
+
create_table 'bookings' do |t|
|
46
|
+
t.string 'title', limit: 100
|
47
|
+
t.decimal 'amount'
|
48
|
+
t.integer 'credit_account_id'
|
49
|
+
t.integer 'debit_account_id'
|
50
|
+
t.date 'value_date'
|
51
|
+
t.text 'comments', limit: 1000
|
52
|
+
t.string 'scan'
|
53
|
+
t.string 'debit_currency', default: 'CHF'
|
54
|
+
t.string 'credit_currency', default: 'CHF'
|
55
|
+
t.float 'exchange_rate', default: 1.0
|
56
|
+
t.datetime 'created_at'
|
57
|
+
t.datetime 'updated_at'
|
58
|
+
t.integer 'reference_id'
|
59
|
+
t.string 'reference_type'
|
60
60
|
end
|
61
61
|
|
62
|
-
add_index
|
63
|
-
add_index
|
64
|
-
add_index
|
65
|
-
add_index
|
62
|
+
add_index 'bookings', ['credit_account_id'], name: 'index_bookings_on_credit_account_id'
|
63
|
+
add_index 'bookings', ['debit_account_id'], name: 'index_bookings_on_debit_account_id'
|
64
|
+
add_index 'bookings', %w(reference_id reference_type), name: 'index_bookings_on_reference_id_and_reference_type'
|
65
|
+
add_index 'bookings', ['value_date'], name: 'index_bookings_on_value_date'
|
66
66
|
end
|
67
67
|
|
68
68
|
def self.down
|
@@ -1,20 +1,20 @@
|
|
1
1
|
class CreateBookingTemplates < ActiveRecord::Migration
|
2
2
|
def change
|
3
3
|
create_table :booking_templates do |t|
|
4
|
-
t.string
|
5
|
-
t.string
|
6
|
-
t.integer
|
7
|
-
t.integer
|
8
|
-
t.text
|
9
|
-
t.datetime
|
10
|
-
t.datetime
|
11
|
-
t.string
|
12
|
-
t.string
|
13
|
-
t.string
|
14
|
-
t.string
|
15
|
-
t.string
|
16
|
-
t.string
|
17
|
-
t.integer
|
4
|
+
t.string 'title'
|
5
|
+
t.string 'amount'
|
6
|
+
t.integer 'credit_account_id'
|
7
|
+
t.integer 'debit_account_id'
|
8
|
+
t.text 'comments'
|
9
|
+
t.datetime 'created_at', null: false
|
10
|
+
t.datetime 'updated_at', null: false
|
11
|
+
t.string 'code'
|
12
|
+
t.string 'matcher'
|
13
|
+
t.string 'amount_relates_to'
|
14
|
+
t.string 'type'
|
15
|
+
t.string 'charge_rate_code'
|
16
|
+
t.string 'salary_declaration_code'
|
17
|
+
t.integer 'position'
|
18
18
|
|
19
19
|
t.timestamps
|
20
20
|
end
|
@@ -15,14 +15,14 @@ module HasAccounts #:nodoc:
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
module BigDecimal
|
20
20
|
module Rounding
|
21
21
|
def currency_round
|
22
22
|
if self.nil?
|
23
|
-
return BigDecimal.new(
|
23
|
+
return BigDecimal.new('0')
|
24
24
|
else
|
25
|
-
return (self * 20).round / BigDecimal(
|
25
|
+
return (self * 20).round / BigDecimal('20')
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
data/lib/has_accounts/model.rb
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
module HasAccounts
|
2
2
|
module Model
|
3
3
|
extend ActiveSupport::Concern
|
4
|
-
|
4
|
+
|
5
5
|
included do
|
6
6
|
class_attribute :direct_account
|
7
7
|
|
8
|
-
has_many :bookings, :
|
8
|
+
has_many :bookings, as: :reference, dependent: :nullify, inverse_of: :reference do
|
9
9
|
# TODO: duplicated in Booking (without parameter)
|
10
10
|
def direct_balance(value_date = nil, direct_account = nil)
|
11
11
|
return BigDecimal.new('0') unless proxy_association.owner.direct_account
|
12
|
-
|
12
|
+
|
13
13
|
direct_account ||= proxy_association.owner.direct_account
|
14
14
|
balance = BigDecimal.new('0')
|
15
15
|
|
16
16
|
# Scope by value_date
|
17
|
-
if value_date.is_a?
|
18
|
-
direct_bookings = where(
|
17
|
+
if value_date.is_a?(Range) || value_date.is_a?(Array)
|
18
|
+
direct_bookings = where('date(value_date) BETWEEN :from AND :to', from: value_date.first, to: value_date.last)
|
19
19
|
elsif value_date
|
20
|
-
direct_bookings = where(
|
20
|
+
direct_bookings = where('date(value_date) <= ?', value_date) if value_date
|
21
21
|
else
|
22
22
|
direct_bookings = scoped
|
23
23
|
end
|
@@ -43,7 +43,7 @@ module HasAccounts
|
|
43
43
|
booking_template = BookingTemplate.find_by_code(template_code)
|
44
44
|
|
45
45
|
# Prepare booking parameters
|
46
|
-
booking_params = {:
|
46
|
+
booking_params = { reference: self }
|
47
47
|
booking_params.merge!(params)
|
48
48
|
|
49
49
|
# Build and assign booking
|
data/lib/has_accounts/railtie.rb
CHANGED
data/lib/has_accounts/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: has_accounts
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Simon Hürlimann (CyT)
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-02-
|
11
|
+
date: 2015-02-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -38,7 +38,7 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
-
description: HasAccounts is a full featured Rails
|
41
|
+
description: HasAccounts is a full featured Rails gem providing models for financial
|
42
42
|
accounting.
|
43
43
|
email:
|
44
44
|
- simon.huerlimann@cyt.ch
|
@@ -89,9 +89,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
89
89
|
version: '0'
|
90
90
|
requirements: []
|
91
91
|
rubyforge_project:
|
92
|
-
rubygems_version: 2.
|
92
|
+
rubygems_version: 2.2.2
|
93
93
|
signing_key:
|
94
94
|
specification_version: 4
|
95
95
|
summary: HasAccounts provides models for financial accounting.
|
96
96
|
test_files: []
|
97
|
-
has_rdoc:
|