has_accounts 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/app/models/booking.rb +1 -1
- data/app/models/booking.rb~ +166 -0
- data/lib/has_accounts/model.rb +9 -2
- data/lib/has_accounts/model.rb~ +51 -0
- metadata +6 -4
data/app/models/booking.rb
CHANGED
@@ -43,7 +43,7 @@ class Booking < ActiveRecord::Base
|
|
43
43
|
rescue ArgumentError
|
44
44
|
end
|
45
45
|
|
46
|
-
where("title LIKE :text OR amount = :amount OR value_date = :value_date", :text => text, :amount => amount, :value_date => date)
|
46
|
+
where("title LIKE :text OR remarks = :text OR amount = :amount OR value_date = :value_date", :text => text, :amount => amount, :value_date => date)
|
47
47
|
}
|
48
48
|
|
49
49
|
# Returns array of all years we have bookings for
|
@@ -0,0 +1,166 @@
|
|
1
|
+
class Booking < ActiveRecord::Base
|
2
|
+
# Validation
|
3
|
+
validates_presence_of :debit_account, :credit_account, :title, :amount, :value_date
|
4
|
+
validates_time :value_date
|
5
|
+
|
6
|
+
# Associations
|
7
|
+
belongs_to :debit_account, :foreign_key => 'debit_account_id', :class_name => "Account"
|
8
|
+
belongs_to :credit_account, :foreign_key => 'credit_account_id', :class_name => "Account"
|
9
|
+
|
10
|
+
# Scoping
|
11
|
+
default_scope order('value_date, id')
|
12
|
+
|
13
|
+
scope :by_value_date, lambda {|value_date| where(:value_date => value_date) }
|
14
|
+
scope :by_value_period, lambda {|from, to| where(:value_date => (from..to)) }
|
15
|
+
|
16
|
+
scope :by_account, lambda {|account_id|
|
17
|
+
{ :conditions => ["debit_account_id = :account_id OR credit_account_id = :account_id", {:account_id => account_id}] }
|
18
|
+
} do
|
19
|
+
# Returns array of all booking titles.
|
20
|
+
def titles
|
21
|
+
find(:all, :group => :title).map{|booking| booking.title}
|
22
|
+
end
|
23
|
+
|
24
|
+
# Statistics per booking title.
|
25
|
+
#
|
26
|
+
# The statistics are an array of hashes with keys title, count, sum, average.
|
27
|
+
def statistics
|
28
|
+
find(:all, :select => "title, count(*) AS count, sum(amount) AS sum, avg(amount) AS avg", :group => :title).map{|stat| stat.attributes}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
scope :by_text, lambda {|value|
|
33
|
+
text = '%' + value + '%'
|
34
|
+
|
35
|
+
amount = value.delete("'").to_f
|
36
|
+
if amount == 0.0
|
37
|
+
amount = nil unless value.match(/^[0.]*$/)
|
38
|
+
end
|
39
|
+
|
40
|
+
date = nil
|
41
|
+
begin
|
42
|
+
date = Date.parse(value)
|
43
|
+
rescue ArgumentError
|
44
|
+
end
|
45
|
+
|
46
|
+
where("title LIKE :text OR amount = :amount OR value_date = :value_date", :text => text, :amount => amount, :value_date => date)
|
47
|
+
}
|
48
|
+
|
49
|
+
# Returns array of all years we have bookings for
|
50
|
+
def self.fiscal_years
|
51
|
+
with_exclusive_scope do
|
52
|
+
select("DISTINCT year(value_date) AS year").all.map{|booking| booking.year}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.scope_by_value_date(value_date)
|
57
|
+
scoping = self.default_scoping - [@by_value_scope]
|
58
|
+
|
59
|
+
@by_value_scope = {:find => {:conditions => {:value_date => value_date}}}
|
60
|
+
scoping << @by_value_scope
|
61
|
+
|
62
|
+
Thread.current["#{self}_scoped_methods"] = nil
|
63
|
+
self.default_scoping = scoping
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.filter(controller, &block)
|
67
|
+
if controller.value_date_scope
|
68
|
+
with_scope(:find => {:conditions => {:value_date => controller.value_date_scope}}, &block)
|
69
|
+
else
|
70
|
+
block.call
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Standard methods
|
75
|
+
def to_s(format = :default)
|
76
|
+
case format
|
77
|
+
when :short
|
78
|
+
"%s: %s / %s CHF %s" % [
|
79
|
+
value_date ? value_date : '?',
|
80
|
+
credit_account ? credit_account.code : '?',
|
81
|
+
debit_account ? debit_account.code : '?',
|
82
|
+
amount ? "%0.2f" % amount : '?',
|
83
|
+
]
|
84
|
+
else
|
85
|
+
"%s: %s an %s CHF %s, %s (%s)" % [
|
86
|
+
value_date ? value_date : '?',
|
87
|
+
credit_account ? "#{credit_account.title} (#{credit_account.code})" : '?',
|
88
|
+
debit_account ? "#{debit_account.title} (#{debit_account.code})" : '?',
|
89
|
+
amount ? "%0.2f" % amount : '?',
|
90
|
+
title.present? ? title : '?',
|
91
|
+
comments.present? ? comments : '?'
|
92
|
+
]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Helpers
|
97
|
+
def accounted_amount(account)
|
98
|
+
if credit_account == account
|
99
|
+
balance = -(amount)
|
100
|
+
elsif debit_account == account
|
101
|
+
balance = amount
|
102
|
+
else
|
103
|
+
return BigDecimal.new('0')
|
104
|
+
end
|
105
|
+
|
106
|
+
if account.is_asset_account?
|
107
|
+
return -(balance)
|
108
|
+
else
|
109
|
+
return balance
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def amount_as_string
|
114
|
+
'%0.2f' % amount
|
115
|
+
end
|
116
|
+
|
117
|
+
def amount_as_string=(value)
|
118
|
+
self.amount = value
|
119
|
+
end
|
120
|
+
|
121
|
+
def rounded_amount
|
122
|
+
if amount.nil?
|
123
|
+
return 0
|
124
|
+
else
|
125
|
+
return (amount * 20).round / 20.0
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Templates
|
130
|
+
def booking_template_id
|
131
|
+
nil
|
132
|
+
end
|
133
|
+
|
134
|
+
def booking_template_id=(value)
|
135
|
+
end
|
136
|
+
|
137
|
+
# Reference
|
138
|
+
belongs_to :reference, :polymorphic => true
|
139
|
+
after_save :notify_references
|
140
|
+
|
141
|
+
# Safety net for form assignments
|
142
|
+
def reference_type=(value)
|
143
|
+
write_attribute(:reference_type, value) unless value.blank?
|
144
|
+
end
|
145
|
+
|
146
|
+
scope :by_reference, lambda {|value|
|
147
|
+
where(:reference_id => value.id, :reference_type => value.class.base_class)
|
148
|
+
} do
|
149
|
+
# TODO duplicated in Invoice
|
150
|
+
def direct_balance(direct_account)
|
151
|
+
balance = 0.0
|
152
|
+
|
153
|
+
for booking in all
|
154
|
+
balance += booking.accounted_amount(direct_account)
|
155
|
+
end
|
156
|
+
|
157
|
+
balance
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
private
|
162
|
+
def notify_references
|
163
|
+
return unless reference and reference.respond_to?(:booking_saved)
|
164
|
+
reference.booking_saved(self)
|
165
|
+
end
|
166
|
+
end
|
data/lib/has_accounts/model.rb
CHANGED
@@ -34,9 +34,16 @@ module HasAccounts
|
|
34
34
|
self.class.direct_account
|
35
35
|
end
|
36
36
|
|
37
|
-
|
38
|
-
|
37
|
+
# Build booking
|
38
|
+
def build_booking(params = {}, template_code = nil)
|
39
|
+
template_code ||= self.class.to_s.underscore + ':invoice'
|
40
|
+
booking_template = BookingTemplate.find_by_code(template_code)
|
39
41
|
|
42
|
+
# Prepare booking parameters
|
43
|
+
booking_params = {:value_date => value_date, :amount => amount}
|
44
|
+
booking_params.merge!(params)
|
45
|
+
|
46
|
+
# Build and assign booking
|
40
47
|
booking = booking_template.build_booking(:value_date => value_date, :amount => amount)
|
41
48
|
bookings << booking
|
42
49
|
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module HasAccounts
|
2
|
+
module Model
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
class_inheritable_accessor :direct_account
|
7
|
+
|
8
|
+
has_many :bookings, :as => :reference, :dependent => :destroy do
|
9
|
+
# TODO: duplicated in Booking (without parameter)
|
10
|
+
def direct_balance(value_date = nil, direct_account = nil)
|
11
|
+
return BigDecimal.new('0') unless proxy_owner.direct_account
|
12
|
+
|
13
|
+
direct_account ||= proxy_owner.direct_account
|
14
|
+
balance = BigDecimal.new('0')
|
15
|
+
|
16
|
+
direct_bookings = scoped
|
17
|
+
direct_bookings = direct_bookings.where("value_date <= ?", value_date) if value_date
|
18
|
+
|
19
|
+
for booking in direct_bookings.all
|
20
|
+
balance += booking.accounted_amount(direct_account)
|
21
|
+
end
|
22
|
+
|
23
|
+
balance
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module ClassMethods
|
29
|
+
end
|
30
|
+
|
31
|
+
module InstanceMethods
|
32
|
+
# Delegate to class
|
33
|
+
def direct_account
|
34
|
+
self.class.direct_account
|
35
|
+
end
|
36
|
+
|
37
|
+
def build_booking
|
38
|
+
booking_template = BookingTemplate.find_by_code(self.class.to_s.underscore + ':invoice')
|
39
|
+
|
40
|
+
booking = booking_template.build_booking(:value_date => value_date, :amount => amount)
|
41
|
+
bookings << booking
|
42
|
+
|
43
|
+
booking
|
44
|
+
end
|
45
|
+
|
46
|
+
def balance(value_date = nil)
|
47
|
+
bookings.direct_balance(value_date)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 3
|
8
|
+
- 0
|
9
|
+
version: 0.3.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- "Simon H\xC3\xBCrlimann (CyT)"
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-04-
|
17
|
+
date: 2011-04-13 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|
@@ -35,7 +35,9 @@ files:
|
|
35
35
|
- app/models/booking.rb
|
36
36
|
- app/models/account_type.rb
|
37
37
|
- app/models/bank_account.rb
|
38
|
+
- app/models/booking.rb~
|
38
39
|
- lib/has_accounts.rb
|
40
|
+
- lib/has_accounts/model.rb~
|
39
41
|
- lib/has_accounts/class_methods.rb
|
40
42
|
- lib/has_accounts/railtie.rb~
|
41
43
|
- lib/has_accounts/core_ext/rounding.rb~
|